diff options
Diffstat (limited to 'phpBB/includes')
168 files changed, 11369 insertions, 21528 deletions
diff --git a/phpBB/includes/acp/acp_attachments.php b/phpBB/includes/acp/acp_attachments.php index 958a6456c2..6e9360f599 100644 --- a/phpBB/includes/acp/acp_attachments.php +++ b/phpBB/includes/acp/acp_attachments.php @@ -1,9 +1,13 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -15,12 +19,9 @@ if (!defined('IN_PHPBB')) exit; } -/** -* @package acp -*/ class acp_attachments { - /** @var \phpbb\db\driver\driver */ + /** @var \phpbb\db\driver\driver_interface */ protected $db; /** @var \phpbb\config\config */ @@ -35,14 +36,20 @@ class acp_attachments /** @var \phpbb\user */ protected $user; + /** @var \phpbb\filesystem\filesystem_interface */ + protected $filesystem; + + /** @var \phpbb\attachment\manager */ + protected $attachment_manager; + public $id; public $u_action; protected $new_config; function main($id, $mode) { - global $db, $user, $auth, $template, $cache, $phpbb_container; - global $config, $phpbb_admin_path, $phpbb_root_path, $phpEx; + global $db, $user, $auth, $template, $cache, $phpbb_container, $phpbb_filesystem; + global $config, $phpbb_admin_path, $phpbb_root_path, $phpEx, $phpbb_log, $request; $this->id = $id; $this->db = $db; @@ -50,12 +57,14 @@ class acp_attachments $this->template = $template; $this->user = $user; $this->phpbb_container = $phpbb_container; + $this->filesystem = $phpbb_filesystem; + $this->attachment_manager = $phpbb_container->get('attachment.manager'); $user->add_lang(array('posting', 'viewtopic', 'acp/attachments')); $error = $notify = array(); $submit = (isset($_POST['submit'])) ? true : false; - $action = request_var('action', ''); + $action = $request->variable('action', ''); $form_key = 'acp_attach'; add_form_key($form_key); @@ -105,7 +114,10 @@ class acp_attachments { case 'attach': - include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx); + if (!function_exists('get_supported_image_types')) + { + include($phpbb_root_path . 'includes/functions_posting.' . $phpEx); + } $sql = 'SELECT group_name, cat_id FROM ' . EXTENSION_GROUPS_TABLE . ' @@ -147,20 +159,19 @@ class acp_attachments 'secure_allow_empty_referer' => array('lang' => 'SECURE_EMPTY_REFERRER', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'check_attachment_content' => array('lang' => 'CHECK_CONTENT', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), - 'legend2' => $l_legend_cat_images, 'img_display_inlined' => array('lang' => 'DISPLAY_INLINED', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'img_create_thumbnail' => array('lang' => 'CREATE_THUMBNAIL', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'img_max_thumb_width' => array('lang' => 'MAX_THUMB_WIDTH', 'validate' => 'int:0:999999999999999', 'type' => 'number:0:999999999999999', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']), 'img_min_thumb_filesize' => array('lang' => 'MIN_THUMB_FILESIZE', 'validate' => 'int:0:999999999999999', 'type' => 'number:0:999999999999999', 'explain' => true, 'append' => ' ' . $user->lang['BYTES']), - 'img_imagick' => array('lang' => 'IMAGICK_PATH', 'validate' => 'string', 'type' => 'text:20:200', 'explain' => true, 'append' => ' <span>[ <a href="' . $this->u_action . '&action=imgmagick">' . $user->lang['SEARCH_IMAGICK'] . '</a> ]</span>'), + 'img_imagick' => array('lang' => 'IMAGICK_PATH', 'validate' => 'absolute_path', 'type' => 'text:20:200', 'explain' => true, 'append' => ' <span>[ <a href="' . $this->u_action . '&action=imgmagick">' . $user->lang['SEARCH_IMAGICK'] . '</a> ]</span>'), 'img_max' => array('lang' => 'MAX_IMAGE_SIZE', 'validate' => 'int:0:9999', 'type' => 'dimension:0:9999', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']), 'img_link' => array('lang' => 'IMAGE_LINK_SIZE', 'validate' => 'int:0:9999', 'type' => 'dimension:0:9999', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']), ) ); $this->new_config = $config; - $cfg_array = (isset($_REQUEST['config'])) ? request_var('config', array('' => '')) : $this->new_config; + $cfg_array = (isset($_REQUEST['config'])) ? $request->variable('config', array('' => '')) : $this->new_config; $error = array(); // We validate the complete config if whished @@ -184,13 +195,13 @@ class acp_attachments if (in_array($config_name, array('attachment_quota', 'max_filesize', 'max_filesize_pm'))) { - $size_var = request_var($config_name, ''); + $size_var = $request->variable($config_name, ''); $this->new_config[$config_name] = $config_value = ($size_var == 'kb') ? round($config_value * 1024) : (($size_var == 'mb') ? round($config_value * 1048576) : $config_value); } if ($submit) { - set_config($config_name, $config_value); + $config->set($config_name, $config_value); } } @@ -198,7 +209,7 @@ class acp_attachments if ($submit) { - add_log('admin', 'LOG_CONFIG_ATTACH'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CONFIG_ATTACH'); // Check Settings $this->test_upload($error, $this->new_config['upload_path'], false); @@ -334,8 +345,8 @@ class acp_attachments if ($submit) { // Change Extensions ? - $extension_change_list = request_var('extension_change_list', array(0)); - $group_select_list = request_var('group_select', array(0)); + $extension_change_list = $request->variable('extension_change_list', array(0)); + $group_select_list = $request->variable('group_select', array(0)); // Generate correct Change List $extensions = array(); @@ -359,13 +370,13 @@ class acp_attachments WHERE extension_id = ' . $row['extension_id']; $db->sql_query($sql); - add_log('admin', 'LOG_ATTACH_EXT_UPDATE', $row['extension']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ATTACH_EXT_UPDATE', false, array($row['extension'])); } } $db->sql_freeresult($result); // Delete Extension? - $extension_id_list = request_var('extension_id_list', array(0)); + $extension_id_list = $request->variable('extension_id_list', array(0)); if (sizeof($extension_id_list)) { @@ -386,13 +397,13 @@ class acp_attachments WHERE ' . $db->sql_in_set('extension_id', $extension_id_list); $db->sql_query($sql); - add_log('admin', 'LOG_ATTACH_EXT_DEL', $extension_list); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ATTACH_EXT_DEL', false, array($extension_list)); } } // Add Extension? - $add_extension = strtolower(request_var('add_extension', '')); - $add_extension_group = request_var('add_group_select', 0); + $add_extension = strtolower($request->variable('add_extension', '')); + $add_extension_group = $request->variable('add_group_select', 0); $add = (isset($_POST['add_extension_check'])) ? true : false; if ($add_extension && $add) @@ -418,7 +429,8 @@ class acp_attachments ); $db->sql_query('INSERT INTO ' . EXTENSIONS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); - add_log('admin', 'LOG_ATTACH_EXT_ADD', $add_extension); + + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ATTACH_EXT_ADD', false, array($add_extension)); } } } @@ -475,8 +487,8 @@ class acp_attachments if ($submit) { - $action = request_var('action', ''); - $group_id = request_var('g', 0); + $action = $request->variable('action', ''); + $group_id = $request->variable('g', 0); if ($action != 'add' && $action != 'edit') { @@ -507,7 +519,7 @@ class acp_attachments $ext_row = array(); } - $group_name = utf8_normalize_nfc(request_var('group_name', '', true)); + $group_name = $request->variable('group_name', '', true); $new_group_name = ($action == 'add') ? $group_name : (($ext_row['group_name'] != $group_name) ? $group_name : ''); if (!$group_name) @@ -537,12 +549,12 @@ class acp_attachments if (!sizeof($error)) { // Ok, build the update/insert array - $upload_icon = request_var('upload_icon', 'no_image'); - $size_select = request_var('size_select', 'b'); - $forum_select = request_var('forum_select', false); - $allowed_forums = request_var('allowed_forums', array(0)); + $upload_icon = $request->variable('upload_icon', 'no_image'); + $size_select = $request->variable('size_select', 'b'); + $forum_select = $request->variable('forum_select', false); + $allowed_forums = $request->variable('allowed_forums', array(0)); $allow_in_pm = (isset($_POST['allow_in_pm'])) ? true : false; - $max_filesize = request_var('max_filesize', 0); + $max_filesize = $request->variable('max_filesize', 0); $max_filesize = ($size_select == 'kb') ? round($max_filesize * 1024) : (($size_select == 'mb') ? round($max_filesize * 1048576) : $max_filesize); $allow_group = (isset($_POST['allow_group'])) ? true : false; @@ -558,7 +570,7 @@ class acp_attachments $group_ary = array( 'group_name' => $group_name, - 'cat_id' => request_var('special_category', ATTACHMENT_CATEGORY_NONE), + 'cat_id' => $request->variable('special_category', ATTACHMENT_CATEGORY_NONE), 'allow_group' => ($allow_group) ? 1 : 0, 'upload_icon' => ($upload_icon == 'no_image') ? '' : $upload_icon, 'max_filesize' => $max_filesize, @@ -583,10 +595,10 @@ class acp_attachments } $group_name = (isset($user->lang['EXT_GROUP_' . $group_name])) ? $user->lang['EXT_GROUP_' . $group_name] : $group_name; - add_log('admin', 'LOG_ATTACH_EXTGROUP_' . strtoupper($action), $group_name); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ATTACH_EXTGROUP_' . strtoupper($action), false, array($group_name)); } - $extension_list = request_var('extensions', array(0)); + $extension_list = $request->variable('extensions', array(0)); if ($action == 'edit' && sizeof($extension_list)) { @@ -615,13 +627,10 @@ class acp_attachments $cat_lang = array( ATTACHMENT_CATEGORY_NONE => $user->lang['NO_FILE_CAT'], ATTACHMENT_CATEGORY_IMAGE => $user->lang['CAT_IMAGES'], - ATTACHMENT_CATEGORY_WM => $user->lang['CAT_WM_FILES'], - ATTACHMENT_CATEGORY_RM => $user->lang['CAT_RM_FILES'], ATTACHMENT_CATEGORY_FLASH => $user->lang['CAT_FLASH_FILES'], - ATTACHMENT_CATEGORY_QUICKTIME => $user->lang['CAT_QUICKTIME_FILES'], ); - $group_id = request_var('g', 0); + $group_id = $request->variable('g', 0); $action = (isset($_POST['add'])) ? 'add' : $action; switch ($action) @@ -648,7 +657,7 @@ class acp_attachments WHERE group_id = $group_id"; $db->sql_query($sql); - add_log('admin', 'LOG_ATTACH_EXTGROUP_DEL', $group_name); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ATTACH_EXTGROUP_DEL', false, array($group_name)); $cache->destroy('_extensions'); @@ -689,7 +698,7 @@ class acp_attachments if ($action == 'add') { $ext_group_row = array( - 'group_name' => utf8_normalize_nfc(request_var('group_name', '', true)), + 'group_name' => $request->variable('group_name', '', true), 'cat_id' => 0, 'allow_group' => 1, 'allow_in_pm' => 1, @@ -700,8 +709,6 @@ class acp_attachments $forum_ids = array(); } - $extensions = array(); - $sql = 'SELECT * FROM ' . EXTENSIONS_TABLE . " WHERE group_id = $group_id @@ -905,9 +912,9 @@ class acp_attachments if ($submit) { - $delete_files = (isset($_POST['delete'])) ? array_keys(request_var('delete', array('' => 0))) : array(); - $add_files = (isset($_POST['add'])) ? array_keys(request_var('add', array('' => 0))) : array(); - $post_ids = request_var('post_id', array('' => 0)); + $delete_files = (isset($_POST['delete'])) ? array_keys($request->variable('delete', array('' => 0))) : array(); + $add_files = (isset($_POST['add'])) ? array_keys($request->variable('add', array('' => 0))) : array(); + $post_ids = $request->variable('post_id', array('' => 0)); if (sizeof($delete_files)) { @@ -920,11 +927,11 @@ class acp_attachments $delete_files = array(); while ($row = $db->sql_fetchrow($result)) { - phpbb_unlink($row['physical_filename'], 'file'); + $this->attachment_manager->unlink($row['physical_filename'], 'file'); if ($row['thumbnail']) { - phpbb_unlink($row['physical_filename'], 'thumbnail'); + $this->attachment_manager->unlink($row['physical_filename'], 'thumbnail'); } $delete_files[$row['attach_id']] = $row['real_filename']; @@ -938,7 +945,7 @@ class acp_attachments WHERE ' . $db->sql_in_set('attach_id', array_keys($delete_files)); $db->sql_query($sql); - add_log('admin', 'LOG_ATTACH_ORPHAN_DEL', implode(', ', $delete_files)); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ATTACH_ORPHAN_DEL', false, array(implode(', ', $delete_files))); $notify[] = sprintf($user->lang['LOG_ATTACH_ORPHAN_DEL'], implode($user->lang['COMMA_SEPARATOR'], $delete_files)); } @@ -1029,14 +1036,14 @@ class acp_attachments $space_taken += $row['filesize']; $files_added++; - add_log('admin', 'LOG_ATTACH_FILEUPLOAD', $post_row['post_id'], $row['real_filename']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ATTACH_FILEUPLOAD', false, array($post_row['post_id'], $row['real_filename'])); } $db->sql_freeresult($result); if ($files_added) { - set_config_count('upload_dir_size', $space_taken, true); - set_config_count('num_files', $files_added, true); + $config->increment('upload_dir_size', $space_taken, false); + $config->increment('num_files', $files_added, false); } } } @@ -1073,7 +1080,7 @@ class acp_attachments if ($submit) { - $delete_files = (isset($_POST['delete'])) ? array_keys(request_var('delete', array('' => 0))) : array(); + $delete_files = (isset($_POST['delete'])) ? array_keys($request->variable('delete', array('' => 0))) : array(); if (sizeof($delete_files)) { @@ -1089,13 +1096,14 @@ class acp_attachments } $db->sql_freeresult($result); - if ($num_deleted = delete_attachments('attach', $delete_files)) + if ($num_deleted = $this->attachment_manager->delete('attach', $delete_files)) { if (sizeof($delete_files) != $num_deleted) { $error[] = $user->lang['FILES_GONE']; } - add_log('admin', 'LOG_ATTACHMENTS_DELETED', implode(', ', $deleted_filenames)); + + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ATTACHMENTS_DELETED', false, array(implode(', ', $deleted_filenames))); $notify[] = sprintf($user->lang['LOG_ATTACHMENTS_DELETED'], implode($user->lang['COMMA_SEPARATOR'], $deleted_filenames)); } else @@ -1115,23 +1123,18 @@ class acp_attachments if ($stats_error) { $error[] = $stats_error; - - // Show option to resync stats - $this->template->assign_vars(array( - 'S_ACTION_OPTIONS' => $auth->acl_get('a_board'), - )); } $template->assign_vars(array( 'S_MANAGE' => true, )); - $start = request_var('start', 0); + $start = $request->variable('start', 0); // Sort keys - $sort_days = request_var('st', 0); - $sort_key = request_var('sk', 't'); - $sort_dir = request_var('sd', 'd'); + $sort_days = $request->variable('st', 0); + $sort_key = $request->variable('sk', 't'); + $sort_dir = $request->variable('sd', 'd'); // Sorting $limit_days = array(0 => $user->lang['ALL_ENTRIES'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']); @@ -1152,6 +1155,7 @@ class acp_attachments $total_size = $stats['upload_dir_size']; // Make sure $start is set to the last page if it exceeds the amount + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); $start = $pagination->validate_start($start, $attachments_per_page, $num_files); @@ -1228,7 +1232,7 @@ class acp_attachments 'ATTACHMENT_POSTER' => get_username_string('full', (int) $row['poster_id'], (string) $row['username'], (string) $row['user_colour'], (string) $row['username']), 'FILESIZE' => get_formatted_filesize((int) $row['filesize']), 'FILETIME' => $user->format_date((int) $row['filetime']), - 'REAL_FILENAME' => (!$row['in_message']) ? utf8_wordwrap(utf8_basename((string) $row['real_filename']), 40, '<br />', true) : '', + 'REAL_FILENAME' => (!$row['in_message']) ? utf8_basename((string) $row['real_filename']) : '', 'PHYSICAL_FILENAME' => utf8_basename((string) $row['physical_filename']), 'EXT_GROUP_NAME' => (!empty($extensions[$row['extension']]['group_name'])) ? $user->lang['EXT_GROUP_' . $extensions[$row['extension']]['group_name']] : '', 'COMMENT' => $comment, @@ -1292,7 +1296,7 @@ class acp_attachments /** * Set config attachment stat values * - * @param $stats array Array of config key => value pairs to set. + * @param $stats array Array of config key => value pairs to set. * @return null */ public function set_attachment_stats($stats) @@ -1306,7 +1310,6 @@ class acp_attachments /** * Check accuracy of attachment statistics. * - * @param $resync bool Resync stats if they're incorrect. * @return bool|string Returns false if stats are correct or error message * otherwise. */ @@ -1317,11 +1320,19 @@ class acp_attachments // Get current files stats $num_files = (int) $this->config['num_files']; - $total_size = (float) $this->config['upload_dir_size']; + $total_size = (float) $this->config['upload_dir_size']; if (($num_files != $stats['num_files']) || ($total_size != $stats['upload_dir_size'])) { - return $this->user->lang('FILES_STATS_WRONG', (int) $stats['num_files'], get_formatted_filesize($stats['upload_dir_size'])); + $u_resync = $this->u_action . '&action=stats'; + + return $this->user->lang( + 'FILES_STATS_WRONG', + (int) $stats['num_files'], + get_formatted_filesize($stats['upload_dir_size']), + '<a href="' . $u_resync . '">', + '</a>' + ); } return false; } @@ -1344,6 +1355,8 @@ class acp_attachments else { $this->set_attachment_stats($this->get_attachment_stats()); + + /* @var $log \phpbb\log\log_interface */ $log = $this->phpbb_container->get('log'); $log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_RESYNC_FILES_STATS'); } @@ -1360,10 +1373,7 @@ class acp_attachments $types = array( ATTACHMENT_CATEGORY_NONE => $user->lang['NO_FILE_CAT'], ATTACHMENT_CATEGORY_IMAGE => $user->lang['CAT_IMAGES'], - ATTACHMENT_CATEGORY_WM => $user->lang['CAT_WM_FILES'], - ATTACHMENT_CATEGORY_RM => $user->lang['CAT_RM_FILES'], ATTACHMENT_CATEGORY_FLASH => $user->lang['CAT_FLASH_FILES'], - ATTACHMENT_CATEGORY_QUICKTIME => $user->lang['CAT_QUICKTIME_FILES'], ); if ($group_id) @@ -1494,7 +1504,15 @@ class acp_attachments if (!file_exists($phpbb_root_path . $upload_dir)) { @mkdir($phpbb_root_path . $upload_dir, 0777); - phpbb_chmod($phpbb_root_path . $upload_dir, CHMOD_READ | CHMOD_WRITE); + + try + { + $this->filesystem->phpbb_chmod($phpbb_root_path . $upload_dir, CHMOD_READ | CHMOD_WRITE); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } } } @@ -1510,7 +1528,7 @@ class acp_attachments return; } - if (!phpbb_is_writable($phpbb_root_path . $upload_dir)) + if (!$this->filesystem->is_writable($phpbb_root_path . $upload_dir)) { $error[] = sprintf($user->lang['NO_WRITE_UPLOAD'], $upload_dir); return; @@ -1522,13 +1540,12 @@ class acp_attachments */ function perform_site_list() { - global $db, $user; - global $request; + global $db, $user, $request, $phpbb_log; if (isset($_REQUEST['securesubmit'])) { // Grab the list of entries - $ips = request_var('ips', ''); + $ips = $request->variable('ips', ''); $ip_list = array_unique(explode("\n", $ips)); $ip_list_log = implode(', ', $ip_list); @@ -1553,7 +1570,6 @@ class acp_attachments if ($ip_2_counter == 0 && $ip_2_end == 254) { $ip_2_counter = 256; - $ip_2_fragment = 256; $iplist[] = "'$ip_1_counter.*'"; } @@ -1566,7 +1582,6 @@ class acp_attachments if ($ip_3_counter == 0 && $ip_3_end == 254) { $ip_3_counter = 256; - $ip_3_fragment = 256; $iplist[] = "'$ip_1_counter.$ip_2_counter.*'"; } @@ -1579,7 +1594,6 @@ class acp_attachments if ($ip_4_counter == 0 && $ip_4_end == 254) { $ip_4_counter = 256; - $ip_4_fragment = 256; $iplist[] = "'$ip_1_counter.$ip_2_counter.$ip_3_counter.*'"; } @@ -1674,14 +1688,14 @@ class acp_attachments { // Update log $log_entry = ($ip_exclude) ? 'LOG_DOWNLOAD_EXCLUDE_IP' : 'LOG_DOWNLOAD_IP'; - add_log('admin', $log_entry, $ip_list_log); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, $log_entry, false, array($ip_list_log)); } trigger_error($user->lang['SECURE_DOWNLOAD_UPDATE_SUCCESS'] . adm_back_link($this->u_action)); } else if (isset($_POST['unsecuresubmit'])) { - $unip_sql = request_var('unip', array(0)); + $unip_sql = $request->variable('unip', array(0)); if (sizeof($unip_sql)) { @@ -1703,7 +1717,7 @@ class acp_attachments WHERE ' . $db->sql_in_set('site_id', $unip_sql); $db->sql_query($sql); - add_log('admin', 'LOG_DOWNLOAD_REMOVE_IP', $l_unip_list); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_DOWNLOAD_REMOVE_IP', false, array($l_unip_list)); } trigger_error($user->lang['SECURE_DOWNLOAD_UPDATE_SUCCESS'] . adm_back_link($this->u_action)); diff --git a/phpBB/includes/acp/acp_ban.php b/phpBB/includes/acp/acp_ban.php index 3ed9c225f5..5aed78be08 100644 --- a/phpBB/includes/acp/acp_ban.php +++ b/phpBB/includes/acp/acp_ban.php @@ -1,9 +1,13 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -15,23 +19,22 @@ if (!defined('IN_PHPBB')) exit; } -/** -* @package acp -*/ class acp_ban { var $u_action; function main($id, $mode) { - global $config, $db, $user, $auth, $template, $cache; - global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix; + global $user, $template, $request, $phpbb_dispatcher; + global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + if (!function_exists('user_ban')) + { + include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + } - $bansubmit = (isset($_POST['bansubmit'])) ? true : false; - $unbansubmit = (isset($_POST['unbansubmit'])) ? true : false; - $current_time = time(); + $bansubmit = $request->is_set_post('bansubmit'); + $unbansubmit = $request->is_set_post('unbansubmit'); $user->add_lang(array('acp/ban', 'acp/users')); $this->tpl_name = 'acp_ban'; @@ -47,23 +50,79 @@ class acp_ban if ($bansubmit) { // Grab the list of entries - $ban = utf8_normalize_nfc(request_var('ban', '', true)); - $ban_len = request_var('banlength', 0); - $ban_len_other = request_var('banlengthother', ''); - $ban_exclude = request_var('banexclude', 0); - $ban_reason = utf8_normalize_nfc(request_var('banreason', '', true)); - $ban_give_reason = utf8_normalize_nfc(request_var('bangivereason', '', true)); + $ban = $request->variable('ban', '', true); + $ban_length = $request->variable('banlength', 0); + $ban_length_other = $request->variable('banlengthother', ''); + $ban_exclude = $request->variable('banexclude', 0); + $ban_reason = $request->variable('banreason', '', true); + $ban_give_reason = $request->variable('bangivereason', '', true); if ($ban) { - user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reason, $ban_give_reason); + $abort_ban = false; + /** + * Use this event to modify the ban details before the ban is performed + * + * @event core.acp_ban_before + * @var string mode One of the following: user, ip, email + * @var string ban Either string or array with usernames, ips or email addresses + * @var int ban_length Ban length in minutes + * @var string ban_length_other Ban length as a date (YYYY-MM-DD) + * @var bool ban_exclude Are we banning or excluding from another ban + * @var string ban_reason Ban reason displayed to moderators + * @var string ban_give_reason Ban reason displayed to the banned user + * @var mixed abort_ban Either false, or an error message that is displayed to the user. + * If a string is given the bans are not issued. + * @since 3.1.0-RC5 + */ + $vars = array( + 'mode', + 'ban', + 'ban_length', + 'ban_length_other', + 'ban_exclude', + 'ban_reason', + 'ban_give_reason', + 'abort_ban', + ); + extract($phpbb_dispatcher->trigger_event('core.acp_ban_before', compact($vars))); + + if ($abort_ban) + { + trigger_error($abort_ban . adm_back_link($this->u_action)); + } + user_ban($mode, $ban, $ban_length, $ban_length_other, $ban_exclude, $ban_reason, $ban_give_reason); + + /** + * Use this event to perform actions after the ban has been performed + * + * @event core.acp_ban_after + * @var string mode One of the following: user, ip, email + * @var string ban Either string or array with usernames, ips or email addresses + * @var int ban_length Ban length in minutes + * @var string ban_length_other Ban length as a date (YYYY-MM-DD) + * @var bool ban_exclude Are we banning or excluding from another ban + * @var string ban_reason Ban reason displayed to moderators + * @var string ban_give_reason Ban reason displayed to the banned user + * @since 3.1.0-RC5 + */ + $vars = array( + 'mode', + 'ban', + 'ban_length', + 'ban_length_other', + 'ban_exclude', + 'ban_reason', + 'ban_give_reason', + ); + extract($phpbb_dispatcher->trigger_event('core.acp_ban_after', compact($vars))); trigger_error($user->lang['BAN_UPDATE_SUCCESSFUL'] . adm_back_link($this->u_action)); } } else if ($unbansubmit) { - $ban = request_var('unban', array('')); + $ban = $request->variable('unban', array('')); if ($ban) { @@ -109,7 +168,7 @@ class acp_ban 'L_NO_BAN_CELL' => $l_no_ban_cell, 'S_USERNAME_BAN' => ($mode == 'user') ? true : false, - + 'U_ACTION' => $this->u_action, 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=acp_ban&field=ban'), )); @@ -136,7 +195,6 @@ class acp_ban case 'user': $field = 'username'; - $l_ban_cell = $user->lang['USERNAME']; $sql = 'SELECT b.*, u.user_id, u.username, u.username_clean FROM ' . BANLIST_TABLE . ' b, ' . USERS_TABLE . ' u @@ -149,7 +207,6 @@ class acp_ban case 'ip': $field = 'ban_ip'; - $l_ban_cell = $user->lang['IP_HOSTNAME']; $sql = 'SELECT * FROM ' . BANLIST_TABLE . ' @@ -162,7 +219,6 @@ class acp_ban case 'email': $field = 'ban_email'; - $l_ban_cell = $user->lang['EMAIL_ADDRESS']; $sql = 'SELECT * FROM ' . BANLIST_TABLE . ' @@ -175,8 +231,6 @@ class acp_ban $result = $db->sql_query($sql); $banned_options = $excluded_options = array(); - $ban_length = $ban_reasons = $ban_give_reasons = array(); - while ($row = $db->sql_fetchrow($result)) { $option = '<option value="' . $row['ban_id'] . '">' . $row[$field] . '</option>'; @@ -195,60 +249,31 @@ class acp_ban if ($time_length == 0) { // Banned permanently - $ban_length[$row['ban_id']] = $user->lang['PERMANENT']; + $ban_length = $user->lang['PERMANENT']; } else if (isset($ban_end_text[$time_length])) { // Banned for a given duration - $ban_length[$row['ban_id']] = sprintf($user->lang['BANNED_UNTIL_DURATION'], $ban_end_text[$time_length], $user->format_date($row['ban_end'], false, true)); + $ban_length = $user->lang('BANNED_UNTIL_DURATION', $ban_end_text[$time_length], $user->format_date($row['ban_end'], false, true)); } else { // Banned until given date - $ban_length[$row['ban_id']] = sprintf($user->lang['BANNED_UNTIL_DATE'], $user->format_date($row['ban_end'], false, true)); + $ban_length = $user->lang('BANNED_UNTIL_DATE', $user->format_date($row['ban_end'], false, true)); } - $ban_reasons[$row['ban_id']] = $row['ban_reason']; - $ban_give_reasons[$row['ban_id']] = $row['ban_give_reason']; + $template->assign_block_vars('bans', array( + 'BAN_ID' => (int) $row['ban_id'], + 'LENGTH' => $ban_length, + 'A_LENGTH' => addslashes($ban_length), + 'REASON' => $row['ban_reason'], + 'A_REASON' => addslashes($row['ban_reason']), + 'GIVE_REASON' => $row['ban_give_reason'], + 'A_GIVE_REASON' => addslashes($row['ban_give_reason']), + )); } $db->sql_freeresult($result); - if (sizeof($ban_length)) - { - foreach ($ban_length as $ban_id => $length) - { - $template->assign_block_vars('ban_length', array( - 'BAN_ID' => (int) $ban_id, - 'LENGTH' => $length, - 'A_LENGTH' => addslashes($length), - )); - } - } - - if (sizeof($ban_reasons)) - { - foreach ($ban_reasons as $ban_id => $reason) - { - $template->assign_block_vars('ban_reason', array( - 'BAN_ID' => $ban_id, - 'REASON' => $reason, - 'A_REASON' => addslashes($reason), - )); - } - } - - if (sizeof($ban_give_reasons)) - { - foreach ($ban_give_reasons as $ban_id => $reason) - { - $template->assign_block_vars('ban_give_reason', array( - 'BAN_ID' => $ban_id, - 'REASON' => $reason, - 'A_REASON' => addslashes($reason), - )); - } - } - $options = ''; if ($excluded_options) { diff --git a/phpBB/includes/acp/acp_bbcodes.php b/phpBB/includes/acp/acp_bbcodes.php index 84382b6276..dab18289c7 100644 --- a/phpBB/includes/acp/acp_bbcodes.php +++ b/phpBB/includes/acp/acp_bbcodes.php @@ -1,9 +1,13 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -15,23 +19,21 @@ if (!defined('IN_PHPBB')) exit; } -/** -* @package acp -*/ class acp_bbcodes { var $u_action; function main($id, $mode) { - global $db, $user, $auth, $template, $cache, $request, $phpbb_dispatcher; - global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + global $db, $user, $template, $cache, $request, $phpbb_dispatcher, $phpbb_container; + global $phpbb_log; $user->add_lang('acp/posting'); // Set up general vars - $action = request_var('action', ''); - $bbcode_id = request_var('bbcode', 0); + $action = $request->variable('action', ''); + $bbcode_id = $request->variable('bbcode', 0); + $submit = $request->is_set_post('submit'); $this->tpl_name = 'acp_bbcodes'; $this->page_title = 'ACP_BBCODES'; @@ -39,6 +41,11 @@ class acp_bbcodes add_form_key($form_key); + if ($submit && !check_form_key($form_key)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + // Set up mode-specific vars switch ($action) { @@ -82,11 +89,11 @@ class acp_bbcodes // No break here case 'create': - $display_on_posting = request_var('display_on_posting', 0); + $display_on_posting = $request->variable('display_on_posting', 0); - $bbcode_match = request_var('bbcode_match', ''); - $bbcode_tpl = htmlspecialchars_decode(utf8_normalize_nfc(request_var('bbcode_tpl', '', true))); - $bbcode_helpline = utf8_normalize_nfc(request_var('bbcode_helpline', '', true)); + $bbcode_match = $request->variable('bbcode_match', ''); + $bbcode_tpl = htmlspecialchars_decode($request->variable('bbcode_tpl', '', true)); + $bbcode_helpline = $request->variable('bbcode_helpline', '', true); break; } @@ -142,7 +149,7 @@ class acp_bbcodes case 'create': $sql_ary = $hidden_fields = array(); - + /** * Modify custom bbcode data before the modify/create action * @@ -159,7 +166,16 @@ class acp_bbcodes * submitting form when $warn_text is true * @since 3.1.0-a3 */ - $vars = array('action', 'sql_ary', 'bbcode_id', 'display_on_posting', 'bbcode_match', 'bbcode_tpl', 'bbcode_helpline', 'hidden_fields'); + $vars = array( + 'action', + 'sql_ary', + 'bbcode_id', + 'display_on_posting', + 'bbcode_match', + 'bbcode_tpl', + 'bbcode_helpline', + 'hidden_fields', + ); extract($phpbb_dispatcher->trigger_event('core.acp_bbcodes_modify_create', compact($vars))); $warn_text = preg_match('%<[^>]*\{text[\d]*\}[^>]*>%i', $bbcode_tpl); @@ -210,7 +226,6 @@ class acp_bbcodes trigger_error($user->lang['BBCODE_TAG_DEF_TOO_LONG'] . adm_back_link($this->u_action), E_USER_WARNING); } - if (strlen($bbcode_helpline) > 255) { trigger_error($user->lang['BBCODE_HELPLINE_TOO_LONG'] . adm_back_link($this->u_action), E_USER_WARNING); @@ -260,6 +275,7 @@ class acp_bbcodes $db->sql_query('INSERT INTO ' . BBCODES_TABLE . $db->sql_build_array('INSERT', $sql_ary)); $cache->destroy('sql', BBCODES_TABLE); + $phpbb_container->get('text_formatter.cache')->invalidate(); $lang = 'BBCODE_ADDED'; $log_action = 'LOG_BBCODE_ADD'; @@ -271,12 +287,13 @@ class acp_bbcodes WHERE bbcode_id = ' . $bbcode_id; $db->sql_query($sql); $cache->destroy('sql', BBCODES_TABLE); + $phpbb_container->get('text_formatter.cache')->invalidate(); $lang = 'BBCODE_EDITED'; $log_action = 'LOG_BBCODE_EDIT'; } - add_log('admin', $log_action, $data['bbcode_tag']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, $log_action, false, array($data['bbcode_tag'])); trigger_error($user->lang[$lang] . adm_back_link($this->u_action)); } @@ -310,8 +327,9 @@ class acp_bbcodes { $db->sql_query('DELETE FROM ' . BBCODES_TABLE . " WHERE bbcode_id = $bbcode_id"); $cache->destroy('sql', BBCODES_TABLE); - add_log('admin', 'LOG_BBCODE_DELETE', $row['bbcode_tag']); - + $phpbb_container->get('text_formatter.cache')->invalidate(); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_BBCODE_DELETE', false, array($row['bbcode_tag'])); + if ($request->is_ajax()) { $json_response = new \phpbb\json_response; @@ -400,9 +418,9 @@ class acp_bbcodes { $bbcode_match = trim($bbcode_match); $bbcode_tpl = trim($bbcode_tpl); - $utf8 = strpos($bbcode_match, 'INTTEXT') !== false; - $utf8_pcre_properties = phpbb_pcre_utf8_support(); + // Allow unicode characters for URL|LOCAL_URL|RELATIVE_URL|INTTEXT tokens + $utf8 = preg_match('/(URL|LOCAL_URL|RELATIVE_URL|INTTEXT)/', $bbcode_match); $fp_match = preg_quote($bbcode_match, '!'); $fp_replace = preg_replace('#^\[(.*?)\]#', '[$1:$uid]', $bbcode_match); @@ -434,7 +452,7 @@ class acp_bbcodes '!([a-zA-Z0-9-+.,_ ]+)!' => "$1" ), 'INTTEXT' => array( - ($utf8_pcre_properties) ? '!([\p{L}\p{N}\-+,_. ]+)!u' : '!([a-zA-Z0-9\-+,_. ]+)!u' => "$1" + '!([\p{L}\p{N}\-+,_. ]+)!u' => "$1" ), 'IDENTIFIER' => array( '!([a-zA-Z0-9-_]+)!' => "$1" @@ -454,7 +472,7 @@ class acp_bbcodes 'EMAIL' => '(' . get_preg_expression('email') . ')', 'TEXT' => '(.*?)', 'SIMPLETEXT' => '([a-zA-Z0-9-+.,_ ]+)', - 'INTTEXT' => ($utf8_pcre_properties) ? '([\p{L}\p{N}\-+,_. ]+)' : '([a-zA-Z0-9\-+,_. ]+)', + 'INTTEXT' => '([\p{L}\p{N}\-+,_. ]+)', 'IDENTIFIER' => '([a-zA-Z0-9-_]+)', 'COLOR' => '([a-zA-Z]+|#[0-9abcdefABCDEF]+)', 'NUMBER' => '([0-9]+)', @@ -462,7 +480,7 @@ class acp_bbcodes $pad = 0; $modifiers = 'i'; - $modifiers .= ($utf8 && $utf8_pcre_properties) ? 'u' : ''; + $modifiers .= ($utf8) ? 'u' : ''; if (preg_match_all('/\{(' . implode('|', array_keys($tokens)) . ')[0-9]*\}/i', $bbcode_match, $m)) { @@ -477,7 +495,9 @@ class acp_bbcodes if (preg_match_all('/(?<!\\\\)\$([0-9]+)/', $replace, $repad)) { $repad = $pad + sizeof(array_unique($repad[0])); - $replace = preg_replace('/(?<!\\\\)\$([0-9]+)/e', "'\${' . (\$1 + \$pad) . '}'", $replace); + $replace = preg_replace_callback('/(?<!\\\\)\$([0-9]+)/', function ($match) use ($pad) { + return '${' . ($match[1] + $pad) . '}'; + }, $replace); $pad = $repad; } @@ -542,10 +562,18 @@ class acp_bbcodes trigger_error($user->lang['BBCODE_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); } - $fp_match = preg_replace('#\[/?' . $bbcode_search . '#ie', "strtolower('\$0')", $fp_match); - $fp_replace = preg_replace('#\[/?' . $bbcode_search . '#ie', "strtolower('\$0')", $fp_replace); - $sp_match = preg_replace('#\[/?' . $bbcode_search . '#ie', "strtolower('\$0')", $sp_match); - $sp_replace = preg_replace('#\[/?' . $bbcode_search . '#ie', "strtolower('\$0')", $sp_replace); + $fp_match = preg_replace_callback('#\[/?' . $bbcode_search . '#i', function ($match) { + return strtolower($match[0]); + }, $fp_match); + $fp_replace = preg_replace_callback('#\[/?' . $bbcode_search . '#i', function ($match) { + return strtolower($match[0]); + }, $fp_replace); + $sp_match = preg_replace_callback('#\[/?' . $bbcode_search . '#i', function ($match) { + return strtolower($match[0]); + }, $sp_match); + $sp_replace = preg_replace_callback('#\[/?' . $bbcode_search . '#i', function ($match) { + return strtolower($match[0]); + }, $sp_replace); return array( 'bbcode_tag' => $bbcode_tag, diff --git a/phpBB/includes/acp/acp_board.php b/phpBB/includes/acp/acp_board.php index 10fbde8c9b..26663d2a62 100644 --- a/phpBB/includes/acp/acp_board.php +++ b/phpBB/includes/acp/acp_board.php @@ -1,10 +1,17 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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 add cron intervals to server settings? (database_gc, queue_interval, session_gc, search_gc, cache_gc, warnings_gc) */ @@ -16,9 +23,6 @@ if (!defined('IN_PHPBB')) exit; } -/** -* @package acp -*/ class acp_board { var $u_action; @@ -26,13 +30,12 @@ class acp_board function main($id, $mode) { - global $db, $user, $auth, $template; - global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; - global $cache, $phpbb_container; + global $user, $template, $request; + global $config, $phpbb_root_path, $phpEx; + global $cache, $phpbb_container, $phpbb_dispatcher, $phpbb_log; $user->add_lang('acp/board'); - $action = request_var('action', ''); $submit = (isset($_POST['submit']) || isset($_POST['allow_quick_reply_enable'])) ? true : false; $form_key = 'acp_board'; @@ -61,13 +64,16 @@ class acp_board 'default_lang' => array('lang' => 'DEFAULT_LANGUAGE', 'validate' => 'lang', 'type' => 'select', 'function' => 'language_select', 'params' => array('{CONFIG_VALUE}'), 'explain' => false), 'default_dateformat' => array('lang' => 'DEFAULT_DATE_FORMAT', 'validate' => 'string', 'type' => 'custom', 'method' => 'dateformat_select', 'explain' => true), 'board_timezone' => array('lang' => 'SYSTEM_TIMEZONE', 'validate' => 'timezone', 'type' => 'custom', 'method' => 'timezone_select', 'explain' => true), - 'default_style' => array('lang' => 'DEFAULT_STYLE', 'validate' => 'int', 'type' => 'select', 'function' => 'style_select', 'params' => array('{CONFIG_VALUE}', false), 'explain' => false), + + 'legend2' => 'BOARD_STYLE', + 'default_style' => array('lang' => 'DEFAULT_STYLE', 'validate' => 'int', 'type' => 'select', 'function' => 'style_select', 'params' => array('{CONFIG_VALUE}', false), 'explain' => true), + 'guest_style' => array('lang' => 'GUEST_STYLE', 'validate' => 'int', 'type' => 'select', 'function' => 'style_select', 'params' => array($this->guest_style_get(), false), 'explain' => true), 'override_user_style' => array('lang' => 'OVERRIDE_STYLE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), - 'legend2' => 'WARNINGS', + 'legend3' => 'WARNINGS', 'warnings_expire_days' => array('lang' => 'WARNINGS_EXPIRE', 'validate' => 'int:0:9999', 'type' => 'number:0:9999', 'explain' => true, 'append' => ' ' . $user->lang['DAYS']), - 'legend3' => 'ACP_SUBMIT_CHANGES', + 'legend4' => 'ACP_SUBMIT_CHANGES', ) ); break; @@ -87,6 +93,7 @@ class acp_board 'allow_bbcode' => array('lang' => 'ALLOW_BBCODE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), 'allow_smilies' => array('lang' => 'ALLOW_SMILIES', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), 'allow_sig' => array('lang' => 'ALLOW_SIG', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_board_notifications' => array('lang' => 'ALLOW_BOARD_NOTIFICATIONS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), 'allow_nocensors' => array('lang' => 'ALLOW_NO_CENSORS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'allow_bookmarks' => array('lang' => 'ALLOW_BOOKMARKS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'allow_birthdays' => array('lang' => 'ALLOW_BIRTHDAYS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), @@ -108,6 +115,7 @@ class acp_board break; case 'avatar': + /* @var $phpbb_avatar_manager \phpbb\avatar\manager */ $phpbb_avatar_manager = $phpbb_container->get('avatar.manager'); $avatar_drivers = $phpbb_avatar_manager->get_all_drivers(); @@ -345,6 +353,7 @@ class acp_board 'load_user_activity' => array('lang' => 'LOAD_USER_ACTIVITY', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'load_tplcompile' => array('lang' => 'RECOMPILE_STYLES', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'allow_cdn' => array('lang' => 'ALLOW_CDN', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'allow_live_searches' => array('lang' => 'ALLOW_LIVE_SEARCHES', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'legend3' => 'CUSTOM_PROFILE_FIELDS', 'load_cpf_memberlist' => array('lang' => 'LOAD_CPF_MEMBERLIST', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), @@ -362,7 +371,7 @@ class acp_board 'title' => 'ACP_AUTH_SETTINGS', 'vars' => array( 'legend1' => 'ACP_AUTH_SETTINGS', - 'auth_method' => array('lang' => 'AUTH_METHOD', 'validate' => 'string', 'type' => 'select', 'method' => 'select_auth_method', 'explain' => false), + 'auth_method' => array('lang' => 'AUTH_METHOD', 'validate' => 'string', 'type' => 'select:1:toggable', 'method' => 'select_auth_method', 'explain' => false), ) ); break; @@ -405,7 +414,7 @@ class acp_board 'ip_check' => array('lang' => 'IP_VALID', 'validate' => 'int', 'type' => 'custom', 'method' => 'select_ip_check', 'explain' => true), 'browser_check' => array('lang' => 'BROWSER_VALID', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'forwarded_for_check' => array('lang' => 'FORWARDED_FOR_VALID', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), - 'referer_validation' => array('lang' => 'REFERER_VALID', 'validate' => 'int:0:3','type' => 'custom', 'method' => 'select_ref_check', 'explain' => true), + 'referer_validation' => array('lang' => 'REFERRER_VALID', 'validate' => 'int:0:3','type' => 'custom', 'method' => 'select_ref_check', 'explain' => true), 'check_dnsbl' => array('lang' => 'CHECK_DNSBL', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'email_check_mx' => array('lang' => 'EMAIL_CHECK_MX', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'max_pass_chars' => array('lang' => 'PASSWORD_LENGTH', 'validate' => 'int:8:255', 'type' => false, 'method' => false, 'explain' => false,), @@ -434,9 +443,11 @@ class acp_board 'email_function_name' => array('lang' => 'EMAIL_FUNCTION_NAME', 'validate' => 'string', 'type' => 'text:20:50', 'explain' => true), 'email_package_size' => array('lang' => 'EMAIL_PACKAGE_SIZE', 'validate' => 'int:0', 'type' => 'number:0:99999', 'explain' => true), 'board_contact' => array('lang' => 'CONTACT_EMAIL', 'validate' => 'email', 'type' => 'email:25:100', 'explain' => true), + 'board_contact_name' => array('lang' => 'CONTACT_EMAIL_NAME', 'validate' => 'string', 'type' => 'text:25:50', 'explain' => true), 'board_email' => array('lang' => 'ADMIN_EMAIL', 'validate' => 'email', 'type' => 'email:25:100', 'explain' => true), 'board_email_sig' => array('lang' => 'EMAIL_SIG', 'validate' => 'string', 'type' => 'textarea:5:30', 'explain' => true), 'board_hide_emails' => array('lang' => 'BOARD_HIDE_EMAILS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'send_test_email' => array('lang' => 'SEND_TEST_EMAIL', 'validate' => 'bool', 'type' => 'custom', 'method' => 'send_test_email', 'explain' => true), 'legend2' => 'SMTP_SETTINGS', 'smtp_delivery' => array('lang' => 'USE_SMTP', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), @@ -456,13 +467,25 @@ class acp_board break; } + /** + * Event to add and/or modify acp_board configurations + * + * @event core.acp_board_config_edit_add + * @var array display_vars Array of config values to display and process + * @var string mode Mode of the config page we are displaying + * @var boolean submit Do we display the form or process the submission + * @since 3.1.0-a4 + */ + $vars = array('display_vars', 'mode', 'submit'); + extract($phpbb_dispatcher->trigger_event('core.acp_board_config_edit_add', compact($vars))); + if (isset($display_vars['lang'])) { $user->add_lang($display_vars['lang']); } $this->new_config = $config; - $cfg_array = (isset($_REQUEST['config'])) ? utf8_normalize_nfc(request_var('config', array('' => ''), true)) : $this->new_config; + $cfg_array = (isset($_REQUEST['config'])) ? $request->variable('config', array('' => ''), true) : $this->new_config; $error = array(); // We validate the complete config if wished @@ -479,7 +502,7 @@ class acp_board } // We go through the display_vars to make sure no one is trying to set variables he/she is not allowed to... - foreach ($display_vars['vars'] as $config_name => $null) + foreach ($display_vars['vars'] as $config_name => $data) { if (!isset($cfg_array[$config_name]) || strpos($config_name, 'legend') !== false) { @@ -491,6 +514,15 @@ class acp_board continue; } + if ($config_name == 'guest_style') + { + if (isset($cfg_array[$config_name])) + { + $this->guest_style_set($cfg_array[$config_name]); + } + continue; + } + $this->new_config[$config_name] = $config_value = $cfg_array[$config_name]; if ($config_name == 'email_function_name') @@ -502,7 +534,14 @@ class acp_board if ($submit) { - set_config($config_name, $config_value); + if (strpos($data['type'], 'password') === 0 && $config_value === '********') + { + // Do not update password fields if the content is ********, + // because that is the password replacement we use to not + // send the password to the output + continue; + } + $config->set($config_name, $config_value); if ($config_name == 'allow_quick_reply' && isset($_POST['allow_quick_reply_enable'])) { @@ -524,12 +563,14 @@ class acp_board if ($mode == 'auth') { // Retrieve a list of auth plugins and check their config values + /* @var $auth_providers \phpbb\auth\provider_collection */ $auth_providers = $phpbb_container->get('auth.provider_collection'); $updated_auth_settings = false; $old_auth_config = array(); foreach ($auth_providers as $provider) { + /** @var \phpbb\auth\provider\provider_interface $provider */ if ($fields = $provider->acp()) { // Check if we need to create config fields for this plugin and save config when submit was pressed @@ -537,7 +578,7 @@ class acp_board { if (!isset($config[$field])) { - set_config($field, ''); + $config->set($field, ''); } if (!isset($cfg_array[$field]) || strpos($field, 'legend') !== false) @@ -545,6 +586,14 @@ class acp_board continue; } + if (substr($field, -9) === '_password' && $cfg_array[$field] === '********') + { + // Do not update password fields if the content is ********, + // because that is the password replacement we use to not + // send the password to the output + continue; + } + $old_auth_config[$field] = $this->new_config[$field]; $config_value = $cfg_array[$field]; $this->new_config[$field] = $config_value; @@ -552,7 +601,7 @@ class acp_board if ($submit) { $updated_auth_settings = true; - set_config($field, $config_value); + $config->set($field, $config_value); } } } @@ -569,11 +618,11 @@ class acp_board { foreach ($old_auth_config as $config_name => $config_value) { - set_config($config_name, $config_value); + $config->set($config_name, $config_value); } trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING); } - set_config('auth_method', basename($cfg_array['auth_method'])); + $config->set('auth_method', basename($cfg_array['auth_method'])); } else { @@ -582,11 +631,40 @@ class acp_board } } + if ($mode == 'email' && $request->is_set_post('send_test_email')) + { + if ($config['email_enable']) + { + include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); + + $messenger = new messenger(false); + $messenger->template('test'); + $messenger->set_addresses($user->data); + $messenger->anti_abuse_headers($config, $user); + $messenger->send(NOTIFY_EMAIL); + + trigger_error($user->lang('TEST_EMAIL_SENT') . adm_back_link($this->u_action)); + } + else + { + $user->add_lang('memberlist'); + trigger_error($user->lang('EMAIL_DISABLED') . adm_back_link($this->u_action), E_USER_WARNING); + } + } + if ($submit) { - add_log('admin', 'LOG_CONFIG_' . strtoupper($mode)); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CONFIG_' . strtoupper($mode)); - trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action)); + $message = $user->lang('CONFIG_UPDATED'); + $message_type = E_USER_NOTICE; + if (!$config['email_enable'] && in_array($mode, array('email', 'registration')) && + in_array($config['require_activation'], array(USER_ACTIVATION_SELF, USER_ACTIVATION_ADMIN))) + { + $message .= '<br /><br />' . $user->lang('ACC_ACTIVATION_WARNING'); + $message_type = E_USER_WARNING; + } + trigger_error($message . adm_back_link($this->u_action), $message_type); } $this->tpl_name = 'acp_board'; @@ -681,10 +759,11 @@ class acp_board */ function select_auth_method($selected_method, $key = '') { - global $phpbb_root_path, $phpEx, $phpbb_container; + global $phpbb_container; - $auth_plugins = array(); + /* @var $auth_providers \phpbb\auth\provider_collection */ $auth_providers = $phpbb_container->get('auth.provider_collection'); + $auth_plugins = array(); foreach ($auth_providers as $key => $value) { @@ -701,7 +780,7 @@ class acp_board foreach ($auth_plugins as $method) { $selected = ($selected_method == $method) ? ' selected="selected"' : ''; - $auth_select .= '<option value="' . $method . '"' . $selected . '>' . ucfirst($method) . '</option>'; + $auth_select .= "<option value=\"$method\"$selected data-toggle-setting=\"#auth_{$method}_settings\">" . ucfirst($method) . '</option>'; } return $auth_select; @@ -763,20 +842,19 @@ class acp_board global $user, $config; $act_ary = array( - 'ACC_DISABLE' => USER_ACTIVATION_DISABLE, - 'ACC_NONE' => USER_ACTIVATION_NONE, + 'ACC_DISABLE' => array(true, USER_ACTIVATION_DISABLE), + 'ACC_NONE' => array(true, USER_ACTIVATION_NONE), + 'ACC_USER' => array($config['email_enable'], USER_ACTIVATION_SELF), + 'ACC_ADMIN' => array($config['email_enable'], USER_ACTIVATION_ADMIN), ); - if ($config['email_enable']) - { - $act_ary['ACC_USER'] = USER_ACTIVATION_SELF; - $act_ary['ACC_ADMIN'] = USER_ACTIVATION_ADMIN; - } - $act_options = ''; - foreach ($act_ary as $key => $value) + $act_options = ''; + foreach ($act_ary as $key => $data) { + list($available, $value) = $data; $selected = ($selected_value == $value) ? ' selected="selected"' : ''; - $act_options .= '<option value="' . $value . '"' . $selected . '>' . $user->lang[$key] . '</option>'; + $class = (!$available) ? ' class="disabled-option"' : ''; + $act_options .= '<option value="' . $value . '"' . $selected . $class . '>' . $user->lang($key) . '</option>'; } return $act_options; @@ -861,8 +939,6 @@ class acp_board */ function board_disable($value, $key) { - global $user; - $radio_ary = array(1 => 'YES', 0 => 'NO'); return h_radio('config[board_disable]', $radio_ary, $value) . '<br /><input id="' . $key . '" type="text" name="config[board_disable_msg]" maxlength="255" size="40" value="' . $this->new_config['board_disable_msg'] . '" />'; @@ -886,12 +962,44 @@ class acp_board */ function timezone_select($value, $key) { - global $user; + global $template, $user; + + $timezone_select = phpbb_timezone_select($template, $user, $value, true); + + return '<select name="config[' . $key . ']" id="' . $key . '">' . $timezone_select . '</select>'; + } + + /** + * Get guest style + */ + public function guest_style_get() + { + global $db; + + $sql = 'SELECT user_style + FROM ' . USERS_TABLE . ' + WHERE user_id = ' . ANONYMOUS; + $result = $db->sql_query($sql); + + $style = (int) $db->sql_fetchfield('user_style'); + $db->sql_freeresult($result); - $timezone_select = phpbb_timezone_select($user, $value, true); - $timezone_select['tz_select']; + return $style; + } - return '<select name="config[' . $key . ']" id="' . $key . '">' . $timezone_select['tz_select'] . '</select>'; + /** + * Set guest style + * + * @param int $style_id The style ID + */ + public function guest_style_set($style_id) + { + global $db; + + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_style = ' . (int) $style_id . ' + WHERE user_id = ' . ANONYMOUS; + $db->sql_query($sql); } /** @@ -907,7 +1015,7 @@ class acp_board { $user->timezone = new DateTimeZone($config['board_timezone']); } - catch (Exception $e) + catch (\Exception $e) { // If the board timezone is invalid, we just use the users timezone. } @@ -940,8 +1048,6 @@ class acp_board */ function select_news_forums($value, $key) { - global $user, $config; - $forum_list = make_forum_select(false, false, true, true, true, false, true); // Build forum options @@ -959,8 +1065,6 @@ class acp_board function select_exclude_forums($value, $key) { - global $user, $config; - $forum_list = make_forum_select(false, false, true, true, true, false, true); // Build forum options @@ -978,10 +1082,10 @@ class acp_board function store_feed_forums($option, $key) { - global $db, $cache; + global $db, $cache, $request; // Get key - $values = request_var($key, array(0 => 0)); + $values = $request->variable($key, array(0 => 0)); // Empty option bit for all forums $sql = 'UPDATE ' . FORUMS_TABLE . ' @@ -1016,7 +1120,7 @@ class acp_board */ function enable_mod_rewrite($value, $key) { - global $user, $config; + global $user; // Determine whether mod_rewrite is enabled on the server // NOTE: This only works on Apache servers on which PHP is NOT @@ -1050,4 +1154,11 @@ class acp_board return h_radio($field_name, array(1 => 'YES', 0 => 'NO'), $value) . ($message !== false ? '<br /><span>' . $user->lang($message) . '</span>' : ''); } + + function send_test_email($value, $key) + { + global $user; + + return '<input class="button2" type="submit" id="' . $key . '" name="' . $key . '" value="' . $user->lang['SEND_TEST_EMAIL'] . '" />'; + } } diff --git a/phpBB/includes/acp/acp_bots.php b/phpBB/includes/acp/acp_bots.php index e28a8d6451..e89b16663c 100644 --- a/phpBB/includes/acp/acp_bots.php +++ b/phpBB/includes/acp/acp_bots.php @@ -1,9 +1,13 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -15,22 +19,19 @@ if (!defined('IN_PHPBB')) exit; } -/** -* @package acp -*/ class acp_bots { var $u_action; function main($id, $mode) { - global $config, $db, $user, $auth, $template, $cache, $request; - global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix; + global $config, $db, $user, $template, $cache, $request, $phpbb_log; + global $phpbb_root_path, $phpEx; - $action = request_var('action', ''); + $action = $request->variable('action', ''); $submit = (isset($_POST['submit'])) ? true : false; - $mark = request_var('mark', array(0)); - $bot_id = request_var('id', 0); + $mark = $request->variable('mark', array(0)); + $bot_id = $request->variable('id', 0); if (isset($_POST['add'])) { @@ -123,7 +124,7 @@ class acp_bots $cache->destroy('_bots'); - add_log('admin', 'LOG_BOT_DELETE', implode(', ', $bot_name_ary)); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_BOT_DELETE', false, array(implode(', ', $bot_name_ary))); trigger_error($user->lang['BOT_DELETED'] . adm_back_link($this->u_action)); } else @@ -140,15 +141,19 @@ class acp_bots case 'edit': case 'add': - include_once($phpbb_root_path . 'includes/functions_user.' . $phpEx); + + if (!function_exists('user_update_name')) + { + include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + } $bot_row = array( - 'bot_name' => utf8_normalize_nfc(request_var('bot_name', '', true)), - 'bot_agent' => request_var('bot_agent', ''), - 'bot_ip' => request_var('bot_ip', ''), - 'bot_active' => request_var('bot_active', true), - 'bot_lang' => request_var('bot_lang', $config['default_lang']), - 'bot_style' => request_var('bot_style' , $config['default_style']), + 'bot_name' => $request->variable('bot_name', '', true), + 'bot_agent' => $request->variable('bot_agent', ''), + 'bot_ip' => $request->variable('bot_ip', ''), + 'bot_active' => $request->variable('bot_active', true), + 'bot_lang' => $request->variable('bot_lang', $config['default_lang']), + 'bot_style' => $request->variable('bot_style' , $config['default_style']), ); if ($submit) @@ -157,7 +162,7 @@ class acp_bots { $error[] = $user->lang['ERR_BOT_NO_MATCHES']; } - + if ($bot_row['bot_ip'] && !preg_match('#^[\d\.,:]+$#', $bot_row['bot_ip'])) { if (!$ip_list = gethostbynamel($bot_row['bot_ip'])) @@ -176,7 +181,7 @@ class acp_bots { $error[] = $user->lang['ERR_BOT_AGENT_MATCHES_UA']; } - + $bot_name = false; if ($bot_id) { @@ -201,7 +206,7 @@ class acp_bots { $error[] = $user->lang['BOT_NAME_TAKEN']; } - + if (!sizeof($error)) { // New bot? Create a new user and group entry @@ -219,7 +224,6 @@ class acp_bots { trigger_error($user->lang['NO_BOT_GROUP'] . adm_back_link($this->u_action . "&id=$bot_id&action=$action"), E_USER_WARNING); } - $user_id = user_add(array( 'user_type' => (int) USER_IGNORE, @@ -233,7 +237,7 @@ class acp_bots 'user_style' => (int) $bot_row['bot_style'], 'user_allow_massemail' => 0, )); - + $sql = 'INSERT INTO ' . BOTS_TABLE . ' ' . $db->sql_build_array('INSERT', array( 'user_id' => (int) $user_id, 'bot_name' => (string) $bot_row['bot_name'], @@ -242,7 +246,7 @@ class acp_bots 'bot_ip' => (string) $bot_row['bot_ip']) ); $db->sql_query($sql); - + $log = 'ADDED'; } else if ($bot_id) @@ -289,12 +293,12 @@ class acp_bots $log = 'UPDATED'; } - + $cache->destroy('_bots'); - - add_log('admin', 'LOG_BOT_' . $log, $bot_row['bot_name']); + + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_BOT_' . $log, false, array($bot_row['bot_name'])); trigger_error($user->lang['BOT_' . $log] . adm_back_link($this->u_action)); - + } } else if ($bot_id) @@ -335,11 +339,11 @@ class acp_bots 'U_ACTION' => $this->u_action . "&id=$bot_id&action=$action", 'U_BACK' => $this->u_action, 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '', - + 'BOT_NAME' => $bot_row['bot_name'], 'BOT_IP' => $bot_row['bot_ip'], 'BOT_AGENT' => $bot_row['bot_agent'], - + 'S_EDIT_BOT' => true, 'S_ACTIVE_OPTIONS' => $s_active_options, 'S_STYLE_OPTIONS' => $style_select, @@ -352,7 +356,7 @@ class acp_bots break; } - + if ($request->is_ajax() && ($action == 'activate' || $action == 'deactivate')) { $json_response = new \phpbb\json_response; @@ -397,7 +401,7 @@ class acp_bots } $db->sql_freeresult($result); } - + /** * Validate bot name against username table */ @@ -417,7 +421,7 @@ class acp_bots $result = $db->sql_query($sql); $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); - + return ($row) ? false : true; } } diff --git a/phpBB/includes/acp/acp_captcha.php b/phpBB/includes/acp/acp_captcha.php index 1a083c20ac..b49c5ca0d3 100644 --- a/phpBB/includes/acp/acp_captcha.php +++ b/phpBB/includes/acp/acp_captcha.php @@ -1,9 +1,14 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. +* */ /** @@ -14,28 +19,24 @@ if (!defined('IN_PHPBB')) exit; } -/** -* @package acp -*/ class acp_captcha { var $u_action; function main($id, $mode) { - global $db, $user, $auth, $template; - global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + global $user, $template, $phpbb_log, $request; + global $config, $phpbb_container; $user->add_lang('acp/board'); - include($phpbb_root_path . 'includes/captcha/captcha_factory.' . $phpEx); - $factory = new phpbb_captcha_factory(); + /* @var $factory \phpbb\captcha\factory */ + $factory = $phpbb_container->get('captcha.factory'); $captchas = $factory->get_captcha_types(); - $selected = request_var('select_captcha', $config['captcha_plugin']); + $selected = $request->variable('select_captcha', $config['captcha_plugin']); $selected = (isset($captchas['available'][$selected]) || isset($captchas['unavailable'][$selected])) ? $selected : $config['captcha_plugin']; - $configure = request_var('configure', false); - + $configure = $request->variable('configure', false); // Oh, they are just here for the view if (isset($_GET['captcha_demo'])) @@ -46,17 +47,42 @@ class acp_captcha // Delegate if ($configure) { - $config_captcha = phpbb_captcha_factory::get_instance($selected); + $config_captcha = $factory->get_instance($selected); $config_captcha->acp_page($id, $this); } else { $config_vars = array( - 'enable_confirm' => array('tpl' => 'REG_ENABLE', 'default' => false), - 'enable_post_confirm' => array('tpl' => 'POST_ENABLE', 'default' => false), - 'confirm_refresh' => array('tpl' => 'CONFIRM_REFRESH', 'default' => false), - 'max_reg_attempts' => array('tpl' => 'REG_LIMIT', 'default' => 0), - 'max_login_attempts' => array('tpl' => 'MAX_LOGIN_ATTEMPTS', 'default' => 0), + 'enable_confirm' => array( + 'tpl' => 'REG_ENABLE', + 'default' => false, + 'validate' => 'bool', + 'lang' => 'VISUAL_CONFIRM_REG', + ), + 'enable_post_confirm' => array( + 'tpl' => 'POST_ENABLE', + 'default' => false, + 'validate' => 'bool', + 'lang' => 'VISUAL_CONFIRM_POST', + ), + 'confirm_refresh' => array( + 'tpl' => 'CONFIRM_REFRESH', + 'default' => false, + 'validate' => 'bool', + 'lang' => 'VISUAL_CONFIRM_REFRESH', + ), + 'max_reg_attempts' => array( + 'tpl' => 'REG_LIMIT', + 'default' => 0, + 'validate' => 'int:0:99999', + 'lang' => 'REG_LIMIT', + ), + 'max_login_attempts' => array( + 'tpl' => 'MAX_LOGIN_ATTEMPTS', + 'default' => 0, + 'validate' => 'int:0:99999', + 'lang' => 'MAX_LOGIN_ATTEMPTS', + ), ); $this->tpl_name = 'acp_captcha'; @@ -64,13 +90,32 @@ class acp_captcha $form_key = 'acp_captcha'; add_form_key($form_key); - $submit = request_var('main_submit', false); + $submit = $request->variable('main_submit', false); + $error = $cfg_array = array(); - if ($submit && check_form_key($form_key)) + if ($submit) { foreach ($config_vars as $config_var => $options) { - set_config($config_var, request_var($config_var, $options['default'])); + $cfg_array[$config_var] = $request->variable($config_var, $options['default']); + } + validate_config_vars($config_vars, $cfg_array, $error); + + if (!check_form_key($form_key)) + { + $error[] = $user->lang['FORM_INVALID']; + } + if ($error) + { + $submit = false; + } + } + + if ($submit) + { + foreach ($cfg_array as $key => $value) + { + $config->set($key, $value); } if ($selected !== $config['captcha_plugin']) @@ -78,14 +123,14 @@ class acp_captcha // sanity check if (isset($captchas['available'][$selected])) { - $old_captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']); + $old_captcha = $factory->get_instance($config['captcha_plugin']); $old_captcha->uninstall(); - set_config('captcha_plugin', $selected); - $new_captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']); + $config->set('captcha_plugin', $selected); + $new_captcha = $factory->get_instance($config['captcha_plugin']); $new_captcha->install(); - add_log('admin', 'LOG_CONFIG_VISUAL'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CONFIG_VISUAL'); } else { @@ -94,10 +139,6 @@ class acp_captcha } trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action)); } - else if ($submit) - { - trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); - } else { $captcha_select = ''; @@ -113,17 +154,18 @@ class acp_captcha $captcha_select .= '<option value="' . $value . '"' . $current . ' class="disabled-option">' . $user->lang($title) . '</option>'; } - $demo_captcha = phpbb_captcha_factory::get_instance($selected); + $demo_captcha = $factory->get_instance($selected); foreach ($config_vars as $config_var => $options) { - $template->assign_var($options['tpl'], (isset($_POST[$config_var])) ? request_var($config_var, $options['default']) : $config[$config_var]) ; + $template->assign_var($options['tpl'], (isset($_POST[$config_var])) ? $request->variable($config_var, $options['default']) : $config[$config_var]) ; } $template->assign_vars(array( 'CAPTCHA_PREVIEW_TPL' => $demo_captcha->get_demo_template($id), 'S_CAPTCHA_HAS_CONFIG' => $demo_captcha->has_config(), 'CAPTCHA_SELECT' => $captcha_select, + 'ERROR_MSG' => implode('<br />', $error), 'U_ACTION' => $this->u_action, )); @@ -136,9 +178,9 @@ class acp_captcha */ function deliver_demo($selected) { - global $db, $user, $config; + global $phpbb_container; - $captcha = phpbb_captcha_factory::get_instance($selected); + $captcha = $phpbb_container->get('captcha.factory')->get_instance($selected); $captcha->init(CONFIRM_REG); $captcha->execute_demo(); diff --git a/phpBB/includes/acp/acp_contact.php b/phpBB/includes/acp/acp_contact.php new file mode 100644 index 0000000000..1a4d5b95a3 --- /dev/null +++ b/phpBB/includes/acp/acp_contact.php @@ -0,0 +1,138 @@ +<?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; +} + +/** +* @package acp +*/ +class acp_contact +{ + public $u_action; + + public function main($id, $mode) + { + global $user, $request, $template; + global $config, $phpbb_root_path, $phpEx, $phpbb_container; + + $user->add_lang(array('acp/board', 'posting')); + + $this->tpl_name = 'acp_contact'; + $this->page_title = 'ACP_CONTACT_SETTINGS'; + $form_name = 'acp_contact'; + add_form_key($form_name); + $error = ''; + + if (!function_exists('display_custom_bbcodes')) + { + include($phpbb_root_path . 'includes/functions_display.' . $phpEx); + } + if (!class_exists('parse_message')) + { + include($phpbb_root_path . 'includes/message_parser.' . $phpEx); + } + + /* @var $config_text \phpbb\config\db_text */ + $config_text = $phpbb_container->get('config_text'); + + $contact_admin_data = $config_text->get_array(array( + 'contact_admin_info', + 'contact_admin_info_uid', + 'contact_admin_info_bitfield', + 'contact_admin_info_flags', + )); + + $contact_admin_info = $contact_admin_data['contact_admin_info']; + $contact_admin_info_uid = $contact_admin_data['contact_admin_info_uid']; + $contact_admin_info_bitfield= $contact_admin_data['contact_admin_info_bitfield']; + $contact_admin_info_flags = $contact_admin_data['contact_admin_info_flags']; + + if ($request->is_set_post('submit') || $request->is_set_post('preview')) + { + if (!check_form_key($form_name)) + { + $error = $user->lang('FORM_INVALID'); + } + + $contact_admin_info = $request->variable('contact_admin_info', '', true); + + generate_text_for_storage( + $contact_admin_info, + $contact_admin_info_uid, + $contact_admin_info_bitfield, + $contact_admin_info_flags, + !$request->variable('disable_bbcode', false), + !$request->variable('disable_magic_url', false), + !$request->variable('disable_smilies', false) + ); + + if (empty($error) && $request->is_set_post('submit')) + { + $config->set('contact_admin_form_enable', $request->variable('contact_admin_form_enable', false)); + + $config_text->set_array(array( + 'contact_admin_info' => $contact_admin_info, + 'contact_admin_info_uid' => $contact_admin_info_uid, + 'contact_admin_info_bitfield' => $contact_admin_info_bitfield, + 'contact_admin_info_flags' => $contact_admin_info_flags, + )); + + trigger_error($user->lang['CONTACT_US_INFO_UPDATED'] . adm_back_link($this->u_action)); + } + } + + $contact_admin_info_preview = ''; + if ($request->is_set_post('preview')) + { + $contact_admin_info_preview = generate_text_for_display($contact_admin_info, $contact_admin_info_uid, $contact_admin_info_bitfield, $contact_admin_info_flags); + } + + $contact_admin_edit = generate_text_for_edit($contact_admin_info, $contact_admin_info_uid, $contact_admin_info_flags); + + /** @var \phpbb\controller\helper $controller_helper */ + $controller_helper = $phpbb_container->get('controller.helper'); + + $template->assign_vars(array( + 'ERRORS' => $error, + 'CONTACT_ENABLED' => $config['contact_admin_form_enable'], + + 'CONTACT_US_INFO' => $contact_admin_edit['text'], + 'CONTACT_US_INFO_PREVIEW' => $contact_admin_info_preview, + + 'S_BBCODE_DISABLE_CHECKED' => !$contact_admin_edit['allow_bbcode'], + 'S_SMILIES_DISABLE_CHECKED' => !$contact_admin_edit['allow_smilies'], + 'S_MAGIC_URL_DISABLE_CHECKED' => !$contact_admin_edit['allow_urls'], + + 'BBCODE_STATUS' => $user->lang('BBCODE_IS_ON', '<a href="' . $controller_helper->route('phpbb_help_bbcode_controller') . '">', '</a>'), + 'SMILIES_STATUS' => $user->lang['SMILIES_ARE_ON'], + 'IMG_STATUS' => $user->lang['IMAGES_ARE_ON'], + 'FLASH_STATUS' => $user->lang['FLASH_IS_ON'], + 'URL_STATUS' => $user->lang['URL_IS_ON'], + + 'S_BBCODE_ALLOWED' => true, + 'S_SMILIES_ALLOWED' => true, + 'S_BBCODE_IMG' => true, + 'S_BBCODE_FLASH' => true, + 'S_LINKS_ALLOWED' => true, + )); + + // Assigning custom bbcodes + display_custom_bbcodes(); + } +} diff --git a/phpBB/includes/acp/acp_database.php b/phpBB/includes/acp/acp_database.php index 8afc3709b9..c9d24f9254 100644 --- a/phpBB/includes/acp/acp_database.php +++ b/phpBB/includes/acp/acp_database.php @@ -1,9 +1,13 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -15,9 +19,6 @@ if (!defined('IN_PHPBB')) exit; } -/** -* @package acp -*/ class acp_database { var $db_tools; @@ -25,18 +26,17 @@ class acp_database function main($id, $mode) { - global $cache, $db, $user, $auth, $template, $table_prefix; - global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + global $cache, $db, $user, $template, $table_prefix, $request; + global $phpbb_root_path, $phpbb_container, $phpbb_log; - $this->db_tools = new \phpbb\db\tools($db); + $this->db_tools = $phpbb_container->get('dbal.tools'); $user->add_lang('acp/database'); $this->tpl_name = 'acp_database'; $this->page_title = 'ACP_DATABASE'; - $action = request_var('action', ''); - $submit = (isset($_POST['submit'])) ? true : false; + $action = $request->variable('action', ''); $template->assign_vars(array( 'MODE' => $mode @@ -51,10 +51,10 @@ class acp_database switch ($action) { case 'download': - $type = request_var('type', ''); - $table = array_intersect($this->db_tools->sql_list_tables(), request_var('table', array(''))); - $format = request_var('method', ''); - $where = request_var('where', ''); + $type = $request->variable('type', ''); + $table = array_intersect($this->db_tools->sql_list_tables(), $request->variable('table', array(''))); + $format = $request->variable('method', ''); + $where = $request->variable('where', ''); if (!sizeof($table)) { @@ -89,36 +89,9 @@ class acp_database $time = time(); $filename = 'backup_' . $time . '_' . unique_id(); - switch ($db->sql_layer) - { - case 'mysqli': - case 'mysql4': - case 'mysql': - $extractor = new mysql_extractor($format, $filename, $time, $download, $store); - break; - case 'sqlite': - $extractor = new sqlite_extractor($format, $filename, $time, $download, $store); - break; - - case 'postgres': - $extractor = new postgres_extractor($format, $filename, $time, $download, $store); - break; - - case 'oracle': - $extractor = new oracle_extractor($format, $filename, $time, $download, $store); - break; - - case 'mssql': - case 'mssql_odbc': - case 'mssqlnative': - $extractor = new mssql_extractor($format, $filename, $time, $download, $store); - break; - - case 'firebird': - $extractor = new firebird_extractor($format, $filename, $time, $download, $store); - break; - } + $extractor = $phpbb_container->get('dbal.extractor'); + $extractor->init_extractor($format, $filename, $time, $download, $store); $extractor->write_start($table_prefix); @@ -132,10 +105,10 @@ class acp_database else { // We might wanna empty out all that junk :D - switch ($db->sql_layer) + switch ($db->get_sql_layer()) { case 'sqlite': - case 'firebird': + case 'sqlite3': $extractor->flush('DELETE FROM ' . $table_name . ";\n"); break; @@ -164,7 +137,7 @@ class acp_database $extractor->write_end(); - add_log('admin', 'LOG_DB_BACKUP'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_DB_BACKUP'); if ($download == true) { @@ -220,9 +193,9 @@ class acp_database switch ($action) { case 'submit': - $delete = request_var('delete', ''); - $file = request_var('file', ''); - $download = request_var('download', ''); + $delete = $request->variable('delete', ''); + $file = $request->variable('file', ''); + $download = $request->variable('download', ''); if (!preg_match('#^backup_\d{10,}_[a-z\d]{16}\.(sql(?:\.(?:gz|bz2))?)$#', $file, $matches)) { @@ -241,7 +214,7 @@ class acp_database if (confirm_box(true)) { unlink($file_name); - add_log('admin', 'LOG_DB_DELETE'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_DB_DELETE'); trigger_error($user->lang['BACKUP_DELETE'] . adm_back_link($this->u_action)); } else @@ -268,7 +241,7 @@ class acp_database break; } - header('Pragma: no-cache'); + header('Cache-Control: private, no-cache'); header("Content-Type: $mimetype; name=\"$name\""); header("Content-disposition: attachment; filename=$name"); @@ -319,32 +292,19 @@ class acp_database break; } - switch ($db->sql_layer) + switch ($db->get_sql_layer()) { case 'mysql': case 'mysql4': case 'mysqli': case 'sqlite': + case 'sqlite3': while (($sql = $fgetd($fp, ";\n", $read, $seek, $eof)) !== false) { $db->sql_query($sql); } break; - case 'firebird': - $delim = ";\n"; - while (($sql = $fgetd($fp, $delim, $read, $seek, $eof)) !== false) - { - $query = trim($sql); - if (substr($query, 0, 8) === 'SET TERM') - { - $delim = $query[9] . "\n"; - continue; - } - $db->sql_query($query); - } - break; - case 'postgres': $delim = ";\n"; while (($sql = $fgetd($fp, $delim, $read, $seek, $eof)) !== false) @@ -377,10 +337,10 @@ class acp_database { trigger_error($user->lang['RESTORE_FAILURE'] . adm_back_link($this->u_action), E_USER_WARNING); } - pg_put_line($db->db_connect_id, $sub . "\n"); + pg_put_line($db->get_db_connect_id(), $sub . "\n"); } - pg_put_line($db->db_connect_id, "\\.\n"); - pg_end_copy($db->db_connect_id); + pg_put_line($db->get_db_connect_id(), "\\.\n"); + pg_end_copy($db->get_db_connect_id()); } } break; @@ -407,7 +367,7 @@ class acp_database // Purge the cache due to updated data $cache->purge(); - add_log('admin', 'LOG_DB_RESTORE'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_DB_RESTORE'); trigger_error($user->lang['RESTORE_SUCCESS'] . adm_back_link($this->u_action)); break; } @@ -473,1785 +433,6 @@ class acp_database } } -/** -* @package acp -*/ -class base_extractor -{ - var $fh; - var $fp; - var $write; - var $close; - var $store; - var $download; - var $time; - var $format; - var $run_comp = false; - - function base_extractor($format, $filename, $time, $download = false, $store = false) - { - global $request; - - $this->download = $download; - $this->store = $store; - $this->time = $time; - $this->format = $format; - - switch ($format) - { - case 'text': - $ext = '.sql'; - $open = 'fopen'; - $this->write = 'fwrite'; - $this->close = 'fclose'; - $mimetype = 'text/x-sql'; - break; - case 'bzip2': - $ext = '.sql.bz2'; - $open = 'bzopen'; - $this->write = 'bzwrite'; - $this->close = 'bzclose'; - $mimetype = 'application/x-bzip2'; - break; - case 'gzip': - $ext = '.sql.gz'; - $open = 'gzopen'; - $this->write = 'gzwrite'; - $this->close = 'gzclose'; - $mimetype = 'application/x-gzip'; - break; - } - - if ($download == true) - { - $name = $filename . $ext; - header('Pragma: no-cache'); - header("Content-Type: $mimetype; name=\"$name\""); - header("Content-disposition: attachment; filename=$name"); - - switch ($format) - { - case 'bzip2': - ob_start(); - break; - - case 'gzip': - if (strpos($request->header('Accept-Encoding'), 'gzip') !== false && strpos(strtolower($request->header('User-Agent')), 'msie') === false) - { - ob_start('ob_gzhandler'); - } - else - { - $this->run_comp = true; - } - break; - } - } - - if ($store == true) - { - global $phpbb_root_path; - $file = $phpbb_root_path . 'store/' . $filename . $ext; - - $this->fp = $open($file, 'w'); - - if (!$this->fp) - { - trigger_error('FILE_WRITE_FAIL', E_USER_ERROR); - } - } - } - - function write_end() - { - static $close; - - if ($this->store) - { - if ($close === null) - { - $close = $this->close; - } - $close($this->fp); - } - - // bzip2 must be written all the way at the end - if ($this->download && $this->format === 'bzip2') - { - $c = ob_get_clean(); - echo bzcompress($c); - } - } - - function flush($data) - { - static $write; - if ($this->store === true) - { - if ($write === null) - { - $write = $this->write; - } - $write($this->fp, $data); - } - - if ($this->download === true) - { - if ($this->format === 'bzip2' || $this->format === 'text' || ($this->format === 'gzip' && !$this->run_comp)) - { - echo $data; - } - - // we can write the gzip data as soon as we get it - if ($this->format === 'gzip') - { - if ($this->run_comp) - { - echo gzencode($data); - } - else - { - ob_flush(); - flush(); - } - } - } - } -} - -/** -* @package acp -*/ -class mysql_extractor extends base_extractor -{ - function write_start($table_prefix) - { - $sql_data = "#\n"; - $sql_data .= "# phpBB Backup Script\n"; - $sql_data .= "# Dump of tables for $table_prefix\n"; - $sql_data .= "# DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; - $sql_data .= "#\n"; - $this->flush($sql_data); - } - - function write_table($table_name) - { - global $db; - static $new_extract; - - if ($new_extract === null) - { - if ($db->sql_layer === 'mysqli' || version_compare($db->sql_server_info(true), '3.23.20', '>=')) - { - $new_extract = true; - } - else - { - $new_extract = false; - } - } - - if ($new_extract) - { - $this->new_write_table($table_name); - } - else - { - $this->old_write_table($table_name); - } - } - - function write_data($table_name) - { - global $db; - if ($db->sql_layer === 'mysqli') - { - $this->write_data_mysqli($table_name); - } - else - { - $this->write_data_mysql($table_name); - } - } - - function write_data_mysqli($table_name) - { - global $db; - $sql = "SELECT * - FROM $table_name"; - $result = mysqli_query($db->db_connect_id, $sql, MYSQLI_USE_RESULT); - if ($result != false) - { - $fields_cnt = mysqli_num_fields($result); - - // Get field information - $field = mysqli_fetch_fields($result); - $field_set = array(); - - for ($j = 0; $j < $fields_cnt; $j++) - { - $field_set[] = $field[$j]->name; - } - - $search = array("\\", "'", "\x00", "\x0a", "\x0d", "\x1a", '"'); - $replace = array("\\\\", "\\'", '\0', '\n', '\r', '\Z', '\\"'); - $fields = implode(', ', $field_set); - $sql_data = 'INSERT INTO ' . $table_name . ' (' . $fields . ') VALUES '; - $first_set = true; - $query_len = 0; - $max_len = get_usable_memory(); - - while ($row = mysqli_fetch_row($result)) - { - $values = array(); - if ($first_set) - { - $query = $sql_data . '('; - } - else - { - $query .= ',('; - } - - for ($j = 0; $j < $fields_cnt; $j++) - { - if (!isset($row[$j]) || is_null($row[$j])) - { - $values[$j] = 'NULL'; - } - else if (($field[$j]->flags & 32768) && !($field[$j]->flags & 1024)) - { - $values[$j] = $row[$j]; - } - else - { - $values[$j] = "'" . str_replace($search, $replace, $row[$j]) . "'"; - } - } - $query .= implode(', ', $values) . ')'; - - $query_len += strlen($query); - if ($query_len > $max_len) - { - $this->flush($query . ";\n\n"); - $query = ''; - $query_len = 0; - $first_set = true; - } - else - { - $first_set = false; - } - } - mysqli_free_result($result); - - // check to make sure we have nothing left to flush - if (!$first_set && $query) - { - $this->flush($query . ";\n\n"); - } - } - } - - function write_data_mysql($table_name) - { - global $db; - $sql = "SELECT * - FROM $table_name"; - $result = mysql_unbuffered_query($sql, $db->db_connect_id); - - if ($result != false) - { - $fields_cnt = mysql_num_fields($result); - - // Get field information - $field = array(); - for ($i = 0; $i < $fields_cnt; $i++) - { - $field[] = mysql_fetch_field($result, $i); - } - $field_set = array(); - - for ($j = 0; $j < $fields_cnt; $j++) - { - $field_set[] = $field[$j]->name; - } - - $search = array("\\", "'", "\x00", "\x0a", "\x0d", "\x1a", '"'); - $replace = array("\\\\", "\\'", '\0', '\n', '\r', '\Z', '\\"'); - $fields = implode(', ', $field_set); - $sql_data = 'INSERT INTO ' . $table_name . ' (' . $fields . ') VALUES '; - $first_set = true; - $query_len = 0; - $max_len = get_usable_memory(); - - while ($row = mysql_fetch_row($result)) - { - $values = array(); - if ($first_set) - { - $query = $sql_data . '('; - } - else - { - $query .= ',('; - } - - for ($j = 0; $j < $fields_cnt; $j++) - { - if (!isset($row[$j]) || is_null($row[$j])) - { - $values[$j] = 'NULL'; - } - else if ($field[$j]->numeric && ($field[$j]->type !== 'timestamp')) - { - $values[$j] = $row[$j]; - } - else - { - $values[$j] = "'" . str_replace($search, $replace, $row[$j]) . "'"; - } - } - $query .= implode(', ', $values) . ')'; - - $query_len += strlen($query); - if ($query_len > $max_len) - { - $this->flush($query . ";\n\n"); - $query = ''; - $query_len = 0; - $first_set = true; - } - else - { - $first_set = false; - } - } - mysql_free_result($result); - - // check to make sure we have nothing left to flush - if (!$first_set && $query) - { - $this->flush($query . ";\n\n"); - } - } - } - - function new_write_table($table_name) - { - global $db; - - $sql = 'SHOW CREATE TABLE ' . $table_name; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - - $sql_data = '# Table: ' . $table_name . "\n"; - $sql_data .= "DROP TABLE IF EXISTS $table_name;\n"; - $this->flush($sql_data . $row['Create Table'] . ";\n\n"); - - $db->sql_freeresult($result); - } - - function old_write_table($table_name) - { - global $db; - - $sql_data = '# Table: ' . $table_name . "\n"; - $sql_data .= "DROP TABLE IF EXISTS $table_name;\n"; - $sql_data .= "CREATE TABLE $table_name(\n"; - $rows = array(); - - $sql = "SHOW FIELDS - FROM $table_name"; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - $line = ' ' . $row['Field'] . ' ' . $row['Type']; - - if (!is_null($row['Default'])) - { - $line .= " DEFAULT '{$row['Default']}'"; - } - - if ($row['Null'] != 'YES') - { - $line .= ' NOT NULL'; - } - - if ($row['Extra'] != '') - { - $line .= ' ' . $row['Extra']; - } - - $rows[] = $line; - } - $db->sql_freeresult($result); - - $sql = "SHOW KEYS - FROM $table_name"; - - $result = $db->sql_query($sql); - - $index = array(); - while ($row = $db->sql_fetchrow($result)) - { - $kname = $row['Key_name']; - - if ($kname != 'PRIMARY') - { - if ($row['Non_unique'] == 0) - { - $kname = "UNIQUE|$kname"; - } - } - - if ($row['Sub_part']) - { - $row['Column_name'] .= '(' . $row['Sub_part'] . ')'; - } - $index[$kname][] = $row['Column_name']; - } - $db->sql_freeresult($result); - - foreach ($index as $key => $columns) - { - $line = ' '; - - if ($key == 'PRIMARY') - { - $line .= 'PRIMARY KEY (' . implode(', ', $columns) . ')'; - } - else if (strpos($key, 'UNIQUE') === 0) - { - $line .= 'UNIQUE ' . substr($key, 7) . ' (' . implode(', ', $columns) . ')'; - } - else if (strpos($key, 'FULLTEXT') === 0) - { - $line .= 'FULLTEXT ' . substr($key, 9) . ' (' . implode(', ', $columns) . ')'; - } - else - { - $line .= "KEY $key (" . implode(', ', $columns) . ')'; - } - - $rows[] = $line; - } - - $sql_data .= implode(",\n", $rows); - $sql_data .= "\n);\n\n"; - - $this->flush($sql_data); - } -} - -/** -* @package acp -*/ -class sqlite_extractor extends base_extractor -{ - function write_start($prefix) - { - $sql_data = "--\n"; - $sql_data .= "-- phpBB Backup Script\n"; - $sql_data .= "-- Dump of tables for $prefix\n"; - $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; - $sql_data .= "--\n"; - $sql_data .= "BEGIN TRANSACTION;\n"; - $this->flush($sql_data); - } - - function write_table($table_name) - { - global $db; - $sql_data = '-- Table: ' . $table_name . "\n"; - $sql_data .= "DROP TABLE $table_name;\n"; - - $sql = "SELECT sql - FROM sqlite_master - WHERE type = 'table' - AND name = '" . $db->sql_escape($table_name) . "' - ORDER BY type DESC, name;"; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - // Create Table - $sql_data .= $row['sql'] . ";\n"; - - $result = $db->sql_query("PRAGMA index_list('" . $db->sql_escape($table_name) . "');"); - - $ar = array(); - while ($row = $db->sql_fetchrow($result)) - { - $ar[] = $row; - } - $db->sql_freeresult($result); - - foreach ($ar as $value) - { - if (strpos($value['name'], 'autoindex') !== false) - { - continue; - } - - $result = $db->sql_query("PRAGMA index_info('" . $db->sql_escape($value['name']) . "');"); - - $fields = array(); - while ($row = $db->sql_fetchrow($result)) - { - $fields[] = $row['name']; - } - $db->sql_freeresult($result); - - $sql_data .= 'CREATE ' . ($value['unique'] ? 'UNIQUE ' : '') . 'INDEX ' . $value['name'] . ' on ' . $table_name . ' (' . implode(', ', $fields) . ");\n"; - } - - $this->flush($sql_data . "\n"); - } - - function write_data($table_name) - { - global $db; - - $col_types = sqlite_fetch_column_types($db->db_connect_id, $table_name); - - $sql = "SELECT * - FROM $table_name"; - $result = sqlite_unbuffered_query($db->db_connect_id, $sql); - $rows = sqlite_fetch_all($result, SQLITE_ASSOC); - $sql_insert = 'INSERT INTO ' . $table_name . ' (' . implode(', ', array_keys($col_types)) . ') VALUES ('; - foreach ($rows as $row) - { - foreach ($row as $column_name => $column_data) - { - if (is_null($column_data)) - { - $row[$column_name] = 'NULL'; - } - else if ($column_data == '') - { - $row[$column_name] = "''"; - } - else if (strpos($col_types[$column_name], 'text') !== false || strpos($col_types[$column_name], 'char') !== false || strpos($col_types[$column_name], 'blob') !== false) - { - $row[$column_name] = sanitize_data_generic(str_replace("'", "''", $column_data)); - } - } - $this->flush($sql_insert . implode(', ', $row) . ");\n"); - } - } - - function write_end() - { - $this->flush("COMMIT;\n"); - parent::write_end(); - } -} - -/** -* @package acp -*/ -class postgres_extractor extends base_extractor -{ - function write_start($prefix) - { - $sql_data = "--\n"; - $sql_data .= "-- phpBB Backup Script\n"; - $sql_data .= "-- Dump of tables for $prefix\n"; - $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; - $sql_data .= "--\n"; - $sql_data .= "BEGIN TRANSACTION;\n"; - $this->flush($sql_data); - } - - function write_table($table_name) - { - global $db; - static $domains_created = array(); - - $sql = "SELECT a.domain_name, a.data_type, a.character_maximum_length, a.domain_default - FROM INFORMATION_SCHEMA.domains a, INFORMATION_SCHEMA.column_domain_usage b - WHERE a.domain_name = b.domain_name - AND b.table_name = '{$table_name}'"; - $result = $db->sql_query($sql); - while ($row = $db->sql_fetchrow($result)) - { - if (empty($domains_created[$row['domain_name']])) - { - $domains_created[$row['domain_name']] = true; - //$sql_data = "DROP DOMAIN {$row['domain_name']};\n"; - $sql_data = "CREATE DOMAIN {$row['domain_name']} as {$row['data_type']}"; - if (!empty($row['character_maximum_length'])) - { - $sql_data .= '(' . $row['character_maximum_length'] . ')'; - } - $sql_data .= ' NOT NULL'; - if (!empty($row['domain_default'])) - { - $sql_data .= ' DEFAULT ' . $row['domain_default']; - } - $this->flush($sql_data . ";\n"); - } - } - - $sql_data = '-- Table: ' . $table_name . "\n"; - $sql_data .= "DROP TABLE $table_name;\n"; - // PGSQL does not "tightly" bind sequences and tables, we must guess... - $sql = "SELECT relname - FROM pg_class - WHERE relkind = 'S' - AND relname = '{$table_name}_seq'"; - $result = $db->sql_query($sql); - // We don't even care about storing the results. We already know the answer if we get rows back. - if ($db->sql_fetchrow($result)) - { - $sql_data .= "DROP SEQUENCE {$table_name}_seq;\n"; - $sql_data .= "CREATE SEQUENCE {$table_name}_seq;\n"; - } - $db->sql_freeresult($result); - - $field_query = "SELECT a.attnum, a.attname as field, t.typname as type, a.attlen as length, a.atttypmod as lengthvar, a.attnotnull as notnull - FROM pg_class c, pg_attribute a, pg_type t - WHERE c.relname = '" . $db->sql_escape($table_name) . "' - AND a.attnum > 0 - AND a.attrelid = c.oid - AND a.atttypid = t.oid - ORDER BY a.attnum"; - $result = $db->sql_query($field_query); - - $sql_data .= "CREATE TABLE $table_name(\n"; - $lines = array(); - while ($row = $db->sql_fetchrow($result)) - { - // Get the data from the table - $sql_get_default = "SELECT pg_get_expr(d.adbin, d.adrelid) as rowdefault - FROM pg_attrdef d, pg_class c - WHERE (c.relname = '" . $db->sql_escape($table_name) . "') - AND (c.oid = d.adrelid) - AND d.adnum = " . $row['attnum']; - $def_res = $db->sql_query($sql_get_default); - $def_row = $db->sql_fetchrow($def_res); - $db->sql_freeresult($def_res); - - if (empty($def_row)) - { - unset($row['rowdefault']); - } - else - { - $row['rowdefault'] = $def_row['rowdefault']; - } - - if ($row['type'] == 'bpchar') - { - // Internally stored as bpchar, but isn't accepted in a CREATE TABLE statement. - $row['type'] = 'char'; - } - - $line = ' ' . $row['field'] . ' ' . $row['type']; - - if (strpos($row['type'], 'char') !== false) - { - if ($row['lengthvar'] > 0) - { - $line .= '(' . ($row['lengthvar'] - 4) . ')'; - } - } - - if (strpos($row['type'], 'numeric') !== false) - { - $line .= '('; - $line .= sprintf("%s,%s", (($row['lengthvar'] >> 16) & 0xffff), (($row['lengthvar'] - 4) & 0xffff)); - $line .= ')'; - } - - if (isset($row['rowdefault'])) - { - $line .= ' DEFAULT ' . $row['rowdefault']; - } - - if ($row['notnull'] == 't') - { - $line .= ' NOT NULL'; - } - - $lines[] = $line; - } - $db->sql_freeresult($result); - - - // Get the listing of primary keys. - $sql_pri_keys = "SELECT ic.relname as index_name, bc.relname as tab_name, ta.attname as column_name, i.indisunique as unique_key, i.indisprimary as primary_key - FROM pg_class bc, pg_class ic, pg_index i, pg_attribute ta, pg_attribute ia - WHERE (bc.oid = i.indrelid) - AND (ic.oid = i.indexrelid) - AND (ia.attrelid = i.indexrelid) - AND (ta.attrelid = bc.oid) - AND (bc.relname = '" . $db->sql_escape($table_name) . "') - AND (ta.attrelid = i.indrelid) - AND (ta.attnum = i.indkey[ia.attnum-1]) - ORDER BY index_name, tab_name, column_name"; - - $result = $db->sql_query($sql_pri_keys); - - $index_create = $index_rows = $primary_key = array(); - - // We do this in two steps. It makes placing the comma easier - while ($row = $db->sql_fetchrow($result)) - { - if ($row['primary_key'] == 't') - { - $primary_key[] = $row['column_name']; - $primary_key_name = $row['index_name']; - } - else - { - // We have to store this all this info because it is possible to have a multi-column key... - // we can loop through it again and build the statement - $index_rows[$row['index_name']]['table'] = $table_name; - $index_rows[$row['index_name']]['unique'] = ($row['unique_key'] == 't') ? true : false; - $index_rows[$row['index_name']]['column_names'][] = $row['column_name']; - } - } - $db->sql_freeresult($result); - - if (!empty($index_rows)) - { - foreach ($index_rows as $idx_name => $props) - { - $index_create[] = 'CREATE ' . ($props['unique'] ? 'UNIQUE ' : '') . "INDEX $idx_name ON $table_name (" . implode(', ', $props['column_names']) . ");"; - } - } - - if (!empty($primary_key)) - { - $lines[] = " CONSTRAINT $primary_key_name PRIMARY KEY (" . implode(', ', $primary_key) . ")"; - } - - // Generate constraint clauses for CHECK constraints - $sql_checks = "SELECT conname as index_name, consrc - FROM pg_constraint, pg_class bc - WHERE conrelid = bc.oid - AND bc.relname = '" . $db->sql_escape($table_name) . "' - AND NOT EXISTS ( - SELECT * - FROM pg_constraint as c, pg_inherits as i - WHERE i.inhrelid = pg_constraint.conrelid - AND c.conname = pg_constraint.conname - AND c.consrc = pg_constraint.consrc - AND c.conrelid = i.inhparent - )"; - $result = $db->sql_query($sql_checks); - - // Add the constraints to the sql file. - while ($row = $db->sql_fetchrow($result)) - { - if (!is_null($row['consrc'])) - { - $lines[] = ' CONSTRAINT ' . $row['index_name'] . ' CHECK ' . $row['consrc']; - } - } - $db->sql_freeresult($result); - - $sql_data .= implode(", \n", $lines); - $sql_data .= "\n);\n"; - - if (!empty($index_create)) - { - $sql_data .= implode("\n", $index_create) . "\n\n"; - } - $this->flush($sql_data); - } - - function write_data($table_name) - { - global $db; - // Grab all of the data from current table. - $sql = "SELECT * - FROM $table_name"; - $result = $db->sql_query($sql); - - $i_num_fields = pg_num_fields($result); - $seq = ''; - - for ($i = 0; $i < $i_num_fields; $i++) - { - $ary_type[] = pg_field_type($result, $i); - $ary_name[] = pg_field_name($result, $i); - - - $sql = "SELECT pg_get_expr(d.adbin, d.adrelid) as rowdefault - FROM pg_attrdef d, pg_class c - WHERE (c.relname = '{$table_name}') - AND (c.oid = d.adrelid) - AND d.adnum = " . strval($i + 1); - $result2 = $db->sql_query($sql); - if ($row = $db->sql_fetchrow($result2)) - { - // Determine if we must reset the sequences - if (strpos($row['rowdefault'], "nextval('") === 0) - { - $seq .= "SELECT SETVAL('{$table_name}_seq',(select case when max({$ary_name[$i]})>0 then max({$ary_name[$i]})+1 else 1 end FROM {$table_name}));\n"; - } - } - } - - $this->flush("COPY $table_name (" . implode(', ', $ary_name) . ') FROM stdin;' . "\n"); - while ($row = $db->sql_fetchrow($result)) - { - $schema_vals = array(); - - // Build the SQL statement to recreate the data. - for ($i = 0; $i < $i_num_fields; $i++) - { - $str_val = $row[$ary_name[$i]]; - - if (preg_match('#char|text|bool|bytea#i', $ary_type[$i])) - { - $str_val = str_replace(array("\n", "\t", "\r", "\b", "\f", "\v"), array('\n', '\t', '\r', '\b', '\f', '\v'), addslashes($str_val)); - $str_empty = ''; - } - else - { - $str_empty = '\N'; - } - - if (empty($str_val) && $str_val !== '0') - { - $str_val = $str_empty; - } - - $schema_vals[] = $str_val; - } - - // Take the ordered fields and their associated data and build it - // into a valid sql statement to recreate that field in the data. - $this->flush(implode("\t", $schema_vals) . "\n"); - } - $db->sql_freeresult($result); - $this->flush("\\.\n"); - - // Write out the sequence statements - $this->flush($seq); - } - - function write_end() - { - $this->flush("COMMIT;\n"); - parent::write_end(); - } -} - -/** -* @package acp -*/ -class mssql_extractor extends base_extractor -{ - function write_end() - { - $this->flush("COMMIT\nGO\n"); - parent::write_end(); - } - - function write_start($prefix) - { - $sql_data = "--\n"; - $sql_data .= "-- phpBB Backup Script\n"; - $sql_data .= "-- Dump of tables for $prefix\n"; - $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; - $sql_data .= "--\n"; - $sql_data .= "BEGIN TRANSACTION\n"; - $sql_data .= "GO\n"; - $this->flush($sql_data); - } - - function write_table($table_name) - { - global $db; - $sql_data = '-- Table: ' . $table_name . "\n"; - $sql_data .= "IF OBJECT_ID(N'$table_name', N'U') IS NOT NULL\n"; - $sql_data .= "DROP TABLE $table_name;\n"; - $sql_data .= "GO\n"; - $sql_data .= "\nCREATE TABLE [$table_name] (\n"; - $rows = array(); - - $text_flag = false; - - $sql = "SELECT COLUMN_NAME, COLUMN_DEFAULT, IS_NULLABLE, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, COLUMNPROPERTY(object_id(TABLE_NAME), COLUMN_NAME, 'IsIdentity') as IS_IDENTITY - FROM INFORMATION_SCHEMA.COLUMNS - WHERE TABLE_NAME = '$table_name'"; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - $line = "\t[{$row['COLUMN_NAME']}] [{$row['DATA_TYPE']}]"; - - if ($row['DATA_TYPE'] == 'text') - { - $text_flag = true; - } - - if ($row['IS_IDENTITY']) - { - $line .= ' IDENTITY (1 , 1)'; - } - - if ($row['CHARACTER_MAXIMUM_LENGTH'] && $row['DATA_TYPE'] !== 'text') - { - $line .= ' (' . $row['CHARACTER_MAXIMUM_LENGTH'] . ')'; - } - - if ($row['IS_NULLABLE'] == 'YES') - { - $line .= ' NULL'; - } - else - { - $line .= ' NOT NULL'; - } - - if ($row['COLUMN_DEFAULT']) - { - $line .= ' DEFAULT ' . $row['COLUMN_DEFAULT']; - } - - $rows[] = $line; - } - $db->sql_freeresult($result); - - $sql_data .= implode(",\n", $rows); - $sql_data .= "\n) ON [PRIMARY]"; - - if ($text_flag) - { - $sql_data .= " TEXTIMAGE_ON [PRIMARY]"; - } - - $sql_data .= "\nGO\n\n"; - $rows = array(); - - $sql = "SELECT CONSTRAINT_NAME, COLUMN_NAME - FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE - WHERE TABLE_NAME = '$table_name'"; - $result = $db->sql_query($sql); - while ($row = $db->sql_fetchrow($result)) - { - if (!sizeof($rows)) - { - $sql_data .= "ALTER TABLE [$table_name] WITH NOCHECK ADD\n"; - $sql_data .= "\tCONSTRAINT [{$row['CONSTRAINT_NAME']}] PRIMARY KEY CLUSTERED \n\t(\n"; - } - $rows[] = "\t\t[{$row['COLUMN_NAME']}]"; - } - if (sizeof($rows)) - { - $sql_data .= implode(",\n", $rows); - $sql_data .= "\n\t) ON [PRIMARY] \nGO\n"; - } - $db->sql_freeresult($result); - - $index = array(); - $sql = "EXEC sp_statistics '$table_name'"; - $result = $db->sql_query($sql); - while ($row = $db->sql_fetchrow($result)) - { - if ($row['TYPE'] == 3) - { - $index[$row['INDEX_NAME']][] = '[' . $row['COLUMN_NAME'] . ']'; - } - } - $db->sql_freeresult($result); - - foreach ($index as $index_name => $column_name) - { - $index[$index_name] = implode(', ', $column_name); - } - - foreach ($index as $index_name => $columns) - { - $sql_data .= "\nCREATE INDEX [$index_name] ON [$table_name]($columns) ON [PRIMARY]\nGO\n"; - } - $this->flush($sql_data); - } - - function write_data($table_name) - { - global $db; - - if ($db->sql_layer === 'mssql') - { - $this->write_data_mssql($table_name); - } - else if($db->sql_layer === 'mssqlnative') - { - $this->write_data_mssqlnative($table_name); - } - else - { - $this->write_data_odbc($table_name); - } - } - - function write_data_mssql($table_name) - { - global $db; - $ary_type = $ary_name = array(); - $ident_set = false; - $sql_data = ''; - - // Grab all of the data from current table. - $sql = "SELECT * - FROM $table_name"; - $result = $db->sql_query($sql); - - $retrieved_data = mssql_num_rows($result); - - $i_num_fields = mssql_num_fields($result); - - for ($i = 0; $i < $i_num_fields; $i++) - { - $ary_type[$i] = mssql_field_type($result, $i); - $ary_name[$i] = mssql_field_name($result, $i); - } - - if ($retrieved_data) - { - $sql = "SELECT 1 as has_identity - FROM INFORMATION_SCHEMA.COLUMNS - WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1"; - $result2 = $db->sql_query($sql); - $row2 = $db->sql_fetchrow($result2); - if (!empty($row2['has_identity'])) - { - $sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n"; - $ident_set = true; - } - $db->sql_freeresult($result2); - } - - while ($row = $db->sql_fetchrow($result)) - { - $schema_vals = $schema_fields = array(); - - // Build the SQL statement to recreate the data. - for ($i = 0; $i < $i_num_fields; $i++) - { - $str_val = $row[$ary_name[$i]]; - - if (preg_match('#char|text|bool|varbinary#i', $ary_type[$i])) - { - $str_quote = ''; - $str_empty = "''"; - $str_val = sanitize_data_mssql(str_replace("'", "''", $str_val)); - } - else if (preg_match('#date|timestamp#i', $ary_type[$i])) - { - if (empty($str_val)) - { - $str_quote = ''; - } - else - { - $str_quote = "'"; - } - } - else - { - $str_quote = ''; - $str_empty = 'NULL'; - } - - if (empty($str_val) && $str_val !== '0' && !(is_int($str_val) || is_float($str_val))) - { - $str_val = $str_empty; - } - - $schema_vals[$i] = $str_quote . $str_val . $str_quote; - $schema_fields[$i] = $ary_name[$i]; - } - - // Take the ordered fields and their associated data and build it - // into a valid sql statement to recreate that field in the data. - $sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\nGO\n"; - - $this->flush($sql_data); - $sql_data = ''; - } - $db->sql_freeresult($result); - - if ($retrieved_data && $ident_set) - { - $sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n"; - } - $this->flush($sql_data); - } - - function write_data_mssqlnative($table_name) - { - global $db; - $ary_type = $ary_name = array(); - $ident_set = false; - $sql_data = ''; - - // Grab all of the data from current table. - $sql = "SELECT * FROM $table_name"; - $db->mssqlnative_set_query_options(array('Scrollable' => SQLSRV_CURSOR_STATIC)); - $result = $db->sql_query($sql); - - $retrieved_data = $db->mssqlnative_num_rows($result); - - if (!$retrieved_data) - { - $db->sql_freeresult($result); - return; - } - - $sql = "SELECT COLUMN_NAME, DATA_TYPE - FROM INFORMATION_SCHEMA.COLUMNS - WHERE INFORMATION_SCHEMA.COLUMNS.TABLE_NAME = '" . $db->sql_escape($table_name) . "'"; - $result_fields = $db->sql_query($sql); - - $i_num_fields = 0; - while ($row = $db->sql_fetchrow($result_fields)) - { - $ary_type[$i_num_fields] = $row['DATA_TYPE']; - $ary_name[$i_num_fields] = $row['COLUMN_NAME']; - $i_num_fields++; - } - $db->sql_freeresult($result_fields); - - $sql = "SELECT 1 as has_identity - FROM INFORMATION_SCHEMA.COLUMNS - WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1"; - $result2 = $db->sql_query($sql); - $row2 = $db->sql_fetchrow($result2); - - if (!empty($row2['has_identity'])) - { - $sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n"; - $ident_set = true; - } - $db->sql_freeresult($result2); - - while ($row = $db->sql_fetchrow($result)) - { - $schema_vals = $schema_fields = array(); - - // Build the SQL statement to recreate the data. - for ($i = 0; $i < $i_num_fields; $i++) - { - $str_val = $row[$ary_name[$i]]; - - // defaults to type number - better quote just to be safe, so check for is_int too - if (is_int($ary_type[$i]) || preg_match('#char|text|bool|varbinary#i', $ary_type[$i])) - { - $str_quote = ''; - $str_empty = "''"; - $str_val = sanitize_data_mssql(str_replace("'", "''", $str_val)); - } - else if (preg_match('#date|timestamp#i', $ary_type[$i])) - { - if (empty($str_val)) - { - $str_quote = ''; - } - else - { - $str_quote = "'"; - } - } - else - { - $str_quote = ''; - $str_empty = 'NULL'; - } - - if (empty($str_val) && $str_val !== '0' && !(is_int($str_val) || is_float($str_val))) - { - $str_val = $str_empty; - } - - $schema_vals[$i] = $str_quote . $str_val . $str_quote; - $schema_fields[$i] = $ary_name[$i]; - } - - // Take the ordered fields and their associated data and build it - // into a valid sql statement to recreate that field in the data. - $sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\nGO\n"; - - $this->flush($sql_data); - $sql_data = ''; - } - $db->sql_freeresult($result); - - if ($ident_set) - { - $sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n"; - } - $this->flush($sql_data); - } - - function write_data_odbc($table_name) - { - global $db; - $ary_type = $ary_name = array(); - $ident_set = false; - $sql_data = ''; - - // Grab all of the data from current table. - $sql = "SELECT * - FROM $table_name"; - $result = $db->sql_query($sql); - - $retrieved_data = odbc_num_rows($result); - - if ($retrieved_data) - { - $sql = "SELECT 1 as has_identity - FROM INFORMATION_SCHEMA.COLUMNS - WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1"; - $result2 = $db->sql_query($sql); - $row2 = $db->sql_fetchrow($result2); - if (!empty($row2['has_identity'])) - { - $sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n"; - $ident_set = true; - } - $db->sql_freeresult($result2); - } - - $i_num_fields = odbc_num_fields($result); - - for ($i = 0; $i < $i_num_fields; $i++) - { - $ary_type[$i] = odbc_field_type($result, $i + 1); - $ary_name[$i] = odbc_field_name($result, $i + 1); - } - - while ($row = $db->sql_fetchrow($result)) - { - $schema_vals = $schema_fields = array(); - - // Build the SQL statement to recreate the data. - for ($i = 0; $i < $i_num_fields; $i++) - { - $str_val = $row[$ary_name[$i]]; - - if (preg_match('#char|text|bool|varbinary#i', $ary_type[$i])) - { - $str_quote = ''; - $str_empty = "''"; - $str_val = sanitize_data_mssql(str_replace("'", "''", $str_val)); - } - else if (preg_match('#date|timestamp#i', $ary_type[$i])) - { - if (empty($str_val)) - { - $str_quote = ''; - } - else - { - $str_quote = "'"; - } - } - else - { - $str_quote = ''; - $str_empty = 'NULL'; - } - - if (empty($str_val) && $str_val !== '0' && !(is_int($str_val) || is_float($str_val))) - { - $str_val = $str_empty; - } - - $schema_vals[$i] = $str_quote . $str_val . $str_quote; - $schema_fields[$i] = $ary_name[$i]; - } - - // Take the ordered fields and their associated data and build it - // into a valid sql statement to recreate that field in the data. - $sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\nGO\n"; - - $this->flush($sql_data); - - $sql_data = ''; - - } - $db->sql_freeresult($result); - - if ($retrieved_data && $ident_set) - { - $sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n"; - } - $this->flush($sql_data); - } - -} - -/** -* @package acp -*/ -class oracle_extractor extends base_extractor -{ - function write_table($table_name) - { - global $db; - $sql_data = '-- Table: ' . $table_name . "\n"; - $sql_data .= "DROP TABLE $table_name\n/\n"; - $sql_data .= "\nCREATE TABLE $table_name (\n"; - - $sql = "SELECT COLUMN_NAME, DATA_TYPE, DATA_PRECISION, DATA_LENGTH, NULLABLE, DATA_DEFAULT - FROM ALL_TAB_COLS - WHERE table_name = '{$table_name}'"; - $result = $db->sql_query($sql); - - $rows = array(); - while ($row = $db->sql_fetchrow($result)) - { - $line = ' "' . $row['column_name'] . '" ' . $row['data_type']; - - if ($row['data_type'] !== 'CLOB') - { - if ($row['data_type'] !== 'VARCHAR2' && $row['data_type'] !== 'CHAR') - { - $line .= '(' . $row['data_precision'] . ')'; - } - else - { - $line .= '(' . $row['data_length'] . ')'; - } - } - - if (!empty($row['data_default'])) - { - $line .= ' DEFAULT ' . $row['data_default']; - } - - if ($row['nullable'] == 'N') - { - $line .= ' NOT NULL'; - } - $rows[] = $line; - } - $db->sql_freeresult($result); - - $sql = "SELECT A.CONSTRAINT_NAME, A.COLUMN_NAME - FROM USER_CONS_COLUMNS A, USER_CONSTRAINTS B - WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME - AND B.CONSTRAINT_TYPE = 'P' - AND A.TABLE_NAME = '{$table_name}'"; - $result = $db->sql_query($sql); - - $primary_key = array(); - $contraint_name = ''; - while ($row = $db->sql_fetchrow($result)) - { - $constraint_name = '"' . $row['constraint_name'] . '"'; - $primary_key[] = '"' . $row['column_name'] . '"'; - } - $db->sql_freeresult($result); - - if (sizeof($primary_key)) - { - $rows[] = " CONSTRAINT {$constraint_name} PRIMARY KEY (" . implode(', ', $primary_key) . ')'; - } - - $sql = "SELECT A.CONSTRAINT_NAME, A.COLUMN_NAME - FROM USER_CONS_COLUMNS A, USER_CONSTRAINTS B - WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME - AND B.CONSTRAINT_TYPE = 'U' - AND A.TABLE_NAME = '{$table_name}'"; - $result = $db->sql_query($sql); - - $unique = array(); - $contraint_name = ''; - while ($row = $db->sql_fetchrow($result)) - { - $constraint_name = '"' . $row['constraint_name'] . '"'; - $unique[] = '"' . $row['column_name'] . '"'; - } - $db->sql_freeresult($result); - - if (sizeof($unique)) - { - $rows[] = " CONSTRAINT {$constraint_name} UNIQUE (" . implode(', ', $unique) . ')'; - } - - $sql_data .= implode(",\n", $rows); - $sql_data .= "\n)\n/\n"; - - $sql = "SELECT A.REFERENCED_NAME, C.* - FROM USER_DEPENDENCIES A, USER_TRIGGERS B, USER_SEQUENCES C - WHERE A.REFERENCED_TYPE = 'SEQUENCE' - AND A.NAME = B.TRIGGER_NAME - AND B.TABLE_NAME = '{$table_name}' - AND C.SEQUENCE_NAME = A.REFERENCED_NAME"; - $result = $db->sql_query($sql); - - $type = request_var('type', ''); - - while ($row = $db->sql_fetchrow($result)) - { - $sql_data .= "\nDROP SEQUENCE \"{$row['referenced_name']}\"\n/\n"; - $sql_data .= "\nCREATE SEQUENCE \"{$row['referenced_name']}\""; - - if ($type == 'full') - { - $sql_data .= ' START WITH ' . $row['last_number']; - } - - $sql_data .= "\n/\n"; - } - $db->sql_freeresult($result); - - $sql = "SELECT DESCRIPTION, WHEN_CLAUSE, TRIGGER_BODY - FROM USER_TRIGGERS - WHERE TABLE_NAME = '{$table_name}'"; - $result = $db->sql_query($sql); - while ($row = $db->sql_fetchrow($result)) - { - $sql_data .= "\nCREATE OR REPLACE TRIGGER {$row['description']}WHEN ({$row['when_clause']})\n{$row['trigger_body']}\n/\n"; - } - $db->sql_freeresult($result); - - $sql = "SELECT A.INDEX_NAME, B.COLUMN_NAME - FROM USER_INDEXES A, USER_IND_COLUMNS B - WHERE A.UNIQUENESS = 'NONUNIQUE' - AND A.INDEX_NAME = B.INDEX_NAME - AND B.TABLE_NAME = '{$table_name}'"; - $result = $db->sql_query($sql); - - $index = array(); - - while ($row = $db->sql_fetchrow($result)) - { - $index[$row['index_name']][] = $row['column_name']; - } - - foreach ($index as $index_name => $column_names) - { - $sql_data .= "\nCREATE INDEX $index_name ON $table_name(" . implode(', ', $column_names) . ")\n/\n"; - } - $db->sql_freeresult($result); - $this->flush($sql_data); - } - - function write_data($table_name) - { - global $db; - $ary_type = $ary_name = array(); - - // Grab all of the data from current table. - $sql = "SELECT * - FROM $table_name"; - $result = $db->sql_query($sql); - - $i_num_fields = ocinumcols($result); - - for ($i = 0; $i < $i_num_fields; $i++) - { - $ary_type[$i] = ocicolumntype($result, $i + 1); - $ary_name[$i] = ocicolumnname($result, $i + 1); - } - - $sql_data = ''; - - while ($row = $db->sql_fetchrow($result)) - { - $schema_vals = $schema_fields = array(); - - // Build the SQL statement to recreate the data. - for ($i = 0; $i < $i_num_fields; $i++) - { - // Oracle uses uppercase - we use lowercase - $str_val = $row[strtolower($ary_name[$i])]; - - if (preg_match('#char|text|bool|raw|clob#i', $ary_type[$i])) - { - $str_quote = ''; - $str_empty = "''"; - $str_val = sanitize_data_oracle($str_val); - } - else if (preg_match('#date|timestamp#i', $ary_type[$i])) - { - if (empty($str_val)) - { - $str_quote = ''; - } - else - { - $str_quote = "'"; - } - } - else - { - $str_quote = ''; - $str_empty = 'NULL'; - } - - if (empty($str_val) && $str_val !== '0') - { - $str_val = $str_empty; - } - - $schema_vals[$i] = $str_quote . $str_val . $str_quote; - $schema_fields[$i] = '"' . $ary_name[$i] . '"'; - } - - // Take the ordered fields and their associated data and build it - // into a valid sql statement to recreate that field in the data. - $sql_data = "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ")\n/\n"; - - $this->flush($sql_data); - } - $db->sql_freeresult($result); - } - - function write_start($prefix) - { - $sql_data = "--\n"; - $sql_data .= "-- phpBB Backup Script\n"; - $sql_data .= "-- Dump of tables for $prefix\n"; - $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; - $sql_data .= "--\n"; - $this->flush($sql_data); - } -} - -/** -* @package acp -*/ -class firebird_extractor extends base_extractor -{ - function write_start($prefix) - { - $sql_data = "--\n"; - $sql_data .= "-- phpBB Backup Script\n"; - $sql_data .= "-- Dump of tables for $prefix\n"; - $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; - $sql_data .= "--\n"; - $this->flush($sql_data); - } - - function write_data($table_name) - { - global $db; - $ary_type = $ary_name = array(); - - // Grab all of the data from current table. - $sql = "SELECT * - FROM $table_name"; - $result = $db->sql_query($sql); - - $i_num_fields = ibase_num_fields($result); - - for ($i = 0; $i < $i_num_fields; $i++) - { - $info = ibase_field_info($result, $i); - $ary_type[$i] = $info['type']; - $ary_name[$i] = $info['name']; - } - - while ($row = $db->sql_fetchrow($result)) - { - $schema_vals = $schema_fields = array(); - - // Build the SQL statement to recreate the data. - for ($i = 0; $i < $i_num_fields; $i++) - { - $str_val = $row[strtolower($ary_name[$i])]; - - if (preg_match('#char|text|bool|varbinary|blob#i', $ary_type[$i])) - { - $str_quote = ''; - $str_empty = "''"; - $str_val = sanitize_data_generic(str_replace("'", "''", $str_val)); - } - else if (preg_match('#date|timestamp#i', $ary_type[$i])) - { - if (empty($str_val)) - { - $str_quote = ''; - } - else - { - $str_quote = "'"; - } - } - else - { - $str_quote = ''; - $str_empty = 'NULL'; - } - - if (empty($str_val) && $str_val !== '0') - { - $str_val = $str_empty; - } - - $schema_vals[$i] = $str_quote . $str_val . $str_quote; - $schema_fields[$i] = '"' . $ary_name[$i] . '"'; - } - - // Take the ordered fields and their associated data and build it - // into a valid sql statement to recreate that field in the data. - $sql_data = "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\n"; - - $this->flush($sql_data); - } - $db->sql_freeresult($result); - } - - function write_table($table_name) - { - global $db; - - $sql_data = '-- Table: ' . $table_name . "\n"; - $sql_data .= "DROP TABLE $table_name;\n"; - - $data_types = array(7 => 'SMALLINT', 8 => 'INTEGER', 10 => 'FLOAT', 12 => 'DATE', 13 => 'TIME', 14 => 'CHARACTER', 27 => 'DOUBLE PRECISION', 35 => 'TIMESTAMP', 37 => 'VARCHAR', 40 => 'CSTRING', 261 => 'BLOB', 701 => 'DECIMAL', 702 => 'NUMERIC'); - - $sql_data .= "\nCREATE TABLE $table_name (\n"; - - $sql = 'SELECT DISTINCT R.RDB$FIELD_NAME as FNAME, R.RDB$NULL_FLAG as NFLAG, R.RDB$DEFAULT_SOURCE as DSOURCE, F.RDB$FIELD_TYPE as FTYPE, F.RDB$FIELD_SUB_TYPE as STYPE, F.RDB$FIELD_LENGTH as FLEN - FROM RDB$RELATION_FIELDS R - JOIN RDB$FIELDS F ON R.RDB$FIELD_SOURCE=F.RDB$FIELD_NAME - LEFT JOIN RDB$FIELD_DIMENSIONS D ON R.RDB$FIELD_SOURCE = D.RDB$FIELD_NAME - WHERE F.RDB$SYSTEM_FLAG = 0 - AND R.RDB$RELATION_NAME = \''. $table_name . '\' - ORDER BY R.RDB$FIELD_POSITION'; - $result = $db->sql_query($sql); - - $rows = array(); - while ($row = $db->sql_fetchrow($result)) - { - $line = "\t" . '"' . $row['fname'] . '" ' . $data_types[$row['ftype']]; - - if ($row['ftype'] == 261 && $row['stype'] == 1) - { - $line .= ' SUB_TYPE TEXT'; - } - - if ($row['ftype'] == 37 || $row['ftype'] == 14) - { - $line .= ' (' . $row['flen'] . ')'; - } - - if (!empty($row['dsource'])) - { - $line .= ' ' . $row['dsource']; - } - - if (!empty($row['nflag'])) - { - $line .= ' NOT NULL'; - } - $rows[] = $line; - } - $db->sql_freeresult($result); - - $sql_data .= implode(",\n", $rows); - $sql_data .= "\n);\n"; - $keys = array(); - - $sql = 'SELECT I.RDB$FIELD_NAME as NAME - FROM RDB$RELATION_CONSTRAINTS RC, RDB$INDEX_SEGMENTS I, RDB$INDICES IDX - WHERE (I.RDB$INDEX_NAME = RC.RDB$INDEX_NAME) - AND (IDX.RDB$INDEX_NAME = RC.RDB$INDEX_NAME) - AND (RC.RDB$RELATION_NAME = \''. $table_name . '\') - ORDER BY I.RDB$FIELD_POSITION'; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - $keys[] = $row['name']; - } - - if (sizeof($keys)) - { - $sql_data .= "\nALTER TABLE $table_name ADD PRIMARY KEY (" . implode(', ', $keys) . ');'; - } - - $db->sql_freeresult($result); - - $sql = 'SELECT I.RDB$INDEX_NAME as INAME, I.RDB$UNIQUE_FLAG as UFLAG, S.RDB$FIELD_NAME as FNAME - FROM RDB$INDICES I JOIN RDB$INDEX_SEGMENTS S ON S.RDB$INDEX_NAME=I.RDB$INDEX_NAME - WHERE (I.RDB$SYSTEM_FLAG IS NULL OR I.RDB$SYSTEM_FLAG=0) - AND I.RDB$FOREIGN_KEY IS NULL - AND I.RDB$RELATION_NAME = \''. $table_name . '\' - AND I.RDB$INDEX_NAME NOT STARTING WITH \'RDB$\' - ORDER BY S.RDB$FIELD_POSITION'; - $result = $db->sql_query($sql); - - $index = array(); - while ($row = $db->sql_fetchrow($result)) - { - $index[$row['iname']]['unique'] = !empty($row['uflag']); - $index[$row['iname']]['values'][] = $row['fname']; - } - - foreach ($index as $index_name => $data) - { - $sql_data .= "\nCREATE "; - if ($data['unique']) - { - $sql_data .= 'UNIQUE '; - } - $sql_data .= "INDEX $index_name ON $table_name(" . implode(', ', $data['values']) . ");"; - } - $sql_data .= "\n"; - - $db->sql_freeresult($result); - - $sql = 'SELECT D1.RDB$DEPENDENT_NAME as DNAME, D1.RDB$FIELD_NAME as FNAME, D1.RDB$DEPENDENT_TYPE, R1.RDB$RELATION_NAME - FROM RDB$DEPENDENCIES D1 - LEFT JOIN RDB$RELATIONS R1 ON ((D1.RDB$DEPENDENT_NAME = R1.RDB$RELATION_NAME) AND (NOT (R1.RDB$VIEW_BLR IS NULL))) - WHERE (D1.RDB$DEPENDED_ON_TYPE = 0) - AND (D1.RDB$DEPENDENT_TYPE <> 3) - AND (D1.RDB$DEPENDED_ON_NAME = \'' . $table_name . '\') - UNION SELECT DISTINCT F2.RDB$RELATION_NAME, D2.RDB$FIELD_NAME, D2.RDB$DEPENDENT_TYPE, R2.RDB$RELATION_NAME FROM RDB$DEPENDENCIES D2, RDB$RELATION_FIELDS F2 - LEFT JOIN RDB$RELATIONS R2 ON ((F2.RDB$RELATION_NAME = R2.RDB$RELATION_NAME) AND (NOT (R2.RDB$VIEW_BLR IS NULL))) - WHERE (D2.RDB$DEPENDENT_TYPE = 3) - AND (D2.RDB$DEPENDENT_NAME = F2.RDB$FIELD_SOURCE) - AND (D2.RDB$DEPENDED_ON_NAME = \'' . $table_name . '\') - ORDER BY 1, 2'; - $result = $db->sql_query($sql); - while ($row = $db->sql_fetchrow($result)) - { - $sql = 'SELECT T1.RDB$DEPENDED_ON_NAME as GEN, T1.RDB$FIELD_NAME, T1.RDB$DEPENDED_ON_TYPE - FROM RDB$DEPENDENCIES T1 - WHERE (T1.RDB$DEPENDENT_NAME = \'' . $row['dname'] . '\') - AND (T1.RDB$DEPENDENT_TYPE = 2 AND T1.RDB$DEPENDED_ON_TYPE = 14) - UNION ALL SELECT DISTINCT D.RDB$DEPENDED_ON_NAME, D.RDB$FIELD_NAME, D.RDB$DEPENDED_ON_TYPE - FROM RDB$DEPENDENCIES D, RDB$RELATION_FIELDS F - WHERE (D.RDB$DEPENDENT_TYPE = 3) - AND (D.RDB$DEPENDENT_NAME = F.RDB$FIELD_SOURCE) - AND (F.RDB$RELATION_NAME = \'' . $row['dname'] . '\') - ORDER BY 1,2'; - $result2 = $db->sql_query($sql); - $row2 = $db->sql_fetchrow($result2); - $db->sql_freeresult($result2); - $gen_name = $row2['gen']; - - $sql_data .= "\nDROP GENERATOR " . $gen_name . ";"; - $sql_data .= "\nSET TERM ^ ;"; - $sql_data .= "\nCREATE GENERATOR " . $gen_name . "^"; - $sql_data .= "\nSET GENERATOR " . $gen_name . " TO 0^\n"; - $sql_data .= "\nCREATE TRIGGER {$row['dname']} FOR $table_name"; - $sql_data .= "\nBEFORE INSERT\nAS\nBEGIN"; - $sql_data .= "\n NEW.{$row['fname']} = GEN_ID(" . $gen_name . ", 1);"; - $sql_data .= "\nEND^\n"; - $sql_data .= "\nSET TERM ; ^\n"; - } - - $this->flush($sql_data); - - $db->sql_freeresult($result); - } -} - // get how much space we allow for a chunk of data, very similar to phpMyAdmin's way of doing things ;-) (hey, we only do this for MySQL anyway :P) function get_usable_memory() { diff --git a/phpBB/includes/acp/acp_disallow.php b/phpBB/includes/acp/acp_disallow.php index f613fa325d..70eb398d07 100644 --- a/phpBB/includes/acp/acp_disallow.php +++ b/phpBB/includes/acp/acp_disallow.php @@ -1,9 +1,13 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -15,19 +19,13 @@ if (!defined('IN_PHPBB')) exit; } -/** -* @package acp -*/ class acp_disallow { var $u_action; function main($id, $mode) { - global $db, $user, $auth, $template, $cache; - global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; - - include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + global $db, $user, $template, $cache, $phpbb_log, $request; $user->add_lang('acp/posting'); @@ -48,7 +46,7 @@ class acp_disallow if ($disallow) { - $disallowed_user = str_replace('*', '%', utf8_normalize_nfc(request_var('disallowed_user', '', true))); + $disallowed_user = str_replace('*', '%', $request->variable('disallowed_user', '', true)); if (!$disallowed_user) { @@ -73,13 +71,13 @@ class acp_disallow $cache->destroy('_disallowed_usernames'); $message = $user->lang['DISALLOW_SUCCESSFUL']; - add_log('admin', 'LOG_DISALLOW_ADD', str_replace('%', '*', $disallowed_user)); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_DISALLOW_ADD', false, array(str_replace('%', '*', $disallowed_user))); trigger_error($message . adm_back_link($this->u_action)); } else if ($allow) { - $disallowed_id = request_var('disallowed_id', 0); + $disallowed_id = $request->variable('disallowed_id', 0); if (!$disallowed_id) { @@ -92,7 +90,7 @@ class acp_disallow $cache->destroy('_disallowed_usernames'); - add_log('admin', 'LOG_DISALLOW_DELETE'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_DISALLOW_DELETE'); trigger_error($user->lang['DISALLOWED_DELETED'] . adm_back_link($this->u_action)); } diff --git a/phpBB/includes/acp/acp_email.php b/phpBB/includes/acp/acp_email.php index c9d149b6d7..57eefad02d 100644 --- a/phpBB/includes/acp/acp_email.php +++ b/phpBB/includes/acp/acp_email.php @@ -1,9 +1,13 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -15,17 +19,14 @@ if (!defined('IN_PHPBB')) exit; } -/** -* @package acp -*/ class acp_email { var $u_action; function main($id, $mode) { - global $config, $db, $user, $auth, $template, $cache; - global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix; + global $config, $db, $user, $template, $phpbb_log, $request; + global $phpbb_root_path, $phpbb_admin_path, $phpEx, $phpbb_dispatcher; $user->add_lang('acp/email'); $this->tpl_name = 'acp_email'; @@ -38,10 +39,11 @@ class acp_email $submit = (isset($_POST['submit'])) ? true : false; $error = array(); - $usernames = request_var('usernames', '', true); - $group_id = request_var('g', 0); - $subject = utf8_normalize_nfc(request_var('subject', '', true)); - $message = utf8_normalize_nfc(request_var('message', '', true)); + $usernames = $request->variable('usernames', '', true); + $usernames = (!empty($usernames)) ? explode("\n", $usernames) : array(); + $group_id = $request->variable('g', 0); + $subject = $request->variable('subject', '', true); + $message = $request->variable('message', '', true); // Do the job ... if ($submit) @@ -49,7 +51,7 @@ class acp_email // Error checking needs to go here ... if no subject and/or no message then skip // over the send and return to the form $use_queue = (isset($_POST['send_immediately'])) ? false : true; - $priority = request_var('mail_priority_flag', MAIL_NORMAL_PRIORITY); + $priority = $request->variable('mail_priority_flag', MAIL_NORMAL_PRIORITY); if (!check_form_key($form_key)) { @@ -68,14 +70,18 @@ class acp_email if (!sizeof($error)) { - if ($usernames) + if (!empty($usernames)) { // If giving usernames the admin is able to email inactive users too... - $sql = 'SELECT username, user_email, user_jabber, user_notify_type, user_lang - FROM ' . USERS_TABLE . ' - WHERE ' . $db->sql_in_set('username_clean', array_map('utf8_clean_string', explode("\n", $usernames))) . ' - AND user_allow_massemail = 1 - ORDER BY user_lang, user_notify_type'; // , SUBSTRING(user_email FROM INSTR(user_email, '@')) + $sql_ary = array( + 'SELECT' => 'username, user_email, user_jabber, user_notify_type, user_lang', + 'FROM' => array( + USERS_TABLE => '', + ), + 'WHERE' => $db->sql_in_set('username_clean', array_map('utf8_clean_string', $usernames)) . ' + AND user_allow_massemail = 1', + 'ORDER_BY' => 'user_lang, user_notify_type', + ); } else { @@ -122,8 +128,18 @@ class acp_email ), ); } - $sql = $db->sql_build_query('SELECT', $sql_ary); } + /** + * Modify sql query to change the list of users the email is sent to + * + * @event core.acp_email_modify_sql + * @var array sql_ary Array which is used to build the sql query + * @since 3.1.2-RC1 + */ + $vars = array('sql_ary'); + extract($phpbb_dispatcher->trigger_event('core.acp_email_modify_sql', compact($vars))); + + $sql = $db->sql_build_query('SELECT', $sql_ary); $result = $db->sql_query($sql); $row = $db->sql_fetchrow($result); @@ -173,12 +189,52 @@ class acp_email $db->sql_freeresult($result); // Send the messages - include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); - include_once($phpbb_root_path . 'includes/functions_user.' . $phpEx); + if (!class_exists('messenger')) + { + include($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); + } + + if (!function_exists('get_group_name')) + { + include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + } $messenger = new messenger($use_queue); $errored = false; + $email_template = 'admin_send_email'; + $template_data = array( + 'CONTACT_EMAIL' => phpbb_get_board_contact($config, $phpEx), + 'MESSAGE' => htmlspecialchars_decode($message), + ); + $generate_log_entry = true; + + /** + * Modify email template data before the emails are sent + * + * @event core.acp_email_send_before + * @var string email_template The template to be used for sending the email + * @var string subject The subject of the email + * @var array template_data Array with template data assigned to email template + * @var bool generate_log_entry If false, no log entry will be created + * @var array usernames Usernames which will be displayed in log entry, if it will be created + * @var int group_id The group this email will be sent to + * @var bool use_queue If true, email queue will be used for sending + * @var int priority Priority of sent emails + * @since 3.1.3-RC1 + */ + $vars = array( + 'email_template', + 'subject', + 'template_data', + 'generate_log_entry', + 'usernames', + 'group_id', + 'use_queue', + 'priority', + ); + extract($phpbb_dispatcher->trigger_event('core.acp_email_send_before', compact($vars))); + for ($i = 0, $size = sizeof($email_list); $i < $size; $i++) { $used_lang = $email_list[$i][0]['lang']; @@ -192,17 +248,14 @@ class acp_email $messenger->im($email_row['jabber'], $email_row['name']); } - $messenger->template('admin_send_email', $used_lang); + $messenger->template($email_template, $used_lang); $messenger->anti_abuse_headers($config, $user); $messenger->subject(htmlspecialchars_decode($subject)); $messenger->set_mail_priority($priority); - $messenger->assign_vars(array( - 'CONTACT_EMAIL' => $config['board_contact'], - 'MESSAGE' => htmlspecialchars_decode($message)) - ); + $messenger->assign_vars($template_data); if (!($messenger->send($used_method))) { @@ -213,24 +266,26 @@ class acp_email $messenger->save_queue(); - if ($usernames) - { - $usernames = explode("\n", $usernames); - add_log('admin', 'LOG_MASS_EMAIL', implode(', ', utf8_normalize_nfc($usernames))); - } - else + if ($generate_log_entry) { - if ($group_id) + if (!empty($usernames)) { - $group_name = get_group_name($group_id); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MASS_EMAIL', false, array(implode(', ', utf8_normalize_nfc($usernames)))); } else { - // Not great but the logging routine doesn't cope well with localising on the fly - $group_name = $user->lang['ALL_USERS']; - } + if ($group_id) + { + $group_name = get_group_name($group_id); + } + else + { + // Not great but the logging routine doesn't cope well with localising on the fly + $group_name = $user->lang['ALL_USERS']; + } - add_log('admin', 'LOG_MASS_EMAIL', $group_name); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MASS_EMAIL', false, array($group_name)); + } } if (!$errored) @@ -266,17 +321,31 @@ class acp_email $s_priority_options .= '<option value="' . MAIL_NORMAL_PRIORITY . '" selected="selected">' . $user->lang['MAIL_NORMAL_PRIORITY'] . '</option>'; $s_priority_options .= '<option value="' . MAIL_HIGH_PRIORITY . '">' . $user->lang['MAIL_HIGH_PRIORITY'] . '</option>'; - $template->assign_vars(array( + $template_data = array( 'S_WARNING' => (sizeof($error)) ? true : false, 'WARNING_MSG' => (sizeof($error)) ? implode('<br />', $error) : '', 'U_ACTION' => $this->u_action, 'S_GROUP_OPTIONS' => $select_list, - 'USERNAMES' => $usernames, + 'USERNAMES' => implode("\n", $usernames), 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=acp_email&field=usernames'), 'SUBJECT' => $subject, 'MESSAGE' => $message, - 'S_PRIORITY_OPTIONS' => $s_priority_options) + 'S_PRIORITY_OPTIONS' => $s_priority_options, ); + /** + * Modify custom email template data before we display the form + * + * @event core.acp_email_display + * @var array template_data Array with template data assigned to email template + * @var array exclude Array with groups which are excluded from group selection + * @var array usernames Usernames which will be displayed in form + * + * @since 3.1.4-RC1 + */ + $vars = array('template_data', 'exclude', 'usernames'); + extract($phpbb_dispatcher->trigger_event('core.acp_email_display', compact($vars))); + + $template->assign_vars($template_data); } } diff --git a/phpBB/includes/acp/acp_extensions.php b/phpBB/includes/acp/acp_extensions.php index 2ff479d824..9fbf2f20f1 100644 --- a/phpBB/includes/acp/acp_extensions.php +++ b/phpBB/includes/acp/acp_extensions.php @@ -1,9 +1,13 @@ <?php /** * -* @package acp -* @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -15,9 +19,6 @@ if (!defined('IN_PHPBB')) exit; } -/** -* @package acp -*/ class acp_extensions { var $u_action; @@ -26,16 +27,22 @@ class acp_extensions private $config; private $template; private $user; + private $cache; + private $log; + private $request; function main() { // Start the page - global $config, $user, $template, $request, $phpbb_extension_manager, $db, $phpbb_root_path, $phpEx; + global $config, $user, $template, $request, $phpbb_extension_manager, $db, $phpbb_root_path, $phpbb_log, $cache; $this->db = $db; $this->config = $config; $this->template = $template; $this->user = $user; + $this->cache = $cache; + $this->request = $request; + $this->log = $phpbb_log; $user->add_lang(array('install', 'acp/extensions', 'migrator')); @@ -69,21 +76,52 @@ class acp_extensions { $md_manager->get_metadata('all'); } - catch(\phpbb\extension\exception $e) + catch (\phpbb\extension\exception $e) { - trigger_error($e, E_USER_WARNING); + $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); + trigger_error($message, E_USER_WARNING); } } // What are we doing? switch ($action) { + case 'set_config_version_check_force_unstable': + $force_unstable = $this->request->variable('force_unstable', false); + + if ($force_unstable) + { + $s_hidden_fields = build_hidden_fields(array( + 'force_unstable' => $force_unstable, + )); + + confirm_box(false, $user->lang('EXTENSION_FORCE_UNSTABLE_CONFIRM'), $s_hidden_fields); + } + else + { + $config->set('extension_force_unstable', false); + trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action)); + } + break; + case 'list': default: + if (confirm_box(true)) + { + $config->set('extension_force_unstable', true); + trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action)); + } + $this->list_enabled_exts($phpbb_extension_manager); $this->list_disabled_exts($phpbb_extension_manager); $this->list_available_exts($phpbb_extension_manager); + $this->template->assign_vars(array( + 'U_VERSIONCHECK_FORCE' => $this->u_action . '&action=list&versioncheck_force=1', + 'FORCE_UNSTABLE' => $config['extension_force_unstable'], + 'U_ACTION' => $this->u_action, + )); + $this->tpl_name = 'acp_ext_list'; break; @@ -98,7 +136,13 @@ class acp_extensions trigger_error($user->lang['EXTENSION_NOT_AVAILABLE'] . adm_back_link($this->u_action), E_USER_WARNING); } - if ($phpbb_extension_manager->enabled($ext_name)) + $extension = $phpbb_extension_manager->get_extension($ext_name); + if (!$extension->is_enableable()) + { + trigger_error($user->lang['EXTENSION_NOT_ENABLEABLE'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if ($phpbb_extension_manager->is_enabled($ext_name)) { redirect($this->u_action); } @@ -123,6 +167,12 @@ class acp_extensions trigger_error($user->lang['EXTENSION_NOT_AVAILABLE'] . adm_back_link($this->u_action), E_USER_WARNING); } + $extension = $phpbb_extension_manager->get_extension($ext_name); + if (!$extension->is_enableable()) + { + trigger_error($user->lang['EXTENSION_NOT_ENABLEABLE'] . adm_back_link($this->u_action), E_USER_WARNING); + } + try { while ($phpbb_extension_manager->enable_step($ext_name)) @@ -135,6 +185,7 @@ class acp_extensions meta_refresh(0, $this->u_action . '&action=enable&ext_name=' . urlencode($ext_name) . '&hash=' . generate_link_hash('enable.' . $ext_name)); } } + $this->log->add('admin', $user->data['user_id'], $user->ip, 'LOG_EXT_ENABLE', time(), array($ext_name)); } catch (\phpbb\db\migration\exception $e) { @@ -149,7 +200,7 @@ class acp_extensions break; case 'disable_pre': - if (!$phpbb_extension_manager->enabled($ext_name)) + if (!$phpbb_extension_manager->is_enabled($ext_name)) { redirect($this->u_action); } @@ -164,6 +215,11 @@ class acp_extensions break; case 'disable': + if (!$phpbb_extension_manager->is_enabled($ext_name)) + { + redirect($this->u_action); + } + while ($phpbb_extension_manager->disable_step($ext_name)) { // Are we approaching the time limit? If so we want to pause the update and continue after refreshing @@ -174,6 +230,7 @@ class acp_extensions meta_refresh(0, $this->u_action . '&action=disable&ext_name=' . urlencode($ext_name) . '&hash=' . generate_link_hash('disable.' . $ext_name)); } } + $this->log->add('admin', $user->data['user_id'], $user->ip, 'LOG_EXT_DISABLE', time(), array($ext_name)); $this->tpl_name = 'acp_ext_disable'; @@ -183,7 +240,7 @@ class acp_extensions break; case 'delete_data_pre': - if ($phpbb_extension_manager->enabled($ext_name)) + if ($phpbb_extension_manager->is_enabled($ext_name)) { redirect($this->u_action); } @@ -197,6 +254,11 @@ class acp_extensions break; case 'delete_data': + if ($phpbb_extension_manager->is_enabled($ext_name)) + { + redirect($this->u_action); + } + try { while ($phpbb_extension_manager->purge_step($ext_name)) @@ -209,6 +271,7 @@ class acp_extensions meta_refresh(0, $this->u_action . '&action=delete_data&ext_name=' . urlencode($ext_name) . '&hash=' . generate_link_hash('delete_data.' . $ext_name)); } } + $this->log->add('admin', $user->data['user_id'], $user->ip, 'LOG_EXT_PURGE', time(), array($ext_name)); } catch (\phpbb\db\migration\exception $e) { @@ -226,7 +289,33 @@ class acp_extensions // Output it to the template $md_manager->output_template_data(); - $template->assign_var('U_BACK', $this->u_action . '&action=list'); + try + { + $updates_available = $this->version_check($md_manager, $request->variable('versioncheck_force', false)); + + $template->assign_vars(array( + 'S_UP_TO_DATE' => empty($updates_available), + 'S_VERSIONCHECK' => true, + 'UP_TO_DATE_MSG' => $this->user->lang(empty($updates_available) ? 'UP_TO_DATE' : 'NOT_UP_TO_DATE', $md_manager->get_metadata('display-name')), + )); + + foreach ($updates_available as $branch => $version_data) + { + $template->assign_block_vars('updates_available', $version_data); + } + } + catch (\RuntimeException $e) + { + $template->assign_vars(array( + 'S_VERSIONCHECK_STATUS' => $e->getCode(), + 'VERSIONCHECK_FAIL_REASON' => ($e->getMessage() !== $user->lang('VERSIONCHECK_FAIL')) ? $e->getMessage() : '', + )); + } + + $template->assign_vars(array( + 'U_BACK' => $this->u_action . '&action=list', + 'U_VERSIONCHECK_FORCE' => $this->u_action . '&action=details&versioncheck_force=1&ext_name=' . urlencode($md_manager->get_metadata('name')), + )); $this->tpl_name = 'acp_ext_details'; break; @@ -234,104 +323,179 @@ class acp_extensions } /** - * Lists all the enabled extensions and dumps to the template - * - * @param $phpbb_extension_manager An instance of the extension manager - * @return null - */ + * Lists all the enabled extensions and dumps to the template + * + * @param $phpbb_extension_manager An instance of the extension manager + * @return null + */ public function list_enabled_exts(\phpbb\extension\manager $phpbb_extension_manager) { + $enabled_extension_meta_data = array(); + foreach ($phpbb_extension_manager->all_enabled() as $name => $location) { $md_manager = $phpbb_extension_manager->create_extension_metadata_manager($name, $this->template); try { - $this->template->assign_block_vars('enabled', array( - 'META_DISPLAY_NAME' => $md_manager->get_metadata('display-name'), - - 'U_DETAILS' => $this->u_action . '&action=details&ext_name=' . urlencode($name), - )); - - $this->output_actions('enabled', array( - 'DISABLE' => $this->u_action . '&action=disable_pre&ext_name=' . urlencode($name), - )); + $meta = $md_manager->get_metadata('all'); + $enabled_extension_meta_data[$name] = array( + 'META_DISPLAY_NAME' => $md_manager->get_metadata('display-name'), + 'META_VERSION' => $meta['version'], + ); + + $force_update = $this->request->variable('versioncheck_force', false); + $updates = $this->version_check($md_manager, $force_update, !$force_update); + + $enabled_extension_meta_data[$name]['S_UP_TO_DATE'] = empty($updates); + $enabled_extension_meta_data[$name]['S_VERSIONCHECK'] = true; + $enabled_extension_meta_data[$name]['U_VERSIONCHECK_FORCE'] = $this->u_action . '&action=details&versioncheck_force=1&ext_name=' . urlencode($md_manager->get_metadata('name')); } - catch(\phpbb\extension\exception $e) + catch (\phpbb\extension\exception $e) { + $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); $this->template->assign_block_vars('disabled', array( - 'META_DISPLAY_NAME' => $this->user->lang('EXTENSION_INVALID_LIST', $name, $e), + 'META_DISPLAY_NAME' => $this->user->lang('EXTENSION_INVALID_LIST', $name, $message), + 'S_VERSIONCHECK' => false, )); } + catch (\RuntimeException $e) + { + $enabled_extension_meta_data[$name]['S_VERSIONCHECK'] = false; + } + } + + uasort($enabled_extension_meta_data, array($this, 'sort_extension_meta_data_table')); + + foreach ($enabled_extension_meta_data as $name => $block_vars) + { + $block_vars['NAME'] = $name; + $block_vars['U_DETAILS'] = $this->u_action . '&action=details&ext_name=' . urlencode($name); + + $this->template->assign_block_vars('enabled', $block_vars); + + $this->output_actions('enabled', array( + 'DISABLE' => $this->u_action . '&action=disable_pre&ext_name=' . urlencode($name), + )); } } /** - * Lists all the disabled extensions and dumps to the template - * - * @param $phpbb_extension_manager An instance of the extension manager - * @return null - */ + * Lists all the disabled extensions and dumps to the template + * + * @param $phpbb_extension_manager An instance of the extension manager + * @return null + */ public function list_disabled_exts(\phpbb\extension\manager $phpbb_extension_manager) { + $disabled_extension_meta_data = array(); + foreach ($phpbb_extension_manager->all_disabled() as $name => $location) { $md_manager = $phpbb_extension_manager->create_extension_metadata_manager($name, $this->template); try { - $this->template->assign_block_vars('disabled', array( - 'META_DISPLAY_NAME' => $md_manager->get_metadata('display-name'), - - 'U_DETAILS' => $this->u_action . '&action=details&ext_name=' . urlencode($name), - )); - - $this->output_actions('disabled', array( - 'ENABLE' => $this->u_action . '&action=enable_pre&ext_name=' . urlencode($name), - 'DELETE_DATA' => $this->u_action . '&action=delete_data_pre&ext_name=' . urlencode($name), - )); + $meta = $md_manager->get_metadata('all'); + $disabled_extension_meta_data[$name] = array( + 'META_DISPLAY_NAME' => $md_manager->get_metadata('display-name'), + 'META_VERSION' => $meta['version'], + ); + + $force_update = $this->request->variable('versioncheck_force', false); + $updates = $this->version_check($md_manager, $force_update, !$force_update); + + $disabled_extension_meta_data[$name]['S_UP_TO_DATE'] = empty($updates); + $disabled_extension_meta_data[$name]['S_VERSIONCHECK'] = true; + $disabled_extension_meta_data[$name]['U_VERSIONCHECK_FORCE'] = $this->u_action . '&action=details&versioncheck_force=1&ext_name=' . urlencode($md_manager->get_metadata('name')); } - catch(\phpbb\extension\exception $e) + catch (\phpbb\extension\exception $e) { + $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); $this->template->assign_block_vars('disabled', array( - 'META_DISPLAY_NAME' => $this->user->lang('EXTENSION_INVALID_LIST', $name, $e), + 'META_DISPLAY_NAME' => $this->user->lang('EXTENSION_INVALID_LIST', $name, $message), + 'S_VERSIONCHECK' => false, )); } + catch (\RuntimeException $e) + { + $disabeld_extension_meta_data[$name]['S_VERSIONCHECK'] = false; + } + } + + uasort($disabled_extension_meta_data, array($this, 'sort_extension_meta_data_table')); + + foreach ($disabled_extension_meta_data as $name => $block_vars) + { + $block_vars['NAME'] = $name; + $block_vars['U_DETAILS'] = $this->u_action . '&action=details&ext_name=' . urlencode($name); + + $this->template->assign_block_vars('disabled', $block_vars); + + $this->output_actions('disabled', array( + 'ENABLE' => $this->u_action . '&action=enable_pre&ext_name=' . urlencode($name), + 'DELETE_DATA' => $this->u_action . '&action=delete_data_pre&ext_name=' . urlencode($name), + )); } } /** - * Lists all the available extensions and dumps to the template - * - * @param $phpbb_extension_manager An instance of the extension manager - * @return null - */ + * Lists all the available extensions and dumps to the template + * + * @param $phpbb_extension_manager An instance of the extension manager + * @return null + */ public function list_available_exts(\phpbb\extension\manager $phpbb_extension_manager) { $uninstalled = array_diff_key($phpbb_extension_manager->all_available(), $phpbb_extension_manager->all_configured()); + $available_extension_meta_data = array(); + foreach ($uninstalled as $name => $location) { $md_manager = $phpbb_extension_manager->create_extension_metadata_manager($name, $this->template); try { - $this->template->assign_block_vars('disabled', array( - 'META_DISPLAY_NAME' => $md_manager->get_metadata('display-name'), - - 'U_DETAILS' => $this->u_action . '&action=details&ext_name=' . urlencode($name), - )); - - $this->output_actions('disabled', array( - 'ENABLE' => $this->u_action . '&action=enable_pre&ext_name=' . urlencode($name), - )); + $meta = $md_manager->get_metadata('all'); + $available_extension_meta_data[$name] = array( + 'META_DISPLAY_NAME' => $md_manager->get_metadata('display-name'), + 'META_VERSION' => $meta['version'], + ); + + $force_update = $this->request->variable('versioncheck_force', false); + $updates = $this->version_check($md_manager, $force_update, !$force_update); + + $available_extension_meta_data[$name]['S_UP_TO_DATE'] = empty($updates); + $available_extension_meta_data[$name]['S_VERSIONCHECK'] = true; + $available_extension_meta_data[$name]['U_VERSIONCHECK_FORCE'] = $this->u_action . '&action=details&versioncheck_force=1&ext_name=' . urlencode($md_manager->get_metadata('name')); } - catch(\phpbb\extension\exception $e) + catch (\phpbb\extension\exception $e) { + $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); $this->template->assign_block_vars('disabled', array( - 'META_DISPLAY_NAME' => $this->user->lang('EXTENSION_INVALID_LIST', $name, $e), + 'META_DISPLAY_NAME' => $this->user->lang('EXTENSION_INVALID_LIST', $name, $message), + 'S_VERSIONCHECK' => false, )); } + catch (\RuntimeException $e) + { + $available_extension_meta_data[$name]['S_VERSIONCHECK'] = false; + } + } + + uasort($available_extension_meta_data, array($this, 'sort_extension_meta_data_table')); + + foreach ($available_extension_meta_data as $name => $block_vars) + { + $block_vars['NAME'] = $name; + $block_vars['U_DETAILS'] = $this->u_action . '&action=details&ext_name=' . urlencode($name); + + $this->template->assign_block_vars('disabled', $block_vars); + + $this->output_actions('disabled', array( + 'ENABLE' => $this->u_action . '&action=enable_pre&ext_name=' . urlencode($name), + )); } } @@ -352,4 +516,40 @@ class acp_extensions )); } } + + /** + * Check the version and return the available updates. + * + * @param \phpbb\extension\metadata_manager $md_manager The metadata manager for the version to check. + * @param bool $force_update Ignores cached data. Defaults to false. + * @param bool $force_cache Force the use of the cache. Override $force_update. + * @return string + * @throws RuntimeException + */ + protected function version_check(\phpbb\extension\metadata_manager $md_manager, $force_update = false, $force_cache = false) + { + $meta = $md_manager->get_metadata('all'); + + if (!isset($meta['extra']['version-check'])) + { + throw new \RuntimeException($this->user->lang('NO_VERSIONCHECK'), 1); + } + + $version_check = $meta['extra']['version-check']; + + $version_helper = new \phpbb\version_helper($this->cache, $this->config, new \phpbb\file_downloader(), $this->user); + $version_helper->set_current_version($meta['version']); + $version_helper->set_file_location($version_check['host'], $version_check['directory'], $version_check['filename'], isset($version_check['ssl']) ? $version_check['ssl'] : false); + $version_helper->force_stability($this->config['extension_force_unstable'] ? 'unstable' : null); + + return $updates = $version_helper->get_suggested_updates($force_update, $force_cache); + } + + /** + * Sort helper for the table containing the metadata about the extensions. + */ + protected function sort_extension_meta_data_table($val1, $val2) + { + return strnatcasecmp($val1['META_DISPLAY_NAME'], $val2['META_DISPLAY_NAME']); + } } diff --git a/phpBB/includes/acp/acp_forums.php b/phpBB/includes/acp/acp_forums.php index a1af8c489d..c5d2d0ea09 100644 --- a/phpBB/includes/acp/acp_forums.php +++ b/phpBB/includes/acp/acp_forums.php @@ -1,9 +1,13 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -15,9 +19,6 @@ if (!defined('IN_PHPBB')) exit; } -/** -* @package acp -*/ class acp_forums { var $u_action; @@ -26,7 +27,7 @@ class acp_forums function main($id, $mode) { global $db, $user, $auth, $template, $cache, $request, $phpbb_dispatcher; - global $config, $phpbb_admin_path, $phpbb_root_path, $phpEx; + global $phpbb_admin_path, $phpbb_root_path, $phpEx, $phpbb_log; $user->add_lang('acp/forums'); $this->tpl_name = 'acp_forums'; @@ -35,11 +36,11 @@ class acp_forums $form_key = 'acp_forums'; add_form_key($form_key); - $action = request_var('action', ''); + $action = $request->variable('action', ''); $update = (isset($_POST['update'])) ? true : false; - $forum_id = request_var('f', 0); + $forum_id = $request->variable('f', 0); - $this->parent_id = request_var('parent_id', 0); + $this->parent_id = $request->variable('parent_id', 0); $forum_data = $errors = array(); if ($update && !check_form_key($form_key)) { @@ -51,8 +52,8 @@ class acp_forums switch ($action) { case 'progress_bar': - $start = request_var('start', 0); - $total = request_var('total', 0); + $start = $request->variable('start', 0); + $total = $request->variable('total', 0); $this->display_progress_bar($start, $total); break; @@ -82,10 +83,10 @@ class acp_forums switch ($action) { case 'delete': - $action_subforums = request_var('action_subforums', ''); - $subforums_to_id = request_var('subforums_to_id', 0); - $action_posts = request_var('action_posts', ''); - $posts_to_id = request_var('posts_to_id', 0); + $action_subforums = $request->variable('action_subforums', ''); + $subforums_to_id = $request->variable('subforums_to_id', 0); + $action_posts = $request->variable('action_posts', ''); + $posts_to_id = $request->variable('posts_to_id', 0); $errors = $this->delete_forum($forum_id, $action_posts, $action_subforums, $posts_to_id, $subforums_to_id); @@ -111,42 +112,45 @@ class acp_forums case 'add': $forum_data += array( - 'parent_id' => request_var('forum_parent_id', $this->parent_id), - 'forum_type' => request_var('forum_type', FORUM_POST), - 'type_action' => request_var('type_action', ''), - 'forum_status' => request_var('forum_status', ITEM_UNLOCKED), + 'parent_id' => $request->variable('forum_parent_id', $this->parent_id), + 'forum_type' => $request->variable('forum_type', FORUM_POST), + 'type_action' => $request->variable('type_action', ''), + 'forum_status' => $request->variable('forum_status', ITEM_UNLOCKED), 'forum_parents' => '', - 'forum_name' => utf8_normalize_nfc(request_var('forum_name', '', true)), - 'forum_link' => request_var('forum_link', ''), - 'forum_link_track' => request_var('forum_link_track', false), - 'forum_desc' => utf8_normalize_nfc(request_var('forum_desc', '', true)), + 'forum_name' => $request->variable('forum_name', '', true), + 'forum_link' => $request->variable('forum_link', ''), + 'forum_link_track' => $request->variable('forum_link_track', false), + 'forum_desc' => $request->variable('forum_desc', '', true), 'forum_desc_uid' => '', 'forum_desc_options' => 7, 'forum_desc_bitfield' => '', - 'forum_rules' => utf8_normalize_nfc(request_var('forum_rules', '', true)), + 'forum_rules' => $request->variable('forum_rules', '', true), 'forum_rules_uid' => '', 'forum_rules_options' => 7, 'forum_rules_bitfield' => '', - 'forum_rules_link' => request_var('forum_rules_link', ''), - 'forum_image' => request_var('forum_image', ''), - 'forum_style' => request_var('forum_style', 0), - 'display_subforum_list' => request_var('display_subforum_list', false), - 'display_on_index' => request_var('display_on_index', false), - 'forum_topics_per_page' => request_var('topics_per_page', 0), - 'enable_indexing' => request_var('enable_indexing', true), - 'enable_icons' => request_var('enable_icons', false), - 'enable_prune' => request_var('enable_prune', false), - 'enable_post_review' => request_var('enable_post_review', true), - 'enable_quick_reply' => request_var('enable_quick_reply', false), - 'prune_days' => request_var('prune_days', 7), - 'prune_viewed' => request_var('prune_viewed', 7), - 'prune_freq' => request_var('prune_freq', 1), - 'prune_old_polls' => request_var('prune_old_polls', false), - 'prune_announce' => request_var('prune_announce', false), - 'prune_sticky' => request_var('prune_sticky', false), - 'forum_password' => request_var('forum_password', '', true), - 'forum_password_confirm'=> request_var('forum_password_confirm', '', true), - 'forum_password_unset' => request_var('forum_password_unset', false), + 'forum_rules_link' => $request->variable('forum_rules_link', ''), + 'forum_image' => $request->variable('forum_image', ''), + 'forum_style' => $request->variable('forum_style', 0), + 'display_subforum_list' => $request->variable('display_subforum_list', false), + 'display_on_index' => $request->variable('display_on_index', false), + 'forum_topics_per_page' => $request->variable('topics_per_page', 0), + 'enable_indexing' => $request->variable('enable_indexing', true), + 'enable_icons' => $request->variable('enable_icons', false), + 'enable_prune' => $request->variable('enable_prune', false), + 'enable_post_review' => $request->variable('enable_post_review', true), + 'enable_quick_reply' => $request->variable('enable_quick_reply', false), + 'enable_shadow_prune' => $request->variable('enable_shadow_prune', false), + 'prune_days' => $request->variable('prune_days', 7), + 'prune_viewed' => $request->variable('prune_viewed', 7), + 'prune_freq' => $request->variable('prune_freq', 1), + 'prune_old_polls' => $request->variable('prune_old_polls', false), + 'prune_announce' => $request->variable('prune_announce', false), + 'prune_sticky' => $request->variable('prune_sticky', false), + 'prune_shadow_days' => $request->variable('prune_shadow_days', 7), + 'prune_shadow_freq' => $request->variable('prune_shadow_freq', 1), + 'forum_password' => $request->variable('forum_password', '', true), + 'forum_password_confirm'=> $request->variable('forum_password_confirm', '', true), + 'forum_password_unset' => $request->variable('forum_password_unset', false), ); /** @@ -155,7 +159,7 @@ class acp_forums * @event core.acp_manage_forums_request_data * @var string action Type of the action: add|edit * @var array forum_data Array with new forum data - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('action', 'forum_data'); extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_request_data', compact($vars))); @@ -169,7 +173,7 @@ class acp_forums // Use link_display_on_index setting if forum type is link if ($forum_data['forum_type'] == FORUM_LINK) { - $forum_data['display_on_index'] = request_var('link_display_on_index', false); + $forum_data['display_on_index'] = $request->variable('link_display_on_index', false); } // Linked forums and categories are not able to be locked... @@ -178,25 +182,25 @@ class acp_forums $forum_data['forum_status'] = ITEM_UNLOCKED; } - $forum_data['show_active'] = ($forum_data['forum_type'] == FORUM_POST) ? request_var('display_recent', true) : request_var('display_active', false); + $forum_data['show_active'] = ($forum_data['forum_type'] == FORUM_POST) ? $request->variable('display_recent', true) : $request->variable('display_active', false); // Get data for forum rules if specified... if ($forum_data['forum_rules']) { - generate_text_for_storage($forum_data['forum_rules'], $forum_data['forum_rules_uid'], $forum_data['forum_rules_bitfield'], $forum_data['forum_rules_options'], request_var('rules_parse_bbcode', false), request_var('rules_parse_urls', false), request_var('rules_parse_smilies', false)); + generate_text_for_storage($forum_data['forum_rules'], $forum_data['forum_rules_uid'], $forum_data['forum_rules_bitfield'], $forum_data['forum_rules_options'], $request->variable('rules_parse_bbcode', false), $request->variable('rules_parse_urls', false), $request->variable('rules_parse_smilies', false)); } // Get data for forum description if specified if ($forum_data['forum_desc']) { - generate_text_for_storage($forum_data['forum_desc'], $forum_data['forum_desc_uid'], $forum_data['forum_desc_bitfield'], $forum_data['forum_desc_options'], request_var('desc_parse_bbcode', false), request_var('desc_parse_urls', false), request_var('desc_parse_smilies', false)); + generate_text_for_storage($forum_data['forum_desc'], $forum_data['forum_desc_uid'], $forum_data['forum_desc_bitfield'], $forum_data['forum_desc_options'], $request->variable('desc_parse_bbcode', false), $request->variable('desc_parse_urls', false), $request->variable('desc_parse_smilies', false)); } $errors = $this->update_forum_data($forum_data); if (!sizeof($errors)) { - $forum_perm_from = request_var('forum_perm_from', 0); + $forum_perm_from = $request->variable('forum_perm_from', 0); $cache->destroy('sql', FORUMS_TABLE); $copied_permissions = false; @@ -262,7 +266,7 @@ class acp_forums if ($move_forum_name !== false) { - add_log('admin', 'LOG_FORUM_' . strtoupper($action), $row['forum_name'], $move_forum_name); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_' . strtoupper($action), false, array($row['forum_name'], $move_forum_name)); $cache->destroy('sql', FORUMS_TABLE); } @@ -307,7 +311,7 @@ class acp_forums $row2['min_topic_id'] = (int) $row2['min_topic_id']; $row2['max_topic_id'] = (int) $row2['max_topic_id']; - $start = request_var('start', $row2['min_topic_id']); + $start = $request->variable('start', $row2['min_topic_id']); $batch_size = 2000; $end = $start + $batch_size; @@ -323,7 +327,7 @@ class acp_forums WHERE forum_id = ' . $forum_id . ' AND topic_id BETWEEN ' . $start . ' AND ' . $end; $result = $db->sql_query($sql); - $topics_done = request_var('topics_done', 0) + (int) $db->sql_fetchfield('num_topics'); + $topics_done = $request->variable('topics_done', 0) + (int) $db->sql_fetchfield('num_topics'); $db->sql_freeresult($result); $start += $batch_size; @@ -373,7 +377,8 @@ class acp_forums sync('forum', 'forum_id', $forum_id, false, true); - add_log('admin', 'LOG_FORUM_SYNC', $row['forum_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_SYNC', false, array($row['forum_name'])); + $cache->destroy('sql', FORUMS_TABLE); $template->assign_var('L_FORUM_RESYNCED', sprintf($user->lang['FORUM_RESYNCED'], $row['forum_name'])); @@ -386,13 +391,13 @@ class acp_forums if ($update) { $forum_data['forum_flags'] = 0; - $forum_data['forum_flags'] += (request_var('forum_link_track', false)) ? FORUM_FLAG_LINK_TRACK : 0; - $forum_data['forum_flags'] += (request_var('prune_old_polls', false)) ? FORUM_FLAG_PRUNE_POLL : 0; - $forum_data['forum_flags'] += (request_var('prune_announce', false)) ? FORUM_FLAG_PRUNE_ANNOUNCE : 0; - $forum_data['forum_flags'] += (request_var('prune_sticky', false)) ? FORUM_FLAG_PRUNE_STICKY : 0; + $forum_data['forum_flags'] += ($request->variable('forum_link_track', false)) ? FORUM_FLAG_LINK_TRACK : 0; + $forum_data['forum_flags'] += ($request->variable('prune_old_polls', false)) ? FORUM_FLAG_PRUNE_POLL : 0; + $forum_data['forum_flags'] += ($request->variable('prune_announce', false)) ? FORUM_FLAG_PRUNE_ANNOUNCE : 0; + $forum_data['forum_flags'] += ($request->variable('prune_sticky', false)) ? FORUM_FLAG_PRUNE_STICKY : 0; $forum_data['forum_flags'] += ($forum_data['show_active']) ? FORUM_FLAG_ACTIVE_TOPICS : 0; - $forum_data['forum_flags'] += (request_var('enable_post_review', true)) ? FORUM_FLAG_POST_REVIEW : 0; - $forum_data['forum_flags'] += (request_var('enable_quick_reply', false)) ? FORUM_FLAG_QUICK_REPLY : 0; + $forum_data['forum_flags'] += ($request->variable('enable_post_review', true)) ? FORUM_FLAG_POST_REVIEW : 0; + $forum_data['forum_flags'] += ($request->variable('enable_quick_reply', false)) ? FORUM_FLAG_QUICK_REPLY : 0; } // Initialise $row, so we always have it in the event @@ -440,7 +445,7 @@ class acp_forums 'parent_id' => $this->parent_id, 'forum_type' => FORUM_POST, 'forum_status' => ITEM_UNLOCKED, - 'forum_name' => utf8_normalize_nfc(request_var('forum_name', '', true)), + 'forum_name' => $request->variable('forum_name', '', true), 'forum_link' => '', 'forum_link_track' => false, 'forum_desc' => '', @@ -457,6 +462,9 @@ class acp_forums 'prune_days' => 7, 'prune_viewed' => 7, 'prune_freq' => 1, + 'enable_shadow_prune' => false, + 'prune_shadow_days' => 7, + 'prune_shadow_freq' => 1, 'forum_flags' => FORUM_FLAG_POST_REVIEW + FORUM_FLAG_ACTIVE_TOPICS, 'forum_options' => 0, 'forum_password' => '', @@ -478,7 +486,7 @@ class acp_forums * empty when creating new forum * @var array forum_data Array with new forum data * @var string parents_list List of parent options - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('action', 'update', 'forum_id', 'row', 'forum_data', 'parents_list'); extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_initialise_data', compact($vars))); @@ -504,12 +512,12 @@ class acp_forums { if (!isset($forum_data['forum_rules_uid'])) { - // Before we are able to display the preview and plane text, we need to parse our request_var()'d value... + // Before we are able to display the preview and plane text, we need to parse our $request->variable()'d value... $forum_data['forum_rules_uid'] = ''; $forum_data['forum_rules_bitfield'] = ''; $forum_data['forum_rules_options'] = 0; - generate_text_for_storage($forum_data['forum_rules'], $forum_data['forum_rules_uid'], $forum_data['forum_rules_bitfield'], $forum_data['forum_rules_options'], request_var('rules_allow_bbcode', false), request_var('rules_allow_urls', false), request_var('rules_allow_smilies', false)); + generate_text_for_storage($forum_data['forum_rules'], $forum_data['forum_rules_uid'], $forum_data['forum_rules_bitfield'], $forum_data['forum_rules_options'], $request->variable('rules_allow_bbcode', false), $request->variable('rules_allow_urls', false), $request->variable('rules_allow_smilies', false)); } // Generate preview content @@ -524,12 +532,12 @@ class acp_forums { if (!isset($forum_data['forum_desc_uid'])) { - // Before we are able to display the preview and plane text, we need to parse our request_var()'d value... + // Before we are able to display the preview and plane text, we need to parse our $request->variable()'d value... $forum_data['forum_desc_uid'] = ''; $forum_data['forum_desc_bitfield'] = ''; $forum_data['forum_desc_options'] = 0; - generate_text_for_storage($forum_data['forum_desc'], $forum_data['forum_desc_uid'], $forum_data['forum_desc_bitfield'], $forum_data['forum_desc_options'], request_var('desc_allow_bbcode', false), request_var('desc_allow_urls', false), request_var('desc_allow_smilies', false)); + generate_text_for_storage($forum_data['forum_desc'], $forum_data['forum_desc_uid'], $forum_data['forum_desc_bitfield'], $forum_data['forum_desc_options'], $request->variable('desc_allow_bbcode', false), $request->variable('desc_allow_urls', false), $request->variable('desc_allow_smilies', false)); } // decode... @@ -636,6 +644,8 @@ class acp_forums 'PRUNE_FREQ' => $forum_data['prune_freq'], 'PRUNE_DAYS' => $forum_data['prune_days'], 'PRUNE_VIEWED' => $forum_data['prune_viewed'], + 'PRUNE_SHADOW_FREQ' => $forum_data['prune_shadow_freq'], + 'PRUNE_SHADOW_DAYS' => $forum_data['prune_shadow_days'], 'TOPICS_PER_PAGE' => $forum_data['forum_topics_per_page'], 'FORUM_RULES_LINK' => $forum_data['forum_rules_link'], 'FORUM_RULES' => $forum_data['forum_rules'], @@ -668,6 +678,7 @@ class acp_forums 'S_DISPLAY_SUBFORUM_LIST' => ($forum_data['display_subforum_list']) ? true : false, 'S_DISPLAY_ON_INDEX' => ($forum_data['display_on_index']) ? true : false, 'S_PRUNE_ENABLE' => ($forum_data['enable_prune']) ? true : false, + 'S_PRUNE_SHADOW_ENABLE' => ($forum_data['enable_shadow_prune']) ? true : false, 'S_FORUM_LINK_TRACK' => ($forum_data['forum_flags'] & FORUM_FLAG_LINK_TRACK) ? true : false, 'S_PRUNE_OLD_POLLS' => ($forum_data['forum_flags'] & FORUM_FLAG_PRUNE_POLL) ? true : false, 'S_PRUNE_ANNOUNCE' => ($forum_data['forum_flags'] & FORUM_FLAG_PRUNE_ANNOUNCE) ? true : false, @@ -696,9 +707,18 @@ class acp_forums * ensure to update the template variables * S_ERROR and ERROR_MSG to display it * @var array template_data Array with new forum data - * @since 3.1-A1 + * @since 3.1.0-a1 */ - $vars = array('action', 'update', 'forum_id', 'row', 'forum_data', 'parents_list', 'errors', 'template_data'); + $vars = array( + 'action', + 'update', + 'forum_id', + 'row', + 'forum_data', + 'parents_list', + 'errors', + 'template_data', + ); extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_display_form', compact($vars))); $template->assign_vars($template_data); @@ -760,7 +780,7 @@ class acp_forums break; case 'copy_perm': - $forum_perm_from = request_var('forum_perm_from', 0); + $forum_perm_from = $request->variable('forum_perm_from', 0); // Copy permissions? if (!empty($forum_perm_from) && $forum_perm_from != $forum_id) @@ -924,12 +944,13 @@ class acp_forums /** * Update forum data */ - function update_forum_data(&$forum_data) + function update_forum_data(&$forum_data_ary) { - global $db, $user, $cache, $phpbb_root_path, $phpbb_container, $phpbb_dispatcher; + global $db, $user, $cache, $phpbb_root_path, $phpbb_container, $phpbb_dispatcher, $phpbb_log, $request; $errors = array(); + $forum_data = $forum_data_ary; /** * Validate the forum data before we create/update the forum * @@ -937,46 +958,48 @@ class acp_forums * @var array forum_data Array with new forum data * @var array errors Array of errors, should be strings and not * language key. - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('forum_data', 'errors'); extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_validate_data', compact($vars))); + $forum_data_ary = $forum_data; + unset($forum_data); - if ($forum_data['forum_name'] == '') + if ($forum_data_ary['forum_name'] == '') { $errors[] = $user->lang['FORUM_NAME_EMPTY']; } - if (utf8_strlen($forum_data['forum_desc']) > 4000) + if (utf8_strlen($forum_data_ary['forum_desc']) > 4000) { $errors[] = $user->lang['FORUM_DESC_TOO_LONG']; } - if (utf8_strlen($forum_data['forum_rules']) > 4000) + if (utf8_strlen($forum_data_ary['forum_rules']) > 4000) { $errors[] = $user->lang['FORUM_RULES_TOO_LONG']; } - if ($forum_data['forum_password'] || $forum_data['forum_password_confirm']) + if ($forum_data_ary['forum_password'] || $forum_data_ary['forum_password_confirm']) { - if ($forum_data['forum_password'] != $forum_data['forum_password_confirm']) + if ($forum_data_ary['forum_password'] != $forum_data_ary['forum_password_confirm']) { - $forum_data['forum_password'] = $forum_data['forum_password_confirm'] = ''; + $forum_data_ary['forum_password'] = $forum_data_ary['forum_password_confirm'] = ''; $errors[] = $user->lang['FORUM_PASSWORD_MISMATCH']; } } - if ($forum_data['prune_days'] < 0 || $forum_data['prune_viewed'] < 0 || $forum_data['prune_freq'] < 0) + if ($forum_data_ary['prune_days'] < 0 || $forum_data_ary['prune_viewed'] < 0 || $forum_data_ary['prune_freq'] < 0) { - $forum_data['prune_days'] = $forum_data['prune_viewed'] = $forum_data['prune_freq'] = 0; + $forum_data_ary['prune_days'] = $forum_data_ary['prune_viewed'] = $forum_data_ary['prune_freq'] = 0; $errors[] = $user->lang['FORUM_DATA_NEGATIVE']; } $range_test_ary = array( - array('lang' => 'FORUM_TOPICS_PAGE', 'value' => $forum_data['forum_topics_per_page'], 'column_type' => 'TINT:0'), + array('lang' => 'FORUM_TOPICS_PAGE', 'value' => $forum_data_ary['forum_topics_per_page'], 'column_type' => 'TINT:0'), ); - if (!empty($forum_data['forum_image']) && !file_exists($phpbb_root_path . $forum_data['forum_image'])) + if (!empty($forum_data_ary['forum_image']) && !file_exists($phpbb_root_path . $forum_data_ary['forum_image'])) { $errors[] = $user->lang['FORUM_IMAGE_NO_EXIST']; } @@ -990,17 +1013,17 @@ class acp_forums // 8 = prune stickies // 16 = show active topics // 32 = enable post review - $forum_data['forum_flags'] = 0; - $forum_data['forum_flags'] += ($forum_data['forum_link_track']) ? FORUM_FLAG_LINK_TRACK : 0; - $forum_data['forum_flags'] += ($forum_data['prune_old_polls']) ? FORUM_FLAG_PRUNE_POLL : 0; - $forum_data['forum_flags'] += ($forum_data['prune_announce']) ? FORUM_FLAG_PRUNE_ANNOUNCE : 0; - $forum_data['forum_flags'] += ($forum_data['prune_sticky']) ? FORUM_FLAG_PRUNE_STICKY : 0; - $forum_data['forum_flags'] += ($forum_data['show_active']) ? FORUM_FLAG_ACTIVE_TOPICS : 0; - $forum_data['forum_flags'] += ($forum_data['enable_post_review']) ? FORUM_FLAG_POST_REVIEW : 0; - $forum_data['forum_flags'] += ($forum_data['enable_quick_reply']) ? FORUM_FLAG_QUICK_REPLY : 0; + $forum_data_ary['forum_flags'] = 0; + $forum_data_ary['forum_flags'] += ($forum_data_ary['forum_link_track']) ? FORUM_FLAG_LINK_TRACK : 0; + $forum_data_ary['forum_flags'] += ($forum_data_ary['prune_old_polls']) ? FORUM_FLAG_PRUNE_POLL : 0; + $forum_data_ary['forum_flags'] += ($forum_data_ary['prune_announce']) ? FORUM_FLAG_PRUNE_ANNOUNCE : 0; + $forum_data_ary['forum_flags'] += ($forum_data_ary['prune_sticky']) ? FORUM_FLAG_PRUNE_STICKY : 0; + $forum_data_ary['forum_flags'] += ($forum_data_ary['show_active']) ? FORUM_FLAG_ACTIVE_TOPICS : 0; + $forum_data_ary['forum_flags'] += ($forum_data_ary['enable_post_review']) ? FORUM_FLAG_POST_REVIEW : 0; + $forum_data_ary['forum_flags'] += ($forum_data_ary['enable_quick_reply']) ? FORUM_FLAG_QUICK_REPLY : 0; // Unset data that are not database fields - $forum_data_sql = $forum_data; + $forum_data_sql = $forum_data_ary; unset($forum_data_sql['forum_link_track']); unset($forum_data_sql['prune_old_polls']); @@ -1031,12 +1054,14 @@ class acp_forums else { // Instantiate passwords manager + /* @var $passwords_manager \phpbb\passwords\manager */ $passwords_manager = $phpbb_container->get('passwords.manager'); $forum_data_sql['forum_password'] = $passwords_manager->hash($forum_data_sql['forum_password']); } unset($forum_data_sql['forum_password_unset']); + $forum_data = $forum_data_ary; /** * Remove invalid values from forum_data_sql that should not be updated * @@ -1045,10 +1070,12 @@ class acp_forums * @var array forum_data_sql Array with data we are going to update * If forum_data_sql[forum_id] is set, we update * that forum, otherwise a new one is created. - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('forum_data', 'forum_data_sql'); extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_update_data_before', compact($vars))); + $forum_data_ary = $forum_data; + unset($forum_data); $is_new_forum = !isset($forum_data_sql['forum_id']); @@ -1105,9 +1132,9 @@ class acp_forums $sql = 'INSERT INTO ' . FORUMS_TABLE . ' ' . $db->sql_build_array('INSERT', $forum_data_sql); $db->sql_query($sql); - $forum_data['forum_id'] = $db->sql_nextid(); + $forum_data_ary['forum_id'] = $db->sql_nextid(); - add_log('admin', 'LOG_FORUM_ADD', $forum_data['forum_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_ADD', false, array($forum_data_ary['forum_name'])); } else { @@ -1125,7 +1152,7 @@ class acp_forums // we're turning a postable forum into a non-postable forum if ($forum_data_sql['type_action'] == 'move') { - $to_forum_id = request_var('to_forum_id', 0); + $to_forum_id = $request->variable('to_forum_id', 0); if ($to_forum_id) { @@ -1155,8 +1182,8 @@ class acp_forums if ($row['right_id'] - $row['left_id'] > 1) { // We are turning a category into a link - but need to decide what to do with the subforums. - $action_subforums = request_var('action_subforums', ''); - $subforums_to_id = request_var('subforums_to_id', 0); + $action_subforums = $request->variable('action_subforums', ''); + $subforums_to_id = $request->variable('subforums_to_id', 0); if ($action_subforums == 'delete') { @@ -1237,8 +1264,6 @@ class acp_forums return array($user->lang['NO_FORUM']); } - $subforums_to_name = $_row['forum_name']; - $sql = 'SELECT forum_id FROM ' . FORUMS_TABLE . " WHERE parent_id = {$row['forum_id']}"; @@ -1322,11 +1347,12 @@ class acp_forums $db->sql_query($sql); // Add it back - $forum_data['forum_id'] = $forum_id; + $forum_data_ary['forum_id'] = $forum_id; - add_log('admin', 'LOG_FORUM_EDIT', $forum_data['forum_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_EDIT', false, array($forum_data_ary['forum_name'])); } + $forum_data = $forum_data_ary; /** * Event after a forum was updated or created * @@ -1338,10 +1364,12 @@ class acp_forums * ensure to set forum_data_sql[forum_id] * @var array errors Array of errors, should be strings and not * language key. - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('forum_data', 'forum_data_sql', 'is_new_forum', 'errors'); extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_update_data_after', compact($vars))); + $forum_data_ary = $forum_data; + unset($forum_data); return $errors; } @@ -1353,7 +1381,7 @@ class acp_forums { global $db, $user, $phpbb_dispatcher; - $to_data = $moved_ids = $errors = array(); + $errors = array(); // Check if we want to move to a parent with link type if ($to_id > 0) @@ -1376,7 +1404,7 @@ class acp_forums * @var int to_id If of the new parent forum * @var array errors Array of errors, should be strings and not * language key. - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('from_id', 'to_id', 'errors'); extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_move_children', compact($vars))); @@ -1480,7 +1508,7 @@ class acp_forums * @var array errors Array of errors, should be strings and not * language key. If this array is not empty, * The content will not be moved. - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('from_id', 'to_id', 'sync', 'errors'); extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_move_content', compact($vars))); @@ -1526,7 +1554,7 @@ class acp_forums */ function delete_forum($forum_id, $action_posts = 'delete', $action_subforums = 'delete', $posts_to_id = 0, $subforums_to_id = 0) { - global $db, $user, $cache; + global $db, $user, $cache, $phpbb_log; $forum_data = $this->get_forum_info($forum_id); @@ -1723,39 +1751,39 @@ class acp_forums switch ($log_action) { case 'MOVE_POSTS_MOVE_FORUMS': - add_log('admin', 'LOG_FORUM_DEL_MOVE_POSTS_MOVE_FORUMS', $posts_to_name, $subforums_to_name, $forum_data['forum_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_DEL_MOVE_POSTS_MOVE_FORUMS', false, array($posts_to_name, $subforums_to_name, $forum_data['forum_name'])); break; case 'MOVE_POSTS_FORUMS': - add_log('admin', 'LOG_FORUM_DEL_MOVE_POSTS_FORUMS', $posts_to_name, $forum_data['forum_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_DEL_MOVE_POSTS_FORUMS', false, array($posts_to_name, $forum_data['forum_name'])); break; case 'POSTS_MOVE_FORUMS': - add_log('admin', 'LOG_FORUM_DEL_POSTS_MOVE_FORUMS', $subforums_to_name, $forum_data['forum_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_DEL_POSTS_MOVE_FORUMS', false, array($subforums_to_name, $forum_data['forum_name'])); break; case '_MOVE_FORUMS': - add_log('admin', 'LOG_FORUM_DEL_MOVE_FORUMS', $subforums_to_name, $forum_data['forum_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_DEL_MOVE_FORUMS', false, array($subforums_to_name, $forum_data['forum_name'])); break; case 'MOVE_POSTS_': - add_log('admin', 'LOG_FORUM_DEL_MOVE_POSTS', $posts_to_name, $forum_data['forum_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_DEL_MOVE_POSTS', false, array($posts_to_name, $forum_data['forum_name'])); break; case 'POSTS_FORUMS': - add_log('admin', 'LOG_FORUM_DEL_POSTS_FORUMS', $forum_data['forum_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_DEL_POSTS_FORUMS', false, array($forum_data['forum_name'])); break; case '_FORUMS': - add_log('admin', 'LOG_FORUM_DEL_FORUMS', $forum_data['forum_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_DEL_FORUMS', false, array($forum_data['forum_name'])); break; case 'POSTS_': - add_log('admin', 'LOG_FORUM_DEL_POSTS', $forum_data['forum_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_DEL_POSTS', false, array($forum_data['forum_name'])); break; default: - add_log('admin', 'LOG_FORUM_DEL_FORUM', $forum_data['forum_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_DEL_FORUM', false, array($forum_data['forum_name'])); break; } @@ -1767,7 +1795,7 @@ class acp_forums */ function delete_forum_content($forum_id) { - global $db, $config, $phpbb_root_path, $phpEx; + global $db, $config, $phpbb_root_path, $phpEx, $phpbb_container, $phpbb_dispatcher; include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx); @@ -1788,7 +1816,10 @@ class acp_forums } $db->sql_freeresult($result); - delete_attachments('topic', $topic_ids, false); + /** @var \phpbb\attachment\manager $attachment_manager */ + $attachment_manager = $phpbb_container->get('attachment.manager'); + $attachment_manager->delete('topic', $topic_ids, false); + unset($attachment_manager); // Delete shadow topics pointing to topics in this forum delete_topic_shadows($forum_id); @@ -1808,7 +1839,7 @@ class acp_forums } $db->sql_freeresult($result); - switch ($db->sql_layer) + switch ($db->get_sql_layer()) { case 'mysql4': case 'mysqli': @@ -1899,6 +1930,24 @@ class acp_forums $table_ary = array(FORUMS_ACCESS_TABLE, FORUMS_TRACK_TABLE, FORUMS_WATCH_TABLE, LOG_TABLE, MODERATOR_CACHE_TABLE, POSTS_TABLE, TOPICS_TABLE, TOPICS_TRACK_TABLE); + /** + * Perform additional actions before forum content deletion + * + * @event core.delete_forum_content_before_query + * @var array table_ary Array of tables from which all rows will be deleted that hold the forum_id + * @var int forum_id the forum id + * @var array topic_ids Array of the topic ids from the forum to be deleted + * @var array post_counts Array of counts of posts in the forum, by poster_id + * @since 3.1.6-RC1 + */ + $vars = array( + 'table_ary', + 'forum_id', + 'topic_ids', + 'post_counts', + ); + extract($phpbb_dispatcher->trigger_event('core.delete_forum_content_before_query', compact($vars))); + foreach ($table_ary as $table) { $db->sql_query("DELETE FROM $table WHERE forum_id = $forum_id"); @@ -1941,7 +1990,7 @@ class acp_forums $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); - set_config('num_posts', (int) $row['stat'], true); + $config->set('num_posts', (int) $row['stat'], false); $sql = 'SELECT COUNT(topic_id) AS stat FROM ' . TOPICS_TABLE . ' @@ -1950,7 +1999,7 @@ class acp_forums $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); - set_config('num_topics', (int) $row['stat'], true); + $config->set('num_topics', (int) $row['stat'], false); $sql = 'SELECT COUNT(attach_id) as stat FROM ' . ATTACHMENTS_TABLE; @@ -1958,7 +2007,7 @@ class acp_forums $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); - set_config('num_files', (int) $row['stat'], true); + $config->set('num_files', (int) $row['stat'], false); $sql = 'SELECT SUM(filesize) as stat FROM ' . ATTACHMENTS_TABLE; @@ -1966,7 +2015,7 @@ class acp_forums $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); - set_config('upload_dir_size', (float) $row['stat'], true); + $config->set('upload_dir_size', (float) $row['stat'], false); return array(); } diff --git a/phpBB/includes/acp/acp_groups.php b/phpBB/includes/acp/acp_groups.php index 7ecedcf51e..1f965b334c 100644 --- a/phpBB/includes/acp/acp_groups.php +++ b/phpBB/includes/acp/acp_groups.php @@ -1,9 +1,13 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -15,9 +19,6 @@ if (!defined('IN_PHPBB')) exit; } -/** -* @package acp -*/ class acp_groups { var $u_action; @@ -25,8 +26,8 @@ class acp_groups function main($id, $mode) { global $config, $db, $user, $auth, $template, $cache; - global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix, $file_uploads; - global $request, $phpbb_container; + global $phpbb_root_path, $phpbb_admin_path, $phpEx; + global $request, $phpbb_container, $phpbb_dispatcher; $user->add_lang('acp/groups'); $this->tpl_name = 'acp_groups'; @@ -41,18 +42,23 @@ class acp_groups return; } - include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + if (!function_exists('group_user_attributes')) + { + include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + } // Check and set some common vars - $action = (isset($_POST['add'])) ? 'add' : ((isset($_POST['addusers'])) ? 'addusers' : request_var('action', '')); - $group_id = request_var('g', 0); - $mark_ary = request_var('mark', array(0)); - $name_ary = request_var('usernames', '', true); - $leader = request_var('leader', 0); - $default = request_var('default', 0); - $start = request_var('start', 0); + $action = (isset($_POST['add'])) ? 'add' : ((isset($_POST['addusers'])) ? 'addusers' : $request->variable('action', '')); + $group_id = $request->variable('g', 0); + $mark_ary = $request->variable('mark', array(0)); + $name_ary = $request->variable('usernames', '', true); + $leader = $request->variable('leader', 0); + $default = $request->variable('default', 0); + $start = $request->variable('start', 0); $update = (isset($_POST['update'])) ? true : false; + /** @var \phpbb\group\helper $group_helper */ + $group_helper = $phpbb_container->get('group_helper'); // Clear some vars $group_row = array(); @@ -98,7 +104,7 @@ class acp_groups } // Approve, demote or promote - $group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name']; + $group_name = $group_helper->get_name($group_row['group_name']); $error = group_user_attributes($action, $group_id, $mark_ary, false, $group_name); if (!$error) @@ -139,8 +145,8 @@ class acp_groups if (confirm_box(true)) { - $group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name']; - group_user_attributes('default', $group_id, $mark_ary, false, $group_name, $group_row); + $group_name = $group_helper->get_name($group_row['group_name']); + group_user_attributes('default', $group_id, $mark_ary, false, $group_name, $group_row); trigger_error($user->lang['GROUP_DEFS_UPDATED'] . adm_back_link($this->u_action . '&action=list&g=' . $group_id)); } else @@ -158,7 +164,7 @@ class acp_groups case 'set_default_on_all': if (confirm_box(true)) { - $group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name']; + $group_name = $group_helper->get_name($group_row['group_name']); $start = 0; @@ -236,7 +242,7 @@ class acp_groups break; case 'deleteusers': - $group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name']; + $group_name = $group_helper->get_name($group_row['group_name']); $error = group_user_del($group_id, $mark_ary, false, $group_name); break; } @@ -280,7 +286,7 @@ class acp_groups } $name_ary = array_unique(explode("\n", $name_ary)); - $group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name']; + $group_name = $group_helper->get_name($group_row['group_name']); // Add user/s to group if ($error = group_user_add($group_id, false, $name_ary, $group_name, $default, $leader, 0, $group_row)) @@ -295,9 +301,10 @@ class acp_groups case 'edit': case 'add': - include($phpbb_root_path . 'includes/functions_display.' . $phpEx); - - $data = $submit_ary = array(); + if (!function_exists('display_forums')) + { + include($phpbb_root_path . 'includes/functions_display.' . $phpEx); + } if ($action == 'edit' && !$group_id) { @@ -320,6 +327,7 @@ class acp_groups if ($config['allow_avatar']) { + /* @var $phpbb_avatar_manager \phpbb\avatar\manager */ $phpbb_avatar_manager = $phpbb_container->get('avatar.manager'); $avatar_drivers = $phpbb_avatar_manager->get_enabled_drivers(); @@ -331,6 +339,27 @@ class acp_groups } } + if ($request->is_set_post('avatar_delete')) + { + if (confirm_box(true)) + { + $avatar_data['id'] = substr($avatar_data['id'], 1); + $phpbb_avatar_manager->handle_avatar_delete($db, $user, $avatar_data, GROUPS_TABLE, 'group_'); + + $message = ($action == 'edit') ? 'GROUP_UPDATED' : 'GROUP_CREATED'; + trigger_error($user->lang[$message] . adm_back_link($this->u_action)); + } + else + { + confirm_box(false, $user->lang('CONFIRM_AVATAR_DELETE'), build_hidden_fields(array( + 'avatar_delete' => true, + 'i' => $id, + 'mode' => $mode, + 'g' => $group_id, + 'action' => $action)) + ); + } + } // Did we submit? if ($update) @@ -340,24 +369,24 @@ class acp_groups trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); } - $group_name = utf8_normalize_nfc(request_var('group_name', '', true)); - $group_desc = utf8_normalize_nfc(request_var('group_desc', '', true)); - $group_type = request_var('group_type', GROUP_FREE); + $group_name = $request->variable('group_name', '', true); + $group_desc = $request->variable('group_desc', '', true); + $group_type = $request->variable('group_type', GROUP_FREE); - $allow_desc_bbcode = request_var('desc_parse_bbcode', false); - $allow_desc_urls = request_var('desc_parse_urls', false); - $allow_desc_smilies = request_var('desc_parse_smilies', false); + $allow_desc_bbcode = $request->variable('desc_parse_bbcode', false); + $allow_desc_urls = $request->variable('desc_parse_urls', false); + $allow_desc_smilies = $request->variable('desc_parse_smilies', false); $submit_ary = array( - 'colour' => request_var('group_colour', ''), - 'rank' => request_var('group_rank', 0), + 'colour' => $request->variable('group_colour', ''), + 'rank' => $request->variable('group_rank', 0), 'receive_pm' => isset($_REQUEST['group_receive_pm']) ? 1 : 0, 'legend' => isset($_REQUEST['group_legend']) ? 1 : 0, 'teampage' => isset($_REQUEST['group_teampage']) ? 1 : 0, - 'message_limit' => request_var('group_message_limit', 0), - 'max_recipients' => request_var('group_max_recipients', 0), + 'message_limit' => $request->variable('group_message_limit', 0), + 'max_recipients' => $request->variable('group_max_recipients', 0), 'founder_manage' => 0, - 'skip_auth' => request_var('group_skip_auth', 0), + 'skip_auth' => $request->variable('group_skip_auth', 0), ); if ($user->data['user_type'] == USER_FOUNDER) @@ -411,6 +440,42 @@ class acp_groups 'colour' => array('hex_colour', true), ); + /** + * Request group data and operate on it + * + * @event core.acp_manage_group_request_data + * @var string action Type of the action: add|edit + * @var int group_id The group id + * @var array group_row Array with new group data + * @var array error Array of errors, if you add errors + * ensure to update the template variables + * S_ERROR and ERROR_MSG to display it + * @var string group_name The group name + * @var string group_desc The group description + * @var int group_type The group type + * @var bool allow_desc_bbcode Allow bbcode in group description: true|false + * @var bool allow_desc_urls Allow urls in group description: true|false + * @var bool allow_desc_smilies Allow smiles in group description: true|false + * @var array submit_ary Array with new group data + * @var array validation_checks Array with validation data + * @since 3.1.0-b5 + */ + $vars = array( + 'action', + 'group_id', + 'group_row', + 'error', + 'group_name', + 'group_desc', + 'group_type', + 'allow_desc_bbcode', + 'allow_desc_urls', + 'allow_desc_smilies', + 'submit_ary', + 'validation_checks', + ); + extract($phpbb_dispatcher->trigger_event('core.acp_manage_group_request_data', compact($vars))); + if ($validation_error = validate_data($submit_ary, $validation_checks)) { // Replace "error" string with its real, localised form @@ -443,6 +508,42 @@ class acp_groups 'skip_auth' => 'int', ); + /** + * Initialise data before we display the add/edit form + * + * @event core.acp_manage_group_initialise_data + * @var string action Type of the action: add|edit + * @var int group_id The group id + * @var array group_row Array with new group data + * @var array error Array of errors, if you add errors + * ensure to update the template variables + * S_ERROR and ERROR_MSG to display it + * @var string group_name The group name + * @var string group_desc The group description + * @var int group_type The group type + * @var bool allow_desc_bbcode Allow bbcode in group description: true|false + * @var bool allow_desc_urls Allow urls in group description: true|false + * @var bool allow_desc_smilies Allow smiles in group description: true|false + * @var array submit_ary Array with new group data + * @var array test_variables Array with variables for test + * @since 3.1.0-b5 + */ + $vars = array( + 'action', + 'group_id', + 'group_row', + 'error', + 'group_name', + 'group_desc', + 'group_type', + 'allow_desc_bbcode', + 'allow_desc_urls', + 'allow_desc_smilies', + 'submit_ary', + 'test_variables', + ); + extract($phpbb_dispatcher->trigger_event('core.acp_manage_group_initialise_data', compact($vars))); + foreach ($test_variables as $test => $type) { if (isset($submit_ary[$test]) && ($action == 'add' || $group_row['group_' . $test] != $submit_ary[$test] || isset($group_attributes['group_avatar']) && strpos($test, 'avatar') === 0 || in_array($test, $set_attributes))) @@ -454,7 +555,7 @@ class acp_groups if (!($error = group_create($group_id, $group_type, $group_name, $group_desc, $group_attributes, $allow_desc_bbcode, $allow_desc_urls, $allow_desc_smilies))) { - $group_perm_from = request_var('group_perm_from', 0); + $group_perm_from = $request->variable('group_perm_from', 0); // Copy permissions? // If the user has the a_authgroups permission and at least one additional permission ability set the permissions are fully transferred. @@ -524,7 +625,7 @@ class acp_groups } else if (!$group_id) { - $group_name = utf8_normalize_nfc(request_var('group_name', '', true)); + $group_name = $request->variable('group_name', '', true); $group_desc_data = array( 'text' => '', 'allow_bbcode' => true, @@ -573,9 +674,8 @@ class acp_groups $driver = $phpbb_avatar_manager->get_driver($current_driver); $avatars_enabled = true; - $config_name = $phpbb_avatar_manager->get_driver_config_name($driver); $template->set_filenames(array( - 'avatar' => "acp_avatar_options_{$config_name}.html", + 'avatar' => $driver->get_acp_template_name(), )); if ($driver->prepare_form($request, $template, $user, $avatar_data, $avatar_error)) @@ -602,12 +702,12 @@ class acp_groups $error = array_merge($error, $phpbb_avatar_manager->localize_errors($user, $avatar_error)); } - $back_link = request_var('back_link', ''); + $back_link = $request->variable('back_link', ''); switch ($back_link) { case 'acp_users_groups': - $u_back = append_sid("{$phpbb_admin_path}index.$phpEx", 'i=users&mode=groups&u=' . request_var('u', 0)); + $u_back = append_sid("{$phpbb_admin_path}index.$phpEx", 'i=users&mode=groups&u=' . $request->variable('u', 0)); break; default: @@ -626,7 +726,7 @@ class acp_groups 'S_AVATARS_ENABLED' => ($config['allow_avatar'] && $avatars_enabled), 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '', - 'GROUP_NAME' => ($group_type == GROUP_SPECIAL) ? $user->lang['G_' . $group_name] : $group_name, + 'GROUP_NAME' => $group_helper->get_name($group_name), 'GROUP_INTERNAL_NAME' => $group_name, 'GROUP_DESC' => $group_desc_data['text'], 'GROUP_RECEIVE_PM' => (isset($group_row['group_receive_pm']) && $group_row['group_receive_pm']) ? ' checked="checked"' : '', @@ -665,6 +765,39 @@ class acp_groups 'L_AVATAR_EXPLAIN' => phpbb_avatar_explanation_string(), )); + /** + * Modify group template data before we display the form + * + * @event core.acp_manage_group_display_form + * @var string action Type of the action: add|edit + * @var bool update Do we display the form only + * or did the user press submit + * @var int group_id The group id + * @var array group_row Array with new group data + * @var string group_name The group name + * @var int group_type The group type + * @var array group_desc_data The group description data + * @var string group_rank The group rank + * @var string rank_options The rank options + * @var array error Array of errors, if you add errors + * ensure to update the template variables + * S_ERROR and ERROR_MSG to display it + * @since 3.1.0-b5 + */ + $vars = array( + 'action', + 'update', + 'group_id', + 'group_row', + 'group_desc_data', + 'group_name', + 'group_type', + 'group_rank', + 'rank_options', + 'error', + ); + extract($phpbb_dispatcher->trigger_event('core.acp_manage_group_display_form', compact($vars))); + return; break; @@ -675,8 +808,9 @@ class acp_groups trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action), E_USER_WARNING); } - $this->page_title = 'GROUP_MEMBERS'; + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); + $this->page_title = 'GROUP_MEMBERS'; // Grab the leaders - always, on every page... $sql = 'SELECT u.user_id, u.username, u.username_clean, u.user_regdate, u.user_colour, u.user_posts, u.group_id, ug.group_leader, ug.user_pending @@ -727,7 +861,7 @@ class acp_groups 'S_GROUP_SPECIAL' => ($group_row['group_type'] == GROUP_SPECIAL) ? true : false, 'S_ACTION_OPTIONS' => $s_action_options, - 'GROUP_NAME' => ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name'], + 'GROUP_NAME' => $group_helper->get_name($group_row['group_name']), 'U_ACTION' => $this->u_action . "&g=$group_id", 'U_BACK' => $this->u_action, @@ -856,6 +990,9 @@ class acp_groups $teampage_id = $request->variable('t', 0); $category_id = $request->variable('c', 0); + /** @var \phpbb\group\helper $group_helper */ + $group_helper = $phpbb_container->get('group_helper'); + if ($field && !in_array($field, array('legend', 'teampage'))) { // Invalid mode @@ -863,7 +1000,7 @@ class acp_groups } else if ($field && in_array($field, array('legend', 'teampage'))) { - + /* @var $group_position \phpbb\groupposition\groupposition_interface */ $group_position = $phpbb_container->get('groupposition.' . $field); } @@ -955,10 +1092,9 @@ class acp_groups ORDER BY group_legend ASC, group_type DESC, group_name ASC'; $result = $db->sql_query($sql); - $s_group_select_legend = ''; while ($row = $db->sql_fetchrow($result)) { - $group_name = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']; + $group_name = $group_helper->get_name($row['group_name']); if ($row['group_legend']) { $template->assign_block_vars('legend', array( @@ -993,7 +1129,6 @@ class acp_groups ORDER BY t.teampage_position ASC'; $result = $db->sql_query($sql); - $category_data = array(); while ($row = $db->sql_fetchrow($result)) { if ($row['teampage_id'] == $category_id) @@ -1006,7 +1141,7 @@ class acp_groups if ($row['group_id']) { - $group_name = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']; + $group_name = $group_helper->get_name($row['group_name']); $group_type = $user->lang[\phpbb\groupposition\teampage::group_type_language($row['group_type'])]; } else @@ -1036,10 +1171,9 @@ class acp_groups ORDER BY g.group_type DESC, g.group_name ASC'; $result = $db->sql_query($sql); - $s_group_select_teampage = ''; while ($row = $db->sql_fetchrow($result)) { - $group_name = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']; + $group_name = $group_helper->get_name($row['group_name']); $template->assign_block_vars('add_teampage', array( 'GROUP_ID' => (int) $row['group_id'], 'GROUP_NAME' => $group_name, diff --git a/phpBB/includes/acp/acp_icons.php b/phpBB/includes/acp/acp_icons.php index 20b1f56182..0293dca9d3 100644 --- a/phpBB/includes/acp/acp_icons.php +++ b/phpBB/includes/acp/acp_icons.php @@ -1,9 +1,13 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -17,7 +21,6 @@ if (!defined('IN_PHPBB')) /** * @todo [smilies] check regular expressions for special char replacements (stored specialchared in db) -* @package acp */ class acp_icons { @@ -25,18 +28,18 @@ class acp_icons function main($id, $mode) { - global $db, $user, $auth, $template, $cache; - global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + global $db, $user, $template, $cache; + global $config, $phpbb_root_path; global $request, $phpbb_container; $user->add_lang('acp/posting'); // Set up general vars - $action = request_var('action', ''); + $action = $request->variable('action', ''); $action = (isset($_POST['add'])) ? 'add' : $action; $action = (isset($_POST['edit'])) ? 'edit' : $action; $action = (isset($_POST['import'])) ? 'import' : $action; - $icon_id = request_var('id', 0); + $icon_id = $request->variable('id', 0); $mode = ($mode == 'smilies') ? 'smilies' : 'icons'; @@ -191,7 +194,6 @@ class acp_icons $data = array(); $after = false; - $display = 0; $order_lists = array('', ''); $add_order_lists = array('', ''); $display_count = 0; @@ -203,11 +205,9 @@ class acp_icons unset($_images[$row[$fields . '_url']]); } - if ($row[$fields . '_id'] == $icon_id) { $after = true; - $display = $row['display_on_posting']; $data[$row[$fields . '_url']] = $row; } else @@ -246,7 +246,7 @@ class acp_icons $data = $_images; } - $colspan = (($mode == 'smilies') ? 7 : 5); + $colspan = (($mode == 'smilies') ? 7 : 6); $colspan += ($icon_id) ? 1 : 0; $colspan += ($action == 'add') ? 2 : 0; @@ -290,6 +290,8 @@ class acp_icons 'ID' => (isset($img_row[$fields . '_id'])) ? $img_row[$fields . '_id'] : 0, 'WIDTH' => (!empty($img_row[$fields .'_width'])) ? $img_row[$fields .'_width'] : $img_row['width'], 'HEIGHT' => (!empty($img_row[$fields .'_height'])) ? $img_row[$fields .'_height'] : $img_row['height'], + 'TEXT_ALT' => ($mode == 'icons' && !empty($img_row['icons_alt'])) ? $img_row['icons_alt'] : $img, + 'ALT' => ($mode == 'icons' && !empty($img_row['icons_alt'])) ? $img_row['icons_alt'] : '', 'POSTING_CHECKED' => (!empty($img_row['display_on_posting']) || $action == 'add') ? ' checked="checked"' : '', )); } @@ -324,24 +326,25 @@ class acp_icons case 'modify': // Get items to create/modify - $images = (isset($_POST['image'])) ? array_keys(request_var('image', array('' => 0))) : array(); + $images = (isset($_POST['image'])) ? array_keys($request->variable('image', array('' => 0))) : array(); // Now really get the items - $image_id = (isset($_POST['id'])) ? request_var('id', array('' => 0)) : array(); - $image_order = (isset($_POST['order'])) ? request_var('order', array('' => 0)) : array(); - $image_width = (isset($_POST['width'])) ? request_var('width', array('' => 0)) : array(); - $image_height = (isset($_POST['height'])) ? request_var('height', array('' => 0)) : array(); - $image_add = (isset($_POST['add_img'])) ? request_var('add_img', array('' => 0)) : array(); - $image_emotion = utf8_normalize_nfc(request_var('emotion', array('' => ''), true)); - $image_code = utf8_normalize_nfc(request_var('code', array('' => ''), true)); - $image_display_on_posting = (isset($_POST['display_on_posting'])) ? request_var('display_on_posting', array('' => 0)) : array(); + $image_id = (isset($_POST['id'])) ? $request->variable('id', array('' => 0)) : array(); + $image_order = (isset($_POST['order'])) ? $request->variable('order', array('' => 0)) : array(); + $image_width = (isset($_POST['width'])) ? $request->variable('width', array('' => 0)) : array(); + $image_height = (isset($_POST['height'])) ? $request->variable('height', array('' => 0)) : array(); + $image_add = (isset($_POST['add_img'])) ? $request->variable('add_img', array('' => 0)) : array(); + $image_emotion = $request->variable('emotion', array('' => ''), true); + $image_code = $request->variable('code', array('' => ''), true); + $image_alt = ($request->is_set_post('alt')) ? $request->variable('alt', array('' => ''), true) : array(); + $image_display_on_posting = (isset($_POST['display_on_posting'])) ? $request->variable('display_on_posting', array('' => 0)) : array(); // Ok, add the relevant bits if we are adding new codes to existing emoticons... if ($request->variable('add_additional_code', false, false, \phpbb\request\request_interface::POST)) { - $add_image = request_var('add_image', ''); - $add_code = utf8_normalize_nfc(request_var('add_code', '', true)); - $add_emotion = utf8_normalize_nfc(request_var('add_emotion', '', true)); + $add_image = $request->variable('add_image', ''); + $add_code = $request->variable('add_code', '', true); + $add_emotion = $request->variable('add_emotion', '', true); if ($add_image && $add_emotion && $add_code) { @@ -350,15 +353,15 @@ class acp_icons $image_code[$add_image] = $add_code; $image_emotion[$add_image] = $add_emotion; - $image_width[$add_image] = request_var('add_width', 0); - $image_height[$add_image] = request_var('add_height', 0); + $image_width[$add_image] = $request->variable('add_width', 0); + $image_height[$add_image] = $request->variable('add_height', 0); if ($request->variable('add_display_on_posting', false, false, \phpbb\request\request_interface::POST)) { $image_display_on_posting[$add_image] = 1; } - $image_order[$add_image] = request_var('add_order', 0); + $image_order[$add_image] = $request->variable('add_order', 0); } } @@ -436,6 +439,13 @@ class acp_icons ); } + if ($mode == 'icons') + { + $img_sql = array_merge($img_sql, array( + 'icons_alt' => $image_alt[$image]) + ); + } + // Image_order holds the 'new' order value if (!empty($image_order[$image])) { @@ -484,6 +494,7 @@ class acp_icons $cache->destroy('_icons'); $cache->destroy('sql', $table); + $phpbb_container->get('text_formatter.cache')->invalidate(); $level = ($icons_updated) ? E_USER_NOTICE : E_USER_WARNING; $errormsgs = ''; @@ -504,8 +515,8 @@ class acp_icons case 'import': - $pak = request_var('pak', ''); - $current = request_var('current', ''); + $pak = $request->variable('pak', ''); + $current = $request->variable('current', ''); if ($pak != '') { @@ -536,10 +547,10 @@ class acp_icons // The user has already selected a smilies_pak file if ($current == 'delete') { - switch ($db->sql_layer) + switch ($db->get_sql_layer()) { case 'sqlite': - case 'firebird': + case 'sqlite3': $db->sql_query('DELETE FROM ' . $table); break; @@ -659,6 +670,7 @@ class acp_icons $cache->destroy('_icons'); $cache->destroy('sql', $table); + $phpbb_container->get('text_formatter.cache')->invalidate(); trigger_error($user->lang[$lang . '_IMPORT_SUCCESS'] . adm_back_link($this->u_action)); } @@ -735,7 +747,7 @@ class acp_icons { garbage_collection(); - header('Pragma: public'); + header('Cache-Control: public'); // Send out the Headers header('Content-Type: text/x-delimtext; name="' . $mode . '.pak"'); @@ -781,7 +793,8 @@ class acp_icons $cache->destroy('_icons'); $cache->destroy('sql', $table); - + $phpbb_container->get('text_formatter.cache')->invalidate(); + if ($request->is_ajax()) { $json_response = new \phpbb\json_response; @@ -846,6 +859,7 @@ class acp_icons $cache->destroy('_icons'); $cache->destroy('sql', $table); + $phpbb_container->get('text_formatter.cache')->invalidate(); if ($request->is_ajax()) { @@ -901,9 +915,10 @@ class acp_icons ) ); - $spacer = false; + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); - $pagination_start = request_var('start', 0); + $pagination_start = $request->variable('start', 0); + $spacer = false; $item_count = $this->item_count($table); @@ -914,7 +929,7 @@ class acp_icons while ($row = $db->sql_fetchrow($result)) { - $alt_text = ($mode == 'smilies') ? $row['code'] : ''; + $alt_text = ($mode == 'smilies') ? $row['code'] : (($mode == 'icons' && !empty($row['icons_alt'])) ? $row['icons_alt'] : $row['icons_url']); $template->assign_block_vars('items', array( 'S_SPACER' => (!$spacer && !$row['display_on_posting']) ? true : false, diff --git a/phpBB/includes/acp/acp_inactive.php b/phpBB/includes/acp/acp_inactive.php index 140815f06a..7ec43f45cc 100644 --- a/phpBB/includes/acp/acp_inactive.php +++ b/phpBB/includes/acp/acp_inactive.php @@ -1,9 +1,13 @@ <?php /** * -* @package acp -* @copyright (c) 2006 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -15,9 +19,6 @@ if (!defined('IN_PHPBB')) exit; } -/** -* @package acp -*/ class acp_inactive { var $u_action; @@ -30,31 +31,36 @@ class acp_inactive function main($id, $mode) { - global $config, $db, $user, $auth, $template, $phpbb_container; - global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix; + global $config, $db, $user, $auth, $template, $phpbb_container, $phpbb_log, $request; + global $phpbb_root_path, $phpbb_admin_path, $phpEx; - include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + if (!function_exists('user_active_flip')) + { + include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + } $user->add_lang('memberlist'); - $action = request_var('action', ''); - $mark = (isset($_REQUEST['mark'])) ? request_var('mark', array(0)) : array(); - $start = request_var('start', 0); + $action = $request->variable('action', ''); + $mark = (isset($_REQUEST['mark'])) ? $request->variable('mark', array(0)) : array(); + $start = $request->variable('start', 0); $submit = isset($_POST['submit']); // Sort keys - $sort_days = request_var('st', 0); - $sort_key = request_var('sk', 'i'); - $sort_dir = request_var('sd', 'd'); + $sort_days = $request->variable('st', 0); + $sort_key = $request->variable('sk', 'i'); + $sort_dir = $request->variable('sd', 'd'); $form_key = 'acp_inactive'; add_form_key($form_key); + + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); // We build the sort key and per page settings here, because they may be needed later // Number of entries to display - $per_page = request_var('users_per_page', (int) $config['topics_per_page']); + $per_page = $request->variable('users_per_page', (int) $config['topics_per_page']); // Sorting $limit_days = array(0 => $user->lang['ALL_ENTRIES'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']); @@ -108,7 +114,10 @@ class acp_inactive if ($config['require_activation'] == USER_ACTIVATION_ADMIN && !empty($inactive_users)) { - include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); + if (!class_exists('messenger')) + { + include($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); + } $messenger = new messenger(false); @@ -134,8 +143,10 @@ class acp_inactive { foreach ($inactive_users as $row) { - add_log('admin', 'LOG_USER_ACTIVE', $row['username']); - add_log('user', $row['user_id'], 'LOG_USER_ACTIVE_USER'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_ACTIVE', false, array($row['username'])); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_ACTIVE_USER', false, array( + 'reportee_id' => $row['user_id'] + )); } trigger_error(sprintf($user->lang['LOG_INACTIVE_ACTIVATE'], implode($user->lang['COMMA_SEPARATOR'], $user_affected) . ' ' . adm_back_link($this->u_action))); @@ -158,7 +169,7 @@ class acp_inactive user_delete('retain', $mark, true); - add_log('admin', 'LOG_INACTIVE_' . strtoupper($action), implode(', ', $user_affected)); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_INACTIVE_' . strtoupper($action), false, array(implode(', ', $user_affected))); trigger_error(sprintf($user->lang['LOG_INACTIVE_DELETE'], implode($user->lang['COMMA_SEPARATOR'], $user_affected) . ' ' . adm_back_link($this->u_action))); } @@ -195,7 +206,10 @@ class acp_inactive if ($row = $db->sql_fetchrow($result)) { // Send the messages - include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); + if (!class_exists('messenger')) + { + include($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); + } $messenger = new messenger(); $usernames = $user_ids = array(); @@ -230,7 +244,7 @@ class acp_inactive WHERE ' . $db->sql_in_set('user_id', $user_ids); $db->sql_query($sql); - add_log('admin', 'LOG_INACTIVE_REMIND', implode(', ', $usernames)); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_INACTIVE_REMIND', false, array(implode(', ', $usernames))); trigger_error(sprintf($user->lang['LOG_INACTIVE_REMIND'], implode($user->lang['COMMA_SEPARATOR'], $usernames) . ' ' . adm_back_link($this->u_action))); } @@ -270,9 +284,10 @@ class acp_inactive 'REMINDED_EXPLAIN' => $user->lang('USER_LAST_REMINDED', (int) $row['user_reminded'], $user->format_date($row['user_reminded_time'])), - 'USERNAME_FULL' => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour'], false, append_sid("{$phpbb_admin_path}index.$phpEx", 'i=users&mode=overview')), + 'USERNAME_FULL' => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour'], false, append_sid("{$phpbb_admin_path}index.$phpEx", 'i=users&mode=overview&redirect=acp_inactive')), 'USERNAME' => get_username_string('username', $row['user_id'], $row['username'], $row['user_colour']), 'USER_COLOR' => get_username_string('colour', $row['user_id'], $row['username'], $row['user_colour']), + 'USER_EMAIL' => $row['user_email'], 'U_USER_ADMIN' => append_sid("{$phpbb_admin_path}index.$phpEx", "i=users&mode=overview&u={$row['user_id']}"), 'U_SEARCH_USER' => ($auth->acl_get('u_search')) ? append_sid("{$phpbb_root_path}search.$phpEx", "author_id={$row['user_id']}&sr=posts") : '', diff --git a/phpBB/includes/acp/acp_jabber.php b/phpBB/includes/acp/acp_jabber.php index 96371075d6..5dec6bb7d4 100644 --- a/phpBB/includes/acp/acp_jabber.php +++ b/phpBB/includes/acp/acp_jabber.php @@ -1,10 +1,17 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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/enter/update transport info */ @@ -16,23 +23,22 @@ if (!defined('IN_PHPBB')) exit; } -/** -* @package acp -*/ class acp_jabber { var $u_action; function main($id, $mode) { - global $db, $user, $auth, $template; - global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + global $db, $user, $template, $phpbb_log, $request; + global $config, $phpbb_root_path, $phpEx; $user->add_lang('acp/board'); - include_once($phpbb_root_path . 'includes/functions_jabber.' . $phpEx); + if (!class_exists('jabber')) + { + include($phpbb_root_path . 'includes/functions_jabber.' . $phpEx); + } - $action = request_var('action', ''); $submit = (isset($_POST['submit'])) ? true : false; if ($mode != 'settings') @@ -43,13 +49,13 @@ class acp_jabber $this->tpl_name = 'acp_jabber'; $this->page_title = 'ACP_JABBER_SETTINGS'; - $jab_enable = request_var('jab_enable', (bool) $config['jab_enable']); - $jab_host = request_var('jab_host', (string) $config['jab_host']); - $jab_port = request_var('jab_port', (int) $config['jab_port']); - $jab_username = request_var('jab_username', (string) $config['jab_username']); - $jab_password = request_var('jab_password', (string) $config['jab_password']); - $jab_package_size = request_var('jab_package_size', (int) $config['jab_package_size']); - $jab_use_ssl = request_var('jab_use_ssl', (bool) $config['jab_use_ssl']); + $jab_enable = $request->variable('jab_enable', (bool) $config['jab_enable']); + $jab_host = $request->variable('jab_host', (string) $config['jab_host']); + $jab_port = $request->variable('jab_port', (int) $config['jab_port']); + $jab_username = $request->variable('jab_username', (string) $config['jab_username']); + $jab_password = $request->variable('jab_password', (string) $config['jab_password']); + $jab_package_size = $request->variable('jab_package_size', (int) $config['jab_package_size']); + $jab_use_ssl = $request->variable('jab_use_ssl', (bool) $config['jab_use_ssl']); $form_name = 'acp_jabber'; add_form_key($form_name); @@ -61,8 +67,6 @@ class acp_jabber trigger_error($user->lang['FORM_INVALID']. adm_back_link($this->u_action), E_USER_WARNING); } - $error = array(); - $message = $user->lang['JAB_SETTINGS_CHANGED']; $log = 'JAB_SETTINGS_CHANGED'; @@ -99,15 +103,18 @@ class acp_jabber $db->sql_query($sql); } - set_config('jab_enable', $jab_enable); - set_config('jab_host', $jab_host); - set_config('jab_port', $jab_port); - set_config('jab_username', $jab_username); - set_config('jab_password', $jab_password); - set_config('jab_package_size', $jab_package_size); - set_config('jab_use_ssl', $jab_use_ssl); + $config->set('jab_enable', $jab_enable); + $config->set('jab_host', $jab_host); + $config->set('jab_port', $jab_port); + $config->set('jab_username', $jab_username); + if ($jab_password !== '********') + { + $config->set('jab_password', $jab_password); + } + $config->set('jab_package_size', $jab_package_size); + $config->set('jab_use_ssl', $jab_use_ssl); - add_log('admin', 'LOG_' . $log); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_' . $log); trigger_error($message . adm_back_link($this->u_action)); } @@ -118,7 +125,7 @@ class acp_jabber 'JAB_HOST' => $jab_host, 'JAB_PORT' => ($jab_port) ? $jab_port : '', 'JAB_USERNAME' => $jab_username, - 'JAB_PASSWORD' => $jab_password, + 'JAB_PASSWORD' => $jab_password !== '' ? '********' : '', 'JAB_PACKAGE_SIZE' => $jab_package_size, 'JAB_USE_SSL' => $jab_use_ssl, 'S_CAN_USE_SSL' => jabber::can_use_ssl(), diff --git a/phpBB/includes/acp/acp_language.php b/phpBB/includes/acp/acp_language.php index 013aab670f..03172e475a 100644 --- a/phpBB/includes/acp/acp_language.php +++ b/phpBB/includes/acp/acp_language.php @@ -1,9 +1,13 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -15,9 +19,6 @@ if (!defined('IN_PHPBB')) exit; } -/** -* @package acp -*/ class acp_language { var $u_action; @@ -30,151 +31,39 @@ class acp_language function main($id, $mode) { - global $config, $db, $user, $auth, $template, $cache; - global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix; - global $safe_mode, $file_uploads; - global $request; + global $config, $db, $user, $template, $phpbb_log, $phpbb_container; + global $phpbb_root_path, $phpEx, $request; - include_once($phpbb_root_path . 'includes/functions_user.' . $phpEx); - - $this->default_variables(); + if (!function_exists('validate_language_iso_name')) + { + include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + } // Check and set some common vars - $action = (isset($_POST['update_details'])) ? 'update_details' : ''; - $action = (isset($_POST['download_file'])) ? 'download_file' : $action; - $action = (isset($_POST['upload_file'])) ? 'upload_file' : $action; - $action = (isset($_POST['upload_data'])) ? 'upload_data' : $action; - $action = (isset($_POST['submit_file'])) ? 'submit_file' : $action; $action = (isset($_POST['remove_store'])) ? 'details' : $action; $submit = (empty($action) && !isset($_POST['update']) && !isset($_POST['test_connection'])) ? false : true; - $action = (empty($action)) ? request_var('action', '') : $action; + $action = (empty($action)) ? $request->variable('action', '') : $action; $form_name = 'acp_lang'; add_form_key('acp_lang'); - $lang_id = request_var('id', 0); - if (isset($_POST['missing_file'])) - { - $missing_file = request_var('missing_file', array('' => 0)); - $request->overwrite('language_file', array_shift(array_keys($missing_file))); - } + $lang_id = $request->variable('id', 0); - $selected_lang_file = request_var('language_file', '|common.' . $phpEx); + $selected_lang_file = $request->variable('language_file', '|common.' . $phpEx); list($this->language_directory, $this->language_file) = explode('|', $selected_lang_file); $this->language_directory = basename($this->language_directory); $this->language_file = basename($this->language_file); - // detect language file type - if ($this->language_directory == 'email') - { - $language_file_type = 'email'; - $request_default = ''; - } - else if (strpos($this->language_file, 'help_') === 0) - { - $language_file_type = 'help'; - $request_default = array(0 => array(0 => '')); - } - else - { - $language_file_type = 'normal'; - $request_default = array('' => ''); - } - $user->add_lang('acp/language'); $this->tpl_name = 'acp_language'; $this->page_title = 'ACP_LANGUAGE_PACKS'; - if ($submit && $action == 'upload_data' && request_var('test_connection', '')) - { - $test_connection = false; - $action = 'upload_file'; - $method = request_var('method', ''); - - include_once($phpbb_root_path . 'includes/functions_transfer.' . $phpEx); - - switch ($method) - { - case 'ftp': - $transfer = new ftp( - request_var('host', ''), - request_var('username', ''), - htmlspecialchars_decode($request->untrimmed_variable('password', '')), - request_var('root_path', ''), - request_var('port', ''), - request_var('timeout', '') - ); - break; - - case 'ftp_fsock': - $transfer = new ftp_fsock( - request_var('host', ''), - request_var('username', ''), - htmlspecialchars_decode($request->untrimmed_variable('password', '')), - request_var('root_path', ''), - request_var('port', ''), - request_var('timeout', '') - ); - break; - - default: - trigger_error($user->lang['INVALID_UPLOAD_METHOD'], E_USER_ERROR); - break; - } - - $test_connection = $transfer->open_session(); - $transfer->close_session(); - } - switch ($action) { - case 'upload_file': - - include_once($phpbb_root_path . 'includes/functions_transfer.' . $phpEx); - - $method = request_var('method', ''); - - 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), - )); - } - - $hidden_data = build_hidden_fields(array( - 'file' => $this->language_file, - 'dir' => $this->language_directory, - 'language_file' => $selected_lang_file, - 'method' => $method) - ); - - $hidden_data .= build_hidden_fields(array('entry' => $request->variable('entry', $request_default, true, \phpbb\request\request_interface::POST))); - - $template->assign_vars(array( - 'S_UPLOAD' => true, - 'NAME' => $method, - 'U_ACTION' => $this->u_action . "&id=$lang_id&action=upload_data", - 'U_BACK' => $this->u_action . "&id=$lang_id&action=details&language_file=" . urlencode($selected_lang_file), - 'HIDDEN' => $hidden_data, - - 'S_CONNECTION_SUCCESS' => (request_var('test_connection', '') && $test_connection === true) ? true : false, - 'S_CONNECTION_FAILED' => (request_var('test_connection', '') && $test_connection !== true) ? true : false - )); - break; - case 'update_details': if (!$submit || !check_form_key($form_name)) @@ -195,273 +84,20 @@ class acp_language $db->sql_freeresult($result); $sql_ary = array( - 'lang_english_name' => request_var('lang_english_name', $row['lang_english_name']), - 'lang_local_name' => utf8_normalize_nfc(request_var('lang_local_name', $row['lang_local_name'], true)), - 'lang_author' => utf8_normalize_nfc(request_var('lang_author', $row['lang_author'], true)), + 'lang_english_name' => $request->variable('lang_english_name', $row['lang_english_name']), + 'lang_local_name' => $request->variable('lang_local_name', $row['lang_local_name'], true), + 'lang_author' => $request->variable('lang_author', $row['lang_author'], true), ); $db->sql_query('UPDATE ' . LANG_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' WHERE lang_id = ' . $lang_id); - add_log('admin', 'LOG_LANGUAGE_PACK_UPDATED', $sql_ary['lang_english_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_LANGUAGE_PACK_UPDATED', false, array($sql_ary['lang_english_name'])); trigger_error($user->lang['LANGUAGE_DETAILS_UPDATED'] . adm_back_link($this->u_action)); break; - case 'submit_file': - case 'download_file': - case 'upload_data': - - if (!$submit || !check_form_key($form_name)) - { - trigger_error($user->lang['FORM_INVALID']. adm_back_link($this->u_action), E_USER_WARNING); - } - - $entry_value = $request->variable('entry', $request_default, true, \phpbb\request\request_interface::POST); - - if (!$lang_id || !$entry_value) - { - trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action), E_USER_WARNING); - } - - if (!$this->language_file || (!$this->language_directory && !in_array($this->language_file, $this->main_files))) - { - trigger_error($user->lang['NO_FILE_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING); - } - - $sql = 'SELECT * - FROM ' . LANG_TABLE . " - WHERE lang_id = $lang_id"; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if (!$row) - { - trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action), E_USER_WARNING); - } - - // Before we attempt to write anything let's check if the admin really chose a correct filename - switch ($this->language_directory) - { - case 'email': - // Get email templates - $email_files = filelist($phpbb_root_path . 'language/' . $row['lang_iso'], 'email', 'txt'); - $email_files = $email_files['email/']; - - if (!in_array($this->language_file, $email_files)) - { - trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id), E_USER_WARNING); - } - break; - - case 'acp': - // Get acp files - $acp_files = filelist($phpbb_root_path . 'language/' . $row['lang_iso'], 'acp', $phpEx); - $acp_files = $acp_files['acp/']; - - if (!in_array($this->language_file, $acp_files)) - { - trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id), E_USER_WARNING); - } - break; - - case 'mods': - // Get mod files - $mods_files = filelist($phpbb_root_path . 'language/' . $row['lang_iso'], 'mods', $phpEx); - $mods_files = (isset($mods_files['mods/'])) ? $mods_files['mods/'] : array(); - - if (!in_array($this->language_file, $mods_files)) - { - trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id), E_USER_WARNING); - } - break; - - default: - if (!in_array($this->language_file, $this->main_files)) - { - trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id), E_USER_WARNING); - } - break; - } - - if (!$safe_mode) - { - $mkdir_ary = array('language', 'language/' . $row['lang_iso']); - - if ($this->language_directory) - { - $mkdir_ary[] = 'language/' . $row['lang_iso'] . '/' . $this->language_directory; - } - - foreach ($mkdir_ary as $dir) - { - $dir = $phpbb_root_path . 'store/' . $dir; - - if (!is_dir($dir)) - { - if (!@mkdir($dir, 0777)) - { - trigger_error("Could not create directory $dir", E_USER_ERROR); - } - @chmod($dir, 0777); - } - } - } - - // Get target filename for storage folder - $filename = $this->get_filename($row['lang_iso'], $this->language_directory, $this->language_file, true, true); - $fp = @fopen($phpbb_root_path . $filename, 'wb'); - - if (!$fp) - { - trigger_error(sprintf($user->lang['UNABLE_TO_WRITE_FILE'], $filename) . adm_back_link($this->u_action . '&id=' . $lang_id . '&action=details&language_file=' . urlencode($selected_lang_file)), E_USER_WARNING); - } - - if ($language_file_type == 'email') - { - // Email Template - $entry = $this->prepare_lang_entry(htmlspecialchars_decode($entry_value), false); - fwrite($fp, $entry); - } - else - { - $name = (($this->language_directory) ? $this->language_directory . '_' : '') . $this->language_file; - $header = str_replace(array('{FILENAME}', '{LANG_NAME}', '{CHANGED}', '{AUTHOR}'), array($name, $row['lang_english_name'], date('Y-m-d', time()), $row['lang_author']), $this->language_file_header); - - if ($language_file_type == 'help') - { - // Help File - $header .= '$help = array(' . "\n"; - fwrite($fp, $header); - - foreach ($entry_value as $key => $value) - { - if (!is_array($value)) - { - continue; - } - - $entry = "\tarray(\n"; - - foreach ($value as $_key => $_value) - { - $entry .= "\t\t" . (int) $_key . "\t=> '" . $this->prepare_lang_entry(htmlspecialchars_decode($_value)) . "',\n"; - } - - $entry .= "\t),\n"; - fwrite($fp, $entry); - } - - $footer = ");\n\n?>"; - fwrite($fp, $footer); - } - else if ($language_file_type == 'normal') - { - // Language File - $header .= $this->lang_header; - fwrite($fp, $header); - - foreach ($entry_value as $key => $value) - { - $entry = $this->format_lang_array(htmlspecialchars_decode($key), htmlspecialchars_decode($value)); - fwrite($fp, $entry); - } - - $footer = "));\n\n?>"; - fwrite($fp, $footer); - } - } - - fclose($fp); - - if ($action == 'download_file') - { - header('Pragma: no-cache'); - header('Content-Type: application/octetstream; name="' . $this->language_file . '"'); - header('Content-disposition: attachment; filename=' . $this->language_file); - - $fp = @fopen($phpbb_root_path . $filename, 'rb'); - while ($buffer = fread($fp, 1024)) - { - echo $buffer; - } - fclose($fp); - - add_log('admin', 'LOG_LANGUAGE_FILE_SUBMITTED', $this->language_file); - - exit; - } - else if ($action == 'upload_data') - { - $sql = 'SELECT lang_iso - FROM ' . LANG_TABLE . " - WHERE lang_id = $lang_id"; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - $file = request_var('file', ''); - $dir = request_var('dir', ''); - - $selected_lang_file = $dir . '|' . $file; - - $old_file = '/' . $this->get_filename($row['lang_iso'], $dir, $file, false, true); - $lang_path = 'language/' . $row['lang_iso'] . '/' . (($dir) ? $dir . '/' : ''); - - include_once($phpbb_root_path . 'includes/functions_transfer.' . $phpEx); - $method = request_var('method', ''); - - if ($method != 'ftp' && $method != 'ftp_fsock') - { - trigger_error($user->lang['INVALID_UPLOAD_METHOD'], E_USER_ERROR); - } - - $transfer = new $method( - request_var('host', ''), - request_var('username', ''), - htmlspecialchars_decode($request->untrimmed_variable('password', '')), - request_var('root_path', ''), - request_var('port', ''), - request_var('timeout', '') - ); - - if (($result = $transfer->open_session()) !== true) - { - trigger_error($user->lang[$result] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id . '&language_file=' . urlencode($selected_lang_file)), E_USER_WARNING); - } - - $transfer->rename($lang_path . $file, $lang_path . $file . '.bak'); - $result = $transfer->copy_file('store/' . $lang_path . $file, $lang_path . $file); - - if ($result === false) - { - // If failed, try to rename again and print error out... - $transfer->delete_file($lang_path . $file); - $transfer->rename($lang_path . $file . '.bak', $lang_path . $file); - - trigger_error($user->lang['UPLOAD_FAILED'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id . '&language_file=' . urlencode($selected_lang_file)), E_USER_WARNING); - } - - $transfer->close_session(); - - // Remove from storage folder - if (file_exists($phpbb_root_path . 'store/' . $lang_path . $file)) - { - @unlink($phpbb_root_path . 'store/' . $lang_path . $file); - } - - add_log('admin', 'LOG_LANGUAGE_FILE_REPLACED', $file); - - trigger_error($user->lang['UPLOAD_COMPLETED'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id . '&language_file=' . urlencode($selected_lang_file))); - } - - add_log('admin', 'LOG_LANGUAGE_FILE_SUBMITTED', $this->language_file); - $action = 'details'; - - // no break; - case 'details': if (!$lang_id) @@ -478,308 +114,82 @@ class acp_language $lang_entries = $db->sql_fetchrow($result); $db->sql_freeresult($result); - $lang_iso = $lang_entries['lang_iso']; - $missing_vars = $missing_files = array(); - - // Get email templates - $email_files = filelist($phpbb_root_path . 'language/' . $config['default_lang'], 'email', 'txt'); - $email_files = $email_files['email/']; - - // Get acp files - $acp_files = filelist($phpbb_root_path . 'language/' . $config['default_lang'], 'acp', $phpEx); - $acp_files = $acp_files['acp/']; - - // Get mod files - $mods_files = filelist($phpbb_root_path . 'language/' . $config['default_lang'], 'mods', $phpEx); - $mods_files = (isset($mods_files['mods/'])) ? $mods_files['mods/'] : array(); - - // Check if our current filename matches the files - switch ($this->language_directory) + if (!$lang_entries) { - case 'email': - if (!in_array($this->language_file, $email_files)) - { - trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id), E_USER_WARNING); - } - break; - - case 'acp': - if (!in_array($this->language_file, $acp_files)) - { - trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id), E_USER_WARNING); - } - break; - - case 'mods': - if (!in_array($this->language_file, $mods_files)) - { - trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id), E_USER_WARNING); - } - break; - - default: - if (!in_array($this->language_file, $this->main_files)) - { - trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id), E_USER_WARNING); - } - } - - if (isset($_POST['remove_store'])) - { - $store_filename = $this->get_filename($lang_iso, $this->language_directory, $this->language_file, true, true); - - if (file_exists($phpbb_root_path . $store_filename)) - { - @unlink($phpbb_root_path . $store_filename); - } + trigger_error($user->lang['LANGUAGE_PACK_NOT_EXIST'] . adm_back_link($this->u_action), E_USER_WARNING); } - include_once($phpbb_root_path . 'includes/functions_transfer.' . $phpEx); - - $methods = transfer::methods(); - - foreach ($methods as $method) - { - $template->assign_block_vars('buttons', array( - 'VALUE' => $method - )); - } + $lang_iso = $lang_entries['lang_iso']; $template->assign_vars(array( 'S_DETAILS' => true, 'U_ACTION' => $this->u_action . "&action=details&id=$lang_id", 'U_BACK' => $this->u_action, + 'LANG_LOCAL_NAME' => $lang_entries['lang_local_name'], 'LANG_ENGLISH_NAME' => $lang_entries['lang_english_name'], - 'LANG_ISO' => $lang_entries['lang_iso'], + 'LANG_ISO' => $lang_iso, 'LANG_AUTHOR' => $lang_entries['lang_author'], - 'ALLOW_UPLOAD' => sizeof($methods) - ) - ); + 'L_MISSING_FILES' => $user->lang('THOSE_MISSING_LANG_FILES', $lang_entries['lang_local_name']), + 'L_MISSING_VARS_EXPLAIN' => $user->lang('THOSE_MISSING_LANG_VARIABLES', $lang_entries['lang_local_name']), + )); - // If current lang is different from the default lang, then first try to grab missing/additional vars + // If current lang is different from the default lang, then highlight missing files and variables if ($lang_iso != $config['default_lang']) { - $is_missing_var = false; - - foreach ($this->main_files as $file) + try { - if (file_exists($phpbb_root_path . $this->get_filename($lang_iso, '', $file))) - { - $missing_vars[$file] = $this->compare_language_files($config['default_lang'], $lang_iso, '', $file); - - if (sizeof($missing_vars[$file])) - { - $is_missing_var = true; - } - } - else - { - $missing_files[] = $this->get_filename($lang_iso, '', $file); - } + $iterator = new \RecursiveIteratorIterator( + new \phpbb\recursive_dot_prefix_filter_iterator( + new \RecursiveDirectoryIterator( + $phpbb_root_path . 'language/' . $config['default_lang'] . '/', + \FilesystemIterator::SKIP_DOTS + ) + ), + \RecursiveIteratorIterator::LEAVES_ONLY + ); } - - // Now go through acp/mods directories - foreach ($acp_files as $file) + catch (\Exception $e) { - if (file_exists($phpbb_root_path . $this->get_filename($lang_iso, 'acp', $file))) - { - $missing_vars['acp/' . $file] = $this->compare_language_files($config['default_lang'], $lang_iso, 'acp', $file); - - if (sizeof($missing_vars['acp/' . $file])) - { - $is_missing_var = true; - } - } - else - { - $missing_files[] = $this->get_filename($lang_iso, 'acp', $file); - } + return array(); } - if (sizeof($mods_files)) + foreach ($iterator as $file_info) { - foreach ($mods_files as $file) + /** @var \RecursiveDirectoryIterator $file_info */ + $relative_path = $iterator->getInnerIterator()->getSubPathname(); + $relative_path = str_replace(DIRECTORY_SEPARATOR, '/', $relative_path); + + if (file_exists($phpbb_root_path . 'language/' . $lang_iso . '/' . $relative_path)) { - if (file_exists($phpbb_root_path . $this->get_filename($lang_iso, 'mods', $file))) + if (substr($relative_path, 0 - strlen($phpEx)) === $phpEx) { - $missing_vars['mods/' . $file] = $this->compare_language_files($config['default_lang'], $lang_iso, 'mods', $file); + $missing_vars = $this->compare_language_files($config['default_lang'], $lang_iso, $relative_path); - if (sizeof($missing_vars['mods/' . $file])) + if (!empty($missing_vars)) { - $is_missing_var = true; + $template->assign_block_vars('missing_varfile', array( + 'FILE_NAME' => $relative_path, + )); + + foreach ($missing_vars as $var) + { + $template->assign_block_vars('missing_varfile.variable', array( + 'VAR_NAME' => $var, + )); + } } } - else - { - $missing_files[] = $this->get_filename($lang_iso, 'mods', $file); - } - } - } - - // More missing files... for example email templates? - foreach ($email_files as $file) - { - if (!file_exists($phpbb_root_path . $this->get_filename($lang_iso, 'email', $file))) - { - $missing_files[] = $this->get_filename($lang_iso, 'email', $file); - } - } - - if (sizeof($missing_files)) - { - $template->assign_vars(array( - 'S_MISSING_FILES' => true, - 'L_MISSING_FILES' => sprintf($user->lang['THOSE_MISSING_LANG_FILES'], $lang_entries['lang_local_name']), - 'MISSING_FILES' => implode('<br />', $missing_files)) - ); - } - - if ($is_missing_var) - { - $template->assign_vars(array( - 'S_MISSING_VARS' => true, - 'L_MISSING_VARS_EXPLAIN' => sprintf($user->lang['THOSE_MISSING_LANG_VARIABLES'], $lang_entries['lang_local_name']), - 'U_MISSING_ACTION' => $this->u_action . "&action=$action&id=$lang_id") - ); - - foreach ($missing_vars as $file => $vars) - { - if (!sizeof($vars)) - { - continue; - } - - $template->assign_block_vars('missing', array( - 'FILE' => $file, - 'TPL' => $this->print_language_entries($vars, '', false), - 'KEY' => (strpos($file, '/') === false) ? '|' . $file : str_replace('/', '|', $file)) - ); } - } - } - - // Main language files - $s_lang_options = '<option value="|common.' . $phpEx . '" class="sep">' . $user->lang['LANGUAGE_FILES'] . '</option>'; - foreach ($this->main_files as $file) - { - if (strpos($file, 'help_') === 0) - { - continue; - } - - $prefix = (file_exists($phpbb_root_path . $this->get_filename($lang_iso, '', $file, true, true))) ? '* ' : ''; - - $selected = (!$this->language_directory && $this->language_file == $file) ? ' selected="selected"' : ''; - $s_lang_options .= '<option value="|' . $file . '"' . $selected . '>' . $prefix . $file . '</option>'; - } - - // Help Files - $s_lang_options .= '<option value="|common.' . $phpEx . '" class="sep">' . $user->lang['HELP_FILES'] . '</option>'; - foreach ($this->main_files as $file) - { - if (strpos($file, 'help_') !== 0) - { - continue; - } - - $prefix = (file_exists($phpbb_root_path . $this->get_filename($lang_iso, '', $file, true, true))) ? '* ' : ''; - - $selected = (!$this->language_directory && $this->language_file == $file) ? ' selected="selected"' : ''; - $s_lang_options .= '<option value="|' . $file . '"' . $selected . '>' . $prefix . $file . '</option>'; - } - - // Now every other language directory - $check_files = array('email', 'acp', 'mods'); - - foreach ($check_files as $check) - { - if (!sizeof(${$check . '_files'})) - { - continue; - } - - $s_lang_options .= '<option value="|common.' . $phpEx . '" class="sep">' . $user->lang[strtoupper($check) . '_FILES'] . '</option>'; - - foreach (${$check . '_files'} as $file) - { - $prefix = (file_exists($phpbb_root_path . $this->get_filename($lang_iso, $check, $file, true, true))) ? '* ' : ''; - - $selected = ($this->language_directory == $check && $this->language_file == $file) ? ' selected="selected"' : ''; - $s_lang_options .= '<option value="' . $check . '|' . $file . '"' . $selected . '>' . $prefix . $file . '</option>'; - } - } - - // Get Language Entries - if saved within store folder, we take this one (with the option to remove it) - $lang = array(); - - $is_email_file = ($this->language_directory == 'email') ? true : false; - $is_help_file = (strpos($this->language_file, 'help_') === 0) ? true : false; - - $file_from_store = (file_exists($phpbb_root_path . $this->get_filename($lang_iso, $this->language_directory, $this->language_file, true, true))) ? true : false; - $no_store_filename = $this->get_filename($lang_iso, $this->language_directory, $this->language_file); - - if (!$file_from_store && !file_exists($phpbb_root_path . $no_store_filename)) - { - $print_message = sprintf($user->lang['MISSING_LANGUAGE_FILE'], $no_store_filename); - } - else - { - if ($is_email_file) - { - $lang = file_get_contents($phpbb_root_path . $this->get_filename($lang_iso, $this->language_directory, $this->language_file, $file_from_store)); - } - else - { - $help = array(); - include($phpbb_root_path . $this->get_filename($lang_iso, $this->language_directory, $this->language_file, $file_from_store)); - - if ($is_help_file) + else { - $lang = $help; - unset($help); + $template->assign_block_vars('missing_files', array( + 'FILE_NAME' => $relative_path, + )); } } - - $print_message = (($this->language_directory) ? $this->language_directory . '/' : '') . $this->language_file; - } - - // Normal language pack entries - $template->assign_vars(array( - 'U_ENTRY_ACTION' => $this->u_action . "&action=details&id=$lang_id#entries", - 'S_EMAIL_FILE' => $is_email_file, - 'S_FROM_STORE' => $file_from_store, - 'S_LANG_OPTIONS' => $s_lang_options, - 'PRINT_MESSAGE' => $print_message, - ) - ); - - if (!$is_email_file) - { - $tpl = ''; - $name = (($this->language_directory) ? $this->language_directory . '/' : '') . $this->language_file; - - if (isset($missing_vars[$name]) && sizeof($missing_vars[$name])) - { - $tpl .= $this->print_language_entries($missing_vars[$name], '* '); - } - - $tpl .= $this->print_language_entries($lang); - - $template->assign_var('TPL', $tpl); - unset($tpl); } - else - { - $template->assign_vars(array( - 'LANG' => $lang) - ); - - unset($lang); - } - return; - break; case 'delete': @@ -817,7 +227,7 @@ class acp_language $sql = 'DELETE FROM ' . PROFILE_FIELDS_LANG_TABLE . ' WHERE lang_id = ' . $lang_id; $db->sql_query($sql); - add_log('admin', 'LOG_LANGUAGE_PACK_DELETED', $row['lang_english_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_LANGUAGE_PACK_DELETED', false, array($row['lang_english_name'])); trigger_error(sprintf($user->lang['LANGUAGE_PACK_DELETED'], $row['lang_english_name']) . adm_back_link($this->u_action)); } @@ -829,12 +239,12 @@ class acp_language 'action' => $action, 'id' => $lang_id, ); - confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields($s_hidden_fields)); + confirm_box(false, $user->lang('DELETE_LANGUAGE_CONFIRM', $row['lang_english_name']), build_hidden_fields($s_hidden_fields)); } break; case 'install': - $lang_iso = request_var('iso', ''); + $lang_iso = $request->variable('iso', ''); $lang_iso = basename($lang_iso); if (!$lang_iso || !file_exists("{$phpbb_root_path}language/$lang_iso/iso.txt")) @@ -922,134 +332,13 @@ class acp_language } $db->sql_freeresult($result); - add_log('admin', 'LOG_LANGUAGE_PACK_INSTALLED', $lang_pack['name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_LANGUAGE_PACK_INSTALLED', false, array($lang_pack['name'])); $message = sprintf($user->lang['LANGUAGE_PACK_INSTALLED'], $lang_pack['name']); $message .= ($notify_cpf_update) ? '<br /><br />' . $user->lang['LANGUAGE_PACK_CPF_UPDATE'] : ''; trigger_error($message . adm_back_link($this->u_action)); break; - - case 'download': - - if (!$lang_id) - { - trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action), E_USER_WARNING); - } - - $sql = 'SELECT * - FROM ' . LANG_TABLE . ' - WHERE lang_id = ' . $lang_id; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - $use_method = request_var('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_SELECT_METHOD' => true, - 'U_BACK' => $this->u_action, - 'U_ACTION' => $this->u_action . "&action=$action&id=$lang_id", - 'RADIO_BUTTONS' => $radio_buttons) - ); - - return; - } - - if (!in_array($use_method, $methods)) - { - $use_method = '.tar'; - } - - include_once($phpbb_root_path . 'includes/functions_compress.' . $phpEx); - - if ($use_method == '.zip') - { - $compress = new compress_zip('w', $phpbb_root_path . 'store/lang_' . $row['lang_iso'] . $use_method); - } - else - { - $compress = new compress_tar('w', $phpbb_root_path . 'store/lang_' . $row['lang_iso'] . $use_method, $use_method); - } - - // Get email templates - $email_templates = filelist($phpbb_root_path . 'language/' . $row['lang_iso'], 'email', 'txt'); - $email_templates = $email_templates['email/']; - - // Get acp files - $acp_files = filelist($phpbb_root_path . 'language/' . $row['lang_iso'], 'acp', $phpEx); - $acp_files = $acp_files['acp/']; - - // Get mod files - $mod_files = filelist($phpbb_root_path . 'language/' . $row['lang_iso'], 'mods', $phpEx); - $mod_files = (isset($mod_files['mods/'])) ? $mod_files['mods/'] : array(); - - // Add main files - $this->add_to_archive($compress, $this->main_files, $row['lang_iso']); - - // Add search files if they exist... - if (file_exists($phpbb_root_path . 'language/' . $row['lang_iso'] . '/search_ignore_words.' . $phpEx)) - { - $this->add_to_archive($compress, array("search_ignore_words.$phpEx"), $row['lang_iso']); - } - - if (file_exists($phpbb_root_path . 'language/' . $row['lang_iso'] . '/search_synonyms.' . $phpEx)) - { - $this->add_to_archive($compress, array("search_synonyms.$phpEx"), $row['lang_iso']); - } - - // Write files in folders - $this->add_to_archive($compress, $email_templates, $row['lang_iso'], 'email'); - $this->add_to_archive($compress, $acp_files, $row['lang_iso'], 'acp'); - $this->add_to_archive($compress, $mod_files, $row['lang_iso'], 'mods'); - - // Write ISO File - $iso_src = htmlspecialchars_decode($row['lang_english_name']) . "\n"; - $iso_src .= htmlspecialchars_decode($row['lang_local_name']) . "\n"; - $iso_src .= htmlspecialchars_decode($row['lang_author']); - $compress->add_data($iso_src, 'language/' . $row['lang_iso'] . '/iso.txt'); - - // index.htm files - $compress->add_data('', 'language/' . $row['lang_iso'] . '/index.htm'); - $compress->add_data('', 'language/' . $row['lang_iso'] . '/email/index.htm'); - $compress->add_data('', 'language/' . $row['lang_iso'] . '/acp/index.htm'); - - if (sizeof($mod_files)) - { - $compress->add_data('', 'language/' . $row['lang_iso'] . '/mods/index.htm'); - } - - $compress->close(); - - $compress->download('lang_' . $row['lang_iso']); - @unlink($phpbb_root_path . 'store/lang_' . $row['lang_iso'] . $use_method); - - exit; - - break; } $sql = 'SELECT user_lang, COUNT(user_lang) AS lang_count @@ -1091,37 +380,19 @@ class acp_language $db->sql_freeresult($result); $new_ary = $iso = array(); - $dp = @opendir("{$phpbb_root_path}language"); - if ($dp) + /** @var \phpbb\language\language_file_helper $language_helper */ + $language_helper = $phpbb_container->get('language.helper.language_file'); + $iso = $language_helper->get_available_languages(); + + foreach ($iso as $lang_array) { - while (($file = readdir($dp)) !== false) - { - if ($file[0] == '.' || !is_dir($phpbb_root_path . 'language/' . $file)) - { - continue; - } + $lang_iso = $lang_array['iso']; - if (file_exists("{$phpbb_root_path}language/$file/iso.txt")) - { - if (!in_array($file, $installed)) - { - if ($iso = file("{$phpbb_root_path}language/$file/iso.txt")) - { - if (sizeof($iso) == 3) - { - $new_ary[$file] = array( - 'iso' => $file, - 'name' => trim($iso[0]), - 'local_name'=> trim($iso[1]), - 'author' => trim($iso[2]) - ); - } - } - } - } + if (!in_array($lang_iso, $installed)) + { + $new_ary[$lang_iso] = $lang_array; } - closedir($dp); } unset($installed); @@ -1142,291 +413,31 @@ class acp_language unset($new_ary); } - /** - * Set default language variables/header - */ - function default_variables() - { - global $phpEx; - - $this->language_file_header = '<?php -/** -* -* {FILENAME} [{LANG_NAME}] -* -* @package language -* @copyright (c) ' . date('Y') . ' phpBB Group -* @author {CHANGED} - {AUTHOR} -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 -* -*/ - -/** -* DO NOT CHANGE -*/ -if (!defined(\'IN_PHPBB\')) -{ - exit; -} - -if (empty($lang) || !is_array($lang)) -{ - $lang = array(); -} - -// DEVELOPERS PLEASE NOTE -// -// All language files should use UTF-8 as their encoding and the files must not contain a BOM. -// -// Placeholders can now contain order information, e.g. instead of -// \'Page %s of %s\' you can (and should) write \'Page %1$s of %2$s\', this allows -// translators to re-order the output of data while ensuring it remains correct -// -// You do not need this where single placeholders are used, e.g. \'Message %d\' is fine -// equally where a string contains only two placeholders which are used to wrap text -// in a url you again do not need to specify an order e.g., \'Click %sHERE%s\' is fine -'; - - $this->lang_header = ' -$lang = array_merge($lang, array( -'; - - // Language files in language root directory - $this->main_files = array("captcha_qa.$phpEx", "captcha_recaptcha.$phpEx", "common.$phpEx", "groups.$phpEx", "install.$phpEx", "mcp.$phpEx", "memberlist.$phpEx", "posting.$phpEx", "search.$phpEx", "ucp.$phpEx", "viewforum.$phpEx", "viewtopic.$phpEx", "help_bbcode.$phpEx", "help_faq.$phpEx"); - } - - /** - * Get filename/location of language file - */ - function get_filename($lang_iso, $directory, $filename, $check_store = false, $only_return_filename = false) - { - global $phpbb_root_path, $safe_mode; - - $check_filename = "language/$lang_iso/" . (($directory) ? $directory . '/' : '') . $filename; - - if ($check_store) - { - $check_store_filename = ($safe_mode) ? "store/langfile_{$lang_iso}" . (($directory) ? '_' . $directory : '') . "_{$filename}" : "store/language/$lang_iso/" . (($directory) ? $directory . '/' : '') . $filename; - - if (!$only_return_filename && file_exists($phpbb_root_path . $check_store_filename)) - { - return $check_store_filename; - } - else if ($only_return_filename) - { - return $check_store_filename; - } - } - - return $check_filename; - } - - /** - * Add files to archive + * Compare two language files */ - function add_to_archive(&$compress, $filelist, $lang_iso, $directory = '') + function compare_language_files($source_lang, $dest_lang, $file) { global $phpbb_root_path; - foreach ($filelist as $file) - { - // Get source filename - $source = $this->get_filename($lang_iso, $directory, $file, true); - $destination = 'language/' . $lang_iso . '/' . (($directory) ? $directory . '/' : '') . $file; - - // Add file to archive - $compress->add_custom_file($phpbb_root_path . $source, $destination); - } - } - - /** - * Little helper to add some hardcoded template bits - */ - function add_input_field() - { - $keys = func_get_args(); + $source_file = $phpbb_root_path . 'language/' . $source_lang . '/' . $file; + $dest_file = $phpbb_root_path . 'language/' . $dest_lang . '/' . $file; - $non_static = array_shift($keys); - $value = utf8_normalize_nfc(array_shift($keys)); - - if (!$non_static) + if (!file_exists($dest_file)) { - return '<strong>' . htmlspecialchars($value, ENT_COMPAT, 'UTF-8') . '</strong>'; - } - - // If more then 270 characters, then we present a textarea, else an input field - $textarea = (utf8_strlen($value) > 270) ? true : false; - $tpl = ''; - - $tpl .= ($textarea) ? '<textarea name="' : '<input type="text" name="'; - $tpl .= 'entry[' . implode('][', array_map('utf8_htmlspecialchars', $keys)) . ']"'; - - $tpl .= ($textarea) ? ' cols="80" rows="5" class="langvalue">' : ' class="langvalue" value="'; - $tpl .= htmlspecialchars($value, ENT_COMPAT, 'UTF-8'); - $tpl .= ($textarea) ? '</textarea>' : '" />'; - - return $tpl; - } - - /** - * Print language entries - */ - function print_language_entries(&$lang_ary, $key_prefix = '', $input_field = true) - { - $tpl = ''; - - foreach ($lang_ary as $key => $value) - { - if (is_array($value)) - { - // Write key - $tpl .= ' - <tr> - <td class="row3" colspan="2">' . htmlspecialchars($key_prefix, ENT_COMPAT, 'UTF-8') . '<strong>' . htmlspecialchars($key, ENT_COMPAT, 'UTF-8') . '</strong></td> - </tr>'; - - foreach ($value as $_key => $_value) - { - if (is_array($_value)) - { - // Write key - $tpl .= ' - <tr> - <td class="row3" colspan="2">' . htmlspecialchars($key_prefix, ENT_COMPAT, 'UTF-8') . ' <strong>' . htmlspecialchars($_key, ENT_COMPAT, 'UTF-8') . '</strong></td> - </tr>'; - - foreach ($_value as $__key => $__value) - { - // Write key - $tpl .= ' - <tr> - <td class="row1" style="white-space: nowrap;">' . htmlspecialchars($key_prefix, ENT_COMPAT, 'UTF-8') . '<strong>' . htmlspecialchars($__key, ENT_COMPAT, 'UTF-8') . '</strong></td> - <td class="row2">'; - - $tpl .= $this->add_input_field($input_field, $__value, $key, $_key, $__key); - - $tpl .= '</td> - </tr>'; - } - } - else - { - // Write key - $tpl .= ' - <tr> - <td class="row1" style="white-space: nowrap;">' . htmlspecialchars($key_prefix, ENT_COMPAT, 'UTF-8') . '<strong>' . htmlspecialchars($_key, ENT_COMPAT, 'UTF-8') . '</strong></td> - <td class="row2">'; - - $tpl .= $this->add_input_field($input_field, $_value, $key, $_key); - - $tpl .= '</td> - </tr>'; - } - } - - $tpl .= ' - <tr> - <td class="spacer" colspan="2"> </td> - </tr>'; - } - else - { - // Write key - $tpl .= ' - <tr> - <td class="row1" style="white-space: nowrap;">' . htmlspecialchars($key_prefix, ENT_COMPAT, 'UTF-8') . '<strong>' . htmlspecialchars($key, ENT_COMPAT, 'UTF-8') . '</strong></td> - <td class="row2">'; - - $tpl .= $this->add_input_field($input_field, $value, $key); - - $tpl .= '</td> - </tr>'; - } + return array(); } - return $tpl; - } - - /** - * Compare two language files - */ - function compare_language_files($source_lang, $dest_lang, $directory, $file) - { - global $phpbb_root_path, $phpEx; - - $return_ary = array(); - $lang = array(); - include("{$phpbb_root_path}language/{$source_lang}/" . (($directory) ? $directory . '/' : '') . $file); + include($source_file); $lang_entry_src = $lang; $lang = array(); - - if (!file_exists($phpbb_root_path . $this->get_filename($dest_lang, $directory, $file, true))) - { - return array(); - } - - include($phpbb_root_path . $this->get_filename($dest_lang, $directory, $file, true)); - + include($dest_file); $lang_entry_dst = $lang; unset($lang); - $diff_array_keys = array_diff(array_keys($lang_entry_src), array_keys($lang_entry_dst)); - unset($lang_entry_dst); - - foreach ($diff_array_keys as $key) - { - $return_ary[$key] = $lang_entry_src[$key]; - } - - unset($lang_entry_src); - - return $return_ary; - } - - /** - * Return language string value for storage - */ - function prepare_lang_entry($text, $store = true) - { - $text = (STRIP) ? stripslashes($text) : $text; - - // Adjust for storage... - if ($store) - { - $text = str_replace("'", "\\'", str_replace('\\', '\\\\', $text)); - } - - return $text; - } - - /** - * Format language array for storage - */ - function format_lang_array($key, $value, $tabs = "\t") - { - $entry = ''; - - if (!is_array($value)) - { - $entry .= "{$tabs}'" . $this->prepare_lang_entry($key) . "'\t=> '" . $this->prepare_lang_entry($value) . "',\n"; - } - else - { - $_tabs = $tabs . "\t"; - $entry .= "\n{$tabs}'" . $this->prepare_lang_entry($key) . "'\t=> array(\n"; - - foreach ($value as $_key => $_value) - { - $entry .= $this->format_lang_array($_key, $_value, $_tabs); - } - - $entry .= "{$tabs}),\n\n"; - } - - return $entry; + return array_diff(array_keys($lang_entry_src), array_keys($lang_entry_dst)); } } diff --git a/phpBB/includes/acp/acp_logs.php b/phpBB/includes/acp/acp_logs.php index 10852e3a68..c33ca8c4fc 100644 --- a/phpBB/includes/acp/acp_logs.php +++ b/phpBB/includes/acp/acp_logs.php @@ -1,9 +1,13 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -15,37 +19,35 @@ if (!defined('IN_PHPBB')) exit; } -/** -* @package acp -*/ class acp_logs { var $u_action; function main($id, $mode) { - global $db, $user, $auth, $template, $cache, $phpbb_container; - global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + global $user, $auth, $template, $phpbb_container; + global $config; global $request; $user->add_lang('mcp'); // Set up general vars - $action = request_var('action', ''); - $forum_id = request_var('f', 0); - $topic_id = request_var('t', 0); - $start = request_var('start', 0); + $action = $request->variable('action', ''); + $forum_id = $request->variable('f', 0); + $start = $request->variable('start', 0); $deletemark = $request->variable('delmarked', false, false, \phpbb\request\request_interface::POST); $deleteall = $request->variable('delall', false, false, \phpbb\request\request_interface::POST); - $marked = request_var('mark', array(0)); + $marked = $request->variable('mark', array(0)); // Sort keys - $sort_days = request_var('st', 0); - $sort_key = request_var('sk', 't'); - $sort_dir = request_var('sd', 'd'); + $sort_days = $request->variable('st', 0); + $sort_key = $request->variable('sk', 't'); + $sort_dir = $request->variable('sd', 'd'); $this->tpl_name = 'acp_logs'; $this->log_type = constant('LOG_' . strtoupper($mode)); + + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); // Delete entries if requested and able @@ -53,28 +55,27 @@ class acp_logs { if (confirm_box(true)) { - $where_sql = ''; + $conditions = array(); if ($deletemark && sizeof($marked)) { - $sql_in = array(); - foreach ($marked as $mark) - { - $sql_in[] = $mark; - } - $where_sql = ' AND ' . $db->sql_in_set('log_id', $sql_in); - unset($sql_in); + $conditions['log_id'] = array('IN' => $marked); } - if ($where_sql || $deleteall) + if ($deleteall) { - $sql = 'DELETE FROM ' . LOG_TABLE . " - WHERE log_type = {$this->log_type} - $where_sql"; - $db->sql_query($sql); + if ($sort_days) + { + $conditions['log_time'] = array('>=', time() - ($sort_days * 86400)); + } - add_log('admin', 'LOG_CLEAR_' . strtoupper($mode)); + $keywords = $request->variable('keywords', '', true); + $conditions['keywords'] = $keywords; } + + /* @var $phpbb_log \phpbb\log\log_interface */ + $phpbb_log = $phpbb_container->get('log'); + $phpbb_log->delete($mode, $conditions); } else { @@ -106,7 +107,7 @@ class acp_logs $sql_where = ($sort_days) ? (time() - ($sort_days * 86400)) : 0; $sql_sort = $sort_by_sql[$sort_key] . ' ' . (($sort_dir == 'd') ? 'DESC' : 'ASC'); - $keywords = utf8_normalize_nfc(request_var('keywords', '', true)); + $keywords = $request->variable('keywords', '', true); $keywords_param = !empty($keywords) ? '&keywords=' . urlencode(htmlspecialchars_decode($keywords)) : ''; $l_title = $user->lang['ACP_' . strtoupper($mode) . '_LOGS']; @@ -118,7 +119,7 @@ class acp_logs if ($mode == 'mod') { $forum_box = '<option value="0">' . $user->lang['ALL_FORUMS'] . '</option>' . make_forum_select($forum_id); - + $template->assign_vars(array( 'S_SHOW_FORUMS' => true, 'S_FORUM_BOX' => $forum_box) @@ -149,7 +150,7 @@ class acp_logs foreach ($log_data as $row) { $data = array(); - + $checks = array('viewtopic', 'viewlogs', 'viewforum'); foreach ($checks as $check) { diff --git a/phpBB/includes/acp/acp_main.php b/phpBB/includes/acp/acp_main.php index f01cba0bcc..529c3a1835 100644 --- a/phpBB/includes/acp/acp_main.php +++ b/phpBB/includes/acp/acp_main.php @@ -1,9 +1,13 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -15,17 +19,14 @@ if (!defined('IN_PHPBB')) exit; } -/** -* @package acp -*/ class acp_main { var $u_action; function main($id, $mode) { - global $config, $db, $cache, $user, $auth, $template, $request; - global $phpbb_root_path, $phpbb_admin_path, $phpEx; + global $config, $db, $cache, $user, $auth, $template, $request, $phpbb_log; + global $phpbb_root_path, $phpbb_admin_path, $phpEx, $phpbb_container, $phpbb_dispatcher, $phpbb_filesystem; // Show restore permissions notice if ($user->data['user_perm_from'] && $auth->acl_get('a_switchperm')) @@ -40,11 +41,7 @@ class acp_main $user_row = $db->sql_fetchrow($result); $db->sql_freeresult($result); - $perm_from = '<strong' . (($user_row['user_colour']) ? ' style="color: #' . $user_row['user_colour'] . '">' : '>'); - $perm_from .= ($user_row['user_id'] != ANONYMOUS) ? '<a href="' . append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&u=' . $user_row['user_id']) . '">' : ''; - $perm_from .= $user_row['username']; - $perm_from .= ($user_row['user_id'] != ANONYMOUS) ? '</a>' : ''; - $perm_from .= '</strong>'; + $perm_from = get_username_string('full', $user_row['user_id'], $user_row['username'], $user_row['user_colour']); $template->assign_vars(array( 'S_RESTORE_PERMISSIONS' => true, @@ -56,7 +53,7 @@ class acp_main return; } - $action = request_var('action', ''); + $action = $request->variable('action', ''); if ($action) { @@ -124,9 +121,9 @@ class acp_main trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); } - set_config('record_online_users', 1, true); - set_config('record_online_date', time(), true); - add_log('admin', 'LOG_RESET_ONLINE'); + $config->set('record_online_users', 1, false); + $config->set('record_online_date', time(), false); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_RESET_ONLINE'); if ($request->is_ajax()) { @@ -144,35 +141,35 @@ class acp_main FROM ' . POSTS_TABLE . ' WHERE post_visibility = ' . ITEM_APPROVED; $result = $db->sql_query($sql); - set_config('num_posts', (int) $db->sql_fetchfield('stat'), true); + $config->set('num_posts', (int) $db->sql_fetchfield('stat'), false); $db->sql_freeresult($result); $sql = 'SELECT COUNT(topic_id) AS stat FROM ' . TOPICS_TABLE . ' WHERE topic_visibility = ' . ITEM_APPROVED; $result = $db->sql_query($sql); - set_config('num_topics', (int) $db->sql_fetchfield('stat'), true); + $config->set('num_topics', (int) $db->sql_fetchfield('stat'), false); $db->sql_freeresult($result); $sql = 'SELECT COUNT(user_id) AS stat FROM ' . USERS_TABLE . ' WHERE user_type IN (' . USER_NORMAL . ',' . USER_FOUNDER . ')'; $result = $db->sql_query($sql); - set_config('num_users', (int) $db->sql_fetchfield('stat'), true); + $config->set('num_users', (int) $db->sql_fetchfield('stat'), false); $db->sql_freeresult($result); $sql = 'SELECT COUNT(attach_id) as stat FROM ' . ATTACHMENTS_TABLE . ' WHERE is_orphan = 0'; $result = $db->sql_query($sql); - set_config('num_files', (int) $db->sql_fetchfield('stat'), true); + $config->set('num_files', (int) $db->sql_fetchfield('stat'), false); $db->sql_freeresult($result); $sql = 'SELECT SUM(filesize) as stat FROM ' . ATTACHMENTS_TABLE . ' WHERE is_orphan = 0'; $result = $db->sql_query($sql); - set_config('upload_dir_size', (float) $db->sql_fetchfield('stat'), true); + $config->set('upload_dir_size', (float) $db->sql_fetchfield('stat'), false); $db->sql_freeresult($result); if (!function_exists('update_last_username')) @@ -181,7 +178,7 @@ class acp_main } update_last_username(); - add_log('admin', 'LOG_RESYNC_STATS'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_RESYNC_STATS'); if ($request->is_ajax()) { @@ -218,7 +215,7 @@ class acp_main // Still no maximum post id? Then we are finished if (!$max_post_id) { - add_log('admin', 'LOG_RESYNC_POSTCOUNTS'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_RESYNC_POSTCOUNTS'); break; } @@ -248,7 +245,7 @@ class acp_main $start += $step; } - add_log('admin', 'LOG_RESYNC_POSTCOUNTS'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_RESYNC_POSTCOUNTS'); if ($request->is_ajax()) { @@ -262,8 +259,8 @@ class acp_main trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); } - set_config('board_startdate', time() - 1); - add_log('admin', 'LOG_RESET_DATE'); + $config->set('board_startdate', time() - 1); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_RESET_DATE'); if ($request->is_ajax()) { @@ -272,10 +269,10 @@ class acp_main break; case 'db_track': - switch ($db->sql_layer) + switch ($db->get_sql_layer()) { case 'sqlite': - case 'firebird': + case 'sqlite3': $db->sql_query('DELETE FROM ' . TOPICS_POSTED_TABLE); break; @@ -343,7 +340,7 @@ class acp_main } } - add_log('admin', 'LOG_RESYNC_POST_MARKING'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_RESYNC_POST_MARKING'); if ($request->is_ajax()) { @@ -352,14 +349,19 @@ class acp_main break; case 'purge_cache': - global $cache; + $config->increment('assets_version', 1); $cache->purge(); + // Remove old renderers from the text_formatter service. Since this + // operation is performed after the cache is purged, there is not "current" + // renderer and in effect all renderers will be purged + $phpbb_container->get('text_formatter.cache')->tidy(); + // Clear permissions $auth->acl_clear_prefetch(); phpbb_cache_moderators($db, $cache, $auth); - add_log('admin', 'LOG_PURGE_CACHE'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_PURGE_CACHE'); if ($request->is_ajax()) { @@ -377,10 +379,10 @@ class acp_main foreach ($tables as $table) { - switch ($db->sql_layer) + switch ($db->get_sql_layer()) { case 'sqlite': - case 'firebird': + case 'sqlite3': $db->sql_query("DELETE FROM $table"); break; @@ -410,7 +412,7 @@ class acp_main $sql = 'INSERT INTO ' . SESSIONS_TABLE . ' ' . $db->sql_build_array('INSERT', $reinsert_ary); $db->sql_query($sql); - add_log('admin', 'LOG_PURGE_SESSIONS'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_PURGE_SESSIONS'); if ($request->is_ajax()) { @@ -424,7 +426,7 @@ class acp_main // Version check $user->add_lang('install'); - if ($auth->acl_get('a_server') && version_compare(PHP_VERSION, '5.3.3', '<')) + if ($auth->acl_get('a_server') && version_compare(PHP_VERSION, '5.4', '<')) { $template->assign_vars(array( 'S_PHP_VERSION_OLD' => true, @@ -432,20 +434,39 @@ class acp_main )); } - $latest_version_info = false; - if (($latest_version_info = obtain_latest_version_info(request_var('versioncheck_force', false))) === false) + if ($auth->acl_get('a_board')) { - $template->assign_var('S_VERSIONCHECK_FAIL', true); + /* @var $version_helper \phpbb\version_helper */ + $version_helper = $phpbb_container->get('version_helper'); + try + { + $recheck = $request->variable('versioncheck_force', false); + $updates_available = $version_helper->get_suggested_updates($recheck); + + $template->assign_var('S_VERSION_UP_TO_DATE', empty($updates_available)); + } + catch (\RuntimeException $e) + { + $template->assign_vars(array( + 'S_VERSIONCHECK_FAIL' => true, + 'VERSIONCHECK_FAIL_REASON' => ($e->getMessage() !== $user->lang('VERSIONCHECK_FAIL')) ? $e->getMessage() : '', + )); + } } else { - $latest_version_info = explode("\n", $latest_version_info); - - $template->assign_vars(array( - 'S_VERSION_UP_TO_DATE' => phpbb_version_compare(trim($latest_version_info[0]), $config['version'], '<='), - )); + // We set this template var to true, to not display an outdated version notice. + $template->assign_var('S_VERSION_UP_TO_DATE', true); } + /** + * Notice admin + * + * @event core.acp_main_notice + * @since 3.1.0-RC3 + */ + $phpbb_dispatcher->dispatch('core.acp_main_notice'); + // Get forum statistics $total_posts = $config['num_posts']; $total_topics = $config['num_topics']; @@ -546,6 +567,7 @@ class acp_main 'U_VERSIONCHECK' => append_sid("{$phpbb_admin_path}index.$phpEx", 'i=update&mode=version_check'), 'U_VERSIONCHECK_FORCE' => append_sid("{$phpbb_admin_path}index.$phpEx", 'versioncheck_force=1'), + 'S_VERSIONCHECK' => ($auth->acl_get('a_board')) ? true : false, 'S_ACTION_OPTIONS' => ($auth->acl_get('a_board')) ? true : false, 'S_FOUNDER' => ($user->data['user_type'] == USER_FOUNDER) ? true : false, ) @@ -625,7 +647,7 @@ class acp_main { $error = false; $search_type = $config['search_type']; - $search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user); + $search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher); if (!$search->index_created()) { @@ -636,7 +658,7 @@ class acp_main } } - if (!defined('PHPBB_DISABLE_CONFIG_CHECK') && file_exists($phpbb_root_path . 'config.' . $phpEx) && phpbb_is_writable($phpbb_root_path . 'config.' . $phpEx)) + if (!defined('PHPBB_DISABLE_CONFIG_CHECK') && file_exists($phpbb_root_path . 'config.' . $phpEx) && $phpbb_filesystem->is_writable($phpbb_root_path . 'config.' . $phpEx)) { // World-Writable? (000x) $template->assign_var('S_WRITABLE_CONFIG', (bool) (@fileperms($phpbb_root_path . 'config.' . $phpEx) & 0x0002)); @@ -648,15 +670,15 @@ class acp_main 'S_MBSTRING_LOADED' => true, 'S_MBSTRING_FUNC_OVERLOAD_FAIL' => (intval(@ini_get('mbstring.func_overload')) & (MB_OVERLOAD_MAIL | MB_OVERLOAD_STRING)), 'S_MBSTRING_ENCODING_TRANSLATION_FAIL' => (@ini_get('mbstring.encoding_translation') != 0), - 'S_MBSTRING_HTTP_INPUT_FAIL' => (@ini_get('mbstring.http_input') != 'pass'), - 'S_MBSTRING_HTTP_OUTPUT_FAIL' => (@ini_get('mbstring.http_output') != 'pass'), + 'S_MBSTRING_HTTP_INPUT_FAIL' => !in_array(@ini_get('mbstring.http_input'), array('pass', '')), + 'S_MBSTRING_HTTP_OUTPUT_FAIL' => !in_array(@ini_get('mbstring.http_output'), array('pass', '')), )); } // Fill dbms version if not yet filled if (empty($config['dbms_version'])) { - set_config('dbms_version', $db->sql_server_info(true)); + $config->set('dbms_version', $db->sql_server_info(true)); } $this->tpl_name = 'acp_main'; diff --git a/phpBB/includes/acp/acp_modules.php b/phpBB/includes/acp/acp_modules.php index c124377ba9..d3ecffe81e 100644 --- a/phpBB/includes/acp/acp_modules.php +++ b/phpBB/includes/acp/acp_modules.php @@ -1,9 +1,13 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -15,6 +19,8 @@ if (!defined('IN_PHPBB')) exit; } +use phpbb\module\exception\module_exception; + /** * - Able to check for new module versions (modes changed/adjusted/added/removed) * Icons for: @@ -25,9 +31,6 @@ if (!defined('IN_PHPBB')) * - category disabled */ -/** -* @package acp -*/ class acp_modules { var $module_class = ''; @@ -36,8 +39,10 @@ class acp_modules function main($id, $mode) { - global $db, $user, $auth, $template, $module, $request; - global $config, $phpbb_admin_path, $phpbb_root_path, $phpEx; + global $db, $user, $template, $module, $request, $phpbb_log, $phpbb_container; + + /** @var \phpbb\module\module_manager $module_manager */ + $module_manager = $phpbb_container->get('module.manager'); // Set a global define for modules we might include (the author is able to prevent execution of code by checking this constant) define('MODULE_INCLUDE', true); @@ -64,9 +69,9 @@ class acp_modules $this->page_title = strtoupper($this->module_class); - $this->parent_id = request_var('parent_id', 0); - $module_id = request_var('m', 0); - $action = request_var('action', ''); + $this->parent_id = $request->variable('parent_id', 0); + $module_id = $request->variable('m', 0); + $action = $request->variable('action', ''); $errors = array(); switch ($action) @@ -90,13 +95,20 @@ class acp_modules $db->sql_freeresult($result); } - $errors = $this->delete_module($module_id); - - if (!sizeof($errors)) + try { - $this->remove_cache_file(); - trigger_error($user->lang['MODULE_DELETED'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id)); + $row = $module_manager->get_module_row($module_id, $this->module_class); + $module_manager->delete_module($module_id, $this->module_class); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MODULE_REMOVED', false, array($user->lang($row['module_langname']))); } + catch (module_exception $e) + { + $msg = $user->lang($e->getMessage()); + trigger_error($msg . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + + $module_manager->remove_cache_file($this->module_class); + trigger_error($user->lang['MODULE_DELETED'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id)); } else { @@ -137,8 +149,8 @@ class acp_modules AND module_id = $module_id"; $db->sql_query($sql); - add_log('admin', 'LOG_MODULE_' . strtoupper($action), $this->lang_name($row['module_langname'])); - $this->remove_cache_file(); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MODULE_' . strtoupper($action), false, array($user->lang($row['module_langname']))); + $module_manager->remove_cache_file($this->module_class); break; @@ -162,12 +174,16 @@ class acp_modules trigger_error($user->lang['NO_MODULE'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); } - $move_module_name = $this->move_module_by($row, $action, 1); + try + { + $move_module_name = $module_manager->move_module_by($row, $this->module_class, $action, 1); - if ($move_module_name !== false) + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MODULE_' . strtoupper($action), false, array($user->lang($row['module_langname']), $move_module_name)); + $module_manager->remove_cache_file($this->module_class); + } + catch (module_exception $e) { - add_log('admin', 'LOG_MODULE_' . strtoupper($action), $this->lang_name($row['module_langname']), $move_module_name); - $this->remove_cache_file(); + // Do nothing } if ($request->is_ajax()) @@ -181,7 +197,7 @@ class acp_modules break; case 'quickadd': - $quick_install = request_var('quick_install', ''); + $quick_install = $request->variable('quick_install', ''); if (confirm_box(true)) { @@ -193,7 +209,7 @@ class acp_modules list($module_basename, $module_mode) = explode('::', $quick_install); // Check if module name and mode exist... - $fileinfo = $this->get_module_infos($module_basename); + $fileinfo = $module_manager->get_module_infos($this->module_class, $module_basename); $fileinfo = $fileinfo[$module_basename]; if (isset($fileinfo['modes'][$module_mode])) @@ -209,11 +225,20 @@ class acp_modules 'module_auth' => $fileinfo['modes'][$module_mode]['auth'], ); - $errors = $this->update_module_data($module_data); + try + { + $module_manager->update_module_data($module_data); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MODULE_ADD', false, array($user->lang($module_data['module_langname']))); + } + catch (\phpbb\module\exception\module_exception $e) + { + $msg = $user->lang($e->getMessage()); + trigger_error($msg . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } if (!sizeof($errors)) { - $this->remove_cache_file(); + $module_manager->remove_cache_file($this->module_class); trigger_error($user->lang['MODULE_ADDED'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id)); } @@ -239,7 +264,15 @@ class acp_modules trigger_error($user->lang['NO_MODULE_ID'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); } - $module_row = $this->get_module_row($module_id); + try + { + $module_row = $module_manager->get_module_row($module_id, $this->module_class); + } + catch (\phpbb\module\exception\module_not_found_exception $e) + { + $msg = $user->lang($e->getMessage()); + trigger_error($msg . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } // no break @@ -252,7 +285,7 @@ class acp_modules 'module_enabled' => 0, 'module_display' => 1, 'parent_id' => 0, - 'module_langname' => utf8_normalize_nfc(request_var('module_langname', '', true)), + 'module_langname' => $request->variable('module_langname', '', true), 'module_mode' => '', 'module_auth' => '', ); @@ -260,13 +293,13 @@ class acp_modules $module_data = array(); - $module_data['module_basename'] = request_var('module_basename', (string) $module_row['module_basename']); - $module_data['module_enabled'] = request_var('module_enabled', (int) $module_row['module_enabled']); - $module_data['module_display'] = request_var('module_display', (int) $module_row['module_display']); - $module_data['parent_id'] = request_var('module_parent_id', (int) $module_row['parent_id']); + $module_data['module_basename'] = $request->variable('module_basename', (string) $module_row['module_basename']); + $module_data['module_enabled'] = $request->variable('module_enabled', (int) $module_row['module_enabled']); + $module_data['module_display'] = $request->variable('module_display', (int) $module_row['module_display']); + $module_data['parent_id'] = $request->variable('module_parent_id', (int) $module_row['parent_id']); $module_data['module_class'] = $this->module_class; - $module_data['module_langname'] = utf8_normalize_nfc(request_var('module_langname', (string) $module_row['module_langname'], true)); - $module_data['module_mode'] = request_var('module_mode', (string) $module_row['module_mode']); + $module_data['module_langname'] = $request->variable('module_langname', (string) $module_row['module_langname'], true); + $module_data['module_mode'] = $request->variable('module_mode', (string) $module_row['module_mode']); $submit = (isset($_POST['submit'])) ? true : false; @@ -277,7 +310,7 @@ class acp_modules trigger_error($user->lang['NO_MODULE_LANGNAME'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); } - $module_type = request_var('module_type', 'category'); + $module_type = $request->variable('module_type', 'category'); if ($module_type == 'category') { @@ -293,15 +326,29 @@ class acp_modules // Adjust auth row if ($module_data['module_basename'] && $module_data['module_mode']) { - $fileinfo = $this->get_module_infos($module_data['module_basename']); + $fileinfo = $module_manager->get_module_infos($this->module_class, $module_data['module_basename']); $module_data['module_auth'] = $fileinfo[$module_data['module_basename']]['modes'][$module_data['module_mode']]['auth']; } - $errors = $this->update_module_data($module_data); + try + { + $module_manager->update_module_data($module_data); + $phpbb_log->add('admin', + $user->data['user_id'], + $user->ip, + ($action === 'edit') ? 'LOG_MODULE_EDIT' : 'LOG_MODULE_ADD', + false, + array($user->lang($module_data['module_langname'])) + ); } + catch (\phpbb\module\exception\module_exception $e) + { + $msg = $user->lang($e->getMessage()); + trigger_error($msg . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } if (!sizeof($errors)) { - $this->remove_cache_file(); + $module_manager->remove_cache_file($this->module_class); trigger_error((($action == 'add') ? $user->lang['MODULE_ADDED'] : $user->lang['MODULE_EDITED']) . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id)); } @@ -311,7 +358,7 @@ class acp_modules $is_cat = (!$module_data['module_basename']) ? true : false; // Get module information - $module_infos = $this->get_module_infos(); + $module_infos = $module_manager->get_module_infos($this->module_class); // Build name options $s_name_options = $s_mode_options = ''; @@ -323,7 +370,7 @@ class acp_modules } // Name options - $s_name_options .= '<option value="' . $option . '"' . (($option == $module_data['module_basename']) ? ' selected="selected"' : '') . '>' . $this->lang_name($values['title']) . ' [' . $option . ']</option>'; + $s_name_options .= '<option value="' . $option . '"' . (($option == $module_data['module_basename']) ? ' selected="selected"' : '') . '>' . $user->lang($values['title']) . ' [' . $option . ']</option>'; $template->assign_block_vars('m_names', array('NAME' => $option, 'A_NAME' => addslashes($option))); @@ -332,14 +379,14 @@ class acp_modules { if ($option == $module_data['module_basename']) { - $s_mode_options .= '<option value="' . $m_mode . '"' . (($m_mode == $module_data['module_mode']) ? ' selected="selected"' : '') . '>' . $this->lang_name($m_values['title']) . '</option>'; + $s_mode_options .= '<option value="' . $m_mode . '"' . (($m_mode == $module_data['module_mode']) ? ' selected="selected"' : '') . '>' . $user->lang($m_values['title']) . '</option>'; } $template->assign_block_vars('m_names.modes', array( 'OPTION' => $m_mode, - 'VALUE' => $this->lang_name($m_values['title']), + 'VALUE' => $user->lang($m_values['title']), 'A_OPTION' => addslashes($m_mode), - 'A_VALUE' => addslashes($this->lang_name($m_values['title']))) + 'A_VALUE' => addslashes($user->lang($m_values['title']))) ); } } @@ -357,7 +404,7 @@ class acp_modules 'L_TITLE' => $user->lang[strtoupper($action) . '_MODULE'], - 'MODULENAME' => $this->lang_name($module_data['module_langname']), + 'MODULENAME' => $user->lang($module_data['module_langname']), 'ACTION' => $action, 'MODULE_ID' => $module_id, @@ -405,11 +452,11 @@ class acp_modules { $navigation = '<a href="' . $this->u_action . '">' . strtoupper($this->module_class) . '</a>'; - $modules_nav = $this->get_module_branch($this->parent_id, 'parents', 'descending'); + $modules_nav = $module_manager->get_module_branch($this->parent_id, $this->module_class, 'parents'); foreach ($modules_nav as $row) { - $langname = $this->lang_name($row['module_langname']); + $langname = $user->lang($row['module_langname']); if ($row['module_id'] == $this->parent_id) { @@ -436,7 +483,7 @@ class acp_modules { do { - $langname = $this->lang_name($row['module_langname']); + $langname = $user->lang($row['module_langname']); if (!$row['module_enabled']) { @@ -471,7 +518,15 @@ class acp_modules } else if ($this->parent_id) { - $row = $this->get_module_row($this->parent_id); + try + { + $row = $module_manager->get_module_row($this->parent_id, $this->module_class); + } + catch (\phpbb\module\exception\module_not_found_exception $e) + { + $msg = $user->lang($e->getMessage()); + trigger_error($msg . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } $url = $this->u_action . '&parent_id=' . $this->parent_id . '&m=' . $row['module_id']; @@ -490,19 +545,19 @@ class acp_modules $db->sql_freeresult($result); // Quick adding module - $module_infos = $this->get_module_infos(); + $module_infos = $module_manager->get_module_infos($this->module_class); // Build quick options $s_install_options = ''; foreach ($module_infos as $option => $values) { // Name options - $s_install_options .= '<optgroup label="' . $this->lang_name($values['title']) . ' [' . $option . ']">'; + $s_install_options .= '<optgroup label="' . $user->lang($values['title']) . ' [' . $option . ']">'; // Build module modes foreach ($values['modes'] as $m_mode => $m_values) { - $s_install_options .= '<option value="' . $option . '::' . $m_mode . '"> ' . $this->lang_name($m_values['title']) . '</option>'; + $s_install_options .= '<option value="' . $option . '::' . $m_mode . '"> ' . $user->lang($m_values['title']) . '</option>'; } $s_install_options .= '</optgroup>'; @@ -520,109 +575,11 @@ class acp_modules } /** - * Get row for specified module - */ - function get_module_row($module_id) - { - global $db, $user; - - $sql = 'SELECT * - FROM ' . MODULES_TABLE . " - WHERE module_class = '" . $db->sql_escape($this->module_class) . "' - AND module_id = $module_id"; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if (!$row) - { - trigger_error($user->lang['NO_MODULE'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); - } - - return $row; - } - - /** - * Get available module information from module files - * - * @param string $module - * @param bool|string $module_class - * @param bool $use_all_available Use all available instead of just all - * enabled extensions - * @return array - */ - function get_module_infos($module = '', $module_class = false, $use_all_available = false) - { - global $phpbb_extension_manager, $phpbb_root_path, $phpEx; - - $module_class = ($module_class === false) ? $this->module_class : $module_class; - - $directory = $phpbb_root_path . 'includes/' . $module_class . '/info/'; - $fileinfo = array(); - - $finder = $phpbb_extension_manager->get_finder(); - - $modules = $finder - ->extension_suffix('_module') - ->extension_directory("/$module_class") - ->core_path("includes/$module_class/info/") - ->core_prefix($module_class . '_') - ->get_classes(true, $use_all_available); - - foreach ($modules as $cur_module) - { - // Skip entries we do not need if we know the module we are - // looking for - if ($module && strpos(str_replace('\\', '_', $cur_module), $module) === false && $module !== $cur_module) - { - continue; - } - - $info_class = preg_replace('/_module$/', '_info', $cur_module); - - // If the class does not exist it might be following the old - // format. phpbb_acp_info_acp_foo needs to be turned into - // acp_foo_info and the respective file has to be included - // manually because it does not support auto loading - $old_info_class_file = str_replace("phpbb_{$module_class}_info_", '', $cur_module); - $old_info_class = $old_info_class_file . '_info'; - - if (class_exists($old_info_class)) - { - $info_class = $old_info_class; - } - else if (!class_exists($info_class)) - { - $info_class = $old_info_class; - // need to check class exists again because previous checks triggered autoloading - if (!class_exists($info_class) && file_exists($directory . $old_info_class_file . '.' . $phpEx)) - { - include($directory . $old_info_class_file . '.' . $phpEx); - } - } - - if (class_exists($info_class)) - { - $info = new $info_class(); - $module_info = $info->module(); - - $main_class = (isset($module_info['filename'])) ? $module_info['filename'] : $cur_module; - - $fileinfo[$main_class] = $module_info; - } - } - - ksort($fileinfo); - - return $fileinfo; - } - - /** * Simple version of jumpbox, just lists modules */ function make_module_select($select_id = false, $ignore_id = false, $ignore_acl = false, $ignore_nonpost = false, $ignore_emptycat = true, $ignore_noncat = false) { - global $db, $user, $auth, $config; + global $db, $user; $sql = 'SELECT module_id, module_enabled, module_basename, parent_id, module_langname, left_id, right_id, module_auth FROM ' . MODULES_TABLE . " @@ -677,7 +634,7 @@ class acp_modules $selected = (is_array($select_id)) ? ((in_array($row['module_id'], $select_id)) ? ' selected="selected"' : '') : (($row['module_id'] == $select_id) ? ' selected="selected"' : ''); - $langname = $this->lang_name($row['module_langname']); + $langname = $user->lang($row['module_langname']); $module_list .= '<option value="' . $row['module_id'] . '"' . $selected . ((!$row['module_enabled']) ? ' class="disabled"' : '') . '>' . $padding . $langname . '</option>'; $iteration++; @@ -688,400 +645,4 @@ class acp_modules return $module_list; } - - /** - * Get module branch - */ - function get_module_branch($module_id, $type = 'all', $order = 'descending', $include_module = true) - { - global $db; - - switch ($type) - { - case 'parents': - $condition = 'm1.left_id BETWEEN m2.left_id AND m2.right_id'; - break; - - case 'children': - $condition = 'm2.left_id BETWEEN m1.left_id AND m1.right_id'; - break; - - default: - $condition = 'm2.left_id BETWEEN m1.left_id AND m1.right_id OR m1.left_id BETWEEN m2.left_id AND m2.right_id'; - break; - } - - $rows = array(); - - $sql = 'SELECT m2.* - FROM ' . MODULES_TABLE . ' m1 - LEFT JOIN ' . MODULES_TABLE . " m2 ON ($condition) - WHERE m1.module_class = '" . $db->sql_escape($this->module_class) . "' - AND m2.module_class = '" . $db->sql_escape($this->module_class) . "' - AND m1.module_id = $module_id - ORDER BY m2.left_id " . (($order == 'descending') ? 'ASC' : 'DESC'); - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - if (!$include_module && $row['module_id'] == $module_id) - { - continue; - } - - $rows[] = $row; - } - $db->sql_freeresult($result); - - return $rows; - } - - /** - * Remove modules cache file - */ - function remove_cache_file() - { - global $phpbb_container; - - // Sanitise for future path use, it's escaped as appropriate for queries - $p_class = str_replace(array('.', '/', '\\'), '', basename($this->module_class)); - - $phpbb_container->get('cache.driver')->destroy('_modules_' . $p_class); - - // Additionally remove sql cache - $phpbb_container->get('cache.driver')->destroy('sql', MODULES_TABLE); - } - - /** - * Return correct language name - */ - function lang_name($module_langname) - { - global $user; - - return (!empty($user->lang[$module_langname])) ? $user->lang[$module_langname] : $module_langname; - } - - /** - * Update/Add module - * - * @param bool $run_inline if set to true errors will be returned and no logs being written - */ - function update_module_data(&$module_data, $run_inline = false) - { - global $db, $user; - - if (!isset($module_data['module_id'])) - { - // no module_id means we're creating a new category/module - if ($module_data['parent_id']) - { - $sql = 'SELECT left_id, right_id - FROM ' . MODULES_TABLE . " - WHERE module_class = '" . $db->sql_escape($module_data['module_class']) . "' - AND module_id = " . (int) $module_data['parent_id']; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if (!$row) - { - if ($run_inline) - { - return 'PARENT_NO_EXIST'; - } - - trigger_error($user->lang['PARENT_NO_EXIST'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); - } - - // Workaround - $row['left_id'] = (int) $row['left_id']; - $row['right_id'] = (int) $row['right_id']; - - $sql = 'UPDATE ' . MODULES_TABLE . " - SET left_id = left_id + 2, right_id = right_id + 2 - WHERE module_class = '" . $db->sql_escape($module_data['module_class']) . "' - AND left_id > {$row['right_id']}"; - $db->sql_query($sql); - - $sql = 'UPDATE ' . MODULES_TABLE . " - SET right_id = right_id + 2 - WHERE module_class = '" . $db->sql_escape($module_data['module_class']) . "' - AND {$row['left_id']} BETWEEN left_id AND right_id"; - $db->sql_query($sql); - - $module_data['left_id'] = (int) $row['right_id']; - $module_data['right_id'] = (int) $row['right_id'] + 1; - } - else - { - $sql = 'SELECT MAX(right_id) AS right_id - FROM ' . MODULES_TABLE . " - WHERE module_class = '" . $db->sql_escape($module_data['module_class']) . "'"; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - $module_data['left_id'] = (int) $row['right_id'] + 1; - $module_data['right_id'] = (int) $row['right_id'] + 2; - } - - $sql = 'INSERT INTO ' . MODULES_TABLE . ' ' . $db->sql_build_array('INSERT', $module_data); - $db->sql_query($sql); - - $module_data['module_id'] = $db->sql_nextid(); - - if (!$run_inline) - { - add_log('admin', 'LOG_MODULE_ADD', $this->lang_name($module_data['module_langname'])); - } - } - else - { - $row = $this->get_module_row($module_data['module_id']); - - if ($module_data['module_basename'] && !$row['module_basename']) - { - // we're turning a category into a module - $branch = $this->get_module_branch($module_data['module_id'], 'children', 'descending', false); - - if (sizeof($branch)) - { - return array($user->lang['NO_CATEGORY_TO_MODULE']); - } - } - - if ($row['parent_id'] != $module_data['parent_id']) - { - $this->move_module($module_data['module_id'], $module_data['parent_id']); - } - - $update_ary = $module_data; - unset($update_ary['module_id']); - - $sql = 'UPDATE ' . MODULES_TABLE . ' - SET ' . $db->sql_build_array('UPDATE', $update_ary) . " - WHERE module_class = '" . $db->sql_escape($module_data['module_class']) . "' - AND module_id = " . (int) $module_data['module_id']; - $db->sql_query($sql); - - if (!$run_inline) - { - add_log('admin', 'LOG_MODULE_EDIT', $this->lang_name($module_data['module_langname'])); - } - } - - return array(); - } - - /** - * Move module around the tree - */ - function move_module($from_module_id, $to_parent_id) - { - global $db; - - $moved_modules = $this->get_module_branch($from_module_id, 'children', 'descending'); - $from_data = $moved_modules[0]; - $diff = sizeof($moved_modules) * 2; - - $moved_ids = array(); - for ($i = 0; $i < sizeof($moved_modules); ++$i) - { - $moved_ids[] = $moved_modules[$i]['module_id']; - } - - // Resync parents - $sql = 'UPDATE ' . MODULES_TABLE . " - SET right_id = right_id - $diff - WHERE module_class = '" . $db->sql_escape($this->module_class) . "' - AND left_id < " . (int) $from_data['right_id'] . ' - AND right_id > ' . (int) $from_data['right_id']; - $db->sql_query($sql); - - // Resync righthand side of tree - $sql = 'UPDATE ' . MODULES_TABLE . " - SET left_id = left_id - $diff, right_id = right_id - $diff - WHERE module_class = '" . $db->sql_escape($this->module_class) . "' - AND left_id > " . (int) $from_data['right_id']; - $db->sql_query($sql); - - if ($to_parent_id > 0) - { - $to_data = $this->get_module_row($to_parent_id); - - // Resync new parents - $sql = 'UPDATE ' . MODULES_TABLE . " - SET right_id = right_id + $diff - WHERE module_class = '" . $db->sql_escape($this->module_class) . "' - AND " . (int) $to_data['right_id'] . ' BETWEEN left_id AND right_id - AND ' . $db->sql_in_set('module_id', $moved_ids, true); - $db->sql_query($sql); - - // Resync the righthand side of the tree - $sql = 'UPDATE ' . MODULES_TABLE . " - SET left_id = left_id + $diff, right_id = right_id + $diff - WHERE module_class = '" . $db->sql_escape($this->module_class) . "' - AND left_id > " . (int) $to_data['right_id'] . ' - AND ' . $db->sql_in_set('module_id', $moved_ids, true); - $db->sql_query($sql); - - // Resync moved branch - $to_data['right_id'] += $diff; - if ($to_data['right_id'] > $from_data['right_id']) - { - $diff = '+ ' . ($to_data['right_id'] - $from_data['right_id'] - 1); - } - else - { - $diff = '- ' . abs($to_data['right_id'] - $from_data['right_id'] - 1); - } - } - else - { - $sql = 'SELECT MAX(right_id) AS right_id - FROM ' . MODULES_TABLE . " - WHERE module_class = '" . $db->sql_escape($this->module_class) . "' - AND " . $db->sql_in_set('module_id', $moved_ids, true); - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - $diff = '+ ' . (int) ($row['right_id'] - $from_data['left_id'] + 1); - } - - $sql = 'UPDATE ' . MODULES_TABLE . " - SET left_id = left_id $diff, right_id = right_id $diff - WHERE module_class = '" . $db->sql_escape($this->module_class) . "' - AND " . $db->sql_in_set('module_id', $moved_ids); - $db->sql_query($sql); - } - - /** - * Remove module from tree - */ - function delete_module($module_id) - { - global $db, $user; - - $row = $this->get_module_row($module_id); - - $branch = $this->get_module_branch($module_id, 'children', 'descending', false); - - if (sizeof($branch)) - { - return array($user->lang['CANNOT_REMOVE_MODULE']); - } - - // If not move - $diff = 2; - $sql = 'DELETE FROM ' . MODULES_TABLE . " - WHERE module_class = '" . $db->sql_escape($this->module_class) . "' - AND module_id = $module_id"; - $db->sql_query($sql); - - $row['right_id'] = (int) $row['right_id']; - $row['left_id'] = (int) $row['left_id']; - - // Resync tree - $sql = 'UPDATE ' . MODULES_TABLE . " - SET right_id = right_id - $diff - WHERE module_class = '" . $db->sql_escape($this->module_class) . "' - AND left_id < {$row['right_id']} AND right_id > {$row['right_id']}"; - $db->sql_query($sql); - - $sql = 'UPDATE ' . MODULES_TABLE . " - SET left_id = left_id - $diff, right_id = right_id - $diff - WHERE module_class = '" . $db->sql_escape($this->module_class) . "' - AND left_id > {$row['right_id']}"; - $db->sql_query($sql); - - add_log('admin', 'LOG_MODULE_REMOVED', $this->lang_name($row['module_langname'])); - - return array(); - - } - - /** - * Move module position by $steps up/down - */ - function move_module_by($module_row, $action = 'move_up', $steps = 1) - { - global $db; - - /** - * Fetch all the siblings between the module's current spot - * and where we want to move it to. If there are less than $steps - * siblings between the current spot and the target then the - * module will move as far as possible - */ - $sql = 'SELECT module_id, left_id, right_id, module_langname - FROM ' . MODULES_TABLE . " - WHERE module_class = '" . $db->sql_escape($this->module_class) . "' - AND parent_id = " . (int) $module_row['parent_id'] . ' - AND ' . (($action == 'move_up') ? 'right_id < ' . (int) $module_row['right_id'] . ' ORDER BY right_id DESC' : 'left_id > ' . (int) $module_row['left_id'] . ' ORDER BY left_id ASC'); - $result = $db->sql_query_limit($sql, $steps); - - $target = array(); - while ($row = $db->sql_fetchrow($result)) - { - $target = $row; - } - $db->sql_freeresult($result); - - if (!sizeof($target)) - { - // The module is already on top or bottom - return false; - } - - /** - * $left_id and $right_id define the scope of the nodes that are affected by the move. - * $diff_up and $diff_down are the values to substract or add to each node's left_id - * and right_id in order to move them up or down. - * $move_up_left and $move_up_right define the scope of the nodes that are moving - * up. Other nodes in the scope of ($left_id, $right_id) are considered to move down. - */ - if ($action == 'move_up') - { - $left_id = (int) $target['left_id']; - $right_id = (int) $module_row['right_id']; - - $diff_up = (int) ($module_row['left_id'] - $target['left_id']); - $diff_down = (int) ($module_row['right_id'] + 1 - $module_row['left_id']); - - $move_up_left = (int) $module_row['left_id']; - $move_up_right = (int) $module_row['right_id']; - } - else - { - $left_id = (int) $module_row['left_id']; - $right_id = (int) $target['right_id']; - - $diff_up = (int) ($module_row['right_id'] + 1 - $module_row['left_id']); - $diff_down = (int) ($target['right_id'] - $module_row['right_id']); - - $move_up_left = (int) ($module_row['right_id'] + 1); - $move_up_right = (int) $target['right_id']; - } - - // Now do the dirty job - $sql = 'UPDATE ' . MODULES_TABLE . " - SET left_id = left_id + CASE - WHEN left_id BETWEEN {$move_up_left} AND {$move_up_right} THEN -{$diff_up} - ELSE {$diff_down} - END, - right_id = right_id + CASE - WHEN right_id BETWEEN {$move_up_left} AND {$move_up_right} THEN -{$diff_up} - ELSE {$diff_down} - END - WHERE module_class = '" . $db->sql_escape($this->module_class) . "' - AND left_id BETWEEN {$left_id} AND {$right_id} - AND right_id BETWEEN {$left_id} AND {$right_id}"; - $db->sql_query($sql); - - $this->remove_cache_file(); - - return $this->lang_name($target['module_langname']); - } } diff --git a/phpBB/includes/acp/acp_permission_roles.php b/phpBB/includes/acp/acp_permission_roles.php index aca45575d3..93aca295d7 100644 --- a/phpBB/includes/acp/acp_permission_roles.php +++ b/phpBB/includes/acp/acp_permission_roles.php @@ -1,9 +1,13 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -15,9 +19,6 @@ if (!defined('IN_PHPBB')) exit; } -/** -* @package acp -*/ class acp_permission_roles { var $u_action; @@ -25,12 +26,19 @@ class acp_permission_roles function main($id, $mode) { - global $db, $user, $auth, $template, $cache, $phpbb_container; - global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; - global $request; + global $db, $user, $template, $phpbb_container; + global $phpbb_root_path, $phpEx; + global $request, $phpbb_log; + + if (!function_exists('user_get_id_name')) + { + include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + } - include_once($phpbb_root_path . 'includes/functions_user.' . $phpEx); - include_once($phpbb_root_path . 'includes/acp/auth.' . $phpEx); + if (!class_exists('auth_admin')) + { + include($phpbb_root_path . 'includes/acp/auth.' . $phpEx); + } $this->auth_admin = new auth_admin(); @@ -40,8 +48,8 @@ class acp_permission_roles $this->tpl_name = 'acp_permission_roles'; $submit = (isset($_POST['submit'])) ? true : false; - $role_id = request_var('role_id', 0); - $action = request_var('action', ''); + $role_id = $request->variable('role_id', 0); + $action = $request->variable('action', ''); $action = (isset($_POST['add'])) ? 'add' : $action; $form_name = 'acp_permissions'; @@ -108,7 +116,7 @@ class acp_permission_roles $this->remove_role($role_id, $permission_type); $role_name = (!empty($user->lang[$role_row['role_name']])) ? $user->lang[$role_row['role_name']] : $role_row['role_name']; - add_log('admin', 'LOG_' . strtoupper($permission_type) . 'ROLE_REMOVED', $role_name); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_' . strtoupper($permission_type) . 'ROLE_REMOVED', false, array($role_name)); trigger_error($user->lang['ROLE_DELETED'] . adm_back_link($this->u_action)); } else @@ -147,9 +155,9 @@ class acp_permission_roles trigger_error($user->lang['FORM_INVALID']. adm_back_link($this->u_action), E_USER_WARNING); } - $role_name = utf8_normalize_nfc(request_var('role_name', '', true)); - $role_description = utf8_normalize_nfc(request_var('role_description', '', true)); - $auth_settings = request_var('setting', array('' => 0)); + $role_name = $request->variable('role_name', '', true); + $role_description = $request->variable('role_description', '', true); + $auth_settings = $request->variable('setting', array('' => 0)); if (!$role_name) { @@ -211,7 +219,7 @@ class acp_permission_roles $this->auth_admin->acl_set_role($role_id, $auth_settings); $role_name = (!empty($user->lang[$role_name])) ? $user->lang[$role_name] : $role_name; - add_log('admin', 'LOG_' . strtoupper($permission_type) . 'ROLE_' . strtoupper($action), $role_name); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_' . strtoupper($permission_type) . 'ROLE_' . strtoupper($action), false, array($role_name)); trigger_error($user->lang['ROLE_' . strtoupper($action) . '_SUCCESS'] . adm_back_link($this->u_action)); @@ -224,11 +232,11 @@ class acp_permission_roles { case 'add': - $options_from = request_var('options_from', 0); + $options_from = $request->variable('options_from', 0); $role_row = array( - 'role_name' => utf8_normalize_nfc(request_var('role_name', '', true)), - 'role_description' => utf8_normalize_nfc(request_var('role_description', '', true)), + 'role_name' => $request->variable('role_name', '', true), + 'role_description' => $request->variable('role_description', '', true), 'role_type' => $permission_type, ); @@ -252,7 +260,7 @@ class acp_permission_roles { $sql = 'SELECT auth_option_id, auth_option FROM ' . ACL_OPTIONS_TABLE . " - WHERE auth_option " . $db->sql_like_expression($permission_type . $db->any_char) . " + WHERE auth_option " . $db->sql_like_expression($permission_type . $db->get_any_char()) . " AND auth_option <> '{$permission_type}' ORDER BY auth_option_id"; $result = $db->sql_query($sql); @@ -270,7 +278,7 @@ class acp_permission_roles case 'edit': if ($action == 'edit') - { + { $sql = 'SELECT * FROM ' . ACL_ROLES_TABLE . ' WHERE role_id = ' . $role_id; @@ -298,6 +306,7 @@ class acp_permission_roles trigger_error($user->lang['NO_ROLE_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING); } + /* @var $phpbb_permissions \phpbb\permissions */ $phpbb_permissions = $phpbb_container->get('acl.permissions'); $template->assign_vars(array( @@ -314,7 +323,7 @@ class acp_permission_roles // We need to fill the auth options array with ACL_NO options ;) $sql = 'SELECT auth_option_id, auth_option FROM ' . ACL_OPTIONS_TABLE . " - WHERE auth_option " . $db->sql_like_expression($permission_type . $db->any_char) . " + WHERE auth_option " . $db->sql_like_expression($permission_type . $db->get_any_char()) . " AND auth_option <> '{$permission_type}' ORDER BY auth_option_id"; $result = $db->sql_query($sql); @@ -412,7 +421,7 @@ class acp_permission_roles $db->sql_freeresult($result); // Display assigned items? - $display_item = request_var('display_item', 0); + $display_item = $request->variable('display_item', 0); // Select existing roles $sql = 'SELECT * @@ -468,8 +477,9 @@ class acp_permission_roles */ function display_auth_options($auth_options) { - global $template, $user, $phpbb_container; + global $template, $phpbb_container; + /* @var $phpbb_permissions \phpbb\permissions */ $phpbb_permissions = $phpbb_container->get('acl.permissions'); $content_array = $categories = array(); @@ -518,7 +528,7 @@ class acp_permission_roles // Get complete auth array $sql = 'SELECT auth_option, auth_option_id FROM ' . ACL_OPTIONS_TABLE . " - WHERE auth_option " . $db->sql_like_expression($permission_type . $db->any_char); + WHERE auth_option " . $db->sql_like_expression($permission_type . $db->get_any_char()); $result = $db->sql_query($sql); $auth_settings = array(); diff --git a/phpBB/includes/acp/acp_permissions.php b/phpBB/includes/acp/acp_permissions.php index e7dc03db5c..fdac7c4d00 100644 --- a/phpBB/includes/acp/acp_permissions.php +++ b/phpBB/includes/acp/acp_permissions.php @@ -1,9 +1,13 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -15,22 +19,30 @@ if (!defined('IN_PHPBB')) exit; } -/** -* @package acp -*/ class acp_permissions { var $u_action; var $permission_dropdown; + + /** + * @var $phpbb_permissions \phpbb\permissions + */ protected $permissions; function main($id, $mode) { - global $db, $user, $auth, $template, $cache, $phpbb_container; - global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + global $db, $user, $auth, $template, $phpbb_container, $request; + global $config, $phpbb_root_path, $phpEx; + + if (!function_exists('user_get_id_name')) + { + include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + } - include_once($phpbb_root_path . 'includes/functions_user.' . $phpEx); - include_once($phpbb_root_path . 'includes/acp/auth.' . $phpEx); + if (!class_exists('auth_admin')) + { + include($phpbb_root_path . 'includes/acp/auth.' . $phpEx); + } $this->permissions = $phpbb_container->get('acl.permissions'); @@ -44,9 +56,9 @@ class acp_permissions // Trace has other vars if ($mode == 'trace') { - $user_id = request_var('u', 0); - $forum_id = request_var('f', 0); - $permission = request_var('auth', ''); + $user_id = $request->variable('u', 0); + $forum_id = $request->variable('f', 0); + $permission = $request->variable('auth', ''); $this->tpl_name = 'permission_trace'; @@ -75,20 +87,20 @@ class acp_permissions } // Set some vars - $action = request_var('action', array('' => 0)); + $action = $request->variable('action', array('' => 0)); $action = key($action); $action = (isset($_POST['psubmit'])) ? 'apply_permissions' : $action; - $all_forums = request_var('all_forums', 0); - $subforum_id = request_var('subforum_id', 0); - $forum_id = request_var('forum_id', array(0)); + $all_forums = $request->variable('all_forums', 0); + $subforum_id = $request->variable('subforum_id', 0); + $forum_id = $request->variable('forum_id', array(0)); - $username = request_var('username', array(''), true); - $usernames = request_var('usernames', '', true); - $user_id = request_var('user_id', array(0)); + $username = $request->variable('username', array(''), true); + $usernames = $request->variable('usernames', '', true); + $user_id = $request->variable('user_id', array(0)); - $group_id = request_var('group_id', array(0)); - $select_all_groups = request_var('select_all_groups', 0); + $group_id = $request->variable('group_id', array(0)); + $select_all_groups = $request->variable('select_all_groups', 0); $form_name = 'acp_permissions'; add_form_key($form_name); @@ -155,8 +167,6 @@ class acp_permissions } // Define some common variables for every mode - $error = array(); - $permission_scope = (strpos($mode, '_global') !== false) ? 'global' : 'local'; // Showing introductionary page? @@ -227,7 +237,7 @@ class acp_permissions ); // Get permission type - $permission_type = request_var('type', $this->permission_dropdown[0]); + $permission_type = $request->variable('type', $this->permission_dropdown[0]); if (!in_array($permission_type, $this->permission_dropdown)) { @@ -330,15 +340,6 @@ class acp_permissions } } - - // Setting permissions screen - $s_hidden_fields = build_hidden_fields(array( - 'user_id' => $user_id, - 'group_id' => $group_id, - 'forum_id' => $forum_id, - 'type' => $permission_type) - ); - // Go through the screens/options needed and present them in correct order foreach ($permission_victim as $victim) { @@ -471,6 +472,14 @@ class acp_permissions // If there are more than 5 forums selected the admin is not able to select all users/groups too. // We need to see if the number of forums can be increased or need to be decreased. + // Setting permissions screen + $s_hidden_fields = build_hidden_fields(array( + 'user_id' => $user_id, + 'group_id' => $group_id, + 'forum_id' => $forum_id, + 'type' => $permission_type, + )); + $template->assign_vars(array( 'U_ACTION' => $this->u_action, 'ANONYMOUS_USER_ID' => ANONYMOUS, @@ -507,6 +516,14 @@ class acp_permissions return; } + // Setting permissions screen + $s_hidden_fields = build_hidden_fields(array( + 'user_id' => $user_id, + 'group_id' => $group_id, + 'forum_id' => $forum_id, + 'type' => $permission_type, + )); + // Do not allow forum_ids being set and no other setting defined (will bog down the server too much) if (sizeof($forum_id) && !sizeof($user_id) && !sizeof($group_id)) { @@ -662,7 +679,7 @@ class acp_permissions global $db, $cache, $user, $auth; global $request; - $psubmit = request_var('psubmit', array(0 => array(0 => 0))); + $psubmit = $request->variable('psubmit', array(0 => array(0 => 0))); // User or group to be set? $ug_type = (sizeof($user_id)) ? 'user' : 'group'; @@ -673,8 +690,6 @@ class acp_permissions trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); } - $ug_id = $forum_id = 0; - // We loop through the auth settings defined in our submit list($ug_id, ) = each($psubmit); list($forum_id, ) = each($psubmit[$ug_id]); @@ -692,7 +707,7 @@ class acp_permissions $assigned_role = (isset($roles[$ug_id][$forum_id])) ? (int) $roles[$ug_id][$forum_id] : 0; // Do the admin want to set these permissions to other items too? - $inherit = request_var('inherit', array(0 => array(0))); + $inherit = $request->variable('inherit', array(0 => array(0))); $ug_id = array($ug_id); $forum_id = array($forum_id); @@ -897,7 +912,7 @@ class acp_permissions */ function log_action($mode, $action, $permission_type, $ug_type, $ug_id, $forum_id) { - global $db, $user; + global $db, $user, $phpbb_log, $phpbb_container; if (!is_array($ug_id)) { @@ -914,10 +929,14 @@ class acp_permissions $sql .= $db->sql_in_set(($ug_type == 'group') ? 'group_id' : 'user_id', array_map('intval', $ug_id)); $result = $db->sql_query($sql); + /** @var \phpbb\group\helper $group_helper */ + $group_helper = $phpbb_container->get('group_helper'); + $l_ug_list = ''; while ($row = $db->sql_fetchrow($result)) { - $l_ug_list .= (($l_ug_list != '') ? ', ' : '') . ((isset($row['group_type']) && $row['group_type'] == GROUP_SPECIAL) ? '<span class="sep">' . $user->lang['G_' . $row['name']] . '</span>' : $row['name']); + $group_name = $group_helper->get_name($row['name']); + $l_ug_list .= (($l_ug_list != '') ? ', ' : '') . ((isset($row['group_type']) && $row['group_type'] == GROUP_SPECIAL) ? '<span class="sep">' . $group_name . '</span>' : $group_name); } $db->sql_freeresult($result); @@ -925,7 +944,7 @@ class acp_permissions if ($forum_id[0] == 0) { - add_log('admin', 'LOG_ACL_' . strtoupper($action) . '_' . strtoupper($mode) . '_' . strtoupper($permission_type), $l_ug_list); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ACL_' . strtoupper($action) . '_' . strtoupper($mode) . '_' . strtoupper($permission_type), false, array($l_ug_list)); } else { @@ -942,7 +961,7 @@ class acp_permissions } $db->sql_freeresult($result); - add_log('admin', 'LOG_ACL_' . strtoupper($action) . '_' . strtoupper($mode) . '_' . strtoupper($permission_type), $l_forum_list, $l_ug_list); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ACL_' . strtoupper($action) . '_' . strtoupper($mode) . '_' . strtoupper($permission_type), false, array($l_forum_list, $l_ug_list)); } } @@ -951,7 +970,7 @@ class acp_permissions */ function permission_trace($user_id, $forum_id, $permission) { - global $db, $template, $user, $auth; + global $db, $template, $user, $auth, $request, $phpbb_container; if ($user_id != $user->data['user_id']) { @@ -967,6 +986,9 @@ class acp_permissions trigger_error('NO_USERS', E_USER_ERROR); } + /** @var \phpbb\group\helper $group_helper */ + $group_helper = $phpbb_container->get('group_helper'); + $forum_name = false; if ($forum_id) @@ -979,7 +1001,7 @@ class acp_permissions $db->sql_freeresult($result); } - $back = request_var('back', 0); + $back = $request->variable('back', 0); $template->assign_vars(array( 'PERMISSION' => $this->permissions->get_permission_lang($permission), @@ -1013,7 +1035,7 @@ class acp_permissions { $groups[$row['group_id']] = array( 'auth_setting' => ACL_NO, - 'group_name' => ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'] + 'group_name' => $group_helper->get_name($row['group_name']), ); } $db->sql_freeresult($result); @@ -1170,7 +1192,7 @@ class acp_permissions */ function copy_forum_permissions() { - global $db, $auth, $cache, $template, $user; + global $db, $auth, $cache, $template, $user, $request; $user->add_lang('acp/forums'); @@ -1178,8 +1200,8 @@ class acp_permissions if ($submit) { - $src = request_var('src_forum_id', 0); - $dest = request_var('dest_forum_ids', array(0)); + $src = $request->variable('src_forum_id', 0); + $dest = $request->variable('dest_forum_ids', array(0)); if (confirm_box(true)) { @@ -1221,7 +1243,10 @@ class acp_permissions */ function retrieve_defined_user_groups($permission_scope, $forum_id, $permission_type) { - global $db, $user; + global $db, $phpbb_container; + + /** @var \phpbb\group\helper $group_helper */ + $group_helper = $phpbb_container->get('group_helper'); $sql_forum_id = ($permission_scope == 'global') ? 'AND a.forum_id = 0' : ((sizeof($forum_id)) ? 'AND ' . $db->sql_in_set('a.forum_id', $forum_id) : 'AND a.forum_id <> 0'); @@ -1230,7 +1255,7 @@ class acp_permissions $sql = 'SELECT auth_option_id FROM ' . ACL_OPTIONS_TABLE . ' - WHERE auth_option ' . $db->sql_like_expression($permission_type . $db->any_char); + WHERE auth_option ' . $db->sql_like_expression($permission_type . $db->get_any_char()); $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) @@ -1296,7 +1321,7 @@ class acp_permissions $defined_group_ids = array(); while ($row = $db->sql_fetchrow($result)) { - $s_defined_group_options .= '<option' . (($row['group_type'] == GROUP_SPECIAL) ? ' class="sep"' : '') . ' value="' . $row['group_id'] . '">' . (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']) . '</option>'; + $s_defined_group_options .= '<option' . (($row['group_type'] == GROUP_SPECIAL) ? ' class="sep"' : '') . ' value="' . $row['group_id'] . '">' . $group_helper->get_name($row['group_name']) . '</option>'; $defined_group_ids[] = $row['group_id']; } $db->sql_freeresult($result); diff --git a/phpBB/includes/acp/acp_php_info.php b/phpBB/includes/acp/acp_php_info.php index 125b77529f..2a1afe80d4 100644 --- a/phpBB/includes/acp/acp_php_info.php +++ b/phpBB/includes/acp/acp_php_info.php @@ -1,9 +1,13 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -15,17 +19,13 @@ if (!defined('IN_PHPBB')) exit; } -/** -* @package acp -*/ class acp_php_info { var $u_action; function main($id, $mode) { - global $db, $user, $auth, $template; - global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + global $template; if ($mode != 'info') { @@ -46,7 +46,7 @@ class acp_php_info // for this was nabbed from the PHP annotated manual preg_match_all('#<body[^>]*>(.*)</body>#si', $phpinfo, $output); - if (empty($phpinfo) || empty($output)) + if (empty($phpinfo) || empty($output[1][0])) { trigger_error('NO_PHPINFO_AVAILABLE', E_USER_WARNING); } @@ -81,7 +81,7 @@ class acp_php_info $template->assign_var('PHPINFO', $output); } - + function remove_spaces($matches) { return '<a name="' . str_replace(' ', '_', $matches[1]) . '">'; diff --git a/phpBB/includes/acp/acp_profile.php b/phpBB/includes/acp/acp_profile.php index 3a5298fb58..69672ebec0 100644 --- a/phpBB/includes/acp/acp_profile.php +++ b/phpBB/includes/acp/acp_profile.php @@ -1,9 +1,13 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -15,41 +19,49 @@ if (!defined('IN_PHPBB')) exit; } -/** -* @package acp -*/ class acp_profile { var $u_action; var $edit_lang_id; var $lang_defs; + + /** + * @var \phpbb\di\service_collection + */ protected $type_collection; function main($id, $mode) { - global $config, $db, $user, $auth, $template, $cache; - global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix; - global $request, $phpbb_container; + global $config, $db, $user, $template; + global $phpbb_root_path, $phpEx; + global $request, $phpbb_container, $phpbb_log, $phpbb_dispatcher; - include($phpbb_root_path . 'includes/functions_posting.' . $phpEx); - include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + if (!function_exists('generate_smilies')) + { + include($phpbb_root_path . 'includes/functions_posting.' . $phpEx); + } + + if (!function_exists('user_get_id_name')) + { + include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + } $user->add_lang(array('ucp', 'acp/profile')); $this->tpl_name = 'acp_profile'; $this->page_title = 'ACP_CUSTOM_PROFILE_FIELDS'; $field_id = $request->variable('field_id', 0); - $action = (isset($_POST['create'])) ? 'create' : request_var('action', ''); + $action = (isset($_POST['create'])) ? 'create' : $request->variable('action', ''); $error = array(); - $s_hidden_fields = ''; if (!$field_id && in_array($action, array('delete','activate', 'deactivate', 'move_up', 'move_down', 'edit'))) { trigger_error($user->lang['NO_FIELD_ID'] . adm_back_link($this->u_action), E_USER_WARNING); } + /* @var $cp \phpbb\profilefields\manager */ $cp = $phpbb_container->get('profilefields.manager'); $this->type_collection = $phpbb_container->get('profilefields.type_collection'); @@ -111,57 +123,9 @@ class acp_profile $db->sql_query('DELETE FROM ' . PROFILE_FIELDS_LANG_TABLE . " WHERE field_id = $field_id"); $db->sql_query('DELETE FROM ' . PROFILE_LANG_TABLE . " WHERE field_id = $field_id"); - switch ($db->sql_layer) - { - case 'sqlite': - $sql = "SELECT sql - FROM sqlite_master - WHERE type = 'table' - AND name = '" . PROFILE_FIELDS_DATA_TABLE . "' - ORDER BY type DESC, name;"; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - // Create a temp table and populate it, destroy the existing one - $db->sql_query(preg_replace('#CREATE\s+TABLE\s+"?' . PROFILE_FIELDS_DATA_TABLE . '"?#i', 'CREATE TEMPORARY TABLE ' . PROFILE_FIELDS_DATA_TABLE . '_temp', $row['sql'])); - $db->sql_query('INSERT INTO ' . PROFILE_FIELDS_DATA_TABLE . '_temp SELECT * FROM ' . PROFILE_FIELDS_DATA_TABLE); - $db->sql_query('DROP TABLE ' . PROFILE_FIELDS_DATA_TABLE); - - preg_match('#\((.*)\)#s', $row['sql'], $matches); - - $new_table_cols = trim($matches[1]); - $old_table_cols = preg_split('/,(?=[\\sa-z])/im', $new_table_cols); - $column_list = array(); - - foreach ($old_table_cols as $declaration) - { - $entities = preg_split('#\s+#', trim($declaration)); - - if ($entities[0] == 'PRIMARY') - { - continue; - } - - if ($entities[0] !== 'pf_' . $field_ident) - { - $column_list[] = $entities[0]; - } - } - - $columns = implode(',', $column_list); - - $new_table_cols = preg_replace('/' . 'pf_' . $field_ident . '[^,]+,/', '', $new_table_cols); - - // create a new table and fill it up. destroy the temp one - $db->sql_query('CREATE TABLE ' . PROFILE_FIELDS_DATA_TABLE . ' (' . $new_table_cols . ');'); - $db->sql_query('INSERT INTO ' . PROFILE_FIELDS_DATA_TABLE . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . PROFILE_FIELDS_DATA_TABLE . '_temp;'); - $db->sql_query('DROP TABLE ' . PROFILE_FIELDS_DATA_TABLE . '_temp'); - break; - - default: - $db->sql_query('ALTER TABLE ' . PROFILE_FIELDS_DATA_TABLE . " DROP COLUMN pf_$field_ident"); - } + /* @var $db_tools \phpbb\db\tools\tools_interface */ + $db_tools = $phpbb_container->get('dbal.tools'); + $db_tools->sql_column_remove(PROFILE_FIELDS_DATA_TABLE, 'pf_' . $field_ident); $order = 0; @@ -185,7 +149,7 @@ class acp_profile $db->sql_transaction('commit'); - add_log('admin', 'LOG_PROFILE_FIELD_REMOVED', $field_ident); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_PROFILE_FIELD_REMOVED', false, array($field_ident)); trigger_error($user->lang['REMOVED_PROFILE_FIELD'] . adm_back_link($this->u_action)); } else @@ -226,7 +190,7 @@ class acp_profile $field_ident = (string) $db->sql_fetchfield('field_ident'); $db->sql_freeresult($result); - add_log('admin', 'LOG_PROFILE_FIELD_ACTIVATE', $field_ident); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_PROFILE_FIELD_ACTIVATE', false, array($field_ident)); if ($request->is_ajax()) { @@ -262,7 +226,7 @@ class acp_profile )); } - add_log('admin', 'LOG_PROFILE_FIELD_DEACTIVATE', $field_ident); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_PROFILE_FIELD_DEACTIVATE', false, array($field_ident)); trigger_error($user->lang['PROFILE_FIELD_DEACTIVATED'] . adm_back_link($this->u_action)); @@ -303,7 +267,7 @@ class acp_profile case 'create': case 'edit': - $step = request_var('step', 1); + $step = $request->variable('step', 1); $submit = (isset($_REQUEST['next']) || isset($_REQUEST['prev'])) ? true : false; $save = (isset($_REQUEST['save'])) ? true : false; @@ -367,7 +331,7 @@ class acp_profile // We are adding a new field, define basic params $lang_options = $field_row = array(); - $field_type = request_var('field_type', ''); + $field_type = $request->variable('field_type', ''); if (!isset($this->type_collection[$field_type])) { @@ -376,7 +340,7 @@ class acp_profile $profile_field = $this->type_collection[$field_type]; $field_row = array_merge($profile_field->get_default_option_values(), array( - 'field_ident' => str_replace(' ', '_', utf8_clean_string(request_var('field_ident', '', true))), + 'field_ident' => str_replace(' ', '_', utf8_clean_string($request->variable('field_ident', '', true))), 'field_required' => 0, 'field_show_novalue'=> 0, 'field_hide' => 0, @@ -386,7 +350,10 @@ class acp_profile 'field_show_on_pm' => 0, 'field_show_on_vt' => 0, 'field_show_on_ml' => 0, - 'lang_name' => utf8_normalize_nfc(request_var('field_ident', '', true)), + 'field_is_contact' => 0, + 'field_contact_desc'=> '', + 'field_contact_url' => '', + 'lang_name' => $request->variable('field_ident', '', true), 'lang_explain' => '', 'lang_default_value'=> '') ); @@ -396,7 +363,7 @@ class acp_profile // $exclude contains the data we gather in each step $exclude = array( - 1 => array('field_ident', 'lang_name', 'lang_explain', 'field_option_none', 'field_show_on_reg', 'field_show_on_pm', 'field_show_on_vt', 'field_show_on_ml', 'field_required', 'field_show_novalue', 'field_hide', 'field_show_profile', 'field_no_view'), + 1 => array('field_ident', 'lang_name', 'lang_explain', 'field_option_none', 'field_show_on_reg', 'field_show_on_pm', 'field_show_on_vt', 'field_show_on_ml', 'field_required', 'field_show_novalue', 'field_hide', 'field_show_profile', 'field_no_view', 'field_is_contact', 'field_contact_desc', 'field_contact_url'), 2 => array('field_length', 'field_maxlen', 'field_minlen', 'field_validation', 'field_novalue', 'field_default_value'), 3 => array('l_lang_name', 'l_lang_explain', 'l_lang_default_value', 'l_lang_options') ); @@ -411,21 +378,50 @@ class acp_profile 'field_show_on_ml', 'field_show_profile', 'field_hide', + 'field_is_contact', ); + /** + * Event to add initialization for new profile field table fields + * + * @event core.acp_profile_create_edit_init + * @var string action create|edit + * @var int step Configuration step (1|2|3) + * @var bool submit Form has been submitted + * @var bool save Configuration should be saved + * @var string field_type Type of the field we are dealing with + * @var array field_row Array of data about the field + * @var array exclude Array of excluded fields by step + * @var array visibility_ary Array of fields that are visibility related + * @since 3.1.6-RC1 + */ + $vars = array( + 'action', + 'step', + 'submit', + 'save', + 'field_type', + 'field_row', + 'exclude', + 'visibility_ary', + ); + extract($phpbb_dispatcher->trigger_event('core.acp_profile_create_edit_init', compact($vars))); + $options = $profile_field->prepare_options_form($exclude, $visibility_ary); - $cp->vars['field_ident'] = ($action == 'create' && $step == 1) ? utf8_clean_string(request_var('field_ident', $field_row['field_ident'], true)) : request_var('field_ident', $field_row['field_ident']); - $cp->vars['lang_name'] = utf8_normalize_nfc(request_var('lang_name', $field_row['lang_name'], true)); - $cp->vars['lang_explain'] = utf8_normalize_nfc(request_var('lang_explain', $field_row['lang_explain'], true)); - $cp->vars['lang_default_value'] = utf8_normalize_nfc(request_var('lang_default_value', $field_row['lang_default_value'], true)); + $cp->vars['field_ident'] = ($action == 'create' && $step == 1) ? utf8_clean_string($request->variable('field_ident', $field_row['field_ident'], true)) : $request->variable('field_ident', $field_row['field_ident']); + $cp->vars['lang_name'] = $request->variable('lang_name', $field_row['lang_name'], true); + $cp->vars['lang_explain'] = $request->variable('lang_explain', $field_row['lang_explain'], true); + $cp->vars['lang_default_value'] = $request->variable('lang_default_value', $field_row['lang_default_value'], true); + $cp->vars['field_contact_desc'] = $request->variable('field_contact_desc', $field_row['field_contact_desc'], true); + $cp->vars['field_contact_url'] = $request->variable('field_contact_url', $field_row['field_contact_url'], true); foreach ($visibility_ary as $val) { - $cp->vars[$val] = ($submit || $save) ? request_var($val, 0) : $field_row[$val]; + $cp->vars[$val] = ($submit || $save) ? $request->variable($val, 0) : $field_row[$val]; } - $cp->vars['field_no_view'] = request_var('field_no_view', (int) $field_row['field_no_view']); + $cp->vars['field_no_view'] = $request->variable('field_no_view', (int) $field_row['field_no_view']); // If the user has submitted a form with options (i.e. dropdown field) if ($options) @@ -452,7 +448,7 @@ class acp_profile // step 2 foreach ($exclude[2] as $key) { - $var = utf8_normalize_nfc(request_var($key, $field_row[$key], true)); + $var = $request->variable($key, $field_row[$key], true); $field_data = $cp->vars; $var = $profile_field->get_excluded_options($key, $action, $var, $field_data, 2); @@ -479,7 +475,6 @@ class acp_profile } $db->sql_freeresult($result); - $sql = 'SELECT lang_id, lang_name, lang_explain, lang_default_value FROM ' . PROFILE_LANG_TABLE . ' WHERE lang_id <> ' . $this->edit_lang_id . " @@ -499,11 +494,11 @@ class acp_profile foreach ($exclude[3] as $key) { - $cp->vars[$key] = utf8_normalize_nfc(request_var($key, array(0 => ''), true)); + $cp->vars[$key] = $request->variable($key, array(0 => ''), true); if (!$cp->vars[$key] && $action == 'edit') { - $cp->vars[$key] = $$key; + $cp->vars[$key] = ${$key}; } $field_data = $cp->vars; @@ -554,13 +549,14 @@ class acp_profile } } - $step = (isset($_REQUEST['next'])) ? $step + 1 : ((isset($_REQUEST['prev'])) ? $step - 1 : $step); - if (sizeof($error)) { - $step--; $submit = false; } + else + { + $step = (isset($_REQUEST['next'])) ? $step + 1 : ((isset($_REQUEST['prev'])) ? $step - 1 : $step); + } // Build up the specific hidden fields foreach ($exclude as $num => $key_ary) @@ -578,7 +574,7 @@ class acp_profile $var = $profile_field->prepare_hidden_fields($step, $key, $action, $field_data); if ($var !== null) { - $_new_key_ary[$key] = $profile_field->prepare_hidden_fields($step, $key, $action, $field_data); + $_new_key_ary[$key] = $var; } } $cp->vars = $field_data; @@ -588,11 +584,7 @@ class acp_profile if (!sizeof($error)) { - if ($step == 3 && (sizeof($this->lang_defs['iso']) == 1 || $save)) - { - $this->save_profile_field($cp, $field_type, $action); - } - else if ($action == 'edit' && $save) + if (($step == 3 && (sizeof($this->lang_defs['iso']) == 1 || $save)) || ($action == 'edit' && $save)) { $this->save_profile_field($cp, $field_type, $action); } @@ -626,6 +618,9 @@ class acp_profile 'S_FIELD_HIDE' => ($cp->vars['field_hide']) ? true : false, 'S_SHOW_PROFILE' => ($cp->vars['field_show_profile']) ? true : false, 'S_FIELD_NO_VIEW' => ($cp->vars['field_no_view']) ? true : false, + 'S_FIELD_CONTACT' => $cp->vars['field_is_contact'], + 'FIELD_CONTACT_DESC'=> $cp->vars['field_contact_desc'], + 'FIELD_CONTACT_URL' => $cp->vars['field_contact_url'], 'L_LANG_SPECIFIC' => sprintf($user->lang['LANG_SPECIFIC_OPTIONS'], $config['default_lang']), 'FIELD_TYPE' => $profile_field->get_name(), @@ -684,6 +679,33 @@ class acp_profile break; } + $field_data = $cp->vars; + /** + * Event to add template variables for new profile field table fields + * + * @event core.acp_profile_create_edit_after + * @var string action create|edit + * @var int step Configuration step (1|2|3) + * @var bool submit Form has been submitted + * @var bool save Configuration should be saved + * @var string field_type Type of the field we are dealing with + * @var array field_data Array of data about the field + * @var array s_hidden_fields Array of hidden fields in case this needs modification + * @var array options Array of options specific to this step + * @since 3.1.6-RC1 + */ + $vars = array( + 'action', + 'step', + 'submit', + 'save', + 'field_type', + 'field_data', + 's_hidden_fields', + 'options', + ); + extract($phpbb_dispatcher->trigger_event('core.acp_profile_create_edit_after', compact($vars))); + $template->assign_vars(array( 'S_HIDDEN_FIELDS' => $s_hidden_fields) ); @@ -753,7 +775,7 @@ class acp_profile */ function build_language_options(&$cp, $field_type, $action = 'create') { - global $user, $config, $db, $phpbb_container; + global $user, $config, $db, $request; $default_lang_id = (!empty($this->edit_lang_id)) ? $this->edit_lang_id : $this->lang_defs['iso'][$config['default_lang']]; @@ -794,7 +816,7 @@ class acp_profile $lang_options[$lang_id]['lang_iso'] = $lang_iso; foreach ($options as $field => $field_type) { - $value = ($action == 'create') ? utf8_normalize_nfc(request_var('l_' . $field, array(0 => ''), true)) : $cp->vars['l_' . $field]; + $value = ($action == 'create') ? $request->variable('l_' . $field, array(0 => ''), true) : $cp->vars['l_' . $field]; if ($field == 'lang_options') { $var = (!isset($cp->vars['l_lang_options'][$lang_id]) || !is_array($cp->vars['l_lang_options'][$lang_id])) ? $cp->vars['lang_options'] : $cp->vars['l_lang_options'][$lang_id]; @@ -850,9 +872,9 @@ class acp_profile */ function save_profile_field(&$cp, $field_type, $action = 'create') { - global $db, $config, $user, $phpbb_container; + global $db, $config, $user, $phpbb_container, $phpbb_log, $request, $phpbb_dispatcher; - $field_id = request_var('field_id', 0); + $field_id = $request->variable('field_id', 0); // Collect all information, if something is going wrong, abort the operation $profile_sql = $profile_lang = $empty_lang = $profile_lang_fields = array(); @@ -886,9 +908,31 @@ class acp_profile 'field_show_on_ml' => $cp->vars['field_show_on_ml'], 'field_hide' => $cp->vars['field_hide'], 'field_show_profile' => $cp->vars['field_show_profile'], - 'field_no_view' => $cp->vars['field_no_view'] + 'field_no_view' => $cp->vars['field_no_view'], + 'field_is_contact' => $cp->vars['field_is_contact'], + 'field_contact_desc' => $cp->vars['field_contact_desc'], + 'field_contact_url' => $cp->vars['field_contact_url'], ); + $field_data = $cp->vars; + /** + * Event to modify profile field configuration data before saving to database + * + * @event core.acp_profile_create_edit_save_before + * @var string action create|edit + * @var string field_type Type of the field we are dealing with + * @var array field_data Array of data about the field + * @var array profile_fields Array of fields to be sent to the database + * @since 3.1.6-RC1 + */ + $vars = array( + 'action', + 'field_type', + 'field_data', + 'profile_fields', + ); + extract($phpbb_dispatcher->trigger_event('core.acp_profile_create_edit_save_before', compact($vars))); + if ($action == 'create') { $profile_fields += array( @@ -917,11 +961,9 @@ class acp_profile if ($action == 'create') { $field_ident = 'pf_' . $field_ident; - + /* @var $db_tools \phpbb\db\tools\tools_interface */ $db_tools = $phpbb_container->get('dbal.tools'); - - list($sql_type, $null) = $db_tools->get_column_type($profile_field->get_database_column_type()); - $profile_sql[] = $this->add_field_ident($field_ident, $sql_type); + $db_tools->sql_column_add(PROFILE_FIELDS_DATA_TABLE, $field_ident, array($profile_field->get_database_column_type(), null)); } $sql_ary = array( @@ -1104,7 +1146,6 @@ class acp_profile } } - $db->sql_transaction('begin'); if ($action == 'create') @@ -1119,12 +1160,12 @@ class acp_profile if ($action == 'edit') { - add_log('admin', 'LOG_PROFILE_FIELD_EDIT', $cp->vars['field_ident'] . ':' . $cp->vars['lang_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_PROFILE_FIELD_EDIT', false, array($cp->vars['field_ident'] . ':' . $cp->vars['lang_name'])); trigger_error($user->lang['CHANGED_PROFILE_FIELD'] . adm_back_link($this->u_action)); } else { - add_log('admin', 'LOG_PROFILE_FIELD_CREATE', substr($field_ident, 3) . ':' . $cp->vars['lang_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_PROFILE_FIELD_CREATE', false, array(substr($field_ident, 3) . ':' . $cp->vars['lang_name'])); trigger_error($user->lang['ADDED_PROFILE_FIELD'] . adm_back_link($this->u_action)); } } @@ -1176,95 +1217,4 @@ class acp_profile } } } - - /** - * Return sql statement for adding a new field ident (profile field) to the profile fields data table - */ - function add_field_ident($field_ident, $sql_type) - { - global $db; - - switch ($db->sql_layer) - { - case 'mysql': - case 'mysql4': - case 'mysqli': - $sql = 'ALTER TABLE ' . PROFILE_FIELDS_DATA_TABLE . " ADD `$field_ident` " . $sql_type; - - break; - - case 'sqlite': - if (version_compare(sqlite_libversion(), '3.0') == -1) - { - $sql = "SELECT sql - FROM sqlite_master - WHERE type = 'table' - AND name = '" . PROFILE_FIELDS_DATA_TABLE . "' - ORDER BY type DESC, name;"; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - // Create a temp table and populate it, destroy the existing one - $db->sql_query(preg_replace('#CREATE\s+TABLE\s+"?' . PROFILE_FIELDS_DATA_TABLE . '"?#i', 'CREATE TEMPORARY TABLE ' . PROFILE_FIELDS_DATA_TABLE . '_temp', $row['sql'])); - $db->sql_query('INSERT INTO ' . PROFILE_FIELDS_DATA_TABLE . '_temp SELECT * FROM ' . PROFILE_FIELDS_DATA_TABLE); - $db->sql_query('DROP TABLE ' . PROFILE_FIELDS_DATA_TABLE); - - preg_match('#\((.*)\)#s', $row['sql'], $matches); - - $new_table_cols = trim($matches[1]); - $old_table_cols = explode(',', $new_table_cols); - $column_list = array(); - - foreach ($old_table_cols as $declaration) - { - $entities = preg_split('#\s+#', trim($declaration)); - if ($entities[0] == 'PRIMARY') - { - continue; - } - $column_list[] = $entities[0]; - } - - $columns = implode(',', $column_list); - - $new_table_cols = $field_ident . ' ' . $sql_type . ',' . $new_table_cols; - - // create a new table and fill it up. destroy the temp one - $db->sql_query('CREATE TABLE ' . PROFILE_FIELDS_DATA_TABLE . ' (' . $new_table_cols . ');'); - $db->sql_query('INSERT INTO ' . PROFILE_FIELDS_DATA_TABLE . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . PROFILE_FIELDS_DATA_TABLE . '_temp;'); - $db->sql_query('DROP TABLE ' . PROFILE_FIELDS_DATA_TABLE . '_temp'); - } - else - { - $sql = 'ALTER TABLE ' . PROFILE_FIELDS_DATA_TABLE . " ADD $field_ident [$sql_type]"; - } - - break; - - case 'mssql': - case 'mssql_odbc': - case 'mssqlnative': - $sql = 'ALTER TABLE [' . PROFILE_FIELDS_DATA_TABLE . "] ADD [$field_ident] " . $sql_type; - - break; - - case 'postgres': - $sql = 'ALTER TABLE ' . PROFILE_FIELDS_DATA_TABLE . " ADD COLUMN \"$field_ident\" " . $sql_type; - - break; - - case 'firebird': - $sql = 'ALTER TABLE ' . PROFILE_FIELDS_DATA_TABLE . ' ADD "' . strtoupper($field_ident) . '" ' . $sql_type; - - break; - - case 'oracle': - $sql = 'ALTER TABLE ' . PROFILE_FIELDS_DATA_TABLE . " ADD $field_ident " . $sql_type; - - break; - } - - return $sql; - } } diff --git a/phpBB/includes/acp/acp_prune.php b/phpBB/includes/acp/acp_prune.php index 5d9080b55b..d37050869a 100644 --- a/phpBB/includes/acp/acp_prune.php +++ b/phpBB/includes/acp/acp_prune.php @@ -1,9 +1,13 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -15,19 +19,20 @@ if (!defined('IN_PHPBB')) exit; } -/** -* @package acp -*/ class acp_prune { var $u_action; function main($id, $mode) { - global $user, $phpEx, $phpbb_admin_path, $phpbb_root_path; + global $user, $phpEx, $phpbb_root_path; $user->add_lang('acp/prune'); - include_once($phpbb_root_path . 'includes/functions_user.' . $phpEx); + + if (!function_exists('user_active_flip')) + { + include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + } switch ($mode) { @@ -50,11 +55,10 @@ class acp_prune */ function prune_forums($id, $mode) { - global $db, $user, $auth, $template, $cache; - global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + global $db, $user, $auth, $template, $phpbb_log, $request; - $all_forums = request_var('all_forums', 0); - $forum_id = request_var('f', array(0)); + $all_forums = $request->variable('all_forums', 0); + $forum_id = $request->variable('f', array(0)); $submit = (isset($_POST['submit'])) ? true : false; if ($all_forums) @@ -76,14 +80,14 @@ class acp_prune { if (confirm_box(true)) { - $prune_posted = request_var('prune_days', 0); - $prune_viewed = request_var('prune_vieweddays', 0); + $prune_posted = $request->variable('prune_days', 0); + $prune_viewed = $request->variable('prune_vieweddays', 0); $prune_all = (!$prune_posted && !$prune_viewed) ? true : false; - + $prune_flags = 0; - $prune_flags += (request_var('prune_old_polls', 0)) ? 2 : 0; - $prune_flags += (request_var('prune_announce', 0)) ? 4 : 0; - $prune_flags += (request_var('prune_sticky', 0)) ? 8 : 0; + $prune_flags += ($request->variable('prune_old_polls', 0)) ? 2 : 0; + $prune_flags += ($request->variable('prune_announce', 0)) ? 4 : 0; + $prune_flags += ($request->variable('prune_sticky', 0)) ? 8 : 0; // Convert days to seconds for timestamp functions... $prunedate_posted = time() - ($prune_posted * 86400); @@ -109,7 +113,7 @@ class acp_prune $p_result['topics'] = 0; $p_result['posts'] = 0; $log_data = ''; - + do { if (!$auth->acl_get('f_list', $row['forum_id'])) @@ -129,7 +133,7 @@ class acp_prune $p_result['topics'] += $return['topics']; $p_result['posts'] += $return['posts']; } - + if ($prune_viewed) { $return = prune($row['forum_id'], 'viewed', $prunedate_viewed, $prune_flags, false); @@ -145,14 +149,15 @@ class acp_prune 'NUM_TOPICS' => $p_result['topics'], 'NUM_POSTS' => $p_result['posts']) ); - + $log_data .= (($log_data != '') ? ', ' : '') . $row['forum_name']; } while ($row = $db->sql_fetchrow($result)); - + // Sync all pruned forums at once sync('forum', 'forum_id', $prune_ids, true, true); - add_log('admin', 'LOG_PRUNE', $log_data); + + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_PRUNE', false, array($log_data)); } $db->sql_freeresult($result); @@ -167,11 +172,11 @@ class acp_prune 'all_forums' => $all_forums, 'f' => $forum_id, - 'prune_days' => request_var('prune_days', 0), - 'prune_vieweddays' => request_var('prune_vieweddays', 0), - 'prune_old_polls' => request_var('prune_old_polls', 0), - 'prune_announce' => request_var('prune_announce', 0), - 'prune_sticky' => request_var('prune_sticky', 0), + 'prune_days' => $request->variable('prune_days', 0), + 'prune_vieweddays' => $request->variable('prune_vieweddays', 0), + 'prune_old_polls' => $request->variable('prune_old_polls', 0), + 'prune_announce' => $request->variable('prune_announce', 0), + 'prune_sticky' => $request->variable('prune_sticky', 0), ))); } } @@ -227,8 +232,11 @@ class acp_prune */ function prune_users($id, $mode) { - global $db, $user, $auth, $template, $cache; - global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + global $db, $user, $auth, $template, $phpbb_log, $request; + global $phpbb_root_path, $phpbb_admin_path, $phpEx, $phpbb_container; + + /** @var \phpbb\group\helper $group_helper */ + $group_helper = $phpbb_container->get('group_helper'); $user->add_lang('memberlist'); @@ -236,8 +244,8 @@ class acp_prune if ($prune) { - $action = request_var('action', 'deactivate'); - $deleteposts = request_var('deleteposts', 0); + $action = $request->variable('action', 'deactivate'); + $deleteposts = $request->variable('deleteposts', 0); if (confirm_box(true)) { @@ -256,7 +264,7 @@ class acp_prune if ($deleteposts) { user_delete('remove', $user_ids); - + $l_log = 'LOG_PRUNE_USER_DEL_DEL'; } else @@ -267,7 +275,7 @@ class acp_prune } } - add_log('admin', $l_log, implode(', ', $usernames)); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, $l_log, false, array(implode(', ', $usernames))); $msg = $user->lang['USER_' . strtoupper($action) . '_SUCCESS']; } else @@ -294,7 +302,7 @@ class acp_prune $template->assign_block_vars('users', array( 'USERNAME' => $usernames[$user_id], 'USER_ID' => $user_id, - 'U_PROFILE' => append_sid($phpbb_root_path . 'memberlist.' . $phpEx, 'mode=viewprofile&u=' . $user_id), + 'U_PROFILE' => get_username_string('profile', $user_id, $usernames[$user_id]), 'U_USER_ADMIN' => ($auth->acl_get('a_user')) ? append_sid("{$phpbb_admin_path}index.$phpEx", 'i=users&mode=overview&u=' . $user_id, true, $user->session_id) : '', )); } @@ -309,8 +317,8 @@ class acp_prune 'mode' => $mode, 'prune' => 1, - 'deleteposts' => request_var('deleteposts', 0), - 'action' => request_var('action', ''), + 'deleteposts' => $request->variable('deleteposts', 0), + 'action' => $request->variable('action', ''), )), 'confirm_body_prune.html'); } } @@ -340,7 +348,7 @@ class acp_prune $s_group_list = ''; while ($row = $db->sql_fetchrow($result)) { - $s_group_list .= '<option value="' . $row['group_id'] . '">' . $row['group_name'] . '</option>'; + $s_group_list .= '<option value="' . $row['group_id'] . '">' . $group_helper->get_name($row['group_name']) . '</option>'; } $db->sql_freeresult($result); @@ -367,9 +375,9 @@ class acp_prune { global $user, $db, $request; - $users_by_name = request_var('users', '', true); - $users_by_id = request_var('user_ids', array(0)); - $group_id = request_var('group_id', 0); + $users_by_name = $request->variable('users', '', true); + $users_by_id = $request->variable('user_ids', array(0)); + $group_id = $request->variable('group_id', 0); $posts_on_queue = (trim($request->variable('posts_on_queue', '')) === '') ? false : $request->variable('posts_on_queue', 0); if ($users_by_name) @@ -386,18 +394,17 @@ class acp_prune } else { - $username = request_var('username', '', true); - $email = request_var('email', ''); - $website = request_var('website', ''); + $username = $request->variable('username', '', true); + $email = $request->variable('email', ''); - $active_select = request_var('active_select', 'lt'); - $count_select = request_var('count_select', 'eq'); - $queue_select = request_var('queue_select', 'gt'); - $joined_before = request_var('joined_before', ''); - $joined_after = request_var('joined_after', ''); - $active = request_var('active', ''); + $active_select = $request->variable('active_select', 'lt'); + $count_select = $request->variable('count_select', 'eq'); + $queue_select = $request->variable('queue_select', 'gt'); + $joined_before = $request->variable('joined_before', ''); + $joined_after = $request->variable('joined_after', ''); + $active = $request->variable('active', ''); - $count = request_var('count', 0); + $count = ($request->variable('count', '') === '') ? false : $request->variable('count', 0); $active = ($active) ? explode('-', $active) : array(); $joined_before = ($joined_before) ? explode('-', $joined_before) : array(); @@ -433,20 +440,18 @@ class acp_prune } $key_match = array('lt' => '<', 'gt' => '>', 'eq' => '='); - $sort_by_types = array('username', 'user_email', 'user_posts', 'user_regdate', 'user_lastvisit'); $where_sql = ''; - $where_sql .= ($username) ? ' AND username_clean ' . $db->sql_like_expression(str_replace('*', $db->any_char, utf8_clean_string($username))) : ''; - $where_sql .= ($email) ? ' AND user_email ' . $db->sql_like_expression(str_replace('*', $db->any_char, $email)) . ' ' : ''; - $where_sql .= ($website) ? ' AND user_website ' . $db->sql_like_expression(str_replace('*', $db->any_char, $website)) . ' ' : ''; + $where_sql .= ($username) ? ' AND username_clean ' . $db->sql_like_expression(str_replace('*', $db->get_any_char(), utf8_clean_string($username))) : ''; + $where_sql .= ($email) ? ' AND user_email ' . $db->sql_like_expression(str_replace('*', $db->get_any_char(), $email)) . ' ' : ''; $where_sql .= $joined_sql; - $where_sql .= ($count) ? " AND user_posts " . $key_match[$count_select] . ' ' . (int) $count . ' ' : ''; + $where_sql .= ($count !== false) ? " AND user_posts " . $key_match[$count_select] . ' ' . (int) $count . ' ' : ''; // First handle pruning of users who never logged in, last active date is 0000-00-00 if (sizeof($active) && (int) $active[0] == 0 && (int) $active[1] == 0 && (int) $active[2] == 0) { $where_sql .= ' AND user_lastvisit = 0'; - } + } else if (sizeof($active) && $active_select != 'lt') { $where_sql .= ' AND user_lastvisit ' . $key_match[$active_select] . ' ' . gmmktime(0, 0, 0, (int) $active[1], (int) $active[2], (int) $active[0]); @@ -507,9 +512,9 @@ class acp_prune WHERE ug.group_id = ' . (int) $group_id . ' AND ug.user_id <> ' . ANONYMOUS . ' AND u.user_type <> ' . USER_FOUNDER . ' - AND ug.user_pending = 0 ' . - ((!empty($user_ids)) ? 'AND ' . $db->sql_in_set('ug.user_id', $user_ids) : '') . ' - AND u.user_id = ug.user_id'; + AND ug.user_pending = 0 + AND u.user_id = ug.user_id + ' . (!empty($user_ids) ? ' AND ' . $db->sql_in_set('ug.user_id', $user_ids) : ''); $result = $db->sql_query($sql); // we're performing an intersection operation, so all the relevant users @@ -533,10 +538,10 @@ class acp_prune $sql = 'SELECT u.user_id, u.username, COUNT(p.post_id) AS queue_posts FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u WHERE u.user_id <> ' . ANONYMOUS . ' - AND u.user_type <> ' . USER_FOUNDER . - ((!empty($user_ids)) ? 'AND ' . $db->sql_in_set('p.poster_id', $user_ids) : '') . ' - AND p.post_visibility = ' . ITEM_UNAPPROVED . ' + AND u.user_type <> ' . USER_FOUNDER . ' + AND ' . $db->sql_in_set('p.post_visibility', array(ITEM_UNAPPROVED, ITEM_REAPPROVE)) . ' AND u.user_id = p.poster_id + ' . (!empty($user_ids) ? ' AND ' . $db->sql_in_set('p.poster_id', $user_ids) : '') . ' GROUP BY p.poster_id HAVING queue_posts ' . $key_match[$queue_select] . ' ' . $posts_on_queue; $result = $db->sql_query($sql); diff --git a/phpBB/includes/acp/acp_ranks.php b/phpBB/includes/acp/acp_ranks.php index 73e1de44d9..4d2b64d74c 100644 --- a/phpBB/includes/acp/acp_ranks.php +++ b/phpBB/includes/acp/acp_ranks.php @@ -1,9 +1,13 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -15,25 +19,22 @@ if (!defined('IN_PHPBB')) exit; } -/** -* @package acp -*/ class acp_ranks { var $u_action; function main($id, $mode) { - global $db, $user, $auth, $template, $cache, $request; - global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + global $db, $user, $template, $cache, $request, $phpbb_dispatcher; + global $config, $phpbb_root_path, $phpbb_admin_path, $phpbb_log; $user->add_lang('acp/posting'); // Set up general vars - $action = request_var('action', ''); + $action = $request->variable('action', ''); $action = (isset($_POST['add'])) ? 'add' : $action; $action = (isset($_POST['save'])) ? 'save' : $action; - $rank_id = request_var('id', 0); + $rank_id = $request->variable('id', 0); $this->tpl_name = 'acp_ranks'; $this->page_title = 'ACP_MANAGE_RANKS'; @@ -49,10 +50,10 @@ class acp_ranks { trigger_error($user->lang['FORM_INVALID']. adm_back_link($this->u_action), E_USER_WARNING); } - $rank_title = utf8_normalize_nfc(request_var('title', '', true)); - $special_rank = request_var('special_rank', 0); - $min_posts = ($special_rank) ? 0 : max(0, request_var('min_posts', 0)); - $rank_image = request_var('rank_image', ''); + $rank_title = $request->variable('title', '', true); + $special_rank = $request->variable('special_rank', 0); + $min_posts = ($special_rank) ? 0 : max(0, $request->variable('min_posts', 0)); + $rank_image = $request->variable('rank_image', ''); // The rank image has to be a jpg, gif or png if ($rank_image != '' && !preg_match('#(\.gif|\.png|\.jpg|\.jpeg)$#i', $rank_image)) @@ -72,19 +73,30 @@ class acp_ranks 'rank_image' => htmlspecialchars_decode($rank_image) ); + /** + * Modify the SQL array when saving a rank + * + * @event core.acp_ranks_save_modify_sql_ary + * @var int rank_id The ID of the rank (if available) + * @var array sql_ary Array with the rank's data + * @since 3.1.0-RC3 + */ + $vars = array('rank_id', 'sql_ary'); + extract($phpbb_dispatcher->trigger_event('core.acp_ranks_save_modify_sql_ary', compact($vars))); + if ($rank_id) { $sql = 'UPDATE ' . RANKS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " WHERE rank_id = $rank_id"; $message = $user->lang['RANK_UPDATED']; - add_log('admin', 'LOG_RANK_UPDATED', $rank_title); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_RANK_UPDATED', false, array($rank_title)); } else { $sql = 'INSERT INTO ' . RANKS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary); $message = $user->lang['RANK_ADDED']; - add_log('admin', 'LOG_RANK_ADDED', $rank_title); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_RANK_ADDED', false, array($rank_title)); } $db->sql_query($sql); @@ -121,7 +133,7 @@ class acp_ranks $cache->destroy('_ranks'); - add_log('admin', 'LOG_RANK_REMOVED', $rank_title); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_RANK_REMOVED', false, array($rank_title)); if ($request->is_ajax()) { @@ -150,7 +162,7 @@ class acp_ranks case 'edit': case 'add': - $data = $ranks = $existing_imgs = array(); + $ranks = $existing_imgs = array(); $sql = 'SELECT * FROM ' . RANKS_TABLE . ' @@ -201,7 +213,7 @@ class acp_ranks $filename_list = '<option value=""' . (($edit_img == '') ? ' selected="selected"' : '') . '>----------</option>' . $filename_list; unset($existing_imgs, $imglist); - $template->assign_vars(array( + $tpl_ary = array( 'S_EDIT' => true, 'U_BACK' => $this->u_action, 'RANKS_PATH' => $phpbb_root_path . $config['ranks_path'], @@ -211,10 +223,21 @@ class acp_ranks 'S_FILENAME_LIST' => $filename_list, 'RANK_IMAGE' => ($edit_img) ? $phpbb_root_path . $config['ranks_path'] . '/' . $edit_img : htmlspecialchars($phpbb_admin_path) . 'images/spacer.gif', 'S_SPECIAL_RANK' => (isset($ranks['rank_special']) && $ranks['rank_special']) ? true : false, - 'MIN_POSTS' => (isset($ranks['rank_min']) && !$ranks['rank_special']) ? $ranks['rank_min'] : 0) + 'MIN_POSTS' => (isset($ranks['rank_min']) && !$ranks['rank_special']) ? $ranks['rank_min'] : 0, ); - + /** + * Modify the template output array for editing/adding ranks + * + * @event core.acp_ranks_edit_modify_tpl_ary + * @var array ranks Array with the rank's data + * @var array tpl_ary Array with the rank's template data + * @since 3.1.0-RC3 + */ + $vars = array('ranks', 'tpl_ary'); + extract($phpbb_dispatcher->trigger_event('core.acp_ranks_edit_modify_tpl_ary', compact($vars))); + + $template->assign_vars($tpl_ary); return; break; @@ -231,7 +254,7 @@ class acp_ranks while ($row = $db->sql_fetchrow($result)) { - $template->assign_block_vars('ranks', array( + $rank_row = array( 'S_RANK_IMAGE' => ($row['rank_image']) ? true : false, 'S_SPECIAL_RANK' => ($row['rank_special']) ? true : false, @@ -240,8 +263,21 @@ class acp_ranks 'MIN_POSTS' => $row['rank_min'], 'U_EDIT' => $this->u_action . '&action=edit&id=' . $row['rank_id'], - 'U_DELETE' => $this->u_action . '&action=delete&id=' . $row['rank_id']) + 'U_DELETE' => $this->u_action . '&action=delete&id=' . $row['rank_id'], ); + + /** + * Modify the template output array for each listed rank + * + * @event core.acp_ranks_list_modify_rank_row + * @var array row Array with the rank's data + * @var array rank_row Array with the rank's template data + * @since 3.1.0-RC3 + */ + $vars = array('row', 'rank_row'); + extract($phpbb_dispatcher->trigger_event('core.acp_ranks_list_modify_rank_row', compact($vars))); + + $template->assign_block_vars('ranks', $rank_row); } $db->sql_freeresult($result); diff --git a/phpBB/includes/acp/acp_reasons.php b/phpBB/includes/acp/acp_reasons.php index 569bb73ab0..0d221bba3c 100644 --- a/phpBB/includes/acp/acp_reasons.php +++ b/phpBB/includes/acp/acp_reasons.php @@ -1,9 +1,13 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -15,25 +19,21 @@ if (!defined('IN_PHPBB')) exit; } -/** -* @package acp -*/ class acp_reasons { var $u_action; function main($id, $mode) { - global $db, $user, $auth, $template, $cache; - global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; - global $request; + global $db, $user, $template; + global $request, $phpbb_log; $user->add_lang(array('mcp', 'acp/posting')); // Set up general vars - $action = request_var('action', ''); + $action = $request->variable('action', ''); $submit = (isset($_POST['submit'])) ? true : false; - $reason_id = request_var('id', 0); + $reason_id = $request->variable('id', 0); $this->tpl_name = 'acp_reasons'; $this->page_title = 'ACP_REASONS'; @@ -49,8 +49,8 @@ class acp_reasons case 'edit': $reason_row = array( - 'reason_title' => utf8_normalize_nfc(request_var('reason_title', '', true)), - 'reason_description' => utf8_normalize_nfc(request_var('reason_description', '', true)), + 'reason_title' => $request->variable('reason_title', '', true), + 'reason_description' => $request->variable('reason_description', '', true), ); if ($submit) @@ -138,7 +138,7 @@ class acp_reasons $log = 'UPDATED'; } - add_log('admin', 'LOG_REASON_' . $log, $reason_row['reason_title']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_REASON_' . $log, false, array($reason_row['reason_title'])); trigger_error($user->lang['REASON_' . $log] . adm_back_link($this->u_action)); } } @@ -218,7 +218,7 @@ class acp_reasons $other_reason_id = (int) $db->sql_fetchfield('reason_id'); $db->sql_freeresult($result); - switch ($db->sql_layer) + switch ($db->get_sql_layer()) { // The ugly one! case 'mysqli': @@ -251,8 +251,8 @@ class acp_reasons // Teh standard case 'postgres': case 'oracle': - case 'firebird': case 'sqlite': + case 'sqlite3': // Change the reports using this reason to 'other' $sql = 'UPDATE ' . REPORTS_TABLE . ' SET reason_id = ' . $other_reason_id . ", report_text = '" . $db->sql_escape($reason_row['reason_description']) . "\n\n' || report_text @@ -263,7 +263,7 @@ class acp_reasons $db->sql_query('DELETE FROM ' . REPORTS_REASONS_TABLE . ' WHERE reason_id = ' . $reason_id); - add_log('admin', 'LOG_REASON_REMOVED', $reason_row['reason_title']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_REASON_REMOVED', false, array($reason_row['reason_title'])); trigger_error($user->lang['REASON_REMOVED'] . adm_back_link($this->u_action)); } else diff --git a/phpBB/includes/acp/acp_search.php b/phpBB/includes/acp/acp_search.php index 11a2511aee..1f0e8ef539 100644 --- a/phpBB/includes/acp/acp_search.php +++ b/phpBB/includes/acp/acp_search.php @@ -1,9 +1,13 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -15,9 +19,6 @@ if (!defined('IN_PHPBB')) exit; } -/** -* @package acp -*/ class acp_search { var $u_action; @@ -49,8 +50,8 @@ class acp_search function settings($id, $mode) { - global $db, $user, $auth, $template, $cache; - global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + global $user, $template, $phpbb_log, $request; + global $config, $phpbb_admin_path, $phpEx; $submit = (isset($_POST['submit'])) ? true : false; @@ -79,7 +80,8 @@ class acp_search $name = $search->get_name(); $selected = ($config['search_type'] == $type) ? ' selected="selected"' : ''; - $search_options .= '<option value="' . $type . '"' . $selected . '>' . $name . '</option>'; + $identifier = substr($type, strrpos($type, '\\') + 1); + $search_options .= "<option value=\"$type\"$selected data-toggle-setting=\"#search_{$identifier}_settings\">$name</option>"; if (method_exists($search, 'acp')) { @@ -88,9 +90,10 @@ class acp_search if (!$submit) { $template->assign_block_vars('backend', array( - 'NAME' => $name, - 'SETTINGS' => $vars['tpl']) - ); + 'NAME' => $name, + 'SETTINGS' => $vars['tpl'], + 'IDENTIFIER' => $identifier, + )); } else if (is_array($vars['config'])) { @@ -101,8 +104,8 @@ class acp_search unset($search); unset($error); - $cfg_array = (isset($_REQUEST['config'])) ? request_var('config', array('' => ''), true) : array(); - $updated = request_var('updated', false); + $cfg_array = (isset($_REQUEST['config'])) ? $request->variable('config', array('' => ''), true) : array(); + $updated = $request->variable('updated', false); foreach ($settings as $config_name => $var_type) { @@ -130,7 +133,7 @@ class acp_search // only change config if anything was actually changed if ($submit && ($config[$config_name] != $config_value)) { - set_config($config_name, $config_value); + $config->set($config_name, $config_value); $updated = true; } } @@ -140,7 +143,7 @@ class acp_search $extra_message = ''; if ($updated) { - add_log('admin', 'LOG_CONFIG_SEARCH'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CONFIG_SEARCH'); } if (isset($cfg_array['search_type']) && in_array($cfg_array['search_type'], $search_types, true) && ($cfg_array['search_type'] != $config['search_type'])) @@ -154,11 +157,11 @@ class acp_search { if (!method_exists($search, 'init') || !($error = $search->init())) { - set_config('search_type', $cfg_array['search_type']); + $config->set('search_type', $cfg_array['search_type']); if (!$updated) { - add_log('admin', 'LOG_CONFIG_SEARCH'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CONFIG_SEARCH'); } $extra_message = '<br />' . $user->lang['SWITCHED_SEARCH_BACKEND'] . '<br /><a href="' . append_sid("{$phpbb_admin_path}index.$phpEx", 'i=search&mode=index') . '">» ' . $user->lang['GO_TO_SEARCH_INDEX'] . '</a>'; } @@ -229,10 +232,10 @@ class acp_search function index($id, $mode) { - global $db, $user, $auth, $template, $cache; - global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + global $db, $user, $template, $phpbb_log, $request; + global $config, $phpbb_admin_path, $phpEx; - $action = request_var('action', ''); + $action = $request->variable('action', ''); $this->state = explode(',', $config['search_indexing_state']); if (isset($_POST['cancel'])) @@ -247,7 +250,7 @@ class acp_search switch ($action) { case 'progress_bar': - $type = request_var('type', ''); + $type = $request->variable('type', ''); $this->display_progress_bar($type); break; @@ -266,7 +269,7 @@ class acp_search if (empty($this->state[0])) { - $this->state[0] = request_var('search_type', ''); + $this->state[0] = $request->variable('search_type', ''); } $this->search = null; @@ -300,8 +303,7 @@ class acp_search } else { - $starttime = explode(' ', microtime()); - $starttime = $starttime[1] + $starttime[0]; + $starttime = microtime(true); $row_count = 0; while (still_on_time() && $post_counter <= $this->max_post_id) { @@ -333,8 +335,7 @@ class acp_search if ($post_counter <= $this->max_post_id) { - $mtime = explode(' ', microtime()); - $totaltime = $mtime[0] + $mtime[1] - $starttime; + $totaltime = microtime(true) - $starttime; $rows_per_second = $row_count / $totaltime; meta_refresh(1, append_sid($this->u_action . '&action=delete&skip_rows=' . $post_counter)); trigger_error($user->lang('SEARCH_INDEX_DELETE_REDIRECT', (int) $row_count, $post_counter, $rows_per_second)); @@ -346,7 +347,7 @@ class acp_search $this->state = array(''); $this->save_state(); - add_log('admin', 'LOG_SEARCH_INDEX_REMOVED', $name); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_SEARCH_INDEX_REMOVED', false, array($name)); trigger_error($user->lang['SEARCH_INDEX_REMOVED'] . adm_back_link($this->u_action) . $this->close_popup_js()); break; @@ -373,8 +374,7 @@ class acp_search } $db->sql_freeresult($result); - $starttime = explode(' ', microtime()); - $starttime = $starttime[1] + $starttime[0]; + $starttime = microtime(true); $row_count = 0; while (still_on_time() && $post_counter <= $this->max_post_id) { @@ -423,8 +423,7 @@ class acp_search if ($post_counter <= $this->max_post_id) { - $mtime = explode(' ', microtime()); - $totaltime = $mtime[0] + $mtime[1] - $starttime; + $totaltime = microtime(true) - $starttime; $rows_per_second = $row_count / $totaltime; meta_refresh(1, append_sid($this->u_action . '&action=create&skip_rows=' . $post_counter)); trigger_error($user->lang('SEARCH_INDEX_CREATE_REDIRECT', (int) $row_count, $post_counter) . $user->lang('SEARCH_INDEX_CREATE_REDIRECT_RATE', $rows_per_second)); @@ -436,7 +435,7 @@ class acp_search $this->state = array(''); $this->save_state(); - add_log('admin', 'LOG_SEARCH_INDEX_CREATED', $name); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_SEARCH_INDEX_CREATED', false, array($name)); trigger_error($user->lang['SEARCH_INDEX_CREATED'] . adm_back_link($this->u_action) . $this->close_popup_js()); break; } @@ -446,7 +445,6 @@ class acp_search $search = null; $error = false; - $search_options = ''; foreach ($search_types as $type) { if ($this->init_search($type, $search, $error) || !method_exists($search, 'index_created')) @@ -553,7 +551,7 @@ class acp_search function get_search_types() { - global $phpbb_root_path, $phpEx, $phpbb_extension_manager; + global $phpbb_extension_manager; $finder = $phpbb_extension_manager->get_finder(); @@ -579,6 +577,8 @@ class acp_search function save_state($state = false) { + global $config; + if ($state) { $this->state = $state; @@ -586,7 +586,7 @@ class acp_search ksort($this->state); - set_config('search_indexing_state', implode(',', $this->state), true); + $config->set('search_indexing_state', implode(',', $this->state), true); } /** @@ -596,7 +596,7 @@ class acp_search */ function init_search($type, &$search, &$error) { - global $phpbb_root_path, $phpEx, $user, $auth, $config, $db; + global $phpbb_root_path, $phpEx, $user, $auth, $config, $db, $phpbb_dispatcher; if (!class_exists($type) || !method_exists($type, 'keyword_search')) { @@ -605,7 +605,7 @@ class acp_search } $error = false; - $search = new $type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user); + $search = new $type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher); return $error; } diff --git a/phpBB/includes/acp/acp_send_statistics.php b/phpBB/includes/acp/acp_send_statistics.php index 39140b8da4..74da5996f1 100644 --- a/phpBB/includes/acp/acp_send_statistics.php +++ b/phpBB/includes/acp/acp_send_statistics.php @@ -1,9 +1,13 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -15,9 +19,6 @@ if (!defined('IN_PHPBB')) exit; } -/** -* @package acp -*/ class acp_send_statistics { var $u_action; @@ -26,7 +27,10 @@ class acp_send_statistics { global $config, $template, $phpbb_admin_path, $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/questionnaire/questionnaire.' . $phpEx); + if (!class_exists('phpbb_questionnaire_data_collector')) + { + include($phpbb_root_path . 'includes/questionnaire/questionnaire.' . $phpEx); + } $collect_url = "https://www.phpbb.com/stats/receive_stats.php"; @@ -37,7 +41,7 @@ class acp_send_statistics if (!isset($config['questionnaire_unique_id'])) { $install_id = unique_id(); - set_config('questionnaire_unique_id', $install_id); + $config->set('questionnaire_unique_id', $install_id); } else { diff --git a/phpBB/includes/acp/acp_styles.php b/phpBB/includes/acp/acp_styles.php index d5492d85a3..7878cbc8e9 100644 --- a/phpBB/includes/acp/acp_styles.php +++ b/phpBB/includes/acp/acp_styles.php @@ -1,9 +1,13 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -15,9 +19,6 @@ if (!defined('IN_PHPBB')) exit; } -/** -* @package acp -*/ class acp_styles { public $u_action; @@ -28,19 +29,45 @@ class acp_styles protected $styles_path; protected $styles_path_absolute = 'styles'; protected $default_style = 0; + protected $styles_list_cols = 0; + protected $reserved_style_names = array('adm', 'admin', 'all'); + /** @var \phpbb\config\config */ + protected $config; + + /** @var \phpbb\db\driver\driver_interface */ protected $db; + + /** @var \phpbb\user */ protected $user; + + /** @var \phpbb\template\template */ protected $template; + + /** @var \phpbb\request\request_interface */ protected $request; + + /** @var \phpbb\cache\driver\driver_interface */ protected $cache; + + /** @var \phpbb\auth\auth */ protected $auth; + + /** @var \phpbb\textformatter\cache_interface */ + protected $text_formatter_cache; + + /** @var string */ protected $phpbb_root_path; + + /** @var string */ protected $php_ext; + /** @var \phpbb\event\dispatcher_interface */ + protected $dispatcher; + public function main($id, $mode) { - global $db, $user, $phpbb_admin_path, $phpbb_root_path, $phpEx, $template, $request, $cache, $auth, $config; + global $db, $user, $phpbb_admin_path, $phpbb_root_path, $phpEx, $template, $request, $cache, $auth, $config, $phpbb_dispatcher, $phpbb_container; $this->db = $db; $this->user = $user; @@ -48,9 +75,11 @@ class acp_styles $this->request = $request; $this->cache = $cache; $this->auth = $auth; + $this->text_formatter_cache = $phpbb_container->get('text_formatter.cache'); $this->config = $config; $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $phpEx; + $this->dispatcher = $phpbb_dispatcher; $this->default_style = $config['default_style']; $this->styles_path = $this->phpbb_root_path . $this->styles_path_absolute . '/'; @@ -69,11 +98,6 @@ class acp_styles $action = $this->request->variable('action', ''); $post_actions = array('install', 'activate', 'deactivate', 'uninstall'); - if ($action && in_array($action, $post_actions) && !check_link_hash($request->variable('hash', ''), $action)) - { - trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); - } - foreach ($post_actions as $key) { if ($this->request->is_set_post($key)) @@ -82,6 +106,18 @@ class acp_styles } } + // The uninstall action uses confirm_box() to verify the validity of the request, + // so there is no need to check for a valid token here. + if (in_array($action, $post_actions) && $action != 'uninstall') + { + $is_valid_request = check_link_hash($request->variable('hash', ''), $action) || check_form_key('styles_management'); + + if (!$is_valid_request) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + } + if ($action != '') { $this->s_hidden_fields['action'] = $action; @@ -93,6 +129,18 @@ class acp_styles ) ); + /** + * Run code before ACP styles action execution + * + * @event core.acp_styles_action_before + * @var int id Module ID + * @var string mode Active module + * @var string action Module that should be run + * @since 3.1.7-RC1 + */ + $vars = array('id', 'mode', 'action'); + extract($this->dispatcher->trigger_event('core.acp_styles_action_before', compact($vars))); + // Execute actions switch ($action) { @@ -121,6 +169,8 @@ class acp_styles */ protected function frontend() { + add_form_key('styles_management'); + // Check mode switch ($this->mode) { @@ -132,32 +182,11 @@ class acp_styles $this->welcome_message('INSTALL_STYLES', 'INSTALL_STYLES_EXPLAIN'); $this->show_available(); return; - case 'cache': - $this->action_cache(); - return; } trigger_error($this->user->lang['NO_MODE'] . adm_back_link($this->u_action), E_USER_WARNING); } /** - * Purge cache - */ - protected function action_cache() - { - global $db, $cache, $auth; - - $this->cache->purge(); - - // Clear permissions - $this->auth->acl_clear_prefetch(); - phpbb_cache_moderators($db, $cache, $auth); - - add_log('admin', 'LOG_PURGE_CACHE'); - - trigger_error($this->user->lang['PURGED_CACHE'] . adm_back_link($this->u_base_action), E_USER_NOTICE); - } - - /** * Install style(s) */ protected function action_install() @@ -172,9 +201,14 @@ class acp_styles $messages = array(); $installed_names = array(); $installed_dirs = array(); - $last_installed = false; foreach ($dirs as $dir) { + if (in_array($dir, $this->reserved_style_names)) + { + $messages[] = $this->user->lang('STYLE_NAME_RESERVED', htmlspecialchars($dir)); + continue; + } + $found = false; foreach ($styles as &$style) { @@ -189,7 +223,6 @@ class acp_styles $style['style_id'] = $this->install_style($style); $style['_installed'] = true; $found = true; - $last_installed = $style['style_id']; $installed_names[] = $style['style_name']; $installed_dirs[] = $style['style_path']; $messages[] = sprintf($this->user->lang['STYLE_INSTALLED'], htmlspecialchars($style['style_name'])); @@ -201,14 +234,20 @@ class acp_styles } } + // Invalidate the text formatter's cache for the new styles to take effect + if (!empty($installed_names)) + { + $this->text_formatter_cache->invalidate(); + } + // Show message if (!count($messages)) { trigger_error($this->user->lang['NO_MATCHING_STYLES_FOUND'] . adm_back_link($this->u_action), E_USER_WARNING); } $message = implode('<br />', $messages); - $message .= '<br /><br />' . sprintf($this->user->lang['STYLE_INSTALLED_RETURN_STYLES'], $this->u_base_action . '&mode=style'); - $message .= '<br /><br />' . sprintf($this->user->lang['STYLE_INSTALLED_RETURN_UNINSTALLED'], $this->u_base_action . '&mode=install'); + $message .= '<br /><br /><a href="' . $this->u_base_action . '&mode=style' . '">« ' . $this->user->lang('STYLE_INSTALLED_RETURN_INSTALLED_STYLES') . '</a>'; + $message .= '<br /><br /><a href="' . $this->u_base_action . '&mode=install' . '">» ' . $this->user->lang('STYLE_INSTALLED_RETURN_UNINSTALLED_STYLES') . '</a>'; trigger_error($message, E_USER_NOTICE); } @@ -248,6 +287,8 @@ class acp_styles */ protected function action_uninstall_confirmed($ids, $delete_files) { + global $user, $phpbb_log; + $default = $this->default_style; $uninstalled = array(); $messages = array(); @@ -307,7 +348,7 @@ class acp_styles // Log action if (count($uninstalled)) { - add_log('admin', 'LOG_STYLE_DELETE', implode(', ', $uninstalled)); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_STYLE_DELETE', false, array(implode(', ', $uninstalled))); } // Clear cache @@ -379,6 +420,8 @@ class acp_styles */ protected function action_details() { + global $user, $phpbb_log; + $id = $this->request->variable('id', 0); if (!$id) { @@ -510,7 +553,8 @@ class acp_styles $this->cache->purge(); } } - add_log('admin', 'LOG_STYLE_EDIT_DETAILS', $style['style_name']); + + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_STYLE_EDIT_DETAILS', false, array($style['style_name'])); } // Update default style @@ -521,7 +565,7 @@ class acp_styles { trigger_error($this->user->lang['STYLE_DEFAULT_CHANGE_INACTIVE'] . adm_back_link($update_action), E_USER_WARNING); } - set_config('default_style', $id); + $this->config->set('default_style', $id); $this->cache->purge(); } @@ -530,6 +574,9 @@ class acp_styles return; } + // Show page title + $this->welcome_message('ACP_STYLES', null); + // Show parent styles foreach ($list as $row) { @@ -799,7 +846,7 @@ class acp_styles * * @param array $styles Styles list, passed as reference * @param string $name Name of parent style - * @param string $level Styles tree level + * @param int $level Styles tree level */ protected function show_available_child_styles(&$styles, $name, $level) { @@ -817,7 +864,7 @@ class acp_styles * Update styles tree * * @param array $styles Styles list, passed as reference - * @param array $style Current style, false if root + * @param array|false $style Current style, false if root * @return bool True if something was updated, false if not */ protected function update_styles_tree(&$styles, $style = false) @@ -883,7 +930,7 @@ class acp_styles * Show item in styles list * * @param array $style style row - * @param array $level style inheritance level + * @param int $level style inheritance level */ protected function list_style(&$style, $level) { @@ -980,7 +1027,7 @@ class acp_styles // Assign template variables $this->template->assign_block_vars('styles_list', $row); - foreach($actions as $action) + foreach ($actions as $action) { $this->template->assign_block_vars('styles_list.actions', $action); } @@ -1099,11 +1146,13 @@ class acp_styles /** * Install style * - * @param $style style data + * @param array $style style data * @return int Style id */ protected function install_style($style) { + global $user, $phpbb_log; + // Generate row $sql_ary = array(); foreach ($style as $key => $value) @@ -1125,7 +1174,7 @@ class acp_styles $this->db->sql_transaction('commit'); - add_log('admin', 'LOG_STYLE_ADD', $sql_ary['style_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_STYLE_ADD', false, array($sql_ary['style_name'])); return $id; } diff --git a/phpBB/includes/acp/acp_update.php b/phpBB/includes/acp/acp_update.php index 6b5407067d..52897e1043 100644 --- a/phpBB/includes/acp/acp_update.php +++ b/phpBB/includes/acp/acp_update.php @@ -1,9 +1,13 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -15,73 +19,49 @@ if (!defined('IN_PHPBB')) exit; } -/** -* @package acp -*/ class acp_update { var $u_action; function main($id, $mode) { - global $config, $db, $user, $auth, $template, $cache; - global $phpbb_root_path, $phpbb_admin_path, $phpEx; + global $config, $user, $template, $request; + global $phpbb_root_path, $phpEx, $phpbb_container; $user->add_lang('install'); $this->tpl_name = 'acp_update'; $this->page_title = 'ACP_VERSION_CHECK'; - // Get current and latest version - $errstr = ''; - $errno = 0; - - $info = obtain_latest_version_info(request_var('versioncheck_force', false)); - - if (empty($info)) + /* @var $version_helper \phpbb\version_helper */ + $version_helper = $phpbb_container->get('version_helper'); + try { - trigger_error('VERSIONCHECK_FAIL', E_USER_WARNING); + $recheck = $request->variable('versioncheck_force', false); + $updates_available = $version_helper->get_suggested_updates($recheck); } + catch (\RuntimeException $e) + { + $template->assign_var('S_VERSIONCHECK_FAIL', true); - $info = explode("\n", $info); - $latest_version = trim($info[0]); - - $announcement_url = trim($info[1]); - $announcement_url = (strpos($announcement_url, '&') === false) ? str_replace('&', '&', $announcement_url) : $announcement_url; - $update_link = append_sid($phpbb_root_path . 'install/index.' . $phpEx, 'mode=update'); + $updates_available = array(); + } - // next feature release - $next_feature_version = $next_feature_announcement_url = false; - if (isset($info[2]) && trim($info[2]) !== '') + foreach ($updates_available as $branch => $version_data) { - $next_feature_version = trim($info[2]); - $next_feature_announcement_url = trim($info[3]); + $template->assign_block_vars('updates_available', $version_data); } - // Determine automatic update... - $sql = 'SELECT config_value - FROM ' . CONFIG_TABLE . " - WHERE config_name = 'version_update_from'"; - $result = $db->sql_query($sql); - $version_update_from = (string) $db->sql_fetchfield('config_value'); - $db->sql_freeresult($result); - - $current_version = (!empty($version_update_from)) ? $version_update_from : $config['version']; + $update_link = $phpbb_root_path . 'install/app.' . $phpEx; $template->assign_vars(array( - 'S_UP_TO_DATE' => phpbb_version_compare($latest_version, $config['version'], '<='), - 'S_UP_TO_DATE_AUTO' => phpbb_version_compare($latest_version, $current_version, '<='), - 'S_VERSION_CHECK' => true, - 'U_ACTION' => $this->u_action, - 'U_VERSIONCHECK_FORCE' => append_sid($this->u_action . '&versioncheck_force=1'), + 'S_UP_TO_DATE' => empty($updates_available), + 'U_ACTION' => $this->u_action, + 'U_VERSIONCHECK_FORCE' => append_sid($this->u_action . '&versioncheck_force=1'), - 'LATEST_VERSION' => $latest_version, - 'CURRENT_VERSION' => $config['version'], - 'AUTO_VERSION' => $version_update_from, - 'NEXT_FEATURE_VERSION' => $next_feature_version, + 'CURRENT_VERSION' => $config['version'], - 'UPDATE_INSTRUCTIONS' => sprintf($user->lang['UPDATE_INSTRUCTIONS'], $announcement_url, $update_link), - 'UPGRADE_INSTRUCTIONS' => $next_feature_version ? $user->lang('UPGRADE_INSTRUCTIONS', $next_feature_version, $next_feature_announcement_url) : false, + 'UPDATE_INSTRUCTIONS' => sprintf($user->lang['UPDATE_INSTRUCTIONS'], $update_link), )); } } diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php index 87582dcedb..2bec4385c3 100644 --- a/phpBB/includes/acp/acp_users.php +++ b/phpBB/includes/acp/acp_users.php @@ -1,9 +1,13 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -15,9 +19,6 @@ if (!defined('IN_PHPBB')) exit; } -/** -* @package acp -*/ class acp_users { var $u_action; @@ -30,19 +31,23 @@ class acp_users function main($id, $mode) { - global $config, $db, $user, $auth, $template, $cache; - global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix, $file_uploads; + global $config, $db, $user, $auth, $template; + global $phpbb_root_path, $phpbb_admin_path, $phpEx; global $phpbb_dispatcher, $request; - global $phpbb_container; + global $phpbb_container, $phpbb_log; $user->add_lang(array('posting', 'ucp', 'acp/users')); $this->tpl_name = 'acp_users'; - $this->page_title = 'ACP_USER_' . strtoupper($mode); $error = array(); - $username = utf8_normalize_nfc(request_var('username', '', true)); - $user_id = request_var('u', 0); - $action = request_var('action', ''); + $username = $request->variable('username', '', true); + $user_id = $request->variable('u', 0); + $action = $request->variable('action', ''); + + // Get referer to redirect user to the appropriate page after delete action + $redirect = $request->variable('redirect', ''); + $redirect_tag = "redirect=$redirect"; + $redirect_url = append_sid("{$phpbb_admin_path}index.$phpEx", "i=$redirect"); $submit = (isset($_POST['update']) && !isset($_POST['cancel'])) ? true : false; @@ -52,12 +57,15 @@ class acp_users // Whois (special case) if ($action == 'whois') { - include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + if (!function_exists('user_get_id_name')) + { + include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + } $this->page_title = 'WHOIS'; $this->tpl_name = 'simple_body'; - $user_ip = phpbb_ip_normalise(request_var('user_ip', '')); + $user_ip = phpbb_ip_normalise($request->variable('user_ip', '')); $domain = gethostbyaddr($user_ip); $ipwhois = user_ipwhois($user_ip); @@ -146,9 +154,9 @@ class acp_users } $template->assign_vars(array( - 'U_BACK' => $this->u_action, + 'U_BACK' => (empty($redirect)) ? $this->u_action : $redirect_url, 'U_MODE_SELECT' => append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&u=$user_id"), - 'U_ACTION' => $this->u_action . '&u=' . $user_id, + 'U_ACTION' => $this->u_action . '&u=' . $user_id . ((empty($redirect)) ? '' : '&' . $redirect_tag), 'S_FORM_OPTIONS' => $s_form_options, 'MANAGED_USERNAME' => $user_row['username']) ); @@ -159,22 +167,41 @@ class acp_users trigger_error($user->lang['NOT_MANAGE_FOUNDER'] . adm_back_link($this->u_action), E_USER_WARNING); } + $this->page_title = $user_row['username'] . ' :: ' . $user->lang('ACP_USER_' . strtoupper($mode)); + switch ($mode) { case 'overview': - include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + if (!function_exists('user_get_id_name')) + { + include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + } $user->add_lang('acp/ban'); - $delete = request_var('delete', 0); - $delete_type = request_var('delete_type', ''); - $ip = request_var('ip', 'ip'); + $delete = $request->variable('delete', 0); + $delete_type = $request->variable('delete_type', ''); + $ip = $request->variable('ip', 'ip'); + + /** + * Run code at beginning of ACP users overview + * + * @event core.acp_users_overview_before + * @var array user_row Current user data + * @var string mode Active module + * @var string action Module that should be run + * @var bool submit Do we display the form only + * or did the user press submit + * @var array error Array holding error messages + * @since 3.1.3-RC1 + */ + $vars = array('user_row', 'mode', 'action', 'submit', 'error'); + extract($phpbb_dispatcher->trigger_event('core.acp_users_overview_before', compact($vars))); if ($submit) { - // You can't delete the founder - if ($delete && $user_row['user_type'] != USER_FOUNDER) + if ($delete) { if (!$auth->acl_get('a_userdel')) { @@ -187,6 +214,12 @@ class acp_users trigger_error($user->lang['CANNOT_REMOVE_ANONYMOUS'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); } + // Founders can not be deleted. + if ($user_row['user_type'] == USER_FOUNDER) + { + trigger_error($user->lang['CANNOT_REMOVE_FOUNDER'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + if ($user_id == $user->data['user_id']) { trigger_error($user->lang['CANNOT_REMOVE_YOURSELF'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); @@ -198,20 +231,31 @@ class acp_users { user_delete($delete_type, $user_id, $user_row['username']); - add_log('admin', 'LOG_USER_DELETED', $user_row['username']); - trigger_error($user->lang['USER_DELETED'] . adm_back_link($this->u_action)); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_DELETED', false, array($user_row['username'])); + trigger_error($user->lang['USER_DELETED'] . adm_back_link( + (empty($redirect)) ? $this->u_action : $redirect_url + ) + ); } else { - confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + $delete_confirm_hidden_fields = array( 'u' => $user_id, 'i' => $id, 'mode' => $mode, 'action' => $action, 'update' => true, 'delete' => 1, - 'delete_type' => $delete_type)) + 'delete_type' => $delete_type, ); + + // Checks if the redirection page is specified + if (!empty($redirect)) + { + $delete_confirm_hidden_fields['redirect'] = $redirect; + } + + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields($delete_confirm_hidden_fields)); } } else @@ -254,13 +298,11 @@ class acp_users case 'banuser': $ban[] = $user_row['username']; $reason = 'USER_ADMIN_BAN_NAME_REASON'; - $log = 'LOG_USER_BAN_USER'; break; case 'banemail': $ban[] = $user_row['user_email']; $reason = 'USER_ADMIN_BAN_EMAIL_REASON'; - $log = 'LOG_USER_BAN_EMAIL'; break; case 'banip': @@ -278,12 +320,11 @@ class acp_users $db->sql_freeresult($result); $reason = 'USER_ADMIN_BAN_IP_REASON'; - $log = 'LOG_USER_BAN_IP'; break; } - $ban_reason = utf8_normalize_nfc(request_var('ban_reason', $user->lang[$reason], true)); - $ban_give_reason = utf8_normalize_nfc(request_var('ban_give_reason', '', true)); + $ban_reason = $request->variable('ban_reason', $user->lang[$reason], true); + $ban_give_reason = $request->variable('ban_give_reason', '', true); // Log not used at the moment, we simply utilize the ban function. $result = user_ban(substr($action, 3), $ban, 0, 0, 0, $ban_reason, $ban_give_reason); @@ -316,7 +357,10 @@ class acp_users if ($config['email_enable']) { - include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); + if (!class_exists('messenger')) + { + include($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); + } $server_url = generate_board_url(); @@ -359,8 +403,10 @@ class acp_users $messenger->send(NOTIFY_EMAIL); - add_log('admin', 'LOG_USER_REACTIVATE', $user_row['username']); - add_log('user', $user_id, 'LOG_USER_REACTIVATE_USER'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_REACTIVATE', false, array($user_row['username'])); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_REACTIVATE_USER', false, array( + 'reportee_id' => $user_id + )); trigger_error($user->lang['FORCE_REACTIVATION_SUCCESS'] . adm_back_link($this->u_action . '&u=' . $user_id)); } @@ -396,10 +442,14 @@ class acp_users { if ($config['require_activation'] == USER_ACTIVATION_ADMIN) { + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); - $phpbb_notifications->delete_notifications('admin_activate_user', $user_row['user_id']); + $phpbb_notifications->delete_notifications('notification.type.admin_activate_user', $user_row['user_id']); - include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); + if (!class_exists('messenger')) + { + include($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); + } $messenger = new messenger(false); @@ -420,8 +470,10 @@ class acp_users $message = ($user_row['user_type'] == USER_INACTIVE) ? 'USER_ADMIN_ACTIVATED' : 'USER_ADMIN_DEACTIVED'; $log = ($user_row['user_type'] == USER_INACTIVE) ? 'LOG_USER_ACTIVE' : 'LOG_USER_INACTIVE'; - add_log('admin', $log, $user_row['username']); - add_log('user', $user_id, $log . '_USER'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, $log, false, array($user_row['username'])); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, $log . '_USER', false, array( + 'reportee_id' => $user_id + )); trigger_error($user->lang[$message] . adm_back_link($this->u_action . '&u=' . $user_id)); @@ -444,8 +496,10 @@ class acp_users WHERE user_id = $user_id"; $db->sql_query($sql); - add_log('admin', 'LOG_USER_DEL_SIG', $user_row['username']); - add_log('user', $user_id, 'LOG_USER_DEL_SIG_USER'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_DEL_SIG', false, array($user_row['username'])); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_DEL_SIG_USER', false, array( + 'reportee_id' => $user_id + )); trigger_error($user->lang['USER_ADMIN_SIG_REMOVED'] . adm_back_link($this->u_action . '&u=' . $user_id)); @@ -458,28 +512,15 @@ class acp_users trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); } - $sql_ary = array( - 'user_avatar' => '', - 'user_avatar_type' => '', - 'user_avatar_width' => 0, - 'user_avatar_height' => 0, - ); - - $sql = 'UPDATE ' . USERS_TABLE . ' - SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " - WHERE user_id = $user_id"; - $db->sql_query($sql); - // Delete old avatar if present + /* @var $phpbb_avatar_manager \phpbb\avatar\manager */ $phpbb_avatar_manager = $phpbb_container->get('avatar.manager'); - $driver = $phpbb_avatar_manager->get_driver($user_row['user_avatar_type']); - if ($driver) - { - $driver->delete($user_row); - } + $phpbb_avatar_manager->handle_avatar_delete($db, $user, $phpbb_avatar_manager->clean_row($user_row, 'user'), USERS_TABLE, 'user_'); - add_log('admin', 'LOG_USER_DEL_AVATAR', $user_row['username']); - add_log('user', $user_id, 'LOG_USER_DEL_AVATAR_USER'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_DEL_AVATAR', false, array($user_row['username'])); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_DEL_AVATAR_USER', false, array( + 'reportee_id' => $user_id + )); trigger_error($user->lang['USER_ADMIN_AVATAR_REMOVED'] . adm_back_link($this->u_action . '&u=' . $user_id)); break; @@ -491,7 +532,7 @@ class acp_users // Delete posts, attachments, etc. delete_posts('poster_id', $user_id); - add_log('admin', 'LOG_USER_DEL_POSTS', $user_row['username']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_DEL_POSTS', false, array($user_row['username'])); trigger_error($user->lang['USER_POSTS_DELETED'] . adm_back_link($this->u_action . '&u=' . $user_id)); } else @@ -511,9 +552,12 @@ class acp_users if (confirm_box(true)) { - delete_attachments('user', $user_id); + /** @var \phpbb\attachment\manager $attachment_manager */ + $attachment_manager = $phpbb_container->get('attachment.manager'); + $attachment_manager->delete('user', $user_id); + unset($attachment_manager); - add_log('admin', 'LOG_USER_DEL_ATTACH', $user_row['username']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_DEL_ATTACH', false, array($user_row['username'])); trigger_error($user->lang['USER_ATTACHMENTS_REMOVED'] . adm_back_link($this->u_action . '&u=' . $user_id)); } else @@ -559,7 +603,7 @@ class acp_users delete_pm($user_id, $msg_ids, PRIVMSGS_OUTBOX); - add_log('admin', 'LOG_USER_DEL_OUTBOX', $user_row['username']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_DEL_OUTBOX', false, array($user_row['username'])); $lang = 'EMPTIED'; } @@ -588,7 +632,7 @@ class acp_users $user->add_lang('acp/forums'); - $new_forum_id = request_var('new_f', 0); + $new_forum_id = $request->variable('new_f', 0); if (!$new_forum_id) { @@ -651,6 +695,7 @@ class acp_users { if ($topic_id_ary[$row['topic_id']][ITEM_APPROVED] == $row['topic_posts_approved'] && $topic_id_ary[$row['topic_id']][ITEM_UNAPPROVED] == $row['topic_posts_unapproved'] + && $topic_id_ary[$row['topic_id']][ITEM_REAPPROVE] == $row['topic_posts_unapproved'] && $topic_id_ary[$row['topic_id']][ITEM_DELETED] == $row['topic_posts_softdeleted']) { $move_topic_ary[] = $row['topic_id']; @@ -729,9 +774,11 @@ class acp_users sync('forum', 'forum_id', $forum_id_ary, false, true); } - - add_log('admin', 'LOG_USER_MOVE_POSTS', $user_row['username'], $forum_info['forum_name']); - add_log('user', $user_id, 'LOG_USER_MOVE_POSTS_USER', $forum_info['forum_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_MOVE_POSTS', false, array($user_row['username'], $forum_info['forum_name'])); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_MOVE_POSTS_USER', false, array( + 'reportee_id' => $user_id, + $forum_info['forum_name'] + )); trigger_error($user->lang['USER_POSTS_MOVED'] . adm_back_link($this->u_action . '&u=' . $user_id)); @@ -743,7 +790,7 @@ class acp_users { remove_newly_registered($user_id, $user_row); - add_log('admin', 'LOG_USER_REMOVED_NR', $user_row['username']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_REMOVED_NR', false, array($user_row['username'])); trigger_error($user->lang['USER_LIFTED_NR'] . adm_back_link($this->u_action . '&u=' . $user_id)); } else @@ -766,7 +813,7 @@ class acp_users * @event core.acp_users_overview_run_quicktool * @var array user_row Current user data * @var string action Quick tool that should be run - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('action', 'user_row'); extract($phpbb_dispatcher->trigger_event('core.acp_users_overview_run_quicktool', compact($vars))); @@ -775,9 +822,9 @@ class acp_users // Handle registration info updates $data = array( - 'username' => utf8_normalize_nfc(request_var('user', $user_row['username'], true)), - 'user_founder' => request_var('user_founder', ($user_row['user_type'] == USER_FOUNDER) ? 1 : 0), - 'email' => strtolower(request_var('user_email', $user_row['user_email'])), + 'username' => $request->variable('user', $user_row['username'], true), + 'user_founder' => $request->variable('user_founder', ($user_row['user_type'] == USER_FOUNDER) ? 1 : 0), + 'email' => strtolower($request->variable('user_email', $user_row['user_email'])), 'new_password' => $request->variable('new_password', '', true), 'password_confirm' => $request->variable('password_confirm', '', true), ); @@ -807,7 +854,7 @@ class acp_users $check_ary += array( 'email' => array( array('string', false, 6, 60), - array('email', $user_row['user_email']) + array('user_email', $user_row['user_email']), ), ); } @@ -825,6 +872,7 @@ class acp_users } // Instantiate passwords manager + /* @var $passwords_manager \phpbb\passwords\manager */ $passwords_manager = $phpbb_container->get('passwords.manager'); // Which updates do we need to do? @@ -887,7 +935,7 @@ class acp_users * @var array user_row Current user data * @var array data Submitted user data * @var array sql_ary User data we udpate - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('user_row', 'data', 'sql_ary'); extract($phpbb_dispatcher->trigger_event('core.acp_users_overview_modify_data', compact($vars))); @@ -897,7 +945,11 @@ class acp_users $sql_ary['username'] = $update_username; $sql_ary['username_clean'] = utf8_clean_string($update_username); - add_log('user', $user_id, 'LOG_USER_UPDATE_NAME', $user_row['username'], $update_username); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_UPDATE_NAME', false, array( + 'reportee_id' => $user_id, + $user_row['username'], + $update_username + )); } if ($update_email !== false) @@ -907,7 +959,12 @@ class acp_users 'user_email_hash' => phpbb_email_hash($update_email), ); - add_log('user', $user_id, 'LOG_USER_UPDATE_EMAIL', $user_row['username'], $user_row['user_email'], $update_email); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_UPDATE_EMAIL', false, array( + 'reportee_id' => $user_id, + $user_row['username'], + $user_row['user_email'], + $update_email + )); } if ($update_password) @@ -915,11 +972,14 @@ class acp_users $sql_ary += array( 'user_password' => $passwords_manager->hash($data['new_password']), 'user_passchg' => time(), - 'user_pass_convert' => 0, ); $user->reset_login_keys($user_id); - add_log('user', $user_id, 'LOG_USER_NEW_PASSWORD', $user_row['username']); + + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_NEW_PASSWORD', false, array( + 'reportee_id' => $user_id, + $user_row['username'] + )); } if (sizeof($sql_ary)) @@ -938,7 +998,7 @@ class acp_users // Let the users permissions being updated $auth->acl_clear_prefetch($user_id); - add_log('admin', 'LOG_USER_USER_UPDATE', $data['username']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_USER_UPDATE', false, array($data['username'])); trigger_error($user->lang['USER_OVERVIEW_UPDATED'] . adm_back_link($this->u_action . '&u=' . $user_id)); } @@ -1002,7 +1062,7 @@ class acp_users * @event core.acp_users_display_overview * @var array user_row Array with user data * @var array quick_tool_ary Ouick tool options - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('user_row', 'quick_tool_ary'); extract($phpbb_dispatcher->trigger_event('core.acp_users_display_overview', compact($vars))); @@ -1013,7 +1073,7 @@ class acp_users $s_action_options .= '<option value="' . $value . '">' . $user->lang['USER_ADMIN_' . $lang] . '</option>'; } - $last_visit = (!empty($user_row['session_time'])) ? $user_row['session_time'] : $user_row['user_lastvisit']; + $last_active = (!empty($user_row['session_time'])) ? $user_row['session_time'] : $user_row['user_lastvisit']; $inactive_reason = ''; if ($user_row['user_type'] == USER_INACTIVE) @@ -1044,7 +1104,7 @@ class acp_users $sql = 'SELECT COUNT(post_id) as posts_in_queue FROM ' . POSTS_TABLE . ' WHERE poster_id = ' . $user_id . ' - AND post_visibility = ' . ITEM_UNAPPROVED; + AND ' . $db->sql_in_set('post_visibility', array(ITEM_UNAPPROVED, ITEM_REAPPROVE)); $result = $db->sql_query($sql); $user_row['posts_in_queue'] = (int) $db->sql_fetchfield('posts_in_queue'); $db->sql_freeresult($result); @@ -1072,6 +1132,7 @@ class acp_users 'U_SHOW_IP' => $this->u_action . "&u=$user_id&ip=" . (($ip == 'ip') ? 'hostname' : 'ip'), 'U_WHOIS' => $this->u_action . "&action=whois&user_ip={$user_row['user_ip']}", 'U_MCP_QUEUE' => ($auth->acl_getf_global('m_approve')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue', true, $user->session_id) : '', + 'U_SEARCH_USER' => ($config['load_search'] && $auth->acl_get('u_search')) ? append_sid("{$phpbb_root_path}search.$phpEx", "author_id={$user_row['user_id']}&sr=posts") : '', 'U_SWITCH_PERMISSIONS' => ($auth->acl_get('a_switchperm') && $user->data['user_id'] != $user_row['user_id']) ? append_sid("{$phpbb_root_path}ucp.$phpEx", "mode=switch_perm&u={$user_row['user_id']}&hash=" . generate_link_hash('switchperm')) : '', @@ -1079,7 +1140,7 @@ class acp_users 'USER' => $user_row['username'], 'USER_REGISTERED' => $user->format_date($user_row['user_regdate']), 'REGISTERED_IP' => ($ip == 'hostname') ? gethostbyaddr($user_row['user_ip']) : $user_row['user_ip'], - 'USER_LASTACTIVE' => ($last_visit) ? $user->format_date($last_visit) : ' - ', + 'USER_LASTACTIVE' => ($last_active) ? $user->format_date($last_active) : ' - ', 'USER_EMAIL' => $user_row['user_email'], 'USER_WARNINGS' => $user_row['user_warnings'], 'USER_POSTS' => $user_row['user_posts'], @@ -1094,17 +1155,19 @@ class acp_users $user->add_lang('mcp'); // Set up general vars - $start = request_var('start', 0); + $start = $request->variable('start', 0); $deletemark = (isset($_POST['delmarked'])) ? true : false; $deleteall = (isset($_POST['delall'])) ? true : false; - $marked = request_var('mark', array(0)); - $message = utf8_normalize_nfc(request_var('message', '', true)); + $marked = $request->variable('mark', array(0)); + $message = $request->variable('message', '', true); + + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); // Sort keys - $sort_days = request_var('st', 0); - $sort_key = request_var('sk', 't'); - $sort_dir = request_var('sd', 'd'); + $sort_days = $request->variable('st', 0); + $sort_key = $request->variable('sk', 't'); + $sort_dir = $request->variable('sd', 'd'); // Delete entries if requested and able if (($deletemark || $deleteall) && $auth->acl_get('a_clearlogs')) @@ -1134,7 +1197,7 @@ class acp_users $where_sql"; $db->sql_query($sql); - add_log('admin', 'LOG_CLEAR_USER', $user_row['username']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CLEAR_USER', false, array($user_row['username'])); } } @@ -1145,9 +1208,16 @@ class acp_users trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); } - add_log('admin', 'LOG_USER_FEEDBACK', $user_row['username']); - add_log('mod', 0, 0, 'LOG_USER_FEEDBACK', $user_row['username']); - add_log('user', $user_id, 'LOG_USER_GENERAL', $message); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_FEEDBACK', false, array($user_row['username'])); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_USER_FEEDBACK', false, array( + 'forum_id' => 0, + 'topic_id' => 0, + $user_row['username'] + )); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_GENERAL', false, array( + 'reportee_id' => $user_id, + $message + )); trigger_error($user->lang['USER_FEEDBACK_ADDED'] . adm_back_link($this->u_action . '&u=' . $user_id)); } @@ -1198,17 +1268,10 @@ class acp_users $user->add_lang('mcp'); // Set up general vars - $start = request_var('start', 0); $deletemark = (isset($_POST['delmarked'])) ? true : false; $deleteall = (isset($_POST['delall'])) ? true : false; $confirm = (isset($_POST['confirm'])) ? true : false; - $marked = request_var('mark', array(0)); - $message = utf8_normalize_nfc(request_var('message', '', true)); - - // Sort keys - $sort_days = request_var('st', 0); - $sort_key = request_var('sk', 't'); - $sort_dir = request_var('sd', 'd'); + $marked = $request->variable('mark', array(0)); // Delete entries if requested and able if ($deletemark || $deleteall || $confirm) @@ -1216,8 +1279,8 @@ class acp_users if (confirm_box(true)) { $where_sql = ''; - $deletemark = request_var('delmarked', 0); - $deleteall = request_var('delall', 0); + $deletemark = $request->variable('delmarked', 0); + $deleteall = $request->variable('delall', 0); if ($deletemark && $marked) { $where_sql = ' AND ' . $db->sql_in_set('warning_id', array_values($marked)); @@ -1246,17 +1309,13 @@ class acp_users WHERE user_id = $user_id"; $db->sql_query($sql); - switch ($log_warnings) + if ($log_warnings) { - case 2: - add_log('admin', 'LOG_WARNINGS_DELETED', $user_row['username'], $num_warnings); - break; - case 1: - add_log('admin', 'LOG_WARNING_DELETED', $user_row['username']); - break; - default: - add_log('admin', 'LOG_WARNINGS_DELETED_ALL', $user_row['username']); - break; + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_WARNINGS_DELETED', false, array($user_row['username'], $num_warnings)); + } + else + { + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_WARNINGS_DELETED_ALL', false, array($user_row['username'])); } } } @@ -1326,7 +1385,6 @@ class acp_users } } - $template->assign_block_vars('warn', array( 'ID' => $row['warning_id'], 'USERNAME' => ($row['log_operation']) ? get_username_string('full', $row['mod_user_id'], $row['mod_username'], $row['mod_user_colour']) : '-', @@ -1344,8 +1402,12 @@ class acp_users case 'profile': - include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + if (!function_exists('user_get_id_name')) + { + include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + } + /* @var $cp \phpbb\profilefields\manager */ $cp = $phpbb_container->get('profilefields.manager'); $cp_data = $cp_error = array(); @@ -1360,12 +1422,7 @@ class acp_users $user_row['iso_lang_id'] = $row['lang_id']; $data = array( - 'icq' => request_var('icq', $user_row['user_icq']), - 'aim' => request_var('aim', $user_row['user_aim']), - 'msn' => request_var('msn', $user_row['user_msnm']), - 'yim' => request_var('yim', $user_row['user_yim']), - 'jabber' => utf8_normalize_nfc(request_var('jabber', $user_row['user_jabber'], true)), - 'website' => request_var('website', $user_row['user_website']), + 'jabber' => $request->variable('jabber', $user_row['user_jabber'], true), 'bday_day' => 0, 'bday_month' => 0, 'bday_year' => 0, @@ -1376,27 +1433,30 @@ class acp_users list($data['bday_day'], $data['bday_month'], $data['bday_year']) = explode('-', $user_row['user_birthday']); } - $data['bday_day'] = request_var('bday_day', $data['bday_day']); - $data['bday_month'] = request_var('bday_month', $data['bday_month']); - $data['bday_year'] = request_var('bday_year', $data['bday_year']); + $data['bday_day'] = $request->variable('bday_day', $data['bday_day']); + $data['bday_month'] = $request->variable('bday_month', $data['bday_month']); + $data['bday_year'] = $request->variable('bday_year', $data['bday_year']); $data['user_birthday'] = sprintf('%2d-%2d-%4d', $data['bday_day'], $data['bday_month'], $data['bday_year']); + /** + * Modify user data on editing profile in ACP + * + * @event core.acp_users_modify_profile + * @var array data Array with user profile data + * @var bool submit Flag indicating if submit button has been pressed + * @var int user_id The user id + * @var array user_row Array with the full user data + * @since 3.1.4-RC1 + */ + $vars = array('data', 'submit', 'user_id', 'user_row'); + extract($phpbb_dispatcher->trigger_event('core.acp_users_modify_profile', compact($vars))); if ($submit) { $error = validate_data($data, array( - 'icq' => array( - array('string', true, 3, 15), - array('match', true, '#^[0-9]+$#i')), - 'aim' => array('string', true, 3, 255), - 'msn' => array('string', true, 5, 255), 'jabber' => array( array('string', true, 5, 255), array('jabber')), - 'yim' => array('string', true, 5, 255), - 'website' => array( - array('string', true, 12, 255), - array('match', true, '#^http[s]?://(.*?\.)*?[a-z0-9\-]+\.[a-z]{2,4}#i')), 'bday_day' => array('num', true, 1, 31), 'bday_month' => array('num', true, 1, 12), 'bday_year' => array('num', true, 1901, gmdate('Y', time())), @@ -1415,18 +1475,39 @@ class acp_users $error[] = 'FORM_INVALID'; } + /** + * Validate profile data in ACP before submitting to the database + * + * @event core.acp_users_profile_validate + * @var bool submit Flag indicating if submit button has been pressed + * @var array data Array with user profile data + * @var array error Array with the form errors + * @since 3.1.4-RC1 + */ + $vars = array('submit', 'data', 'error'); + extract($phpbb_dispatcher->trigger_event('core.acp_users_profile_validate', compact($vars))); + if (!sizeof($error)) { $sql_ary = array( - 'user_icq' => $data['icq'], - 'user_aim' => $data['aim'], - 'user_msnm' => $data['msn'], - 'user_yim' => $data['yim'], 'user_jabber' => $data['jabber'], - 'user_website' => $data['website'], 'user_birthday' => $data['user_birthday'], ); + /** + * Modify profile data in ACP before submitting to the database + * + * @event core.acp_users_profile_modify_sql_ary + * @var array cp_data Array with the user custom profile fields data + * @var array data Array with user profile data + * @var int user_id The user id + * @var array user_row Array with the full user data + * @var array sql_ary Array with sql data + * @since 3.1.4-RC1 + */ + $vars = array('cp_data', 'data', 'user_id', 'user_row', 'sql_ary'); + extract($phpbb_dispatcher->trigger_event('core.acp_users_profile_modify_sql_ary', compact($vars))); + $sql = 'UPDATE ' . USERS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " WHERE user_id = $user_id"; @@ -1455,7 +1536,6 @@ class acp_users $selected = ($i == $data['bday_month']) ? ' selected="selected"' : ''; $s_birthday_month_options .= "<option value=\"$i\"$selected>$i</option>"; } - $s_birthday_year_options = ''; $now = getdate(); $s_birthday_year_options = '<option value="0"' . ((!$data['bday_year']) ? ' selected="selected"' : '') . '>--</option>'; @@ -1467,13 +1547,7 @@ class acp_users unset($now); $template->assign_vars(array( - 'ICQ' => $data['icq'], - 'YIM' => $data['yim'], - 'AIM' => $data['aim'], - 'MSN' => $data['msn'], 'JABBER' => $data['jabber'], - 'WEBSITE' => $data['website'], - 'S_BIRTHDAY_DAY_OPTIONS' => $s_birthday_day_options, 'S_BIRTHDAY_MONTH_OPTIONS' => $s_birthday_month_options, 'S_BIRTHDAY_YEAR_OPTIONS' => $s_birthday_year_options, @@ -1490,45 +1564,59 @@ class acp_users case 'prefs': - include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + if (!function_exists('user_get_id_name')) + { + include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + } $data = array( - 'dateformat' => utf8_normalize_nfc(request_var('dateformat', $user_row['user_dateformat'], true)), - 'lang' => basename(request_var('lang', $user_row['user_lang'])), - 'tz' => request_var('tz', $user_row['user_timezone']), - 'style' => request_var('style', $user_row['user_style']), - 'viewemail' => request_var('viewemail', $user_row['user_allow_viewemail']), - 'massemail' => request_var('massemail', $user_row['user_allow_massemail']), - 'hideonline' => request_var('hideonline', !$user_row['user_allow_viewonline']), - 'notifymethod' => request_var('notifymethod', $user_row['user_notify_type']), - 'notifypm' => request_var('notifypm', $user_row['user_notify_pm']), - 'allowpm' => request_var('allowpm', $user_row['user_allow_pm']), - - 'topic_sk' => request_var('topic_sk', ($user_row['user_topic_sortby_type']) ? $user_row['user_topic_sortby_type'] : 't'), - 'topic_sd' => request_var('topic_sd', ($user_row['user_topic_sortby_dir']) ? $user_row['user_topic_sortby_dir'] : 'd'), - 'topic_st' => request_var('topic_st', ($user_row['user_topic_show_days']) ? $user_row['user_topic_show_days'] : 0), - - 'post_sk' => request_var('post_sk', ($user_row['user_post_sortby_type']) ? $user_row['user_post_sortby_type'] : 't'), - 'post_sd' => request_var('post_sd', ($user_row['user_post_sortby_dir']) ? $user_row['user_post_sortby_dir'] : 'a'), - 'post_st' => request_var('post_st', ($user_row['user_post_show_days']) ? $user_row['user_post_show_days'] : 0), - - 'view_images' => request_var('view_images', $this->optionget($user_row, 'viewimg')), - 'view_flash' => request_var('view_flash', $this->optionget($user_row, 'viewflash')), - 'view_smilies' => request_var('view_smilies', $this->optionget($user_row, 'viewsmilies')), - 'view_sigs' => request_var('view_sigs', $this->optionget($user_row, 'viewsigs')), - 'view_avatars' => request_var('view_avatars', $this->optionget($user_row, 'viewavatars')), - 'view_wordcensor' => request_var('view_wordcensor', $this->optionget($user_row, 'viewcensors')), - - 'bbcode' => request_var('bbcode', $this->optionget($user_row, 'bbcode')), - 'smilies' => request_var('smilies', $this->optionget($user_row, 'smilies')), - 'sig' => request_var('sig', $this->optionget($user_row, 'attachsig')), - 'notify' => request_var('notify', $user_row['user_notify']), + 'dateformat' => $request->variable('dateformat', $user_row['user_dateformat'], true), + 'lang' => basename($request->variable('lang', $user_row['user_lang'])), + 'tz' => $request->variable('tz', $user_row['user_timezone']), + 'style' => $request->variable('style', $user_row['user_style']), + 'viewemail' => $request->variable('viewemail', $user_row['user_allow_viewemail']), + 'massemail' => $request->variable('massemail', $user_row['user_allow_massemail']), + 'hideonline' => $request->variable('hideonline', !$user_row['user_allow_viewonline']), + 'notifymethod' => $request->variable('notifymethod', $user_row['user_notify_type']), + 'notifypm' => $request->variable('notifypm', $user_row['user_notify_pm']), + 'allowpm' => $request->variable('allowpm', $user_row['user_allow_pm']), + + 'topic_sk' => $request->variable('topic_sk', ($user_row['user_topic_sortby_type']) ? $user_row['user_topic_sortby_type'] : 't'), + 'topic_sd' => $request->variable('topic_sd', ($user_row['user_topic_sortby_dir']) ? $user_row['user_topic_sortby_dir'] : 'd'), + 'topic_st' => $request->variable('topic_st', ($user_row['user_topic_show_days']) ? $user_row['user_topic_show_days'] : 0), + + 'post_sk' => $request->variable('post_sk', ($user_row['user_post_sortby_type']) ? $user_row['user_post_sortby_type'] : 't'), + 'post_sd' => $request->variable('post_sd', ($user_row['user_post_sortby_dir']) ? $user_row['user_post_sortby_dir'] : 'a'), + 'post_st' => $request->variable('post_st', ($user_row['user_post_show_days']) ? $user_row['user_post_show_days'] : 0), + + 'view_images' => $request->variable('view_images', $this->optionget($user_row, 'viewimg')), + 'view_flash' => $request->variable('view_flash', $this->optionget($user_row, 'viewflash')), + 'view_smilies' => $request->variable('view_smilies', $this->optionget($user_row, 'viewsmilies')), + 'view_sigs' => $request->variable('view_sigs', $this->optionget($user_row, 'viewsigs')), + 'view_avatars' => $request->variable('view_avatars', $this->optionget($user_row, 'viewavatars')), + 'view_wordcensor' => $request->variable('view_wordcensor', $this->optionget($user_row, 'viewcensors')), + + 'bbcode' => $request->variable('bbcode', $this->optionget($user_row, 'bbcode')), + 'smilies' => $request->variable('smilies', $this->optionget($user_row, 'smilies')), + 'sig' => $request->variable('sig', $this->optionget($user_row, 'attachsig')), + 'notify' => $request->variable('notify', $user_row['user_notify']), ); + /** + * Modify users preferences data + * + * @event core.acp_users_prefs_modify_data + * @var array data Array with users preferences data + * @var array user_row Array with user data + * @since 3.1.0-b3 + */ + $vars = array('data', 'user_row'); + extract($phpbb_dispatcher->trigger_event('core.acp_users_prefs_modify_data', compact($vars))); + if ($submit) { $error = validate_data($data, array( - 'dateformat' => array('string', false, 1, 30), + 'dateformat' => array('string', false, 1, 64), 'lang' => array('match', false, '#^[a-z_\-]{2,}$#i'), 'tz' => array('timezone'), @@ -1581,37 +1669,53 @@ class acp_users 'user_notify' => $data['notify'], ); - $sql = 'UPDATE ' . USERS_TABLE . ' - SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " - WHERE user_id = $user_id"; - $db->sql_query($sql); + /** + * Modify SQL query before users preferences are updated + * + * @event core.acp_users_prefs_modify_sql + * @var array data Array with users preferences data + * @var array user_row Array with user data + * @var array sql_ary SQL array with users preferences data to update + * @var array error Array with errors data + * @since 3.1.0-b3 + */ + $vars = array('data', 'user_row', 'sql_ary', 'error'); + extract($phpbb_dispatcher->trigger_event('core.acp_users_prefs_modify_sql', compact($vars))); - // Check if user has an active session - if ($user_row['session_id']) + if (!sizeof($error)) { - // We'll update the session if user_allow_viewonline has changed and the user is a bot - // Or if it's a regular user and the admin set it to hide the session - if ($user_row['user_allow_viewonline'] != $sql_ary['user_allow_viewonline'] && $user_row['user_type'] == USER_IGNORE - || $user_row['user_allow_viewonline'] && !$sql_ary['user_allow_viewonline']) + $sql = 'UPDATE ' . USERS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " + WHERE user_id = $user_id"; + $db->sql_query($sql); + + // Check if user has an active session + if ($user_row['session_id']) { - // We also need to check if the user has the permission to cloak. - $user_auth = new \phpbb\auth\auth(); - $user_auth->acl($user_row); + // We'll update the session if user_allow_viewonline has changed and the user is a bot + // Or if it's a regular user and the admin set it to hide the session + if ($user_row['user_allow_viewonline'] != $sql_ary['user_allow_viewonline'] && $user_row['user_type'] == USER_IGNORE + || $user_row['user_allow_viewonline'] && !$sql_ary['user_allow_viewonline']) + { + // We also need to check if the user has the permission to cloak. + $user_auth = new \phpbb\auth\auth(); + $user_auth->acl($user_row); - $session_sql_ary = array( - 'session_viewonline' => ($user_auth->acl_get('u_hideonline')) ? $sql_ary['user_allow_viewonline'] : true, - ); + $session_sql_ary = array( + 'session_viewonline' => ($user_auth->acl_get('u_hideonline')) ? $sql_ary['user_allow_viewonline'] : true, + ); - $sql = 'UPDATE ' . SESSIONS_TABLE . ' - SET ' . $db->sql_build_array('UPDATE', $session_sql_ary) . " - WHERE session_user_id = $user_id"; - $db->sql_query($sql); + $sql = 'UPDATE ' . SESSIONS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $session_sql_ary) . " + WHERE session_user_id = $user_id"; + $db->sql_query($sql); - unset($user_auth); + unset($user_auth); + } } - } - trigger_error($user->lang['USER_PREFS_UPDATED'] . adm_back_link($this->u_action . '&u=' . $user_id)); + trigger_error($user->lang['USER_PREFS_UPDATED'] . adm_back_link($this->u_action . '&u=' . $user_id)); + } } // Replace "error" strings with their real, localised form @@ -1674,8 +1778,8 @@ class acp_users ${'s_sort_' . $sort_option . '_dir'} .= '</select>'; } - $timezone_selects = phpbb_timezone_select($user, $data['tz'], true); - $template->assign_vars(array( + phpbb_timezone_select($template, $user, $data['tz'], true); + $user_prefs_data = array( 'S_PREFS' => true, 'S_JABBER_DISABLED' => ($config['jab_enable'] && $user_row['user_jabber'] && @extension_loaded('xml')) ? false : true, @@ -1713,21 +1817,31 @@ class acp_users 'S_LANG_OPTIONS' => language_select($data['lang']), 'S_STYLE_OPTIONS' => style_select($data['style']), - 'S_TZ_OPTIONS' => $timezone_selects['tz_select'], - 'S_TZ_DATE_OPTIONS' => $timezone_selects['tz_dates'], - ) ); + /** + * Modify users preferences data before assigning it to the template + * + * @event core.acp_users_prefs_modify_template_data + * @var array data Array with users preferences data + * @var array user_row Array with user data + * @var array user_prefs_data Array with users preferences data to be assigned to the template + * @since 3.1.0-b3 + */ + $vars = array('data', 'user_row', 'user_prefs_data'); + extract($phpbb_dispatcher->trigger_event('core.acp_users_prefs_modify_template_data', compact($vars))); + + $template->assign_vars($user_prefs_data); + break; case 'avatar': - include($phpbb_root_path . 'includes/functions_display.' . $phpEx); - $avatars_enabled = false; if ($config['allow_avatar']) { + /* @var $phpbb_avatar_manager \phpbb\avatar\manager */ $phpbb_avatar_manager = $phpbb_container->get('avatar.manager'); $avatar_drivers = $phpbb_avatar_manager->get_enabled_drivers(); @@ -1763,29 +1877,6 @@ class acp_users trigger_error($user->lang['USER_AVATAR_UPDATED'] . adm_back_link($this->u_action . '&u=' . $user_id)); } } - else - { - $driver = $phpbb_avatar_manager->get_driver($avatar_data['avatar_type']); - if ($driver) - { - $driver->delete($avatar_data); - } - - // Removing the avatar - $result = array( - 'user_avatar' => '', - 'user_avatar_type' => '', - 'user_avatar_width' => 0, - 'user_avatar_height' => 0, - ); - - $sql = 'UPDATE ' . USERS_TABLE . ' - SET ' . $db->sql_build_array('UPDATE', $result) . ' - WHERE user_id = ' . (int) $user_id; - - $db->sql_query($sql); - trigger_error($user->lang['USER_AVATAR_UPDATED'] . adm_back_link($this->u_action . '&u=' . $user_id)); - } } else { @@ -1793,6 +1884,23 @@ class acp_users } } + // Handle deletion of avatars + if ($request->is_set_post('avatar_delete')) + { + if (!confirm_box(true)) + { + confirm_box(false, $user->lang('CONFIRM_AVATAR_DELETE'), build_hidden_fields(array( + 'avatar_delete' => true)) + ); + } + else + { + $phpbb_avatar_manager->handle_avatar_delete($db, $user, $avatar_data, USERS_TABLE, 'user_'); + + trigger_error($user->lang['USER_AVATAR_UPDATED'] . adm_back_link($this->u_action . '&u=' . $user_id)); + } + } + $selected_driver = $phpbb_avatar_manager->clean_driver_name($request->variable('avatar_driver', $user_row['user_avatar_type'])); foreach ($avatar_drivers as $current_driver) @@ -1800,9 +1908,8 @@ class acp_users $driver = $phpbb_avatar_manager->get_driver($current_driver); $avatars_enabled = true; - $config_name = $phpbb_avatar_manager->get_driver_config_name($driver); $template->set_filenames(array( - 'avatar' => "acp_avatar_options_{$config_name}.html", + 'avatar' => $driver->get_acp_template_name(), )); if ($driver->prepare_form($request, $template, $user, $avatar_data, $error)) @@ -1850,7 +1957,7 @@ class acp_users trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); } - $rank_id = request_var('user_rank', 0); + $rank_id = $request->variable('user_rank', 0); $sql = 'UPDATE ' . USERS_TABLE . " SET user_rank = $rank_id @@ -1884,50 +1991,70 @@ class acp_users case 'sig': - include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx); - include_once($phpbb_root_path . 'includes/functions_display.' . $phpEx); - - $enable_bbcode = ($config['allow_sig_bbcode']) ? (bool) $this->optionget($user_row, 'sig_bbcode') : false; - $enable_smilies = ($config['allow_sig_smilies']) ? (bool) $this->optionget($user_row, 'sig_smilies') : false; - $enable_urls = ($config['allow_sig_links']) ? (bool) $this->optionget($user_row, 'sig_links') : false; - $signature = utf8_normalize_nfc(request_var('signature', (string) $user_row['user_sig'], true)); - - $preview = (isset($_POST['preview'])) ? true : false; - - if ($submit || $preview) + if (!function_exists('display_custom_bbcodes')) { - include_once($phpbb_root_path . 'includes/message_parser.' . $phpEx); - - $enable_bbcode = ($config['allow_sig_bbcode']) ? ((request_var('disable_bbcode', false)) ? false : true) : false; - $enable_smilies = ($config['allow_sig_smilies']) ? ((request_var('disable_smilies', false)) ? false : true) : false; - $enable_urls = ($config['allow_sig_links']) ? ((request_var('disable_magic_url', false)) ? false : true) : false; + include($phpbb_root_path . 'includes/functions_display.' . $phpEx); + } - $message_parser = new parse_message($signature); + $enable_bbcode = ($config['allow_sig_bbcode']) ? $this->optionget($user_row, 'sig_bbcode') : false; + $enable_smilies = ($config['allow_sig_smilies']) ? $this->optionget($user_row, 'sig_smilies') : false; + $enable_urls = ($config['allow_sig_links']) ? $this->optionget($user_row, 'sig_links') : false; - // Allowing Quote BBCode - $message_parser->parse($enable_bbcode, $enable_urls, $enable_smilies, $config['allow_sig_img'], $config['allow_sig_flash'], true, $config['allow_sig_links'], true, 'sig'); + $decoded_message = generate_text_for_edit($user_row['user_sig'], $user_row['user_sig_bbcode_uid'], $user_row['user_sig_bbcode_bitfield']); + $signature = $request->variable('signature', $decoded_message['text'], true); + $signature_preview = ''; - if (sizeof($message_parser->warn_msg)) - { - $error[] = implode('<br />', $message_parser->warn_msg); - } + if ($submit || $request->is_set_post('preview')) + { + $enable_bbcode = ($config['allow_sig_bbcode']) ? !$request->variable('disable_bbcode', false) : false; + $enable_smilies = ($config['allow_sig_smilies']) ? !$request->variable('disable_smilies', false) : false; + $enable_urls = ($config['allow_sig_links']) ? !$request->variable('disable_magic_url', false) : false; if (!check_form_key($form_name)) { - $error = 'FORM_INVALID'; + $error[] = 'FORM_INVALID'; } + } + + $bbcode_uid = $bbcode_bitfield = $bbcode_flags = ''; + $warn_msg = generate_text_for_storage( + $signature, + $bbcode_uid, + $bbcode_bitfield, + $bbcode_flags, + $enable_bbcode, + $enable_urls, + $enable_smilies, + $config['allow_sig_img'], + $config['allow_sig_flash'], + true, + $config['allow_sig_links'], + 'sig' + ); - if (!sizeof($error) && $submit) + if (sizeof($warn_msg)) + { + $error += $warn_msg; + } + + if (!$submit) + { + // Parse it for displaying + $signature_preview = generate_text_for_display($signature, $bbcode_uid, $bbcode_bitfield, $bbcode_flags); + } + else + { + if (!sizeof($error)) { $this->optionset($user_row, 'sig_bbcode', $enable_bbcode); $this->optionset($user_row, 'sig_smilies', $enable_smilies); $this->optionset($user_row, 'sig_links', $enable_urls); $sql_ary = array( - 'user_sig' => (string) $message_parser->message, + 'user_sig' => $signature, 'user_options' => $user_row['user_options'], - 'user_sig_bbcode_uid' => (string) $message_parser->bbcode_uid, - 'user_sig_bbcode_bitfield' => (string) $message_parser->bbcode_bitfield + 'user_sig_bbcode_uid' => $bbcode_uid, + 'user_sig_bbcode_bitfield' => $bbcode_bitfield, ); $sql = 'UPDATE ' . USERS_TABLE . ' @@ -1937,33 +2064,27 @@ class acp_users trigger_error($user->lang['USER_SIG_UPDATED'] . adm_back_link($this->u_action . '&u=' . $user_id)); } - - // Replace "error" strings with their real, localised form - $error = array_map(array($user, 'lang'), $error); } - $signature_preview = ''; + // Replace "error" strings with their real, localised form + $error = array_map(array($user, 'lang'), $error); - if ($preview) - { - // Now parse it for displaying - $signature_preview = $message_parser->format_display($enable_bbcode, $enable_urls, $enable_smilies, false); - unset($message_parser); - } + $decoded_message = generate_text_for_edit($signature, $bbcode_uid, $bbcode_bitfield); - decode_message($signature, $user_row['user_sig_bbcode_uid']); + /** @var \phpbb\controller\helper $controller_helper */ + $controller_helper = $phpbb_container->get('controller.helper'); $template->assign_vars(array( 'S_SIGNATURE' => true, - 'SIGNATURE' => $signature, + 'SIGNATURE' => $decoded_message['text'], 'SIGNATURE_PREVIEW' => $signature_preview, 'S_BBCODE_CHECKED' => (!$enable_bbcode) ? ' checked="checked"' : '', 'S_SMILIES_CHECKED' => (!$enable_smilies) ? ' checked="checked"' : '', 'S_MAGIC_URL_CHECKED' => (!$enable_urls) ? ' checked="checked"' : '', - 'BBCODE_STATUS' => ($config['allow_sig_bbcode']) ? sprintf($user->lang['BBCODE_IS_ON'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '">', '</a>') : sprintf($user->lang['BBCODE_IS_OFF'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '">', '</a>'), + 'BBCODE_STATUS' => $user->lang(($config['allow_sig_bbcode'] ? 'BBCODE_IS_ON' : 'BBCODE_IS_OFF'), '<a href="' . $controller_helper->route('phpbb_help_bbcode_controller') . '">', '</a>'), 'SMILIES_STATUS' => ($config['allow_sig_smilies']) ? $user->lang['SMILIES_ARE_ON'] : $user->lang['SMILIES_ARE_OFF'], 'IMG_STATUS' => ($config['allow_sig_img']) ? $user->lang['IMAGES_ARE_ON'] : $user->lang['IMAGES_ARE_OFF'], 'FLASH_STATUS' => ($config['allow_sig_flash']) ? $user->lang['FLASH_IS_ON'] : $user->lang['FLASH_IS_OFF'], @@ -1984,15 +2105,16 @@ class acp_users break; case 'attach': + /* @var $pagination \phpbb\pagination */ + $pagination = $phpbb_container->get('pagination'); - $start = request_var('start', 0); + $start = $request->variable('start', 0); $deletemark = (isset($_POST['delmarked'])) ? true : false; - $marked = request_var('mark', array(0)); - $pagination = $phpbb_container->get('pagination'); + $marked = $request->variable('mark', array(0)); // Sort keys - $sort_key = request_var('sk', 'a'); - $sort_dir = request_var('sd', 'd'); + $sort_key = $request->variable('sk', 'a'); + $sort_dir = $request->variable('sd', 'd'); if ($deletemark && sizeof($marked)) { @@ -2027,11 +2149,14 @@ class acp_users } $db->sql_freeresult($result); - delete_attachments('attach', $marked); + /** @var \phpbb\attachment\manager $attachment_manager */ + $attachment_manager = $phpbb_container->get('attachment.manager'); + $attachment_manager->delete('attach', $marked); + unset($attachment_manager); $message = (sizeof($log_attachments) == 1) ? $user->lang['ATTACHMENT_DELETED'] : $user->lang['ATTACHMENTS_DELETED']; - add_log('admin', 'LOG_ATTACHMENTS_DELETED', implode($user->lang['COMMA_SEPARATOR'], $log_attachments)); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ATTACHMENTS_DELETED', false, array(implode($user->lang['COMMA_SEPARATOR'], $log_attachments))); trigger_error($message . adm_back_link($this->u_action . '&u=' . $user_id)); } else @@ -2090,7 +2215,7 @@ class acp_users WHERE a.poster_id = ' . $user_id . " AND a.is_orphan = 0 ORDER BY $order_by"; - $result = $db->sql_query_limit($sql, $config['posts_per_page'], $start); + $result = $db->sql_query_limit($sql, $config['topics_per_page'], $start); while ($row = $db->sql_fetchrow($result)) { @@ -2137,10 +2262,13 @@ class acp_users case 'groups': - include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + if (!function_exists('group_user_attributes')) + { + include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + } $user->add_lang(array('groups', 'acp/groups')); - $group_id = request_var('g', 0); + $group_id = $request->variable('g', 0); if ($group_id) { @@ -2157,10 +2285,6 @@ class acp_users trigger_error($user->lang['NOT_ALLOWED_MANAGE_GROUP'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); } } - else - { - $founder_manage = 0; - } switch ($action) { @@ -2265,6 +2389,8 @@ class acp_users $error = array(); } + /** @var \phpbb\group\helper $group_helper */ + $group_helper = $phpbb_container->get('group_helper'); $sql = 'SELECT ug.*, g.* FROM ' . GROUPS_TABLE . ' g, ' . USER_GROUP_TABLE . " ug @@ -2310,7 +2436,7 @@ class acp_users continue; } - $s_group_options .= '<option' . (($row['group_type'] == GROUP_SPECIAL) ? ' class="sep"' : '') . ' value="' . $row['group_id'] . '">' . (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']) . '</option>'; + $s_group_options .= '<option' . (($row['group_type'] == GROUP_SPECIAL) ? ' class="sep"' : '') . ' value="' . $row['group_id'] . '">' . $group_helper->get_name($row['group_name']) . '</option>'; } $db->sql_freeresult($result); @@ -2354,14 +2480,17 @@ class acp_users case 'perm': - include_once($phpbb_root_path . 'includes/acp/auth.' . $phpEx); + if (!class_exists('auth_admin')) + { + include($phpbb_root_path . 'includes/acp/auth.' . $phpEx); + } $auth_admin = new auth_admin(); $user->add_lang('acp/permissions'); add_permission_language(); - $forum_id = request_var('f', 0); + $forum_id = $request->variable('f', 0); // Global Permissions if (!$forum_id) @@ -2369,7 +2498,7 @@ class acp_users // Select auth options $sql = 'SELECT auth_option, is_local, is_global FROM ' . ACL_OPTIONS_TABLE . ' - WHERE auth_option ' . $db->sql_like_expression($db->any_char . '_') . ' + WHERE auth_option ' . $db->sql_like_expression($db->get_any_char() . '_') . ' AND is_global = 1 ORDER BY auth_option'; $result = $db->sql_query($sql); @@ -2389,7 +2518,7 @@ class acp_users { $sql = 'SELECT auth_option, is_local, is_global FROM ' . ACL_OPTIONS_TABLE . " - WHERE auth_option " . $db->sql_like_expression($db->any_char . '_') . " + WHERE auth_option " . $db->sql_like_expression($db->get_any_char() . '_') . " AND is_local = 1 ORDER BY is_global DESC, auth_option"; $result = $db->sql_query($sql); diff --git a/phpBB/includes/acp/acp_words.php b/phpBB/includes/acp/acp_words.php index d8d14ba4ad..e5eeb7ab07 100644 --- a/phpBB/includes/acp/acp_words.php +++ b/phpBB/includes/acp/acp_words.php @@ -1,9 +1,13 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -17,7 +21,6 @@ if (!defined('IN_PHPBB')) /** * @todo [words] check regular expressions for special char replacements (stored specialchared in db) -* @package acp */ class acp_words { @@ -25,13 +28,12 @@ class acp_words function main($id, $mode) { - global $db, $user, $auth, $template, $cache; - global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + global $db, $user, $template, $cache, $phpbb_log, $request, $phpbb_container; $user->add_lang('acp/posting'); // Set up general vars - $action = request_var('action', ''); + $action = $request->variable('action', ''); $action = (isset($_POST['add'])) ? 'add' : ((isset($_POST['save'])) ? 'save' : $action); $s_hidden_fields = ''; @@ -47,7 +49,7 @@ class acp_words { case 'edit': - $word_id = request_var('id', 0); + $word_id = $request->variable('id', 0); if (!$word_id) { @@ -85,9 +87,9 @@ class acp_words trigger_error($user->lang['FORM_INVALID']. adm_back_link($this->u_action), E_USER_WARNING); } - $word_id = request_var('id', 0); - $word = utf8_normalize_nfc(request_var('word', '', true)); - $replacement = utf8_normalize_nfc(request_var('replacement', '', true)); + $word_id = $request->variable('id', 0); + $word = $request->variable('word', '', true); + $replacement = $request->variable('replacement', '', true); if ($word === '' || $replacement === '') { @@ -101,7 +103,7 @@ class acp_words 'word' => $word, 'replacement' => $replacement ); - + if ($word_id) { $db->sql_query('UPDATE ' . WORDS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' WHERE word_id = ' . $word_id); @@ -112,9 +114,11 @@ class acp_words } $cache->destroy('_word_censors'); + $phpbb_container->get('text_formatter.cache')->invalidate(); $log_action = ($word_id) ? 'LOG_WORD_EDIT' : 'LOG_WORD_ADD'; - add_log('admin', $log_action, $word); + + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, $log_action, false, array($word)); $message = ($word_id) ? $user->lang['WORD_UPDATED'] : $user->lang['WORD_ADDED']; trigger_error($message . adm_back_link($this->u_action)); @@ -123,7 +127,7 @@ class acp_words case 'delete': - $word_id = request_var('id', 0); + $word_id = $request->variable('id', 0); if (!$word_id) { @@ -144,8 +148,9 @@ class acp_words $db->sql_query($sql); $cache->destroy('_word_censors'); + $phpbb_container->get('text_formatter.cache')->invalidate(); - add_log('admin', 'LOG_WORD_DELETE', $deleted_word); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_WORD_DELETE', false, array($deleted_word)); trigger_error($user->lang['WORD_REMOVED'] . adm_back_link($this->u_action)); } @@ -162,7 +167,6 @@ class acp_words break; } - $template->assign_vars(array( 'U_ACTION' => $this->u_action, 'S_HIDDEN_FIELDS' => $s_hidden_fields) diff --git a/phpBB/includes/acp/auth.php b/phpBB/includes/acp/auth.php index a023bced0a..11478842d7 100644 --- a/phpBB/includes/acp/auth.php +++ b/phpBB/includes/acp/auth.php @@ -1,9 +1,13 @@ <?php /** * -* @package phpBB3 -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -17,7 +21,6 @@ if (!defined('IN_PHPBB')) /** * ACP Permission/Auth class -* @package phpBB3 */ class auth_admin extends \phpbb\auth\auth { @@ -139,7 +142,6 @@ class auth_admin extends \phpbb\auth\auth $auth2 = &$auth; } - $hold_ary[$userdata['user_id']] = array(); foreach ($forum_ids as $f_id) { @@ -181,7 +183,10 @@ class auth_admin extends \phpbb\auth\auth } // Defining the user-function here to save some memory - $return_acl_fill = create_function('$value', 'return ' . $acl_fill . ';'); + $return_acl_fill = function () use ($acl_fill) + { + return $acl_fill; + }; // Actually fill the gaps if (sizeof($hold_ary)) @@ -261,9 +266,14 @@ class auth_admin extends \phpbb\auth\auth */ function display_mask($mode, $permission_type, &$hold_ary, $user_mode = 'user', $local = false, $group_display = true) { - global $template, $user, $db, $phpbb_root_path, $phpEx, $phpbb_container; + global $template, $user, $db, $phpbb_container; + + /* @var $phpbb_permissions \phpbb\permissions */ $phpbb_permissions = $phpbb_container->get('acl.permissions'); + /** @var \phpbb\group\helper $group_helper */ + $group_helper = $phpbb_container->get('group_helper'); + // Define names for template loops, might be able to be set $tpl_pmask = 'p_mask'; $tpl_fmask = 'f_mask'; @@ -295,7 +305,7 @@ class auth_admin extends \phpbb\auth\auth $ug_names_ary = array(); while ($row = $db->sql_fetchrow($result)) { - $ug_names_ary[$row['ug_id']] = ($user_mode == 'user') ? $row['ug_name'] : (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['ug_name']] : $row['ug_name']); + $ug_names_ary[$row['ug_id']] = ($user_mode == 'user') ? $row['ug_name'] : $group_helper->get_name($row['ug_name']); } $db->sql_freeresult($result); @@ -403,14 +413,7 @@ class auth_admin extends \phpbb\auth\auth { foreach ($memberships as $row) { - if ($groups[$row['group_id']]['group_type'] == GROUP_SPECIAL) - { - $user_groups_default[$row['user_id']][] = $user->lang['G_' . $groups[$row['group_id']]['group_name']]; - } - else - { - $user_groups_custom[$row['user_id']][] = $groups[$row['group_id']]['group_name']; - } + $user_groups_default[$row['user_id']][] = $group_helper->get_name($groups[$row['group_id']]['group_name']); } } unset($memberships, $groups); @@ -463,7 +466,8 @@ class auth_admin extends \phpbb\auth\auth // Build role dropdown options $current_role_id = (isset($cur_roles[$ug_id][$forum_id])) ? $cur_roles[$ug_id][$forum_id] : 0; - $s_role_options = ''; + // Output current role id to template + $template->assign_var('S_ROLE_ID', $current_role_id); @reset($roles); while (list($role_id, $role_row) = each($roles)) @@ -471,13 +475,12 @@ class auth_admin extends \phpbb\auth\auth $role_description = (!empty($user->lang[$role_row['role_description']])) ? $user->lang[$role_row['role_description']] : nl2br($role_row['role_description']); $role_name = (!empty($user->lang[$role_row['role_name']])) ? $user->lang[$role_row['role_name']] : $role_row['role_name']; - $title = ($role_description) ? ' title="' . $role_description . '"' : ''; - $s_role_options .= '<option value="' . $role_id . '"' . (($role_id == $current_role_id) ? ' selected="selected"' : '') . $title . '>' . $role_name . '</option>'; - } - - if ($s_role_options) - { - $s_role_options = '<option value="0"' . ((!$current_role_id) ? ' selected="selected"' : '') . ' title="' . htmlspecialchars($user->lang['NO_ROLE_ASSIGNED_EXPLAIN']) . '">' . $user->lang['NO_ROLE_ASSIGNED'] . '</option>' . $s_role_options; + $template->assign_block_vars('role_options', array( + 'ID' => $role_id, + 'ROLE_NAME' => $role_name, + 'TITLE' => $role_description, + 'SELECTED' => $role_id == $current_role_id, + )); } if (!$current_role_id && $mode != 'view') @@ -500,7 +503,6 @@ class auth_admin extends \phpbb\auth\auth $template->assign_block_vars($tpl_pmask . '.' . $tpl_fmask, array( 'NAME' => $ug_names_ary[$ug_id], - 'S_ROLE_OPTIONS' => $s_role_options, 'UG_ID' => $ug_id, 'S_CUSTOM' => $s_custom_permissions, 'FORUM_ID' => $forum_id) @@ -549,7 +551,8 @@ class auth_admin extends \phpbb\auth\auth // Build role dropdown options $current_role_id = (isset($cur_roles[$ug_id][$forum_id])) ? $cur_roles[$ug_id][$forum_id] : 0; - $s_role_options = ''; + // Output current role id to template + $template->assign_var('S_ROLE_ID', $current_role_id); @reset($roles); while (list($role_id, $role_row) = each($roles)) @@ -557,13 +560,12 @@ class auth_admin extends \phpbb\auth\auth $role_description = (!empty($user->lang[$role_row['role_description']])) ? $user->lang[$role_row['role_description']] : nl2br($role_row['role_description']); $role_name = (!empty($user->lang[$role_row['role_name']])) ? $user->lang[$role_row['role_name']] : $role_row['role_name']; - $title = ($role_description) ? ' title="' . $role_description . '"' : ''; - $s_role_options .= '<option value="' . $role_id . '"' . (($role_id == $current_role_id) ? ' selected="selected"' : '') . $title . '>' . $role_name . '</option>'; - } - - if ($s_role_options) - { - $s_role_options = '<option value="0"' . ((!$current_role_id) ? ' selected="selected"' : '') . ' title="' . htmlspecialchars($user->lang['NO_ROLE_ASSIGNED_EXPLAIN']) . '">' . $user->lang['NO_ROLE_ASSIGNED'] . '</option>' . $s_role_options; + $template->assign_block_vars('role_options', array( + 'ID' => $role_id, + 'ROLE_NAME' => $role_name, + 'TITLE' => $role_description, + 'SELECTED' => $role_id == $current_role_id, + )); } if (!$current_role_id && $mode != 'view') @@ -587,7 +589,6 @@ class auth_admin extends \phpbb\auth\auth $template->assign_block_vars($tpl_pmask . '.' . $tpl_fmask, array( 'NAME' => ($forum_id == 0) ? $forum_names_ary[0] : $forum_names_ary[$forum_id]['forum_name'], 'PADDING' => ($forum_id == 0) ? '' : $forum_names_ary[$forum_id]['padding'], - 'S_ROLE_OPTIONS' => $s_role_options, 'S_CUSTOM' => $s_custom_permissions, 'UG_ID' => $ug_id, 'FORUM_ID' => $forum_id) @@ -606,13 +607,17 @@ class auth_admin extends \phpbb\auth\auth */ function display_role_mask(&$hold_ary) { - global $db, $template, $user, $phpbb_root_path, $phpbb_admin_path, $phpEx; + global $db, $template, $user, $phpbb_root_path, $phpEx; + global $phpbb_container; if (!sizeof($hold_ary)) { return; } + /** @var \phpbb\group\helper $group_helper */ + $group_helper = $phpbb_container->get('group_helper'); + // Get forum names $sql = 'SELECT forum_id, forum_name FROM ' . FORUMS_TABLE . ' @@ -649,9 +654,9 @@ class auth_admin extends \phpbb\auth\auth { $template->assign_block_vars('role_mask.users', array( 'USER_ID' => $row['user_id'], - 'USERNAME' => $row['username'], - 'U_PROFILE' => append_sid("{$phpbb_root_path}memberlist.$phpEx", "mode=viewprofile&u={$row['user_id']}")) - ); + 'USERNAME' => get_username_string('username', $row['user_id'], $row['username']), + 'U_PROFILE' => get_username_string('profile', $row['user_id'], $row['username']), + )); } $db->sql_freeresult($result); } @@ -668,7 +673,7 @@ class auth_admin extends \phpbb\auth\auth { $template->assign_block_vars('role_mask.groups', array( 'GROUP_ID' => $row['group_id'], - 'GROUP_NAME' => ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'], + 'GROUP_NAME' => $group_helper->get_name($row['group_name']), 'U_PROFILE' => append_sid("{$phpbb_root_path}memberlist.$phpEx", "mode=group&g={$row['group_id']}")) ); } @@ -833,7 +838,7 @@ class auth_admin extends \phpbb\auth\auth } // Remove current auth options... - $auth_option_ids = array((int)$any_option_id); + $auth_option_ids = array((int) $any_option_id); foreach ($auth as $auth_option => $auth_setting) { $auth_option_ids[] = (int) $this->acl_options['id'][$auth_option]; @@ -1022,7 +1027,7 @@ class auth_admin extends \phpbb\auth\auth // Get permission type $sql = 'SELECT auth_option, auth_option_id FROM ' . ACL_OPTIONS_TABLE . " - WHERE auth_option " . $db->sql_like_expression($permission_type . $db->any_char); + WHERE auth_option " . $db->sql_like_expression($permission_type . $db->get_any_char()); $result = $db->sql_query($sql); $auth_id_ary = array(); @@ -1101,13 +1106,19 @@ class auth_admin extends \phpbb\auth\auth */ function assign_cat_array(&$category_array, $tpl_cat, $tpl_mask, $ug_id, $forum_id, $s_view, $show_trace = false) { - global $template, $user, $phpbb_admin_path, $phpEx, $phpbb_container; + global $template, $phpbb_admin_path, $phpEx, $phpbb_container; + /* @var $phpbb_permissions \phpbb\permissions */ $phpbb_permissions = $phpbb_container->get('acl.permissions'); @reset($category_array); while (list($cat, $cat_array) = each($category_array)) { + if (!$phpbb_permissions->category_defined($cat)) + { + continue; + } + $template->assign_block_vars($tpl_cat, array( 'S_YES' => ($cat_array['S_YES'] && !$cat_array['S_NEVER'] && !$cat_array['S_NO']) ? true : false, 'S_NEVER' => ($cat_array['S_NEVER'] && !$cat_array['S_YES'] && !$cat_array['S_NO']) ? true : false, @@ -1134,6 +1145,11 @@ class auth_admin extends \phpbb\auth\auth @reset($cat_array['permissions']); while (list($permission, $allowed) = each($cat_array['permissions'])) { + if (!$phpbb_permissions->permission_defined($permission)) + { + continue; + } + if ($s_view) { $template->assign_block_vars($tpl_cat . '.' . $tpl_mask, array( @@ -1179,8 +1195,9 @@ class auth_admin extends \phpbb\auth\auth */ function build_permission_array(&$permission_row, &$content_array, &$categories, $key_sort_array) { - global $user, $phpbb_container; + global $phpbb_container; + /* @var $phpbb_permissions \phpbb\permissions */ $phpbb_permissions = $phpbb_container->get('acl.permissions'); foreach ($key_sort_array as $forum_id) diff --git a/phpBB/includes/acp/info/acp_attachments.php b/phpBB/includes/acp/info/acp_attachments.php index 8fad241451..057f08201e 100644 --- a/phpBB/includes/acp/info/acp_attachments.php +++ b/phpBB/includes/acp/info/acp_attachments.php @@ -1,15 +1,16 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class acp_attachments_info { function module() @@ -17,7 +18,6 @@ class acp_attachments_info return array( 'filename' => 'acp_attachments', 'title' => 'ACP_ATTACHMENTS', - 'version' => '1.0.0', 'modes' => array( 'attach' => array('title' => 'ACP_ATTACHMENT_SETTINGS', 'auth' => 'acl_a_attach', 'cat' => array('ACP_BOARD_CONFIGURATION', 'ACP_ATTACHMENTS')), 'extensions' => array('title' => 'ACP_MANAGE_EXTENSIONS', 'auth' => 'acl_a_attach', 'cat' => array('ACP_ATTACHMENTS')), diff --git a/phpBB/includes/acp/info/acp_ban.php b/phpBB/includes/acp/info/acp_ban.php index 37f0f021a7..c88f4c2ebb 100644 --- a/phpBB/includes/acp/info/acp_ban.php +++ b/phpBB/includes/acp/info/acp_ban.php @@ -1,15 +1,16 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class acp_ban_info { function module() @@ -17,7 +18,6 @@ class acp_ban_info return array( 'filename' => 'acp_ban', 'title' => 'ACP_BAN', - 'version' => '1.0.0', 'modes' => array( 'email' => array('title' => 'ACP_BAN_EMAILS', 'auth' => 'acl_a_ban', 'cat' => array('ACP_USER_SECURITY')), 'ip' => array('title' => 'ACP_BAN_IPS', 'auth' => 'acl_a_ban', 'cat' => array('ACP_USER_SECURITY')), diff --git a/phpBB/includes/acp/info/acp_bbcodes.php b/phpBB/includes/acp/info/acp_bbcodes.php index 5c88ca8a0f..dfcd43a8ac 100644 --- a/phpBB/includes/acp/info/acp_bbcodes.php +++ b/phpBB/includes/acp/info/acp_bbcodes.php @@ -1,15 +1,16 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class acp_bbcodes_info { function module() @@ -17,7 +18,6 @@ class acp_bbcodes_info return array( 'filename' => 'acp_bbcodes', 'title' => 'ACP_BBCODES', - 'version' => '1.0.0', 'modes' => array( 'bbcodes' => array('title' => 'ACP_BBCODES', 'auth' => 'acl_a_bbcode', 'cat' => array('ACP_MESSAGES')), ), diff --git a/phpBB/includes/acp/info/acp_board.php b/phpBB/includes/acp/info/acp_board.php index 50d5a4f4e1..1a3ee7b6be 100644 --- a/phpBB/includes/acp/info/acp_board.php +++ b/phpBB/includes/acp/info/acp_board.php @@ -1,15 +1,16 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class acp_board_info { function module() @@ -17,7 +18,6 @@ class acp_board_info return array( 'filename' => 'acp_board', 'title' => 'ACP_BOARD_MANAGEMENT', - 'version' => '1.0.0', 'modes' => array( 'settings' => array('title' => 'ACP_BOARD_SETTINGS', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')), 'features' => array('title' => 'ACP_BOARD_FEATURES', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')), diff --git a/phpBB/includes/acp/info/acp_bots.php b/phpBB/includes/acp/info/acp_bots.php index c30ab588ab..26782d8c0b 100644 --- a/phpBB/includes/acp/info/acp_bots.php +++ b/phpBB/includes/acp/info/acp_bots.php @@ -1,15 +1,16 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class acp_bots_info { function module() @@ -17,7 +18,6 @@ class acp_bots_info return array( 'filename' => 'acp_bots', 'title' => 'ACP_BOTS', - 'version' => '1.0.0', 'modes' => array( 'bots' => array('title' => 'ACP_BOTS', 'auth' => 'acl_a_bots', 'cat' => array('ACP_GENERAL_TASKS')), ), diff --git a/phpBB/includes/acp/info/acp_captcha.php b/phpBB/includes/acp/info/acp_captcha.php index 3f31b4c102..3f7bf0351d 100644 --- a/phpBB/includes/acp/info/acp_captcha.php +++ b/phpBB/includes/acp/info/acp_captcha.php @@ -1,15 +1,16 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class acp_captcha_info { function module() @@ -17,7 +18,6 @@ class acp_captcha_info return array( 'filename' => 'acp_captcha', 'title' => 'ACP_CAPTCHA', - 'version' => '1.0.0', 'modes' => array( 'visual' => array('title' => 'ACP_VC_SETTINGS', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')), 'img' => array('title' => 'ACP_VC_CAPTCHA_DISPLAY', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION'), 'display' => false) diff --git a/phpBB/includes/acp/info/acp_contact.php b/phpBB/includes/acp/info/acp_contact.php new file mode 100644 index 0000000000..548eb52816 --- /dev/null +++ b/phpBB/includes/acp/info/acp_contact.php @@ -0,0 +1,30 @@ +<?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. +* +*/ + +/** +* @package module_install +*/ +class acp_contact_info +{ + public function module() + { + return array( + 'filename' => 'acp_contact', + 'title' => 'ACP_CONTACT', + 'version' => '1.0.0', + 'modes' => array( + 'contact' => array('title' => 'ACP_CONTACT_SETTINGS', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')), + ), + ); + } +} diff --git a/phpBB/includes/acp/info/acp_database.php b/phpBB/includes/acp/info/acp_database.php index c8ad65e255..815db53b67 100644 --- a/phpBB/includes/acp/info/acp_database.php +++ b/phpBB/includes/acp/info/acp_database.php @@ -1,15 +1,16 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class acp_database_info { function module() @@ -17,7 +18,6 @@ class acp_database_info return array( 'filename' => 'acp_database', 'title' => 'ACP_DATABASE', - 'version' => '1.0.0', 'modes' => array( 'backup' => array('title' => 'ACP_BACKUP', 'auth' => 'acl_a_backup', 'cat' => array('ACP_CAT_DATABASE')), 'restore' => array('title' => 'ACP_RESTORE', 'auth' => 'acl_a_backup', 'cat' => array('ACP_CAT_DATABASE')), diff --git a/phpBB/includes/acp/info/acp_disallow.php b/phpBB/includes/acp/info/acp_disallow.php index f9dd4c32c0..df4765b6bb 100644 --- a/phpBB/includes/acp/info/acp_disallow.php +++ b/phpBB/includes/acp/info/acp_disallow.php @@ -1,15 +1,16 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class acp_disallow_info { function module() @@ -17,7 +18,6 @@ class acp_disallow_info return array( 'filename' => 'acp_disallow', 'title' => 'ACP_DISALLOW', - 'version' => '1.0.0', 'modes' => array( 'usernames' => array('title' => 'ACP_DISALLOW_USERNAMES', 'auth' => 'acl_a_names', 'cat' => array('ACP_USER_SECURITY')), ), diff --git a/phpBB/includes/acp/info/acp_email.php b/phpBB/includes/acp/info/acp_email.php index 620904c956..e85ef0923a 100644 --- a/phpBB/includes/acp/info/acp_email.php +++ b/phpBB/includes/acp/info/acp_email.php @@ -1,15 +1,16 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class acp_email_info { function module() @@ -17,7 +18,6 @@ class acp_email_info return array( 'filename' => 'acp_email', 'title' => 'ACP_MASS_EMAIL', - 'version' => '1.0.0', 'modes' => array( 'email' => array('title' => 'ACP_MASS_EMAIL', 'auth' => 'acl_a_email && cfg_email_enable', 'cat' => array('ACP_GENERAL_TASKS')), ), diff --git a/phpBB/includes/acp/info/acp_extensions.php b/phpBB/includes/acp/info/acp_extensions.php index 174b365af0..9adcd543b9 100644 --- a/phpBB/includes/acp/info/acp_extensions.php +++ b/phpBB/includes/acp/info/acp_extensions.php @@ -1,15 +1,16 @@ <?php /** * -* @package acp -* @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class acp_extensions_info { function module() @@ -17,7 +18,6 @@ class acp_extensions_info return array( 'filename' => 'acp_extensions', 'title' => 'ACP_EXTENSION_MANAGEMENT', - 'version' => '1.0.0', 'modes' => array( 'main' => array('title' => 'ACP_EXTENSIONS', 'auth' => 'acl_a_extensions', 'cat' => array('ACP_EXTENSION_MANAGEMENT')), ), diff --git a/phpBB/includes/acp/info/acp_forums.php b/phpBB/includes/acp/info/acp_forums.php index e5281a4e58..8b5ce7edc2 100644 --- a/phpBB/includes/acp/info/acp_forums.php +++ b/phpBB/includes/acp/info/acp_forums.php @@ -1,15 +1,16 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class acp_forums_info { function module() @@ -17,7 +18,6 @@ class acp_forums_info return array( 'filename' => 'acp_forums', 'title' => 'ACP_FORUM_MANAGEMENT', - 'version' => '1.0.0', 'modes' => array( 'manage' => array('title' => 'ACP_MANAGE_FORUMS', 'auth' => 'acl_a_forum', 'cat' => array('ACP_MANAGE_FORUMS')), ), diff --git a/phpBB/includes/acp/info/acp_groups.php b/phpBB/includes/acp/info/acp_groups.php index af3f4893fd..e0aafeca0d 100644 --- a/phpBB/includes/acp/info/acp_groups.php +++ b/phpBB/includes/acp/info/acp_groups.php @@ -1,15 +1,16 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class acp_groups_info { function module() @@ -17,7 +18,6 @@ class acp_groups_info return array( 'filename' => 'acp_groups', 'title' => 'ACP_GROUPS_MANAGEMENT', - 'version' => '1.0.0', 'modes' => array( 'manage' => array('title' => 'ACP_GROUPS_MANAGE', 'auth' => 'acl_a_group', 'cat' => array('ACP_GROUPS')), 'position' => array('title' => 'ACP_GROUPS_POSITION', 'auth' => 'acl_a_group', 'cat' => array('ACP_GROUPS')), diff --git a/phpBB/includes/acp/info/acp_icons.php b/phpBB/includes/acp/info/acp_icons.php index e0cf05660c..87eadddd8d 100644 --- a/phpBB/includes/acp/info/acp_icons.php +++ b/phpBB/includes/acp/info/acp_icons.php @@ -1,15 +1,16 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class acp_icons_info { function module() @@ -17,7 +18,6 @@ class acp_icons_info return array( 'filename' => 'acp_icons', 'title' => 'ACP_ICONS_SMILIES', - 'version' => '1.0.0', 'modes' => array( 'icons' => array('title' => 'ACP_ICONS', 'auth' => 'acl_a_icons', 'cat' => array('ACP_MESSAGES')), 'smilies' => array('title' => 'ACP_SMILIES', 'auth' => 'acl_a_icons', 'cat' => array('ACP_MESSAGES')), diff --git a/phpBB/includes/acp/info/acp_inactive.php b/phpBB/includes/acp/info/acp_inactive.php index 02b1fcdaa2..38cb964735 100644 --- a/phpBB/includes/acp/info/acp_inactive.php +++ b/phpBB/includes/acp/info/acp_inactive.php @@ -1,15 +1,16 @@ <?php /** * -* @package acp -* @copyright (c) 2006 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class acp_inactive_info { function module() @@ -17,7 +18,6 @@ class acp_inactive_info return array( 'filename' => 'acp_inactive', 'title' => 'ACP_INACTIVE_USERS', - 'version' => '1.0.0', 'modes' => array( 'list' => array('title' => 'ACP_INACTIVE_USERS', 'auth' => 'acl_a_user', 'cat' => array('ACP_CAT_USERS')), ), diff --git a/phpBB/includes/acp/info/acp_jabber.php b/phpBB/includes/acp/info/acp_jabber.php index 3ad05e1a6a..660299a12d 100644 --- a/phpBB/includes/acp/info/acp_jabber.php +++ b/phpBB/includes/acp/info/acp_jabber.php @@ -1,15 +1,16 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class acp_jabber_info { function module() @@ -17,7 +18,6 @@ class acp_jabber_info return array( 'filename' => 'acp_jabber', 'title' => 'ACP_JABBER_SETTINGS', - 'version' => '1.0.0', 'modes' => array( 'settings' => array('title' => 'ACP_JABBER_SETTINGS', 'auth' => 'acl_a_jabber', 'cat' => array('ACP_CLIENT_COMMUNICATION')), ), diff --git a/phpBB/includes/acp/info/acp_language.php b/phpBB/includes/acp/info/acp_language.php index 7f33a22fa6..1a5a2b6ba8 100644 --- a/phpBB/includes/acp/info/acp_language.php +++ b/phpBB/includes/acp/info/acp_language.php @@ -1,15 +1,16 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class acp_language_info { function module() @@ -17,7 +18,6 @@ class acp_language_info return array( 'filename' => 'acp_language', 'title' => 'ACP_LANGUAGE', - 'version' => '1.0.0', 'modes' => array( 'lang_packs' => array('title' => 'ACP_LANGUAGE_PACKS', 'auth' => 'acl_a_language', 'cat' => array('ACP_LANGUAGE')), ), diff --git a/phpBB/includes/acp/info/acp_logs.php b/phpBB/includes/acp/info/acp_logs.php index 033f9baf50..efa35b2118 100644 --- a/phpBB/includes/acp/info/acp_logs.php +++ b/phpBB/includes/acp/info/acp_logs.php @@ -1,15 +1,16 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class acp_logs_info { function module() @@ -17,7 +18,6 @@ class acp_logs_info return array( 'filename' => 'acp_logs', 'title' => 'ACP_LOGGING', - 'version' => '1.0.0', 'modes' => array( 'admin' => array('title' => 'ACP_ADMIN_LOGS', 'auth' => 'acl_a_viewlogs', 'cat' => array('ACP_FORUM_LOGS')), 'mod' => array('title' => 'ACP_MOD_LOGS', 'auth' => 'acl_a_viewlogs', 'cat' => array('ACP_FORUM_LOGS')), diff --git a/phpBB/includes/acp/info/acp_main.php b/phpBB/includes/acp/info/acp_main.php index 4c1cb6dc0f..48d35da585 100644 --- a/phpBB/includes/acp/info/acp_main.php +++ b/phpBB/includes/acp/info/acp_main.php @@ -1,15 +1,16 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class acp_main_info { function module() @@ -17,7 +18,6 @@ class acp_main_info return array( 'filename' => 'acp_main', 'title' => 'ACP_INDEX', - 'version' => '1.0.0', 'modes' => array( 'main' => array('title' => 'ACP_INDEX', 'auth' => '', 'cat' => array('ACP_CAT_GENERAL')), ), diff --git a/phpBB/includes/acp/info/acp_modules.php b/phpBB/includes/acp/info/acp_modules.php index c9d2cffa72..073e69c6a8 100644 --- a/phpBB/includes/acp/info/acp_modules.php +++ b/phpBB/includes/acp/info/acp_modules.php @@ -1,15 +1,16 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class acp_modules_info { function module() @@ -17,7 +18,6 @@ class acp_modules_info return array( 'filename' => 'acp_modules', 'title' => 'ACP_MODULE_MANAGEMENT', - 'version' => '1.0.0', 'modes' => array( 'acp' => array('title' => 'ACP', 'auth' => 'acl_a_modules', 'cat' => array('ACP_MODULE_MANAGEMENT')), 'ucp' => array('title' => 'UCP', 'auth' => 'acl_a_modules', 'cat' => array('ACP_MODULE_MANAGEMENT')), diff --git a/phpBB/includes/acp/info/acp_permission_roles.php b/phpBB/includes/acp/info/acp_permission_roles.php index ee2a3ee560..34af693b7b 100644 --- a/phpBB/includes/acp/info/acp_permission_roles.php +++ b/phpBB/includes/acp/info/acp_permission_roles.php @@ -1,15 +1,16 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class acp_permission_roles_info { function module() @@ -17,7 +18,6 @@ class acp_permission_roles_info return array( 'filename' => 'acp_permission_roles', 'title' => 'ACP_PERMISSION_ROLES', - 'version' => '1.0.0', 'modes' => array( 'admin_roles' => array('title' => 'ACP_ADMIN_ROLES', 'auth' => 'acl_a_roles && acl_a_aauth', 'cat' => array('ACP_PERMISSION_ROLES')), 'user_roles' => array('title' => 'ACP_USER_ROLES', 'auth' => 'acl_a_roles && acl_a_uauth', 'cat' => array('ACP_PERMISSION_ROLES')), diff --git a/phpBB/includes/acp/info/acp_permissions.php b/phpBB/includes/acp/info/acp_permissions.php index 7b51b67a96..3d415f2b72 100644 --- a/phpBB/includes/acp/info/acp_permissions.php +++ b/phpBB/includes/acp/info/acp_permissions.php @@ -1,15 +1,16 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class acp_permissions_info { function module() @@ -17,7 +18,6 @@ class acp_permissions_info return array( 'filename' => 'acp_permissions', 'title' => 'ACP_PERMISSIONS', - 'version' => '1.0.0', 'modes' => array( 'intro' => array('title' => 'ACP_PERMISSIONS', 'auth' => 'acl_a_authusers || acl_a_authgroups || acl_a_viewauth', 'cat' => array('ACP_CAT_PERMISSIONS')), 'trace' => array('title' => 'ACP_PERMISSION_TRACE', 'auth' => 'acl_a_viewauth', 'display' => false, 'cat' => array('ACP_PERMISSION_MASKS')), diff --git a/phpBB/includes/acp/info/acp_php_info.php b/phpBB/includes/acp/info/acp_php_info.php index a456e4b8b7..c5e60c7e66 100644 --- a/phpBB/includes/acp/info/acp_php_info.php +++ b/phpBB/includes/acp/info/acp_php_info.php @@ -1,15 +1,16 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class acp_php_info_info { function module() @@ -17,7 +18,6 @@ class acp_php_info_info return array( 'filename' => 'acp_php_info', 'title' => 'ACP_PHP_INFO', - 'version' => '1.0.0', 'modes' => array( 'info' => array('title' => 'ACP_PHP_INFO', 'auth' => 'acl_a_phpinfo', 'cat' => array('ACP_GENERAL_TASKS')), ), diff --git a/phpBB/includes/acp/info/acp_profile.php b/phpBB/includes/acp/info/acp_profile.php index 6fa673b094..ede34204b4 100644 --- a/phpBB/includes/acp/info/acp_profile.php +++ b/phpBB/includes/acp/info/acp_profile.php @@ -1,15 +1,16 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class acp_profile_info { function module() @@ -17,7 +18,6 @@ class acp_profile_info return array( 'filename' => 'acp_profile', 'title' => 'ACP_CUSTOM_PROFILE_FIELDS', - 'version' => '1.0.0', 'modes' => array( 'profile' => array('title' => 'ACP_CUSTOM_PROFILE_FIELDS', 'auth' => 'acl_a_profile', 'cat' => array('ACP_CAT_USERS')), ), diff --git a/phpBB/includes/acp/info/acp_prune.php b/phpBB/includes/acp/info/acp_prune.php index 7498e46cad..74e5248aa9 100644 --- a/phpBB/includes/acp/info/acp_prune.php +++ b/phpBB/includes/acp/info/acp_prune.php @@ -1,15 +1,16 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class acp_prune_info { function module() @@ -17,10 +18,9 @@ class acp_prune_info return array( 'filename' => 'acp_prune', 'title' => 'ACP_PRUNING', - 'version' => '1.0.0', 'modes' => array( 'forums' => array('title' => 'ACP_PRUNE_FORUMS', 'auth' => 'acl_a_prune', 'cat' => array('ACP_MANAGE_FORUMS')), - 'users' => array('title' => 'ACP_PRUNE_USERS', 'auth' => 'acl_a_userdel', 'cat' => array('ACP_USER_SECURITY')), + 'users' => array('title' => 'ACP_PRUNE_USERS', 'auth' => 'acl_a_userdel', 'cat' => array('ACP_CAT_USERS')), ), ); } diff --git a/phpBB/includes/acp/info/acp_ranks.php b/phpBB/includes/acp/info/acp_ranks.php index 651a86471d..9bf51eba3c 100644 --- a/phpBB/includes/acp/info/acp_ranks.php +++ b/phpBB/includes/acp/info/acp_ranks.php @@ -1,15 +1,16 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class acp_ranks_info { function module() @@ -17,7 +18,6 @@ class acp_ranks_info return array( 'filename' => 'acp_ranks', 'title' => 'ACP_RANKS', - 'version' => '1.0.0', 'modes' => array( 'ranks' => array('title' => 'ACP_MANAGE_RANKS', 'auth' => 'acl_a_ranks', 'cat' => array('ACP_CAT_USERS')), ), diff --git a/phpBB/includes/acp/info/acp_reasons.php b/phpBB/includes/acp/info/acp_reasons.php index 9f8f2ced77..55a0495d0f 100644 --- a/phpBB/includes/acp/info/acp_reasons.php +++ b/phpBB/includes/acp/info/acp_reasons.php @@ -1,15 +1,16 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class acp_reasons_info { function module() @@ -17,7 +18,6 @@ class acp_reasons_info return array( 'filename' => 'acp_reasons', 'title' => 'ACP_REASONS', - 'version' => '1.0.0', 'modes' => array( 'main' => array('title' => 'ACP_MANAGE_REASONS', 'auth' => 'acl_a_reasons', 'cat' => array('ACP_GENERAL_TASKS')), ), diff --git a/phpBB/includes/acp/info/acp_search.php b/phpBB/includes/acp/info/acp_search.php index 494d8afd67..0635dd9edd 100644 --- a/phpBB/includes/acp/info/acp_search.php +++ b/phpBB/includes/acp/info/acp_search.php @@ -1,15 +1,16 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class acp_search_info { function module() @@ -17,7 +18,6 @@ class acp_search_info return array( 'filename' => 'acp_search', 'title' => 'ACP_SEARCH', - 'version' => '1.0.0', 'modes' => array( 'settings' => array('title' => 'ACP_SEARCH_SETTINGS', 'auth' => 'acl_a_search', 'cat' => array('ACP_SERVER_CONFIGURATION')), 'index' => array('title' => 'ACP_SEARCH_INDEX', 'auth' => 'acl_a_search', 'cat' => array('ACP_CAT_DATABASE')), diff --git a/phpBB/includes/acp/info/acp_send_statistics.php b/phpBB/includes/acp/info/acp_send_statistics.php index 07e7f3ba5c..a0db1a48c4 100644 --- a/phpBB/includes/acp/info/acp_send_statistics.php +++ b/phpBB/includes/acp/info/acp_send_statistics.php @@ -1,15 +1,16 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class acp_send_statistics_info { function module() @@ -17,7 +18,6 @@ class acp_send_statistics_info return array( 'filename' => 'acp_send_statistics', 'title' => 'ACP_SEND_STATISTICS', - 'version' => '1.0.0', 'modes' => array( 'send_statistics' => array('title' => 'ACP_SEND_STATISTICS', 'auth' => 'acl_a_server', 'cat' => array('ACP_SERVER_CONFIGURATION')), ), diff --git a/phpBB/includes/acp/info/acp_styles.php b/phpBB/includes/acp/info/acp_styles.php index 3137c4781b..59b0a64899 100644 --- a/phpBB/includes/acp/info/acp_styles.php +++ b/phpBB/includes/acp/info/acp_styles.php @@ -1,15 +1,16 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class acp_styles_info { function module() @@ -17,11 +18,9 @@ class acp_styles_info return array( 'filename' => 'acp_styles', 'title' => 'ACP_CAT_STYLES', - 'version' => '2.0.0', 'modes' => array( 'style' => array('title' => 'ACP_STYLES', 'auth' => 'acl_a_styles', 'cat' => array('ACP_STYLE_MANAGEMENT')), 'install' => array('title' => 'ACP_STYLES_INSTALL', 'auth' => 'acl_a_styles', 'cat' => array('ACP_STYLE_MANAGEMENT')), - 'cache' => array('title' => 'ACP_STYLES_CACHE', 'auth' => 'acl_a_styles', 'cat' => array('ACP_STYLE_MANAGEMENT')), ), ); } diff --git a/phpBB/includes/acp/info/acp_update.php b/phpBB/includes/acp/info/acp_update.php index 3d491216a8..7806fb4891 100644 --- a/phpBB/includes/acp/info/acp_update.php +++ b/phpBB/includes/acp/info/acp_update.php @@ -1,15 +1,16 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class acp_update_info { function module() @@ -17,7 +18,6 @@ class acp_update_info return array( 'filename' => 'acp_update', 'title' => 'ACP_UPDATE', - 'version' => '1.0.0', 'modes' => array( 'version_check' => array('title' => 'ACP_VERSION_CHECK', 'auth' => 'acl_a_board', 'cat' => array('ACP_AUTOMATION')), ), diff --git a/phpBB/includes/acp/info/acp_users.php b/phpBB/includes/acp/info/acp_users.php index 1848622a1c..cb59d24293 100644 --- a/phpBB/includes/acp/info/acp_users.php +++ b/phpBB/includes/acp/info/acp_users.php @@ -1,15 +1,16 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class acp_users_info { function module() @@ -17,7 +18,6 @@ class acp_users_info return array( 'filename' => 'acp_users', 'title' => 'ACP_USER_MANAGEMENT', - 'version' => '1.0.0', 'modes' => array( 'overview' => array('title' => 'ACP_MANAGE_USERS', 'auth' => 'acl_a_user', 'cat' => array('ACP_CAT_USERS')), 'feedback' => array('title' => 'ACP_USER_FEEDBACK', 'auth' => 'acl_a_user', 'display' => false, 'cat' => array('ACP_CAT_USERS')), diff --git a/phpBB/includes/acp/info/acp_words.php b/phpBB/includes/acp/info/acp_words.php index 48cb3fbdd1..8a6d0d7f20 100644 --- a/phpBB/includes/acp/info/acp_words.php +++ b/phpBB/includes/acp/info/acp_words.php @@ -1,15 +1,16 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class acp_words_info { function module() @@ -17,7 +18,6 @@ class acp_words_info return array( 'filename' => 'acp_words', 'title' => 'ACP_WORDS', - 'version' => '1.0.0', 'modes' => array( 'words' => array('title' => 'ACP_WORDS', 'auth' => 'acl_a_words', 'cat' => array('ACP_MESSAGES')), ), diff --git a/phpBB/includes/bbcode.php b/phpBB/includes/bbcode.php index 683fbf0fd2..eb6133d013 100644 --- a/phpBB/includes/bbcode.php +++ b/phpBB/includes/bbcode.php @@ -1,9 +1,13 @@ <?php /** * -* @package phpBB3 -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -17,7 +21,6 @@ if (!defined('IN_PHPBB')) /** * BBCode class -* @package phpBB3 */ class bbcode { @@ -107,7 +110,18 @@ class bbcode $undid_bbcode_specialchars = true; } - $message = preg_replace($preg['search'], $preg['replace'], $message); + foreach ($preg['search'] as $key => $search) + { + if (is_callable($preg['replace'][$key])) + { + $message = preg_replace_callback($search, $preg['replace'][$key], $message); + } + else + { + $message = preg_replace($search, $preg['replace'][$key], $message); + } + } + $preg = array('search' => array(), 'replace' => array()); } } @@ -126,13 +140,33 @@ class bbcode */ function bbcode_cache_init() { - global $phpbb_root_path, $phpEx, $config, $user, $phpbb_extension_manager, $phpbb_path_helper; + global $user, $phpbb_dispatcher, $phpbb_extension_manager, $phpbb_container, $phpbb_filesystem; if (empty($this->template_filename)) { $this->template_bitfield = new bitfield($user->style['bbcode_bitfield']); - $template = new phpbb\template\twig\twig($phpbb_path_helper, $config, $user, new phpbb\template\context(), $phpbb_extension_manager); + $template = new \phpbb\template\twig\twig( + $phpbb_container->get('path_helper'), + $phpbb_container->get('config'), + new \phpbb\template\context(), + new \phpbb\template\twig\environment( + $phpbb_container->get('config'), + $phpbb_container->get('filesystem'), + $phpbb_container->get('path_helper'), + $phpbb_container, + $phpbb_container->getParameter('core.root_path') . 'cache/', + $phpbb_container->get('ext.manager'), + new \phpbb\template\twig\loader( + $phpbb_filesystem + ) + ), + $phpbb_container->getParameter('core.root_path') . 'cache/', + $phpbb_container->get('user'), + $phpbb_container->get('template.twig.extensions.collection'), + $phpbb_extension_manager + ); + $template->set_style(); $template->set_filenames(array('bbcode.html' => 'bbcode.html')); $this->template_filename = $template->get_source_file_for_handle('bbcode.html'); @@ -179,6 +213,8 @@ class bbcode $db->sql_freeresult($result); } + // To perform custom second pass in extension, use $this->bbcode_second_pass_by_extension() + // method which accepts variable number of parameters foreach ($bbcode_ids as $bbcode_id) { switch ($bbcode_id) @@ -189,7 +225,9 @@ class bbcode '[/quote:$uid]' => $this->bbcode_tpl('quote_close', $bbcode_id) ), 'preg' => array( - '#\[quote(?:="(.*?)")?:$uid\]((?!\[quote(?:=".*?")?:$uid\]).)?#ise' => "\$this->bbcode_second_pass_quote('\$1', '\$2')" + '#\[quote(?:="(.*?)")?:$uid\]((?!\[quote(?:=".*?")?:$uid\]).)?#is' => function ($match) { + return $this->bbcode_second_pass_quote($match[1], $match[2]); + }, ) ); break; @@ -268,7 +306,9 @@ class bbcode case 8: $this->bbcode_cache[$bbcode_id] = array( 'preg' => array( - '#\[code(?:=([a-z]+))?:$uid\](.*?)\[/code:$uid\]#ise' => "\$this->bbcode_second_pass_code('\$1', '\$2')", + '#\[code(?:=([a-z]+))?:$uid\](.*?)\[/code:$uid\]#is' => function ($match) { + return $this->bbcode_second_pass_code($match[1], $match[2]); + }, ) ); break; @@ -278,7 +318,9 @@ class bbcode 'preg' => array( '#(\[\/?(list|\*):[mou]?:?$uid\])[\n]{1}#' => "\$1", '#(\[list=([^\[]+):$uid\])[\n]{1}#' => "\$1", - '#\[list=([^\[]+):$uid\]#e' => "\$this->bbcode_list('\$1')", + '#\[list=([^\[]+):$uid\]#' => function ($match) { + return $this->bbcode_list($match[1]); + }, ), 'str' => array( '[list:$uid]' => $this->bbcode_tpl('ulist_open_default', $bbcode_id), @@ -362,7 +404,9 @@ class bbcode } // Replace {L_*} lang strings - $bbcode_tpl = preg_replace('/{L_([A-Z0-9_]+)}/e', "(!empty(\$user->lang['\$1'])) ? \$user->lang['\$1'] : ucwords(strtolower(str_replace('_', ' ', '\$1')))", $bbcode_tpl); + $bbcode_tpl = preg_replace_callback('/{L_([A-Z0-9_]+)}/', function ($match) use ($user) { + return (!empty($user->lang[$match[1]])) ? $user->lang($match[1]) : ucwords(strtolower(str_replace('_', ' ', $match[1]))); + }, $bbcode_tpl); if (!empty($rowset[$bbcode_id]['second_pass_replace'])) { @@ -385,6 +429,26 @@ class bbcode break; } } + + $bbcode_cache = $this->bbcode_cache; + $bbcode_bitfield = $this->bbcode_bitfield; + $bbcode_uid = $this->bbcode_uid; + + /** + * Use this event to modify the bbcode_cache + * + * @event core.bbcode_cache_init_end + * @var array bbcode_cache The array of cached search and replace patterns of bbcodes + * @var string bbcode_bitfield The bbcode bitfield + * @var string bbcode_uid The bbcode uid + * @since 3.1.3-RC1 + */ + $vars = array('bbcode_cache', 'bbcode_bitfield', 'bbcode_uid'); + extract($phpbb_dispatcher->trigger_event('core.bbcode_cache_init_end', compact($vars))); + + $this->bbcode_cache = $bbcode_cache; + $this->bbcode_bitfield = $bbcode_bitfield; + $this->bbcode_uid = $bbcode_uid; } /** @@ -404,7 +468,7 @@ class bbcode 'i_close' => '</span>', 'u_open' => '<span style="text-decoration: underline">', 'u_close' => '</span>', - 'img' => '<img src="$1" alt="' . $user->lang['IMAGE'] . '" />', + 'img' => '<img src="$1" class="postimage" alt="' . $user->lang['IMAGE'] . '" />', 'size' => '<span style="font-size: $1%; line-height: normal">$2</span>', 'color' => '<span style="color: $1">$2</span>', 'email' => '<a href="mailto:$1">$2</a>' @@ -466,7 +530,9 @@ class bbcode 'email' => array('{EMAIL}' => '$1', '{DESCRIPTION}' => '$2') ); - $tpl = preg_replace('/{L_([A-Z0-9_]+)}/e', "(!empty(\$user->lang['\$1'])) ? \$user->lang['\$1'] : ucwords(strtolower(str_replace('_', ' ', '\$1')))", $tpl); + $tpl = preg_replace_callback('/{L_([A-Z0-9_]+)}/', function ($match) use ($user) { + return (!empty($user->lang[$match[1]])) ? $user->lang($match[1]) : ucwords(strtolower(str_replace('_', ' ', $match[1]))); + }, $tpl); if (!empty($replacements[$tpl_name])) { @@ -590,4 +656,36 @@ class bbcode return $code; } + + /** + * Function to perform custom bbcode second pass by extensions + * can be used to assign bbcode pattern replacement + * Example: '#\[list=([^\[]+):$uid\]#e' => "\$this->bbcode_second_pass_by_extension('\$1')" + * + * Accepts variable number of parameters + * + * @return mixed Second pass result + */ + function bbcode_second_pass_by_extension() + { + global $phpbb_dispatcher; + + $return = false; + $params_array = func_get_args(); + + /** + * Event to perform bbcode second pass with + * the custom validating methods provided by extensions + * + * @event core.bbcode_second_pass_by_extension + * @var array params_array Array with the function parameters + * @var mixed return Second pass result to return + * + * @since 3.1.5-RC1 + */ + $vars = array('params_array', 'return'); + extract($phpbb_dispatcher->trigger_event('core.bbcode_second_pass_by_extension', compact($vars))); + + return $return; + } } diff --git a/phpBB/includes/captcha/captcha_factory.php b/phpBB/includes/captcha/captcha_factory.php deleted file mode 100644 index fac45087e3..0000000000 --- a/phpBB/includes/captcha/captcha_factory.php +++ /dev/null @@ -1,98 +0,0 @@ -<?php -/** -* -* @package VC -* @copyright (c) 2008 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* A small class for 3.0.x (no autoloader in 3.0.x) -* -* @package VC -*/ -class phpbb_captcha_factory -{ - /** - * return an instance of class $name in file $name_plugin.php - */ - static public function get_instance($name) - { - global $phpbb_root_path, $phpEx; - - $name = basename($name); - if (!class_exists($name)) - { - include($phpbb_root_path . "includes/captcha/plugins/{$name}_plugin." . $phpEx); - } - $instance = call_user_func(array($name, 'get_instance')); - return $instance; - } - - /** - * Call the garbage collector - */ - function garbage_collect($name) - { - global $phpbb_root_path, $phpEx; - - $name = basename($name); - if (!class_exists($name)) - { - include($phpbb_root_path . "includes/captcha/plugins/{$name}_plugin." . $phpEx); - } - $captcha = self::get_instance($name); - $captcha->garbage_collect(0); - } - - /** - * return a list of all discovered CAPTCHA plugins - */ - function get_captcha_types() - { - global $phpbb_root_path, $phpEx, $phpbb_extension_manager; - - $captchas = array( - 'available' => array(), - 'unavailable' => array(), - ); - - $finder = $phpbb_extension_manager->get_finder(); - $captcha_plugin_classes = $finder - ->extension_directory('/captcha') - ->suffix('_plugin') - ->core_path('includes/captcha/plugins/') - ->get_classes(); - - foreach ($captcha_plugin_classes as $class) - { - // check if this class needs to be loaded in legacy mode - $old_class = preg_replace('/^phpbb_captcha_plugins_/', '', $class); - if (file_exists($phpbb_root_path . "includes/captcha/plugins/$old_class.$phpEx") && !class_exists($old_class)) - { - include($phpbb_root_path . "includes/captcha/plugins/$old_class.$phpEx"); - $class = preg_replace('/_plugin$/', '', $old_class); - } - - if (call_user_func(array($class, 'is_available'))) - { - $captchas['available'][$class] = call_user_func(array($class, 'get_name')); - } - else - { - $captchas['unavailable'][$class] = call_user_func(array($class, 'get_name')); - } - } - - return $captchas; - } -} diff --git a/phpBB/includes/captcha/captcha_gd.php b/phpBB/includes/captcha/captcha_gd.php deleted file mode 100644 index ab45aa9db6..0000000000 --- a/phpBB/includes/captcha/captcha_gd.php +++ /dev/null @@ -1,2638 +0,0 @@ -<?php -/** -* -* @package VC -* @copyright (c) 2006 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Original Author - Xore (Robert Hetzler) -* With contributions from Neothermic -* -* @package VC -*/ -class captcha -{ - var $width = 360; - var $height = 96; - - /** - * Create the image containing $code with a seed of $seed - */ - function execute($code, $seed) - { - global $config; - - mt_srand($seed); - - // Create image - $img = imagecreatetruecolor($this->width, $this->height); - - // Generate colours - $colour = new colour_manager($img, array( - 'random' => true, - 'min_value' => 60, - ), 'hsv'); - - $scheme = $colour->colour_scheme('background', false); - $scheme = $colour->mono_range($scheme, 10, false); - shuffle($scheme); - - $bg_colours = array_splice($scheme, mt_rand(6, 12)); - - // Generate code characters - $characters = $sizes = $bounding_boxes = $noise = array(); - $width_avail = $this->width - 15; - $code_len = strlen($code); - $captcha_bitmaps = $this->captcha_bitmaps(); - - for ($i = 0; $i < $code_len; ++$i) - { - $characters[$i] = new char_cube3d($captcha_bitmaps, $code[$i]); - - list($min, $max) = $characters[$i]->range(); - $sizes[$i] = mt_rand($min, $max); - - $box = $characters[$i]->dimensions($sizes[$i]); - $width_avail -= ($box[2] - $box[0]); - $bounding_boxes[$i] = $box; - } - - // Redistribute leftover x-space - $offset = array(); - for ($i = 0; $i < $code_len; ++$i) - { - $denom = ($code_len - $i); - $denom = max(1.3, $denom); - $offset[$i] = phpbb_mt_rand(0, (int) round((1.5 * $width_avail) / $denom)); - $width_avail -= $offset[$i]; - } - - if ($config['captcha_gd_x_grid']) - { - $grid = (int) $config['captcha_gd_x_grid']; - for ($y = 0; $y < $this->height; $y += mt_rand($grid - 2, $grid + 2)) - { - $current_colour = $scheme[array_rand($scheme)]; - imageline($img, mt_rand(0,4), mt_rand($y - 3, $y), mt_rand($this->width - 5, $this->width), mt_rand($y - 3, $y), $current_colour); - } - } - - if ($config['captcha_gd_y_grid']) - { - $grid = (int) $config['captcha_gd_y_grid']; - for ($x = 0; $x < $this->width; $x += mt_rand($grid - 2, $grid + 2)) - { - $current_colour = $scheme[array_rand($scheme)]; - imagedashedline($img, mt_rand($x -3, $x + 3), mt_rand(0, 4), mt_rand($x -3, $x + 3), mt_rand($this->height - 5, $this->height), $current_colour); - } - } - - if ($config['captcha_gd_wave'] && ($config['captcha_gd_y_grid'] || $config['captcha_gd_y_grid'])) - { - $this->wave($img); - } - - if ($config['captcha_gd_3d_noise']) - { - $xoffset = mt_rand(0,9); - $noise_bitmaps = $this->captcha_noise_bg_bitmaps(); - for ($i = 0; $i < $code_len; ++$i) - { - $noise[$i] = new char_cube3d($noise_bitmaps, mt_rand(1, sizeof($noise_bitmaps['data']))); - - list($min, $max) = $noise[$i]->range(); - //$box = $noise[$i]->dimensions($sizes[$i]); - } - $xoffset = 0; - for ($i = 0; $i < $code_len; ++$i) - { - $dimm = $bounding_boxes[$i]; - $xoffset += ($offset[$i] - $dimm[0]); - $yoffset = mt_rand(-$dimm[1], $this->height - $dimm[3]); - - $noise[$i]->drawchar($sizes[$i], $xoffset, $yoffset, $img, $colour->get_resource('background'), $scheme); - $xoffset += $dimm[2]; - } - } - - $xoffset = 5; - for ($i = 0; $i < $code_len; ++$i) - { - $dimm = $bounding_boxes[$i]; - $xoffset += ($offset[$i] - $dimm[0]); - $yoffset = mt_rand(-$dimm[1], $this->height - $dimm[3]); - - $characters[$i]->drawchar($sizes[$i], $xoffset, $yoffset, $img, $colour->get_resource('background'), $scheme); - $xoffset += $dimm[2]; - } - - if ($config['captcha_gd_wave']) - { - $this->wave($img); - } - - if ($config['captcha_gd_foreground_noise']) - { - $this->noise_line($img, 0, 0, $this->width, $this->height, $colour->get_resource('background'), $scheme, $bg_colours); - } - - // Send image - header('Content-Type: image/png'); - header('Cache-control: no-cache, no-store'); - imagepng($img); - imagedestroy($img); - } - - /** - * Sinus - */ - function wave($img) - { - global $config; - - $period_x = mt_rand(12,18); - $period_y = mt_rand(7,14); - $amp_x = mt_rand(5,10); - $amp_y = mt_rand(2,4); - $socket = mt_rand(0,100); - - $dampen_x = mt_rand($this->width/5, $this->width/2); - $dampen_y = mt_rand($this->height/5, $this->height/2); - $direction_x = (mt_rand (0, 1)); - $direction_y = (mt_rand (0, 1)); - - for ($i = 0; $i < $this->width; $i++) - { - $dir = ($direction_x) ? $i : ($this->width - $i); - imagecopy($img, $img, $i-1, sin($socket+ $i/($period_x + $dir/$dampen_x)) * $amp_x, $i, 0, 1, $this->height); - } - $socket = mt_rand(0,100); - for ($i = 0; $i < $this->height; $i++) - { - $dir = ($direction_y) ? $i : ($this->height - $i); - imagecopy($img, $img ,sin($socket + $i/($period_y + ($dir)/$dampen_y)) * $amp_y, $i-1, 0, $i, $this->width, 1); - } - return $img; - } - - /** - * Noise line - */ - function noise_line($img, $min_x, $min_y, $max_x, $max_y, $bg, $font, $non_font) - { - imagesetthickness($img, 2); - - $x1 = $min_x; - $x2 = $max_x; - $y1 = $min_y; - $y2 = $min_y; - - do - { - $line = array_merge( - array_fill(0, mt_rand(30, 60), $non_font[array_rand($non_font)]), - array_fill(0, mt_rand(30, 60), $bg) - ); - - imagesetstyle($img, $line); - imageline($img, $x1, $y1, $x2, $y2, IMG_COLOR_STYLED); - - $y1 += mt_rand(12, 35); - $y2 += mt_rand(12, 35); - } - while ($y1 < $max_y && $y2 < $max_y); - - $x1 = $min_x; - $x2 = $min_x; - $y1 = $min_y; - $y2 = $max_y; - - do - { - $line = array_merge( - array_fill(0, mt_rand(30, 60), $non_font[array_rand($non_font)]), - array_fill(0, mt_rand(30, 60), $bg) - ); - - imagesetstyle($img, $line); - imageline($img, $x1, $y1, $x2, $y2, IMG_COLOR_STYLED); - - $x1 += mt_rand(20, 35); - $x2 += mt_rand(20, 35); - } - while ($x1 < $max_x && $x2 < $max_x); - imagesetthickness($img, 1); - } - - function captcha_noise_bg_bitmaps() - { - return array( - 'width' => 15, - 'height' => 5, - 'data' => array( - - 1 => array( - array(1,0,0,0,1,0,0,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,1,0,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,1,0,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,1,0,0,0,0,1,0,0,0), - ), - 2 => array( - array(1,1,mt_rand(0,1),1,0,1,1,1,1,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,1,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0,1,1,0,1,1,1), - ), - 3 => array( - array(1,0,0,0,0,0,0,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,0,0,0,0,0,1,0), - array(0,0,0,0,1,0,0,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,0,0,0,0,0,0,1), - ), - 4 => array( - array(1,0,1,0,1,0,0,1,1,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,1,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), - array(1,0,1,0,0,0,0,0,0,0,0,0,0,0,0), - ), - 5 => array( - array(1,1,1,1,0,0,0,1,1,1,0,0,1,0,1), - array(0,0,0,0,0,0,0,1,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), - array(1,0,1,0,0,0,0,0,0,0,0,0,0,0,0), - ), - 6 => array( - array(mt_rand(0,1),mt_rand(0,1),mt_rand(0,1),mt_rand(0,1),mt_rand(0,1),0,mt_rand(0,1),mt_rand(0,1),mt_rand(0,1),mt_rand(0,1),mt_rand(0,1),0,mt_rand(0,1),mt_rand(0,1),mt_rand(0,1)), - array(0,0,0,0,0,0,0,mt_rand(0,1),0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), - array(mt_rand(0,1),0,mt_rand(0,1),0,0,0,0,0,0,0,0,0,0,0,0), - ), - 7 => array( - array(0,0,0,0,0,0,0,0,0,0,1,1,0,1,1), - array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), - array(0,0,1,1,0,0,0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,1,0,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0), - ), - )); - } - - /** - * Return bitmaps - */ - function captcha_bitmaps() - { - global $config; - - $chars = array( - 'A' => array( - array( - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,1,1,1,1,1,1,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,1,1,0,1,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,1,1,1,1,1,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(1,1,1,0,0,0,1,1,1), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,1,1,1,1,1,0,0), - array(0,1,1,0,0,0,1,1,0), - array(1,1,0,0,0,0,0,1,1), - array(1,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,1,1), - array(0,0,0,0,0,1,1,1,1), - array(0,0,0,1,1,1,0,0,1), - array(0,1,1,1,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,1,0,0,0,0,1,1,1), - array(0,1,1,1,1,1,1,0,1), - ), - ), - 'B' => array( - array( - array(1,1,1,1,1,1,1,0,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,1,0), - array(1,1,1,1,1,1,1,0,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,1,0), - array(1,1,1,1,1,1,1,0,0), - ), - array( - array(1,1,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,1,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(1,1,1,1,1,1,1,0,0), - ), - array( - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,1,1,1,1,1,1,0,0), - ), - ), - 'C' => array( - array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - array( - array(0,0,1,1,1,1,1,0,1), - array(0,1,0,0,0,0,0,1,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,1), - array(0,0,1,1,1,1,1,0,1), - ), - ), - 'D' => array( - array( - array(1,1,1,1,1,1,1,0,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,1,0), - array(1,1,1,1,1,1,1,0,0), - ), - array( - array(1,1,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(1,1,1,1,1,1,1,0,0), - ), - array( - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,1,1,1,1,1,0,1), - array(0,1,1,0,0,0,1,1,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,1,0,0,0,1,1,1), - array(0,0,1,1,1,1,1,0,1), - ), - ), - 'E' => array( - array( - array(1,1,1,1,1,1,1,1,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,1,1,1,1,1,1,1,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,1,1,1,1,1,1,1,1), - ), - array( - array(1,1,1,1,1,1,1,1,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,1,1,1,1,1,1,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,1), - array(1,1,1,1,1,1,1,1,1), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,1,1,1,1,1,0,0), - array(0,1,1,0,0,0,1,1,0), - array(1,1,0,0,0,0,0,1,1), - array(1,1,1,1,1,1,1,1,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,1), - array(1,1,0,0,0,0,0,1,1), - array(0,1,1,1,1,1,1,1,0), - ), - ), - 'F' => array( - array( - array(1,1,1,1,1,1,1,1,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,1,1,1,1,1,1,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - ), - array( - array(0,1,1,1,1,1,1,1,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(1,1,1,0,0,0,0,0,0), - ), - array( - array(0,0,0,1,1,0,0,0,0), - array(0,0,1,1,0,0,0,0,0), - array(0,1,1,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(1,1,1,1,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - ), - ), - 'G' => array( - array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,1,1,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - array( - array(0,0,1,1,1,1,1,0,1), - array(0,1,0,0,0,0,0,1,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,1,1,1,1,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,1), - array(0,0,1,1,1,1,1,0,1), - ), - array( - array(0,0,1,1,1,1,1,0,1), - array(0,1,1,0,0,0,0,1,1), - array(1,1,0,0,0,0,0,1,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,1,1,0,0,0,0,0,1), - array(0,0,1,1,1,1,1,1,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,1,1), - array(1,1,1,1,1,1,1,1,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - ), - ), - 'H' => array( - array( - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,1,1,1,1,1,1,1,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - ), - array( - array(1,1,1,0,0,0,1,1,1), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,1,1,1,1,1,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(1,1,1,0,0,0,1,1,1), - ), - array( - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,1,1,1,0,0,0), - array(1,1,1,1,0,1,1,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,1,0,0), - ), - ), - 'I' => array( - array( - array(1,1,1,1,1,1,1,1,1), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(1,1,1,1,1,1,1,1,1), - ), - array( - array(0,0,0,1,1,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,1,1,1,0,0,0), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,1,1,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,1,1,1,0,0,0), - ), - ), - 'J' => array( - array( - array(1,1,1,1,1,1,1,1,1), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(1,0,0,0,0,1,0,0,0), - array(1,0,0,0,0,1,0,0,0), - array(0,1,0,0,1,0,0,0,0), - array(0,0,1,1,0,0,0,0,0), - ), - array( - array(1,1,1,1,1,1,1,1,1), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(1,0,0,0,0,1,0,0,0), - array(1,0,0,0,0,1,0,0,0), - array(1,1,0,0,1,0,0,0,0), - array(1,0,1,1,0,0,0,0,0), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(1,0,0,0,0,1,0,0,0), - array(1,0,0,0,0,1,0,0,0), - array(0,1,0,0,1,0,0,0,0), - array(0,0,1,1,0,0,0,0,0), - ), - ), - 'K' => array( - array( // New 'K', supplied by NeoThermic - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,1,0,0,0), - array(1,0,0,0,1,0,0,0,0), - array(1,0,0,1,0,0,0,0,0), - array(1,0,1,0,0,0,0,0,0), - array(1,1,0,0,0,0,0,0,0), - array(1,0,1,0,0,0,0,0,0), - array(1,0,0,1,0,0,0,0,0), - array(1,0,0,0,1,0,0,0,0), - array(1,0,0,0,0,1,0,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - ), - array( - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,1,0,0), - array(0,1,0,0,0,1,0,0,0), - array(0,1,0,0,1,0,0,0,0), - array(0,1,0,1,0,0,0,0,0), - array(0,1,1,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,1,0,0,0,0,0,0), - array(0,1,0,1,0,0,0,0,0), - array(0,1,0,0,1,0,0,0,0), - array(0,1,0,0,0,1,0,0,0), - array(0,1,0,0,0,0,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,1,1,0,0,0,1,1,1), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,1,0,0,0), - array(0,1,0,0,1,0,0,0,0), - array(0,1,0,1,0,0,0,0,0), - array(0,1,1,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,1,0,0,0,0,0,0), - array(0,1,0,1,0,0,0,0,0), - array(0,1,0,0,1,0,0,0,0), - array(0,1,0,0,0,1,0,0,0), - array(0,1,0,0,0,0,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - ), - ), - 'L' => array( - array( - array(0,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,1,1,1,1,1,1,1,1), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,1), - array(1,1,1,1,1,1,1,1,1), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,1,0,0,0,0,0,0), - array(0,0,1,1,1,0,0,0,0), - ), - ), - 'M' => array( - array( - array(1,1,0,0,0,0,0,1,1), - array(1,1,0,0,0,0,0,1,1), - array(1,0,1,0,0,0,1,0,1), - array(1,0,1,0,0,0,1,0,1), - array(1,0,1,0,0,0,1,0,1), - array(1,0,0,1,0,1,0,0,1), - array(1,0,0,1,0,1,0,0,1), - array(1,0,0,1,0,1,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,1,0,0,0,1,1,0), - array(0,1,1,0,0,0,1,1,0), - array(0,1,1,0,0,0,1,1,0), - array(0,1,0,1,0,1,0,1,0), - array(0,1,0,1,0,1,0,1,0), - array(0,1,0,1,0,1,0,1,0), - array(0,1,0,0,1,0,0,1,0), - array(0,1,0,0,1,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(1,1,1,0,0,0,1,1,1), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,1,1,1,0,1,1,1,0), - array(1,1,0,1,1,1,0,1,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - ), - ), - 'N' => array( - array( - array(1,1,0,0,0,0,0,0,1), - array(1,1,0,0,0,0,0,0,1), - array(1,0,1,0,0,0,0,0,1), - array(1,0,1,0,0,0,0,0,1), - array(1,0,0,1,0,0,0,0,1), - array(1,0,0,1,0,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,0,1,0,0,1), - array(1,0,0,0,0,1,0,0,1), - array(1,0,0,0,0,0,1,0,1), - array(1,0,0,0,0,0,1,0,1), - array(1,0,0,0,0,0,0,1,1), - array(1,0,0,0,0,0,0,1,1), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,1,0,0,0,0,1,0), - array(0,1,1,0,0,0,0,1,0), - array(0,1,1,0,0,0,0,1,0), - array(0,1,0,1,0,0,0,1,0), - array(0,1,0,1,0,0,0,1,0), - array(0,1,0,1,0,0,0,1,0), - array(0,1,0,0,1,0,0,1,0), - array(0,1,0,0,1,1,0,1,0), - array(0,1,0,0,0,1,0,1,0), - array(0,1,0,0,0,1,1,1,0), - array(0,1,0,0,0,0,1,1,0), - array(0,1,0,0,0,0,0,1,0), - array(1,1,1,0,0,0,1,1,1), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(1,0,1,1,1,1,0,0,0), - array(1,1,1,0,0,1,1,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,1,0,0), - ), - ), - 'O' => array( - array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,1,0,0,0,0,0,1,1), - array(1,1,0,0,0,0,0,1,1), - array(1,1,0,0,0,0,0,1,1), - array(1,1,0,0,0,0,0,1,1), - array(1,1,0,0,0,0,0,1,1), - array(1,1,0,0,0,0,0,1,1), - array(1,1,0,0,0,0,0,1,1), - array(1,1,0,0,0,0,0,1,1), - array(1,1,0,0,0,0,0,1,1), - array(1,1,0,0,0,0,0,1,1), - array(1,1,0,0,0,0,0,1,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,1,1,1,1,1,0,0,0), - array(1,1,1,0,0,1,1,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,1,0,0,0,1,1,0,0), - array(0,1,1,1,1,1,0,0,0), - ), - ), - 'P' => array( - array( - array(1,1,1,1,1,1,1,0,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,1,0), - array(1,1,1,1,1,1,1,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - ), - array( - array(1,1,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(1,1,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(1,1,1,0,0,0,0,0,0), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,1,1,0,0,0,0,0), - array(1,1,0,1,1,0,0,0,0), - array(1,0,0,0,1,0,0,0,0), - array(1,0,0,0,1,0,0,0,0), - array(1,0,0,1,1,0,0,0,0), - array(1,1,1,1,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - ), - ), - 'Q' => array( - array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,1,0,0,1), - array(1,0,0,0,0,0,1,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,1), - ), - array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,1,0,0,1,1,0,1,1), - array(0,1,1,1,1,1,1,1,0), - array(0,0,0,0,0,0,1,1,0), - array(0,0,0,0,0,0,0,1,1), - array(0,0,0,0,0,0,0,0,1), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,1,1,1,1), - array(0,0,0,0,1,1,0,0,1), - array(0,0,0,0,1,0,0,0,1), - array(0,0,0,0,1,0,0,0,1), - array(0,0,0,0,1,1,0,1,1), - array(0,0,0,0,0,1,1,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - ), - ), - 'R' => array( - array( - array(1,1,1,1,1,1,1,0,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,1,0), - array(1,1,1,1,1,1,1,0,0), - array(1,1,1,0,0,0,0,0,0), - array(1,0,0,1,0,0,0,0,0), - array(1,0,0,0,1,0,0,0,0), - array(1,0,0,0,0,1,0,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - ), - array( - array(1,1,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(1,1,1,1,1,1,1,0,0), - array(0,1,1,0,0,0,0,0,0), - array(0,1,1,1,0,0,0,0,0), - array(0,1,0,1,1,0,0,0,0), - array(0,1,0,0,1,1,0,0,0), - array(0,1,0,0,0,1,1,0,0), - array(0,1,0,0,0,0,1,1,0), - array(1,1,1,0,0,0,1,1,1), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,1,1,1,1,0,0,0,0), - array(1,1,0,0,1,1,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - ), - ), - 'S' => array( - array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,0,1,1,1,1,1,0,0), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - array( - array(0,0,1,1,1,1,1,0,1), - array(0,1,0,0,0,0,0,1,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,0,1,1,1,1,1,0,0), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,1,0,0,0,0,0,1,0), - array(1,0,1,1,1,1,1,0,0), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,1,1,1,1,0,0,0,0), - array(1,0,0,0,0,1,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,1,0,0,0,0,0,0,0), - array(0,1,1,1,1,0,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(1,0,0,0,1,1,0,0,0), - array(0,1,1,1,1,0,0,0,0), - ), - ), - 'T' => array( - array( - array(1,1,1,1,1,1,1,1,1), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - ), - array( - array(1,1,1,1,1,1,1,1,1), - array(1,0,0,0,1,0,0,0,1), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,1,1,1,0,0,0), - ), - array( - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,1,1,1,1,1,1,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,1,0,0,0), - array(0,0,0,0,0,1,1,1,0), - ), - ), - 'U' => array( - array( - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - array( - array(1,0,0,0,0,0,0,0,0), - array(1,1,1,0,0,0,1,1,1), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,1,0,0,0,1,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,1,0,0,0,0,0,1), - array(0,0,1,0,0,0,0,0,1), - array(0,0,1,0,0,0,0,0,1), - array(0,0,1,0,0,0,0,0,1), - array(0,0,1,0,0,0,0,0,1), - array(0,0,1,0,0,0,0,1,1), - array(0,0,1,1,0,0,1,1,1), - array(0,0,0,1,1,1,1,0,1), - ), - ), - 'V' => array( - array( - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(1,1,1,0,0,0,1,1,1), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - ), - ), - 'W' => array( - array( - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,1,0,1,0,0,1), - array(1,0,0,1,0,1,0,0,1), - array(1,0,0,1,0,1,0,0,1), - array(1,0,1,0,0,0,1,0,1), - array(1,0,1,0,0,0,1,0,1), - array(1,0,1,0,0,0,1,0,1), - array(1,1,0,0,0,0,0,1,1), - array(1,1,0,0,0,0,0,1,1), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(1,1,1,0,0,0,1,1,1), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,1,0,0,1,0), - array(0,1,0,0,1,0,0,1,0), - array(0,1,0,1,1,1,0,1,0), - array(0,1,0,1,0,1,0,1,0), - array(0,1,1,1,0,1,1,1,0), - array(0,1,1,0,0,0,1,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,0,0), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,1,0,0,1,0), - array(0,1,0,0,1,0,0,1,0), - array(0,1,0,1,1,1,0,1,0), - array(0,1,0,1,0,1,0,1,0), - array(0,1,1,1,0,1,1,1,0), - array(0,1,1,0,0,0,1,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,0,0), - ), - ), - 'X' => array( - array( - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,1,0,0,0,0,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(1,1,1,0,0,0,1,1,1), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,1,0,0,0,0,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,1,1,0,0,0,1,1,1), - array(0,0,0,0,0,0,0,0,0), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,1,0,0,0,1,1,0), - array(0,0,1,1,0,1,1,0,0), - array(0,0,0,1,1,1,0,0,0), - array(0,0,0,1,1,1,0,0,0), - array(0,0,1,1,0,1,1,0,0), - array(0,1,1,0,0,0,1,1,0), - array(0,0,0,0,0,0,0,0,0), - ), - ), - 'Y' => array( - array( - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(1,1,1,0,0,0,1,1,1), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,1,1,1,0,0,0), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,1,0,0,0,0,1), - array(0,0,0,1,1,0,0,0,1), - array(0,0,0,0,1,0,0,1,1), - array(0,0,0,0,1,1,0,1,0), - array(0,0,0,0,0,1,1,1,0), - array(0,0,0,0,0,0,1,0,0), - array(0,0,0,0,0,1,1,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,1,1,0,0,0), - array(0,0,1,1,1,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - ), - ), - 'Z' => array( - array( - array(1,1,1,1,1,1,1,1,1), - array(1,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,1,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,1,0,0,0,0,0), - array(0,0,0,1,0,0,0,0,0), - array(0,0,1,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,1), - array(1,1,1,1,1,1,1,1,1), - ), - array( - array(1,1,1,1,1,1,1,1,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,1,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,1,1,1,1,1,0,0), - array(0,0,0,1,0,0,0,0,0), - array(0,0,0,1,0,0,0,0,0), - array(0,0,1,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,1,1,1,1,1,1,1,1), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,1,1,1,1,1,1,1,0), - array(0,0,0,0,0,1,1,0,0), - array(0,0,0,0,1,1,0,0,0), - array(0,0,0,1,1,0,0,0,0), - array(0,0,1,1,0,0,0,0,0), - array(0,0,1,0,0,0,0,0,0), - array(0,1,1,1,1,1,1,1,0), - ), - ), - ); - return array( - 'width' => 9, - 'height' => 15, - 'data' => array( - - 'A' => $chars['A'][mt_rand(0, min(sizeof($chars['A']), $config['captcha_gd_fonts']) -1)], - 'B' => $chars['B'][mt_rand(0, min(sizeof($chars['B']), $config['captcha_gd_fonts']) -1)], - 'C' => $chars['C'][mt_rand(0, min(sizeof($chars['C']), $config['captcha_gd_fonts']) -1)], - 'D' => $chars['D'][mt_rand(0, min(sizeof($chars['D']), $config['captcha_gd_fonts']) -1)], - 'E' => $chars['E'][mt_rand(0, min(sizeof($chars['E']), $config['captcha_gd_fonts']) -1)], - 'F' => $chars['F'][mt_rand(0, min(sizeof($chars['F']), $config['captcha_gd_fonts']) -1)], - 'G' => $chars['G'][mt_rand(0, min(sizeof($chars['G']), $config['captcha_gd_fonts']) -1)], - 'H' => $chars['H'][mt_rand(0, min(sizeof($chars['H']), $config['captcha_gd_fonts']) -1)], - 'I' => $chars['I'][mt_rand(0, min(sizeof($chars['I']), $config['captcha_gd_fonts']) -1)], - 'J' => $chars['J'][mt_rand(0, min(sizeof($chars['J']), $config['captcha_gd_fonts']) -1)], - 'K' => $chars['K'][mt_rand(0, min(sizeof($chars['K']), $config['captcha_gd_fonts']) -1)], - 'L' => $chars['L'][mt_rand(0, min(sizeof($chars['L']), $config['captcha_gd_fonts']) -1)], - 'M' => $chars['M'][mt_rand(0, min(sizeof($chars['M']), $config['captcha_gd_fonts']) -1)], - 'N' => $chars['N'][mt_rand(0, min(sizeof($chars['N']), $config['captcha_gd_fonts']) -1)], - 'O' => $chars['O'][mt_rand(0, min(sizeof($chars['O']), $config['captcha_gd_fonts']) -1)], - 'P' => $chars['P'][mt_rand(0, min(sizeof($chars['P']), $config['captcha_gd_fonts']) -1)], - 'Q' => $chars['Q'][mt_rand(0, min(sizeof($chars['Q']), $config['captcha_gd_fonts']) -1)], - 'R' => $chars['R'][mt_rand(0, min(sizeof($chars['R']), $config['captcha_gd_fonts']) -1)], - 'S' => $chars['S'][mt_rand(0, min(sizeof($chars['S']), $config['captcha_gd_fonts']) -1)], - 'T' => $chars['T'][mt_rand(0, min(sizeof($chars['T']), $config['captcha_gd_fonts']) -1)], - 'U' => $chars['U'][mt_rand(0, min(sizeof($chars['U']), $config['captcha_gd_fonts']) -1)], - 'V' => $chars['V'][mt_rand(0, min(sizeof($chars['V']), $config['captcha_gd_fonts']) -1)], - 'W' => $chars['W'][mt_rand(0, min(sizeof($chars['W']), $config['captcha_gd_fonts']) -1)], - 'X' => $chars['X'][mt_rand(0, min(sizeof($chars['X']), $config['captcha_gd_fonts']) -1)], - 'Y' => $chars['Y'][mt_rand(0, min(sizeof($chars['Y']), $config['captcha_gd_fonts']) -1)], - 'Z' => $chars['Z'][mt_rand(0, min(sizeof($chars['Z']), $config['captcha_gd_fonts']) -1)], - - '1' => array( - array(0,0,0,1,1,0,0,0,0), - array(0,0,1,0,1,0,0,0,0), - array(0,1,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,1,1,1,1,1,1,1,0), - ), - '2' => array( // New '2' supplied by Anon - array(0,0,0,1,1,1,0,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,1,0,0,0,0,1,1,0), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,1,1), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,1,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,1,0,0,0,0,0), - array(0,0,1,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(1,1,1,1,1,1,1,1,1), - array(0,0,0,0,0,0,0,0,0), - ), - '3' => array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,1,1,0,0), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - '4' => array( - array(0,0,0,0,0,0,1,1,0), - array(0,0,0,0,0,1,0,1,0), - array(0,0,0,0,1,0,0,1,0), - array(0,0,0,1,0,0,0,1,0), - array(0,0,1,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,1,0), - array(1,1,1,1,1,1,1,1,1), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,1,0), - ), - '5' => array( - array(1,1,1,1,1,1,1,1,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,0,1,1,1,1,1,0,0), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - '6' => array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,1,1,1,1,0,0), - array(1,0,1,0,0,0,0,1,0), - array(1,1,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - '7' => array( - array(1,1,1,1,1,1,1,1,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,1,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,1,0,0,0,0,0), - array(0,0,0,1,0,0,0,0,0), - array(0,0,1,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - ), - '8' => array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - '9' => array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,1,1), - array(0,1,0,0,0,0,1,0,1), - array(0,0,1,1,1,1,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - ) - ); - } -} - -/** -* @package VC -*/ -class char_cube3d -{ - var $bitmap; - var $bitmap_width; - var $bitmap_height; - - var $basis_matrix = array(array(1, 0, 0), array(0, 1, 0), array(0, 0, 1)); - var $abs_x = array(1, 0); - var $abs_y = array(0, 1); - var $x = 0; - var $y = 1; - var $z = 2; - var $letter = ''; - - /** - */ - function char_cube3d(&$bitmaps, $letter) - { - $this->bitmap = $bitmaps['data'][$letter]; - $this->bitmap_width = $bitmaps['width']; - $this->bitmap_height = $bitmaps['height']; - - $this->basis_matrix[0][0] = mt_rand(-600, 600); - $this->basis_matrix[0][1] = mt_rand(-600, 600); - $this->basis_matrix[0][2] = (mt_rand(0, 1) * 2000) - 1000; - $this->basis_matrix[1][0] = mt_rand(-1000, 1000); - $this->basis_matrix[1][1] = mt_rand(-1000, 1000); - $this->basis_matrix[1][2] = mt_rand(-1000, 1000); - - $this->normalize($this->basis_matrix[0]); - $this->normalize($this->basis_matrix[1]); - $this->basis_matrix[2] = $this->cross_product($this->basis_matrix[0], $this->basis_matrix[1]); - $this->normalize($this->basis_matrix[2]); - - // $this->basis_matrix[1] might not be (probably isn't) orthogonal to $basis_matrix[0] - $this->basis_matrix[1] = $this->cross_product($this->basis_matrix[0], $this->basis_matrix[2]); - $this->normalize($this->basis_matrix[1]); - - // Make sure our cube is facing into the canvas (assuming +z == in) - for ($i = 0; $i < 3; ++$i) - { - if ($this->basis_matrix[$i][2] < 0) - { - $this->basis_matrix[$i][0] *= -1; - $this->basis_matrix[$i][1] *= -1; - $this->basis_matrix[$i][2] *= -1; - } - } - - // Force our "z" basis vector to be the one with greatest absolute z value - $this->x = 0; - $this->y = 1; - $this->z = 2; - - // Swap "y" with "z" - if ($this->basis_matrix[1][2] > $this->basis_matrix[2][2]) - { - $this->z = 1; - $this->y = 2; - } - - // Swap "x" with "z" - if ($this->basis_matrix[0][2] > $this->basis_matrix[$this->z][2]) - { - $this->x = $this->z; - $this->z = 0; - } - - // Still need to determine which of $x,$y are which. - // wrong orientation if y's y-component is less than it's x-component - // likewise if x's x-component is less than it's y-component - // if they disagree, go with the one with the greater weight difference. - // rotate if positive - $weight = (abs($this->basis_matrix[$this->x][1]) - abs($this->basis_matrix[$this->x][0])) + (abs($this->basis_matrix[$this->y][0]) - abs($this->basis_matrix[$this->y][1])); - - // Swap "x" with "y" - if ($weight > 0) - { - list($this->x, $this->y) = array($this->y, $this->x); - } - - $this->abs_x = array($this->basis_matrix[$this->x][0], $this->basis_matrix[$this->x][1]); - $this->abs_y = array($this->basis_matrix[$this->y][0], $this->basis_matrix[$this->y][1]); - - if ($this->abs_x[0] < 0) - { - $this->abs_x[0] *= -1; - $this->abs_x[1] *= -1; - } - - if ($this->abs_y[1] > 0) - { - $this->abs_y[0] *= -1; - $this->abs_y[1] *= -1; - } - - $this->letter = $letter; - } - - /** - * Draw a character - */ - function drawchar($scale, $xoff, $yoff, $img, $background, $colours) - { - $width = $this->bitmap_width; - $height = $this->bitmap_height; - $bitmap = $this->bitmap; - - $colour1 = $colours[array_rand($colours)]; - $colour2 = $colours[array_rand($colours)]; - - $swapx = ($this->basis_matrix[$this->x][0] > 0); - $swapy = ($this->basis_matrix[$this->y][1] < 0); - - for ($y = 0; $y < $height; ++$y) - { - for ($x = 0; $x < $width; ++$x) - { - $xp = ($swapx) ? ($width - $x - 1) : $x; - $yp = ($swapy) ? ($height - $y - 1) : $y; - - if ($bitmap[$height - $yp - 1][$xp]) - { - $dx = $this->scale($this->abs_x, ($xp - ($swapx ? ($width / 2) : ($width / 2) - 1)) * $scale); - $dy = $this->scale($this->abs_y, ($yp - ($swapy ? ($height / 2) : ($height / 2) - 1)) * $scale); - $xo = $xoff + $dx[0] + $dy[0]; - $yo = $yoff + $dx[1] + $dy[1]; - - $origin = array(0, 0, 0); - $xvec = $this->scale($this->basis_matrix[$this->x], $scale); - $yvec = $this->scale($this->basis_matrix[$this->y], $scale); - $face_corner = $this->sum2($xvec, $yvec); - - $zvec = $this->scale($this->basis_matrix[$this->z], $scale); - $x_corner = $this->sum2($xvec, $zvec); - $y_corner = $this->sum2($yvec, $zvec); - - imagefilledpolygon($img, $this->gen_poly($xo, $yo, $origin, $xvec, $x_corner,$zvec), 4, $colour1); - imagefilledpolygon($img, $this->gen_poly($xo, $yo, $origin, $yvec, $y_corner,$zvec), 4, $colour2); - - $face = $this->gen_poly($xo, $yo, $origin, $xvec, $face_corner, $yvec); - - imagefilledpolygon($img, $face, 4, $background); - imagepolygon($img, $face, 4, $colour1); - } - } - } - } - - /* - * return a roughly acceptable range of sizes for rendering with this texttype - */ - function range() - { - return array(3, 4); - } - - /** - * Vector length - */ - function vectorlen($vector) - { - return sqrt(pow($vector[0], 2) + pow($vector[1], 2) + pow($vector[2], 2)); - } - - /** - * Normalize - */ - function normalize(&$vector, $length = 1) - { - $length = (( $length < 1) ? 1 : $length); - $length /= $this->vectorlen($vector); - $vector[0] *= $length; - $vector[1] *= $length; - $vector[2] *= $length; - } - - /** - */ - function cross_product($vector1, $vector2) - { - $retval = array(0, 0, 0); - $retval[0] = (($vector1[1] * $vector2[2]) - ($vector1[2] * $vector2[1])); - $retval[1] = -(($vector1[0] * $vector2[2]) - ($vector1[2] * $vector2[0])); - $retval[2] = (($vector1[0] * $vector2[1]) - ($vector1[1] * $vector2[0])); - - return $retval; - } - - /** - */ - function sum($vector1, $vector2) - { - return array($vector1[0] + $vector2[0], $vector1[1] + $vector2[1], $vector1[2] + $vector2[2]); - } - - /** - */ - function sum2($vector1, $vector2) - { - return array($vector1[0] + $vector2[0], $vector1[1] + $vector2[1]); - } - - /** - */ - function scale($vector, $length) - { - if (sizeof($vector) == 2) - { - return array($vector[0] * $length, $vector[1] * $length); - } - - return array($vector[0] * $length, $vector[1] * $length, $vector[2] * $length); - } - - /** - */ - function gen_poly($xoff, $yoff, &$vec1, &$vec2, &$vec3, &$vec4) - { - $poly = array(); - $poly[0] = $xoff + $vec1[0]; - $poly[1] = $yoff + $vec1[1]; - $poly[2] = $xoff + $vec2[0]; - $poly[3] = $yoff + $vec2[1]; - $poly[4] = $xoff + $vec3[0]; - $poly[5] = $yoff + $vec3[1]; - $poly[6] = $xoff + $vec4[0]; - $poly[7] = $yoff + $vec4[1]; - - return $poly; - } - - /** - * dimensions - */ - function dimensions($size) - { - $xn = $this->scale($this->basis_matrix[$this->x], -($this->bitmap_width / 2) * $size); - $xp = $this->scale($this->basis_matrix[$this->x], ($this->bitmap_width / 2) * $size); - $yn = $this->scale($this->basis_matrix[$this->y], -($this->bitmap_height / 2) * $size); - $yp = $this->scale($this->basis_matrix[$this->y], ($this->bitmap_height / 2) * $size); - - $p = array(); - $p[0] = $this->sum2($xn, $yn); - $p[1] = $this->sum2($xp, $yn); - $p[2] = $this->sum2($xp, $yp); - $p[3] = $this->sum2($xn, $yp); - - $min_x = $max_x = $p[0][0]; - $min_y = $max_y = $p[0][1]; - - for ($i = 1; $i < 4; ++$i) - { - $min_x = ($min_x > $p[$i][0]) ? $p[$i][0] : $min_x; - $min_y = ($min_y > $p[$i][1]) ? $p[$i][1] : $min_y; - $max_x = ($max_x < $p[$i][0]) ? $p[$i][0] : $max_x; - $max_y = ($max_y < $p[$i][1]) ? $p[$i][1] : $max_y; - } - - return array($min_x, $min_y, $max_x, $max_y); - } -} - -/** -* @package VC -*/ -class colour_manager -{ - var $img; - var $mode; - var $colours; - var $named_colours; - - /** - * Create the colour manager, link it to the image resource - */ - function colour_manager($img, $background = false, $mode = 'ahsv') - { - $this->img = $img; - $this->mode = $mode; - $this->colours = array(); - $this->named_colours = array(); - - if ($background !== false) - { - $bg = $this->allocate_named('background', $background); - imagefill($this->img, 0, 0, $bg); - } - } - - /** - * Lookup a named colour resource - */ - function get_resource($named_colour) - { - if (isset($this->named_colours[$named_colour])) - { - return $this->named_colours[$named_colour]; - } - - if (isset($this->named_rgb[$named_colour])) - { - return $this->allocate_named($named_colour, $this->named_rgb[$named_colour], 'rgb'); - } - - return false; - } - - /** - * Assign a name to a colour resource - */ - function name_colour($name, $resource) - { - $this->named_colours[$name] = $resource; - } - - /** - * names and allocates a colour resource - */ - function allocate_named($name, $colour, $mode = false) - { - $resource = $this->allocate($colour, $mode); - - if ($resource !== false) - { - $this->name_colour($name, $resource); - } - return $resource; - } - - /** - * allocates a specified colour into the image - */ - function allocate($colour, $mode = false) - { - if ($mode === false) - { - $mode = $this->mode; - } - - if (!is_array($colour)) - { - if (isset($this->named_rgb[$colour])) - { - return $this->allocate_named($colour, $this->named_rgb[$colour], 'rgb'); - } - - if (!is_int($colour)) - { - return false; - } - - $mode = 'rgb'; - $colour = array(255 & ($colour >> 16), 255 & ($colour >> 8), 255 & $colour); - } - - if (isset($colour['mode'])) - { - $mode = $colour['mode']; - unset($colour['mode']); - } - - if (isset($colour['random'])) - { - unset($colour['random']); - // everything else is params - return $this->random_colour($colour, $mode); - } - - $rgb = colour_manager::model_convert($colour, $mode, 'rgb'); - $store = ($this->mode == 'rgb') ? $rgb : colour_manager::model_convert($colour, $mode, $this->mode); - $resource = imagecolorallocate($this->img, $rgb[0], $rgb[1], $rgb[2]); - $this->colours[$resource] = $store; - - return $resource; - } - - /** - * randomly generates a colour, with optional params - */ - function random_colour($params = array(), $mode = false) - { - if ($mode === false) - { - $mode = $this->mode; - } - - switch ($mode) - { - case 'rgb': - // @TODO random rgb generation. do we intend to do this, or is it just too tedious? - break; - - case 'ahsv': - case 'hsv': - default: - - $default_params = array( - 'hue_bias' => false, // degree / 'r'/'g'/'b'/'c'/'m'/'y' /'o' - 'hue_range' => false, // if hue bias, then difference range +/- from bias - 'min_saturation' => 30, // 0 - 100 - 'max_saturation' => 80, // 0 - 100 - 'min_value' => 30, // 0 - 100 - 'max_value' => 80, // 0 - 100 - ); - - $alt = ($mode == 'ahsv') ? true : false; - $params = array_merge($default_params, $params); - - $min_hue = 0; - $max_hue = 359; - $min_saturation = max(0, $params['min_saturation']); - $max_saturation = min(100, $params['max_saturation']); - $min_value = max(0, $params['min_value']); - $max_value = min(100, $params['max_value']); - - if ($params['hue_bias'] !== false) - { - if (is_numeric($params['hue_bias'])) - { - $h = intval($params['hue_bias']) % 360; - } - else - { - switch ($params['hue_bias']) - { - case 'o': - $h = $alt ? 60 : 30; - break; - - case 'y': - $h = $alt ? 120 : 60; - break; - - case 'g': - $h = $alt ? 180 : 120; - break; - - case 'c': - $h = $alt ? 210 : 180; - break; - - case 'b': - $h = 240; - break; - - case 'm': - $h = 300; - break; - - case 'r': - default: - $h = 0; - break; - } - } - - $min_hue = $h + 360; - $max_hue = $h + 360; - - if ($params['hue_range']) - { - $min_hue -= min(180, $params['hue_range']); - $max_hue += min(180, $params['hue_range']); - } - } - - $h = mt_rand($min_hue, $max_hue); - $s = mt_rand($min_saturation, $max_saturation); - $v = mt_rand($min_value, $max_value); - - return $this->allocate(array($h, $s, $v), $mode); - - break; - } - } - - /** - */ - function colour_scheme($resource, $include_original = true) - { - $mode = 'hsv'; - - if (($pre = $this->get_resource($resource)) !== false) - { - $resource = $pre; - } - - $colour = colour_manager::model_convert($this->colours[$resource], $this->mode, $mode); - $results = ($include_original) ? array($resource) : array(); - $colour2 = $colour3 = $colour4 = $colour; - $colour2[0] += 150; - $colour3[0] += 180; - $colour4[0] += 210; - - - $results[] = $this->allocate($colour2, $mode); - $results[] = $this->allocate($colour3, $mode); - $results[] = $this->allocate($colour4, $mode); - - return $results; - } - - /** - */ - function mono_range($resource, $count = 5, $include_original = true) - { - if (is_array($resource)) - { - $results = array(); - for ($i = 0, $size = sizeof($resource); $i < $size; ++$i) - { - $results = array_merge($results, $this->mono_range($resource[$i], $count, $include_original)); - } - return $results; - } - - $mode = (in_array($this->mode, array('hsv', 'ahsv'), true) ? $this->mode : 'ahsv'); - if (($pre = $this->get_resource($resource)) !== false) - { - $resource = $pre; - } - - $colour = colour_manager::model_convert($this->colours[$resource], $this->mode, $mode); - - $results = array(); - if ($include_original) - { - $results[] = $resource; - $count--; - } - - // This is a hard problem. I chicken out and try to maintain readability at the cost of less randomness. - - while ($count > 0) - { - $colour[1] = ($colour[1] + mt_rand(40,60)) % 99; - $colour[2] = ($colour[2] + mt_rand(40,60)); - $results[] = $this->allocate($colour, $mode); - $count--; - } - return $results; - } - - /** - * Convert from one colour model to another - */ - function model_convert($colour, $from_model, $to_model) - { - if ($from_model == $to_model) - { - return $colour; - } - - switch ($to_model) - { - case 'hsv': - - switch ($from_model) - { - case 'ahsv': - return colour_manager::ah2h($colour); - break; - - case 'rgb': - return colour_manager::rgb2hsv($colour); - break; - } - break; - - case 'ahsv': - - switch ($from_model) - { - case 'hsv': - return colour_manager::h2ah($colour); - break; - - case 'rgb': - return colour_manager::h2ah(colour_manager::rgb2hsv($colour)); - break; - } - break; - - case 'rgb': - switch ($from_model) - { - case 'hsv': - return colour_manager::hsv2rgb($colour); - break; - - case 'ahsv': - return colour_manager::hsv2rgb(colour_manager::ah2h($colour)); - break; - } - break; - } - return false; - } - - /** - * Slightly altered from wikipedia's algorithm - */ - function hsv2rgb($hsv) - { - colour_manager::normalize_hue($hsv[0]); - - $h = $hsv[0]; - $s = min(1, max(0, $hsv[1] / 100)); - $v = min(1, max(0, $hsv[2] / 100)); - - // calculate hue sector - $hi = floor($hsv[0] / 60); - - // calculate opposite colour - $p = $v * (1 - $s); - - // calculate distance between hex vertices - $f = ($h / 60) - $hi; - - // coming in or going out? - if (!($hi & 1)) - { - $f = 1 - $f; - } - - // calculate adjacent colour - $q = $v * (1 - ($f * $s)); - - switch ($hi) - { - case 0: - $rgb = array($v, $q, $p); - break; - - case 1: - $rgb = array($q, $v, $p); - break; - - case 2: - $rgb = array($p, $v, $q); - break; - - case 3: - $rgb = array($p, $q, $v); - break; - - case 4: - $rgb = array($q, $p, $v); - break; - - case 5: - $rgb = array($v, $p, $q); - break; - - default: - return array(0, 0, 0); - break; - } - - return array(255 * $rgb[0], 255 * $rgb[1], 255 * $rgb[2]); - } - - /** - * (more than) Slightly altered from wikipedia's algorithm - */ - function rgb2hsv($rgb) - { - $r = min(255, max(0, $rgb[0])); - $g = min(255, max(0, $rgb[1])); - $b = min(255, max(0, $rgb[2])); - $max = max($r, $g, $b); - $min = min($r, $g, $b); - - $v = $max / 255; - $s = (!$max) ? 0 : 1 - ($min / $max); - - // if max - min is 0, we want hue to be 0 anyway. - $h = $max - $min; - - if ($h) - { - switch ($max) - { - case $g: - $h = 120 + (60 * ($b - $r) / $h); - break; - - case $b: - $h = 240 + (60 * ($r - $g) / $h); - break; - - case $r: - $h = 360 + (60 * ($g - $b) / $h); - break; - } - } - colour_manager::normalize_hue($h); - - return array($h, $s * 100, $v * 100); - } - - /** - */ - function normalize_hue(&$hue) - { - $hue %= 360; - - if ($hue < 0) - { - $hue += 360; - } - } - - /** - * Alternate hue to hue - */ - function ah2h($ahue) - { - if (is_array($ahue)) - { - $ahue[0] = colour_manager::ah2h($ahue[0]); - return $ahue; - } - colour_manager::normalize_hue($ahue); - - // blue through red is already ok - if ($ahue >= 240) - { - return $ahue; - } - - // ahue green is at 180 - if ($ahue >= 180) - { - // return (240 - (2 * (240 - $ahue))); - return (2 * $ahue) - 240; // equivalent - } - - // ahue yellow is at 120 (RYB rather than RGB) - if ($ahue >= 120) - { - return $ahue - 60; - } - - return $ahue / 2; - } - - /** - * hue to Alternate hue - */ - function h2ah($hue) - { - if (is_array($hue)) - { - $hue[0] = colour_manager::h2ah($hue[0]); - return $hue; - } - colour_manager::normalize_hue($hue); - - // blue through red is already ok - if ($hue >= 240) - { - return $hue; - } - else if ($hue <= 60) - { - return $hue * 2; - } - else if ($hue <= 120) - { - return $hue + 60; - } - else - { - return ($hue + 240) / 2; - } - } -} diff --git a/phpBB/includes/captcha/captcha_gd_wave.php b/phpBB/includes/captcha/captcha_gd_wave.php deleted file mode 100644 index 185352dd4e..0000000000 --- a/phpBB/includes/captcha/captcha_gd_wave.php +++ /dev/null @@ -1,842 +0,0 @@ -<?php -/** -* -* @package VC -* @copyright (c) 2006 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 -* -*/ - -/** -* Wave3D CAPTCHA -* -* @author Robert Hetzler -* @package VC -*/ -class captcha -{ - var $width = 360; - var $height = 96; - - function execute($code, $seed) - { - global $starttime; - - // seed the random generator - mt_srand($seed); - - // set height and width - $img_x = $this->width; - $img_y = $this->height; - - // Generate image - $img = imagecreatetruecolor($img_x, $img_y); - $x_grid = mt_rand(6, 10); - $y_grid = mt_rand(6, 10); - - // Ok, so lets cut to the chase. We could accurately represent this in 3d and - // do all the appropriate linear transforms. my questions is... why bother? - // The computational overhead is unnecessary when you consider the simple fact: - // we're not here to accurately represent a model, but to just show off some random-ish - // polygons - - // Conceive of 3 spaces. - // 1) planar-space (discrete "pixel" grid) - // 2) 3-space. (planar-space with z/height aspect) - // 3) image space (pixels on the screen) - // resolution of the planar-space we're embedding the text code in - $plane_x = 100; - $plane_y = 30; - - $subdivision_factor = 3; - - // $box is the 4 points in img_space that correspond to the corners of the plane in 3-space - $box = array( - 'upper_left' => array( - 'x' => mt_rand(5, 15), - 'y' => mt_rand(10, 15) - ), - 'upper_right' => array( - 'x' => mt_rand($img_x - 35, $img_x - 19), - 'y' => mt_rand(10, 17) - ), - 'lower_left' => array( - 'x' => mt_rand($img_x - 45, $img_x - 5), - 'y' => mt_rand($img_y - 15, $img_y - 0), - ), - ); - - $box['lower_right'] = array( - 'x' => $box['lower_left']['x'] + $box['upper_left']['x'] - $box['upper_right']['x'], - 'y' => $box['lower_left']['y'] + $box['upper_left']['y'] - $box['upper_right']['y'], - ); - - // TODO - $background = imagecolorallocate($img, mt_rand(155, 255), mt_rand(155, 255), mt_rand(155, 255)); - imagefill($img, 0, 0, $background); - $black = imagecolorallocate($img, 0, 0, 0); - - $random = array(); - $fontcolors = array(); - - for ($i = 0; $i < 15; ++$i) - { - $random[$i] = imagecolorallocate($img, mt_rand(120, 255), mt_rand(120, 255), mt_rand(120, 255)); - } - - $fontcolors[0] = imagecolorallocate($img, mt_rand(0, 120), mt_rand(0, 120), mt_rand(0, 120)); - - $colors = array(); - - $minr = mt_rand(20, 30); - $ming = mt_rand(20, 30); - $minb = mt_rand(20, 30); - - $maxr = mt_rand(150, 230); - $maxg = mt_rand(150, 230); - $maxb = mt_rand(150, 230); - - for ($i = -30; $i <= 30; ++$i) - { - $coeff1 = ($i + 12) / 45; - $coeff2 = 1 - $coeff1; - $colors[$i] = imagecolorallocate($img, ($coeff2 * $maxr) + ($coeff1 * $minr), ($coeff2 * $maxg) + ($coeff1 * $ming), ($coeff2 * $maxb) + ($coeff1 * $minb)); - } - - // $img_buffer is the last row of 3-space positions (converted to img-space), cached - // (using this means we don't need to recalculate all 4 positions for each new polygon, - // merely the newest point that we're adding, which is then cached. - $img_buffer = array(array(), array()); - - // In image-space, the x- and y-offset necessary to move one unit in the x-direction in planar-space - $dxx = ($box['upper_right']['x'] - $box['upper_left']['x']) / ($subdivision_factor * $plane_x); - $dxy = ($box['upper_right']['y'] - $box['upper_left']['y']) / ($subdivision_factor * $plane_x); - - // In image-space, the x- and y-offset necessary to move one unit in the y-direction in planar-space - $dyx = ($box['lower_right']['x'] - $box['upper_left']['x']) / ($subdivision_factor * $plane_y); - $dyy = ($box['lower_right']['y'] - $box['upper_left']['y']) / ($subdivision_factor * $plane_y); - - // Initial captcha-letter offset in planar-space - $plane_offset_x = mt_rand(3, 8); - $plane_offset_y = mt_rand( 12, 15); - - // character map - $map = $this->captcha_bitmaps(); - - // matrix - $plane = array(); - - // for each character, we'll silkscreen it into our boolean pixel plane - for ($c = 0, $code_num = strlen($code); $c < $code_num; ++$c) - { - $letter = $code[$c]; - - for ($x = $map['width'] - 1; $x >= 0; --$x) - { - for ($y = $map['height'] - 1; $y >= 0; --$y) - { - if ($map['data'][$letter][$y][$x]) - { - $plane[$y + $plane_offset_y + (($c & 1) ? 1 : -1)][$x + $plane_offset_x] = true; - } - } - } - $plane_offset_x += 11; - } - - // calculate our first buffer, we can't actually draw polys with these yet - // img_pos_prev == screen x,y location to our immediate left. - // img_pos_cur == current screen x,y location - // we calculate screen position of our - // current cell based on the difference from the previous cell - // rather than recalculating from absolute coordinates - // What we cache into the $img_buffer contains the raised text coordinates. - $img_pos_prev = $img_buffer[0][0] = array($box['upper_left']['x'], $box['upper_left']['y']); - $cur_height = $prev_height = $this->wave_height(0, 0, $subdivision_factor); - $full_x = $plane_x * $subdivision_factor; - $full_y = $plane_y * $subdivision_factor; - - for ($x = 1; $x <= $full_x; ++$x) - { - $cur_height = $this->wave_height($x, 0, $subdivision_factor); - $offset = $cur_height - $prev_height; - $img_pos_cur = array($img_pos_prev[0] + $dxx, $img_pos_prev[1] + $dxy + $offset); - - $img_buffer[0][$x] = $img_pos_cur; - $img_pos_prev = $img_pos_cur; - $prev_height = $cur_height; - } - - for ($y = 1; $y <= $full_y; ++$y) - { - // swap buffers - $buffer_cur = $y & 1; - $buffer_prev = 1 - $buffer_cur; - - $prev_height = $this->wave_height(0, $y, $subdivision_factor); - $offset = $prev_height - $this->wave_height(0, $y - 1, $subdivision_factor); - $img_pos_cur = array($img_buffer[$buffer_prev][0][0] + $dyx, min($img_buffer[$buffer_prev][0][1] + $dyy + $offset, $img_y - 1)); - - // make sure we don't try to write off the page - $img_pos_prev = $img_pos_cur; - - $img_buffer[$buffer_cur][0] = $img_pos_cur; - - for ($x = 1; $x <= $full_x; ++$x) - { - $cur_height = $this->wave_height($x, $y, $subdivision_factor) + $this->grid_height($x, $y, $x_grid, $y_grid, 1); - - // height is a z-factor, not a y-factor - $offset = $cur_height - $prev_height; - $img_pos_cur = array($img_pos_prev[0] + $dxx, $img_pos_prev[1] + $dxy + $offset); - - // height is float, index it to an int, get closest color - $color = $colors[intval($cur_height)]; - $img_pos_prev = $img_pos_cur; - $prev_height = $cur_height; - - $y_index_old = intval(($y - 1) / $subdivision_factor); - $y_index_new = intval($y / $subdivision_factor); - $x_index_old = intval(($x - 1) / $subdivision_factor); - $x_index_new = intval($x / $subdivision_factor); - - if (!empty($plane[$y_index_new][$x_index_new])) - { - $img_pos_cur[1] += $this->wave_height($x, $y, $subdivision_factor, 1) - 30 - $cur_height; - $color = $colors[20]; - } - $img_pos_cur[1] = min($img_pos_cur[1], $img_y - 1); - $img_buffer[$buffer_cur][$x] = $img_pos_cur; - - // Smooth the edges as much as possible by having not more than one low<->high traingle per square - // Otherwise, just - $diag_down = (empty($plane[$y_index_old][$x_index_old]) == empty($plane[$y_index_new][$x_index_new])); - $diag_up = (empty($plane[$y_index_old][$x_index_new]) == empty($plane[$y_index_new][$x_index_old])); - - // natural switching - $mode = ($x + $y) & 1; - - // override if it requires it - if ($diag_down != $diag_up) - { - $mode = $diag_up; - } - - if ($mode) - { - // +-/ / - // 1 |/ 2 /| - // / /-+ - $poly1 = array_merge($img_buffer[$buffer_cur][$x - 1], $img_buffer[$buffer_prev][$x - 1], $img_buffer[$buffer_prev][$x]); - $poly2 = array_merge($img_buffer[$buffer_cur][$x - 1], $img_buffer[$buffer_cur][$x], $img_buffer[$buffer_prev][$x]); - } - else - { - // \ \-+ - // 1 |\ 2 \| - // +-\ \ - $poly1 = array_merge($img_buffer[$buffer_cur][$x - 1], $img_buffer[$buffer_prev][$x - 1], $img_buffer[$buffer_cur][$x]); - $poly2 = array_merge($img_buffer[$buffer_prev][$x - 1], $img_buffer[$buffer_prev][$x], $img_buffer[$buffer_cur][$x]); - } - - imagefilledpolygon($img, $poly1, 3, $color); - imagefilledpolygon($img, $poly2, 3, $color); - } - } - - // Output image - header('Content-Type: image/png'); - header('Cache-control: no-cache, no-store'); - //$mtime = explode(' ', microtime()); - //$totaltime = $mtime[0] + $mtime[1] - $starttime; - - //echo $totaltime . "<br />\n"; - //echo memory_get_usage() - $tmp; - imagepng($img); - imagedestroy($img); - } - - function wave_height($x, $y, $factor = 1, $tweak = 0.7) - { - // stretch the wave. TODO: pretty it up - $x = $x/5 + 180; - $y = $y/4; - return ((sin($x / (3 * $factor)) + sin($y / (3 * $factor))) * 10 * $tweak); - } - - function grid_height($x, $y, $x_grid, $y_grid, $factor = 1) - { - return ((!($x % ($x_grid * $factor)) || !($y % ($y_grid * $factor))) ? 3 : 0); - } - - function captcha_bitmaps() - { - return array( - 'width' => 9, - 'height' => 13, - 'data' => array( - 'A' => array( - array(0,0,1,1,1,1,0,0,0), - array(0,1,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,1,0), - array(1,1,1,1,1,1,1,1,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,0,0), - ), - 'B' => array( - array(1,1,1,1,1,1,0,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,1,0,0), - array(1,1,1,1,1,1,0,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,1,0,0), - array(1,1,1,1,1,1,0,0,0), - array(0,0,0,0,0,0,0,0,0), - ), - 'C' => array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - ), - 'D' => array( - array(1,1,1,1,1,1,1,0,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,1,0), - array(1,1,1,1,1,1,1,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - ), - 'E' => array( - array(0,0,1,1,1,1,1,1,1), - array(0,1,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,1,1,1,1,1,1,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,0,1,1,1,1,1,1,1), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - ), - 'F' => array( - array(0,0,1,1,1,1,1,1,0), - array(0,1,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,1,1,1,1,1,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - ), - 'G' => array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,1,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - ), - 'H' => array( - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,1,1,1,1,1,1,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,1,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - ), - 'I' => array( - array(0,1,1,1,1,1,1,1,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,1,1,1,1,1,1,1,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - ), - 'J' => array( - array(0,0,0,0,0,0,1,1,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,0,1,0,0,0,0,1,0), - array(0,0,0,1,1,1,1,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - ), - 'K' => array( - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,1,0,0,0), - array(1,0,0,0,1,0,0,0,0), - array(1,0,0,1,0,0,0,0,0), - array(1,0,1,0,0,0,0,0,0), - array(1,1,0,0,0,0,0,0,0), - array(1,0,1,0,0,0,0,0,0), - array(1,0,0,1,0,0,0,0,0), - array(1,0,0,0,1,0,0,0,0), - array(1,0,0,0,0,1,0,0,0), - array(1,0,0,0,0,0,1,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - ), - 'L' => array( - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,0,1,1,1,1,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - ), - 'M' => array( - array(0,1,0,0,0,0,0,1,0), - array(0,1,1,0,0,0,1,1,0), - array(0,1,0,1,0,1,0,1,0), - array(0,1,0,0,1,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - ), - 'N' => array( - array(1,0,0,0,0,0,0,0,1), - array(1,1,0,0,0,0,0,0,1), - array(1,0,1,0,0,0,0,0,1), - array(1,0,0,1,0,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,0,1,0,0,1), - array(1,0,0,0,0,0,1,0,1), - array(1,0,0,0,0,0,0,1,1), - array(1,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - ), - 'O' => array( - array(0,0,0,1,1,1,0,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,0,1,1,1,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - ), - 'P' => array( - array(1,1,1,1,1,1,0,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,1,0,0), - array(1,1,1,1,1,1,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - ), - 'Q' => array( - array(0,0,1,1,1,1,0,0,0), - array(0,1,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,1,0,0,1,0), - array(1,0,0,0,0,1,0,1,0), - array(0,1,0,0,0,0,1,0,0), - array(0,0,1,1,1,1,0,1,0), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - ), - 'R' => array( - array(1,1,1,1,1,1,0,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,1,0,0), - array(1,1,1,1,1,1,0,0,0), - array(1,0,1,0,0,0,0,0,0), - array(1,0,0,1,0,0,0,0,0), - array(1,0,0,0,1,0,0,0,0), - array(1,0,0,0,0,1,0,0,0), - array(1,0,0,0,0,0,1,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - ), - 'S' => array( - array(0,0,1,1,1,1,1,1,1), - array(0,1,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,0,1,1,1,1,1,0,0), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,1,0), - array(1,1,1,1,1,1,1,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - ), - 'T' => array( - array(1,1,1,1,1,1,1,1,1), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - ), - 'U' => array( - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - ), - 'V' => array( - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - ), - 'W' => array( - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,1,0,1,0,0,1), - array(1,0,1,0,0,0,1,0,1), - array(1,1,0,0,0,0,0,1,1), - array(1,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - ), - 'X' => array( - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - ), - 'Y' => array( - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - ), - 'Z' => array( - array(1,1,1,1,1,1,1,1,1), - array(1,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,1,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,1,0,0,0,0,0), - array(0,0,1,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,1), - array(1,1,1,1,1,1,1,1,1), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - ), - '1' => array( - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,1,1,0,0,0,0), - array(0,0,1,0,1,0,0,0,0), - array(0,1,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,1,1,1,1,1,1,1,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - ), - '2' => array( - array(0,0,0,1,1,1,0,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,1,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,1,0,0,0,0,0), - array(0,0,1,0,0,0,0,0,0), - array(0,1,1,1,1,1,1,1,1), - array(0,0,0,0,0,0,0,0,0), - ), - '3' => array( - array(0,0,0,1,1,1,1,0,0), - array(0,0,1,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,1,1,0,0), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,0,1,0,0,0,0,1,0), - array(0,0,0,1,1,1,1,0,0), - array(0,0,0,0,0,0,0,0,0), - ), - '4' => array( - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,1,1,0), - array(0,0,0,0,0,1,0,1,0), - array(0,0,0,0,1,0,0,1,0), - array(0,0,0,1,0,0,0,1,0), - array(0,0,1,0,0,0,0,1,0), - array(0,1,1,1,1,1,1,1,1), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - ), - '5' => array( - array(1,1,1,1,1,1,1,1,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,0,1,1,1,1,1,0,0), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - ), - '6' => array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,1,1,1,1,0,0), - array(1,0,1,0,0,0,0,1,0), - array(1,1,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - ), - '7' => array( - array(1,1,1,1,1,1,1,1,1), - array(1,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,1,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - ), - '8' => array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - array(0,0,0,0,0,0,0,0,0), - ), - '9' => array( - array(0,0,0,1,1,1,1,0,0), - array(0,0,1,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,1), - array(0,0,1,1,1,1,1,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,0,1,0,0,0,0,1,0), - array(0,0,0,1,1,1,1,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - ), - ) - ); - } -} diff --git a/phpBB/includes/captcha/captcha_non_gd.php b/phpBB/includes/captcha/captcha_non_gd.php deleted file mode 100644 index bb5067cafa..0000000000 --- a/phpBB/includes/captcha/captcha_non_gd.php +++ /dev/null @@ -1,389 +0,0 @@ -<?php -/** -* -* @package VC -* @copyright (c) 2006 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Main non-gd captcha class -* @ignore -* @package VC -*/ -class captcha -{ - var $filtered_pngs; - var $width = 320; - var $height = 50; - - /** - * Define filtered pngs on init - */ - function captcha() - { - // If we can we will generate a single filtered png, we avoid nastiness via emulation of some Zlib stuff - $this->define_filtered_pngs(); - } - - /** - * Create the image containing $code with a seed of $seed - */ - function execute($code, $seed) - { - $img_height = $this->height - 10; - $img_width = 0; - - mt_srand($seed); - - $char_widths = $hold_chars = array(); - $code_len = strlen($code); - - for ($i = 0; $i < $code_len; $i++) - { - $char = $code[$i]; - - $width = mt_rand(0, 4); - $raw_width = $this->filtered_pngs[$char]['width']; - $char_widths[$i] = $width; - $img_width += $raw_width - $width; - - // Split the char into chunks of $raw_width + 1 length - if (empty($hold_chars[$char])) - { - $hold_chars[$char] = str_split(base64_decode($this->filtered_pngs[$char]['data']), $raw_width + 1); - } - } - - $offset_x = mt_rand(0, $this->width - $img_width); - $offset_y = mt_rand(0, $this->height - $img_height); - - $image = ''; - for ($i = 0; $i < $this->height; $i++) - { - $image .= chr(0); - - if ($i > $offset_y && $i < $offset_y + $img_height) - { - for ($j = 0; $j < $offset_x; $j++) - { - $image .= chr(mt_rand(140, 255)); - } - - for ($j = 0; $j < $code_len; $j++) - { - $image .= $this->randomise(substr($hold_chars[$code{$j}][$i - $offset_y - 1], 1), $char_widths[$j]); - } - - for ($j = $offset_x + $img_width; $j < $this->width; $j++) - { - $image .= chr(mt_rand(140, 255)); - } - } - else - { - for ($j = 0; $j < $this->width; $j++) - { - $image .= chr(mt_rand(140, 255)); - } - } - } - unset($hold_chars); - - $image = $this->create_png($image, $this->width, $this->height); - - // Output image - header('Content-Type: image/png'); - header('Cache-control: no-cache, no-store'); - echo $image; - exit; - } - - /** - * This is designed to randomise the pixels of the image data within - * certain limits so as to keep it readable. It also varies the image - * width a little - */ - function randomise($scanline, $width) - { - $new_line = ''; - - $end = strlen($scanline) - ceil($width/2); - for ($i = (int) floor($width / 2); $i < $end; $i++) - { - $pixel = ord($scanline{$i}); - - if ($pixel < 190) - { - $new_line .= chr(mt_rand(0, 205)); - } - else if ($pixel > 190) - { - $new_line .= chr(mt_rand(145, 255)); - } - else - { - $new_line .= $scanline{$i}; - } - } - - return $new_line; - } - - /** - * This creates a chunk of the given type, with the given data - * of the given length adding the relevant crc - */ - function png_chunk($length, $type, $data) - { - $raw = $type . $data; - - return pack('N', $length) . $raw . pack('N', crc32($raw)); - } - - /** - * Creates greyscale 8bit png - The PNG spec can be found at - * http://www.libpng.org/pub/png/spec/PNG-Contents.html we use - * png because it's a fully recognised open standard and supported - * by practically all modern browsers and OSs - */ - function create_png($raw_image, $width, $height) - { - // SIG - $image = pack('C8', 137, 80, 78, 71, 13, 10, 26, 10); - - // IHDR - $raw = pack('N2', $width, $height); - $raw .= pack('C5', 8, 0, 0, 0, 0); - $image .= $this->png_chunk(13, 'IHDR', $raw); - - // IDAT - if (@extension_loaded('zlib')) - { - $raw_image = gzcompress($raw_image); - $length = strlen($raw_image); - } - else - { - // The total length of this image, uncompressed, is just a calculation of pixels - $length = ($width + 1) * $height; - - // Adler-32 hash generation - // Note: The hash is _backwards_ so we must reverse it - - if (@extension_loaded('hash')) - { - $adler_hash = strrev(hash('adler32', $raw_image, true)); - } - else if (@extension_loaded('mhash')) - { - $adler_hash = strrev(mhash(MHASH_ADLER32, $raw_image)); - } - else - { - // Optimized Adler-32 loop ported from the GNU Classpath project - $temp_length = $length; - $s1 = 1; - $s2 = $index = 0; - - while ($temp_length > 0) - { - // We can defer the modulo operation: - // s1 maximally grows from 65521 to 65521 + 255 * 3800 - // s2 maximally grows by 3800 * median(s1) = 2090079800 < 2^31 - $substract_value = ($temp_length < 3800) ? $temp_length : 3800; - $temp_length -= $substract_value; - - while (--$substract_value >= 0) - { - $s1 += ord($raw_image[$index]); - $s2 += $s1; - - $index++; - } - - $s1 %= 65521; - $s2 %= 65521; - } - $adler_hash = pack('N', ($s2 << 16) | $s1); - } - - // This is the same thing as gzcompress($raw_image, 0) but does not need zlib - $raw_image = pack('C3v2', 0x78, 0x01, 0x01, $length, ~$length) . $raw_image . $adler_hash; - - // The Zlib header + Adler hash make us add on 11 - $length += 11; - } - - // IDAT - $image .= $this->png_chunk($length, 'IDAT', $raw_image); - - // IEND - $image .= $this->png_chunk(0, 'IEND', ''); - - return $image; - } - - /** - * png image data - * Each 'data' element is base64_encoded uncompressed IDAT - */ - function define_filtered_pngs() - { - $this->filtered_pngs = array( - '0' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A///////////////////olFAkBAAAGDyA4P///M31/////////////wD////////////////0dAgAAAAAAAAAAAAEcPipFGHn////////////AP//////////////6DAAAAAAAAAAAAAAAAAALSEAN+T///////////8A//////////////xAAAAAAAAAAAAAAAAAAAAAACPA/////////////wD/////////////oAAAAAAAAAAAAAAAAAAAAAAAev//////////////AP////////////8oAAAAAAAAPNj/zDAAAAAAAABD//////////////8A////////////1AAAAAAAABjw////5BAAAAAAAADo/////////////wD///////////+QAAAAAAAAbP//////QgAAAAAAAKj/////////////AP///////////1wAAAAAAACs/////8AXAAAAAAAAcP////////////8A////////////OAAAAAAAAND////dNwAAAAAAAABI/////////////wD///////////8gAAAAAAAA4P//7koACwAAAAAAACT/////////////AP///////////wgAAAAAAAD///VqAwaPAAAAAAAAEP////////////8A////////////AAAAAAAAAP/8kQYDavUAAAAAAAAA/////////////wD///////////8AAAAAAAAA/6kNAEru/wAAAAAAAAD/////////////AP///////////wAAAAAAAADAIwA33f//AAAAAAAAAP////////////8A////////////FAAAAAAAADYAI8D///8AAAAAAAAQ/////////////wD///////////8kAAAAAAAAAA2p////5AAAAAAAACD/////////////AP///////////0gAAAAAAAAFkfz////UAAAAAAAAQP////////////8A////////////cAAAAAAAAET1/////7AAAAAAAABo/////////////wD///////////+oAAAAAAAAXfX/////sAAAAAAAAGj/////////////AAAAALgAAAAAAAAwAAAAAAAAAAAAAAD////////////oAAAAAAAACOT////oEAAAAAAAAOD/////////////AP////////////8+AAAAAAAAKMz/zDQAAAAAAAA0//////////////8A////////////7jgAAAAAAAAAAAAAAAAAAAAAAKT//////////////wD///////////VqAwIAAAAAAAAAAAAAAAAAAAA8////////////////AP//////////rQcDaVEAAAAAAAAAAAAAAAAAKOj///////////////8A///////////nblnu/IAIAAAAAAAAAAAAAFzw/////////////////wD////////////79////+iITCAAAAAgSITg////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////w==', - 'width' => 40 - ), - '1' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////8BAAAAAAAP//////////////////AP////////////////////////9sAAAAAAAA//////////////////8A////////////////////////pAAAAAAAAAD//////////////////wD//////////////////////6wEAAAAAAAAAP//////////////////AP////////////////////h4AAAAAAAAAAAA//////////////////8A//////////////////ygJAAAAAAAAAAAAAD//////////////////wD//////////////9x8HAAAAAAAAAAAAAAAAP//////////////////AP//////////////AAAAAAAAAAAAAAAAAAAA//////////////////8A//////////////8AAAAAAAAAAAAAAAAAAAD//////////////////wD//////////////wAAAAAAAAR4AAAAAAAAAP//////////////////AP//////////////AAAAAAA4zP8AAAAAAAAA//////////////////8A//////////////8AAAA4sP///wAAAAAAAAD//////////////////wD//////////////yR80P//////AAAAAAAAAP//////////////////AP////////////////////////8AAAAAAAAA//////////////////8A/////////////////////////wAAAAAAAAD//////////////////wD/////////////////////////AAAAAAAAAP//////////////////AP////////////////////////8AAAAAAAAA//////////////////8A/////////////////////////wAAAAAAAAD//////////////////wD/////////////////////////AAAAAAAAAP//////////////////AP////////////////////////8AAAAAAAAA//////////////////8A/////////////////////////wAAAAAAAAD//////////////////wD/////////////////////////AAAAAAAAAP//////////////////AP////////////////////////8AAAAAAAAA//////////////////8A/////////////////////////wAAAAAAAAD//////////////////wD/////////////////////////AAAAAAAAAP//////////////////AP////////////////////////8AAAAAAAAA//////////////////8A/////////////////////////wAAAAAAAAD//////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - '2' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP/////////////////okFAkCAAABCBIfNT///////////////////8A///////////////8hAgAAAAAAAAAAAAAAFTo/////////////////wD//////////////1QAAAAAAAAAAAAAAAAAACjo////////////////AP////////////+MAAAAAAAAAAAAAAAAAAAAADj///////////////8A////////////9BAAAAAAAAAAAAAAAAAAAAAAALD//////////////wD///////////+gAAAAAAAAAHjs+KwMAAAAAAAAVP//////////////AP///////////1gAAAAAAABM/////6QAAAAAAAAU//////////////8A////////////KAAAAAAAALj/////+AAAAAAAAAD//////////////wD///////////+MfGBMOCAI8P/////wAAAAAAAACP//////////////AP///////////////////////////5wAAAAAAAAw//////////////8A///////////////////////////oFAAAAAAAAHz//////////////wD/////////////////////////6CgAAAAAAAAE3P//////////////AP///////////////////////9ggAAAAAAAAAHT///////////////8A//////////////////////+0DAAAAAAAAAA8+P///////////////wD/////////////////////gAAAAAAAAAAAKOj/////////////////AP//////////////////9FAAAAAAAAAAADzw//////////////////8A/////////////////+g4AAAAAAAAAABk/P///////////////////wD////////////////oKAAAAAAAAAAMqP//////////////////////AP//////////////6CgAAAAAAAAAMNz///////////////////////8A//////////////g4AAAAAAAAAFT0/////////////////////////wD/////////////bAAAAAAAAABU/P//////////////////////////AP///////////8wAAAAAAAAAAAAAAAAAAAAAAAAA//////////////8A////////////SAAAAAAAAAAAAAAAAAAAAAAAAAD//////////////wD//////////9wAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////////AP//////////hAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////////8A//////////9AAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////////wD//////////xAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - '3' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD////////////////8sGg0FAAAACA4cLz8////////////////////AP//////////////rBgAAAAAAAAAAAAAACTA//////////////////8A/////////////3QAAAAAAAAAAAAAAAAAAASs/////////////////wD///////////+YAAAAAAAAAAAAAAAAAAAAAAjc////////////////AP//////////6AwAAAAAAAAAAAAAAAAAAAAAAGT///////////////8A//////////94AAAAAAAABJDw/8g4AAAAAAAAHP///////////////wD//////////yAAAAAAAACE/////9gAAAAAAAAA////////////////AP///////////NSwiGQ4FOT//////AAAAAAAABD///////////////8A//////////////////////////+YAAAAAAAAVP///////////////wD//////////////////////P/ggAQAAAAAAATM////////////////AP////////////////////9gAAAAAAAAAAAElP////////////////8A/////////////////////0AAAAAAAAAAHLj//////////////////wD/////////////////////OAAAAAAAAAAwkPj/////////////////AP////////////////////8gAAAAAAAAAAAAINj///////////////8A/////////////////////xAAAAAAAAAAAAAAIPD//////////////wD/////////////////////uOz/4HgEAAAAAAAAhP//////////////AP///////////////////////////3wAAAAAAAAw//////////////8A////////////////////////////6AAAAAAAAAj//////////////wD/////////////////////////////AAAAAAAAAP//////////////AP//////////tJh8YEQoDNz//////+AAAAAAAAAY//////////////8A//////////88AAAAAAAAaP//////dAAAAAAAAEz//////////////wD//////////6QAAAAAAAAAdOD/5HQAAAAAAAAApP//////////////AP///////////CgAAAAAAAAAAAAAAAAAAAAAACD4//////////////8A////////////yAQAAAAAAAAAAAAAAAAAAAAEuP///////////////wD/////////////rAQAAAAAAAAAAAAAAAAABJD/////////////////AP//////////////zDQAAAAAAAAAAAAAACTA//////////////////8A/////////////////8BwOCAAAAAUNGi0/P///////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - '4' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP//////////////////////////nAAAAAAAAAD///////////////8A/////////////////////////8AEAAAAAAAAAP///////////////wD////////////////////////gGAAAAAAAAAAA////////////////AP//////////////////////9DAAAAAAAAAAAAD///////////////8A//////////////////////9UAAAAAAAAAAAAAP///////////////wD/////////////////////hAAAAAAAAAAAAAAA////////////////AP///////////////////7QAAAAAAAAAAAAAAAD///////////////8A///////////////////UDAAAAAAUAAAAAAAAAP///////////////wD/////////////////7CQAAAAABMAAAAAAAAAA////////////////AP////////////////xEAAAAAACU/wAAAAAAAAD///////////////8A////////////////cAAAAAAAZP//AAAAAAAAAP///////////////wD//////////////6AAAAAAADz8//8AAAAAAAAA////////////////AP/////////////IBAAAAAAc6P///wAAAAAAAAD///////////////8A////////////5BgAAAAADMz/////AAAAAAAAAP///////////////wD///////////g0AAAAAACk//////8AAAAAAAAA////////////////AP//////////XAAAAAAAfP///////wAAAAAAAAD///////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////////8A////////////////////////////AAAAAAAAAP///////////////wD///////////////////////////8AAAAAAAAA////////////////AP///////////////////////////wAAAAAAAAD///////////////8A////////////////////////////AAAAAAAAAP///////////////wD///////////////////////////8AAAAAAAAA////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - '5' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP//////////////8AAAAAAAAAAAAAAAAAAAAAAA//////////////8A///////////////MAAAAAAAAAAAAAAAAAAAAAAD//////////////wD//////////////6wAAAAAAAAAAAAAAAAAAAAAAP//////////////AP//////////////iAAAAAAAAAAAAAAAAAAAAAAA//////////////8A//////////////9kAAAAAAAAAAAAAAAAAAAAAAD//////////////wD//////////////0QAAAAAAAAAAAAAAAAAAAAAAP//////////////AP//////////////IAAAAAAAYP////////////////////////////8A//////////////wAAAAAAAB8/////////////////////////////wD/////////////3AAAAAAAAIj/////////////////////////////AP////////////+4AAAAAAAAoLRYHAAEKGTE//////////////////8A/////////////5QAAAAAAAAQAAAAAAAAAABY9P///////////////wD/////////////dAAAAAAAAAAAAAAAAAAAAAA89P//////////////AP////////////9QAAAAAAAAAAAAAAAAAAAAAABg//////////////8A/////////////zAAAAAAAAAAAAAAAAAAAAAAAADQ/////////////wD/////////////IAAAAAAAAGjY/+h4BAAAAAAAAGz/////////////AP//////////////9NS0lHSc//////90AAAAAAAALP////////////8A/////////////////////////////9QAAAAAAAAE/////////////wD//////////////////////////////wAAAAAAAAD/////////////AP/////////////////////////////8AAAAAAAAEP////////////8A////////////pIRwWEAgDOD//////8wAAAAAAAA8/////////////wD///////////9EAAAAAAAAaP//////ZAAAAAAAAHz/////////////AP///////////6QAAAAAAAAAaOD/4GQAAAAAAAAE4P////////////8A/////////////CQAAAAAAAAAAAAAAAAAAAAAAGD//////////////wD/////////////yAQAAAAAAAAAAAAAAAAAAAAc7P//////////////AP//////////////rAwAAAAAAAAAAAAAAAAAGNj///////////////8A////////////////0EAAAAAAAAAAAAAAAFTo/////////////////wD//////////////////8h4QCAAAAAcQHzU////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - '6' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD///////////////////+0ZCwMAAAUNGjI////////////////////AP/////////////////EMAAAAAAAAAAAAABM6P////////////////8A////////////////lAQAAAAAAAAAAAAAAAAo6P///////////////wD//////////////6wAAAAAAAAAAAAAAAAAAABI////////////////AP/////////////oEAAAAAAAAAAAAAAAAAAAAACw//////////////8A/////////////3AAAAAAAAAoxP/YPAAAAAAAAEj//////////////wD////////////4EAAAAAAACOD////YDCBAVGiAoP//////////////AP///////////7gAAAAAAABY//////////////////////////////8A////////////eAAAAAAAAJT//////////////////////////////wD///////////9MAAAAAAAAvP/IXBgABCx03P//////////////////AP///////////ygAAAAAAADcdAAAAAAAAAAEiP////////////////8A////////////FAAAAAAAAFAAAAAAAAAAAAAAcP///////////////wD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAlP//////////////AP///////////wAAAAAAAAAAAAAAAAAAAAAAAAAQ8P////////////8A////////////AAAAAAAAAABAyP/kZAAAAAAAAACQ/////////////wD///////////8MAAAAAAAALPj/////WAAAAAAAAET/////////////AP///////////yQAAAAAAACY///////MAAAAAAAAFP////////////8A////////////SAAAAAAAAMD///////wAAAAAAAAA/////////////wD///////////9wAAAAAAAAvP///////wAAAAAAAAD/////////////AP///////////7QAAAAAAACI///////UAAAAAAAAJP////////////8A////////////+AwAAAAAACDw/////2wAAAAAAABY/////////////wD/////////////cAAAAAAAADC8/Ox4AAAAAAAAAKj/////////////AP/////////////oEAAAAAAAAAAAAAAAAAAAAAAk/P////////////8A//////////////+oAAAAAAAAAAAAAAAAAAAABLj//////////////wD///////////////+QAAAAAAAAAAAAAAAAAACQ////////////////AP////////////////+0JAAAAAAAAAAAAAAkuP////////////////8A///////////////////8sGg0FAAADCxgqPz//////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - '7' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP///////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP///////////wAAAAAAAAAAAAAAAAAAAAAAAAAABP////////////8A////////////AAAAAAAAAAAAAAAAAAAAAAAAAAy4/////////////wD//////////////////////////+QUAAAAAAAEuP//////////////AP/////////////////////////8QAAAAAAAAKT///////////////8A/////////////////////////4wAAAAAAAB0/////////////////wD////////////////////////cCAAAAAAANPz/////////////////AP///////////////////////0QAAAAAAATY//////////////////8A//////////////////////+0AAAAAAAAeP///////////////////wD//////////////////////CQAAAAAABTw////////////////////AP////////////////////+gAAAAAAAAkP////////////////////8A/////////////////////ywAAAAAABDw/////////////////////wD///////////////////+4AAAAAAAAbP//////////////////////AP///////////////////1wAAAAAAADQ//////////////////////8A///////////////////4DAAAAAAAMP///////////////////////wD//////////////////7QAAAAAAAB8////////////////////////AP//////////////////aAAAAAAAAMj///////////////////////8A//////////////////8oAAAAAAAM/P///////////////////////wD/////////////////8AAAAAAAAET/////////////////////////AP////////////////+0AAAAAAAAcP////////////////////////8A/////////////////4wAAAAAAACY/////////////////////////wD/////////////////WAAAAAAAAMD/////////////////////////AP////////////////80AAAAAAAA4P////////////////////////8A/////////////////xAAAAAAAAD4/////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - '8' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD////////////////////IdDQUAAAEIEiA1P//////////////////AP/////////////////gRAAAAAAAAAAAAAAAROD///////////////8A////////////////0BgAAAAAAAAAAAAAAAAAEMj//////////////wD///////////////AcAAAAAAAAAAAAAAAAAAAAHPD/////////////AP//////////////hAAAAAAAAAAAAAAAAAAAAAAAhP////////////8A//////////////8sAAAAAAAAKMz/zCgAAAAAAAAs/////////////wD//////////////wAAAAAAAADM////zAAAAAAAAAD/////////////AP//////////////BAAAAAAAAP//////AAAAAAAABP////////////8A//////////////8sAAAAAAAAzP///9QAAAAAAAAw/////////////wD//////////////3wAAAAAAAAoyP/YNAAAAAAAAIT/////////////AP//////////////7BgAAAAAAAAAAAAAAAAAAAAc8P////////////8A////////////////xBgAAAAAAAAAAAAAAAAAGNj//////////////wD/////////////////tAQAAAAAAAAAAAAAAACo////////////////AP///////////////HAAAAAAAAAAAAAAAAAAAAB8//////////////8A//////////////9gAAAAAAAAAAAAAAAAAAAAAAB8/////////////wD/////////////wAAAAAAAAABk4P/UWAAAAAAAAATQ////////////AP////////////9UAAAAAAAAaP//////XAAAAAAAAGT///////////8A/////////////xgAAAAAAADg///////cAAAAAAAAJP///////////wD/////////////AAAAAAAAAP////////8AAAAAAAAA////////////AP////////////8AAAAAAAAA4P//////3AAAAAAAAAT///////////8A/////////////ygAAAAAAABg//////9cAAAAAAAALP///////////wD/////////////ZAAAAAAAAABY1P/cXAAAAAAAAABw////////////AP/////////////QAAAAAAAAAAAAAAAAAAAAAAAABNz///////////8A//////////////9gAAAAAAAAAAAAAAAAAAAAAAB0/////////////wD///////////////Q8AAAAAAAAAAAAAAAAAAAAUPz/////////////AP////////////////x4CAAAAAAAAAAAAAAAEIT8//////////////8A///////////////////smFQwGAAAABg0ZKT0/////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - '9' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD///////////////////ysYCwMAAAUNGiw/P//////////////////AP////////////////+4JAAAAAAAAAAAAAAkuP////////////////8A////////////////lAQAAAAAAAAAAAAAAAAAkP///////////////wD//////////////8AEAAAAAAAAAAAAAAAAAAAAqP//////////////AP/////////////8JAAAAAAAAAAAAAAAAAAAAAAQ7P////////////8A/////////////6wAAAAAAAAAfOz8vCwAAAAAAABw/////////////wD/////////////WAAAAAAAAHD/////7BgAAAAAAAz4////////////AP////////////8kAAAAAAAA1P//////hAAAAAAAALT///////////8A/////////////wAAAAAAAAD///////+4AAAAAAAAcP///////////wD/////////////AAAAAAAAAPz//////8AAAAAAAABI////////////AP////////////8UAAAAAAAAzP//////lAAAAAAAACT///////////8A/////////////0QAAAAAAABY//////gsAAAAAAAADP///////////wD/////////////kAAAAAAAAABw5P/IPAAAAAAAAAAA////////////AP/////////////wEAAAAAAAAAAAAAAAAAAAAAAAAAD///////////8A//////////////+UAAAAAAAAAAAAAAAAAAAAAAAAAP///////////wD///////////////9wAAAAAAAAAAAAAFAAAAAAAAAU////////////AP////////////////+IBAAAAAAAAABw3AAAAAAAACj///////////8A///////////////////cdCwEABhcxP+8AAAAAAAATP///////////wD//////////////////////////////5AAAAAAAAB4////////////AP//////////////////////////////UAAAAAAAALj///////////8A//////////////+kgGxUQCAM2P///+AIAAAAAAAQ+P///////////wD//////////////0gAAAAAAAA42P/EKAAAAAAAAHD/////////////AP//////////////sAAAAAAAAAAAAAAAAAAAAAAQ6P////////////8A////////////////TAAAAAAAAAAAAAAAAAAAAKz//////////////wD////////////////oKAAAAAAAAAAAAAAAAASU////////////////AP/////////////////sUAAAAAAAAAAAAAAwxP////////////////8A////////////////////yHA0FAAADCxktP///////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'A' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD//////////////////+QAAAAAAAAAAAAAAOT/////////////////AP//////////////////kAAAAAAAAAAAAAAAkP////////////////8A//////////////////88AAAAAAAAAAAAAAA8/////////////////wD/////////////////5AAAAAAAAAAAAAAAAADk////////////////AP////////////////+QAAAAAAAAAAAAAAAAAJD///////////////8A/////////////////zwAAAAAAAAAAAAAAAAAPP///////////////wD////////////////kAAAAAAAAAAgAAAAAAAAA5P//////////////AP///////////////5AAAAAAAAAAgAAAAAAAAACQ//////////////8A////////////////PAAAAAAAAAz8HAAAAAAAADz//////////////wD//////////////+QAAAAAAAAAWP9kAAAAAAAAANz/////////////AP//////////////kAAAAAAAAACk/7wAAAAAAAAAhP////////////8A//////////////88AAAAAAAABOz//BQAAAAAAAAw/////////////wD/////////////4AAAAAAAAAA8////ZAAAAAAAAADc////////////AP////////////+EAAAAAAAAAIj///+8AAAAAAAAAIT///////////8A/////////////zAAAAAAAAAA2P////wQAAAAAAAAMP///////////wD////////////cAAAAAAAAACT//////1wAAAAAAAAA3P//////////AP///////////4QAAAAAAAAAAAAAAAAAAAAAAAAAAACE//////////8A////////////MAAAAAAAAAAAAAAAAAAAAAAAAAAAADD//////////wD//////////9wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANz/////////AP//////////hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhP////////8A//////////8wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAw/////////wD/////////3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADc////////AP////////+EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIT///////8A/////////zAAAAAAAAAAhP///////////2QAAAAAAAAAMP///////wD////////cAAAAAAAAAADM////////////vAAAAAAAAAAA3P//////AP///////4QAAAAAAAAAHP/////////////4DAAAAAAAAACE//////8A////////MAAAAAAAAABk//////////////9cAAAAAAAAADD//////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'B' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAEDh83P///////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAEhP//////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAeP////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAxP///////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAABY////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAABT///////////8A//////////8AAAAAAAAAAP/////4zEwAAAAAAAAAAP///////////wD//////////wAAAAAAAAAA////////7AAAAAAAAAAQ////////////AP//////////AAAAAAAAAAD////////sAAAAAAAAAEj///////////8A//////////8AAAAAAAAAAP/////4zEQAAAAAAAAAtP///////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAFz/////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAiA/P////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAIjPj//////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAGKz/////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAJT///////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAABNz//////////wD//////////wAAAAAAAAAA///////sqCAAAAAAAAAAbP//////////AP//////////AAAAAAAAAAD/////////yAAAAAAAAAAs//////////8A//////////8AAAAAAAAAAP//////////AAAAAAAAAAT//////////wD//////////wAAAAAAAAAA/////////7wAAAAAAAAAAP//////////AP//////////AAAAAAAAAAD//////+ikGAAAAAAAAAAY//////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFT//////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsP//////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAADj///////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAc6P///////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAATOj/////////////AP//////////AAAAAAAAAAAAAAAAAAAEIEBkkNj///////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'C' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP//////////////////5JRULBAAAAgkTIDQ//////////////////8A////////////////1FAAAAAAAAAAAAAAAABAyP///////////////wD//////////////4gEAAAAAAAAAAAAAAAAAAAElP//////////////AP////////////9wAAAAAAAAAAAAAAAAAAAAAAAAlP////////////8A////////////kAAAAAAAAAAAAAAAAAAAAAAAAAAEyP///////////wD//////////9wIAAAAAAAAAAAAAAAAAAAAAAAAAAAw////////////AP//////////WAAAAAAAAAAAWMz/8JwQAAAAAAAAAACw//////////8A/////////+wEAAAAAAAAAID//////9QMAAAAAAAAAET//////////wD/////////nAAAAAAAAAAo/P///////3wAAAAABDBspP//////////AP////////9gAAAAAAAAAIz/////////3BxQjMT0//////////////8A/////////zQAAAAAAAAAzP///////////////////////////////wD/////////GAAAAAAAAADo////////////////////////////////AP////////8AAAAAAAAAAP////////////////////////////////8A/////////wAAAAAAAAAA/////////////////////////////////wD/////////AAAAAAAAAAD/////////////////////////////////AP////////8cAAAAAAAAAOj///////////////////////////////8A/////////zgAAAAAAAAA0P/////////kIGio7P///////////////wD/////////bAAAAAAAAACg/////////5wAAAAAMHS49P//////////AP////////+oAAAAAAAAAEz/////////PAAAAAAAAAAc//////////8A//////////QIAAAAAAAAALz//////6QAAAAAAAAAAGT//////////wD//////////3AAAAAAAAAADIzo/+SEBAAAAAAAAAAAyP//////////AP//////////7BAAAAAAAAAAAAAAAAAAAAAAAAAAAED///////////8A////////////rAAAAAAAAAAAAAAAAAAAAAAAAAAE0P///////////wD/////////////fAAAAAAAAAAAAAAAAAAAAAAAAJz/////////////AP//////////////iAQAAAAAAAAAAAAAAAAAAASY//////////////8A////////////////yEAAAAAAAAAAAAAAAAA8yP///////////////wD//////////////////9yIUCwQAAAAIEB4yP//////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'D' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD///////////8AAAAAAAAAAAAAAAAADChQkOT/////////////////AP///////////wAAAAAAAAAAAAAAAAAAAAAABGjw//////////////8A////////////AAAAAAAAAAAAAAAAAAAAAAAAACDY/////////////wD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAABjk////////////AP///////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAED///////////8A////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAKj//////////wD///////////8AAAAAAAAAAP///+isSAAAAAAAAAAANP//////////AP///////////wAAAAAAAAAA////////hAAAAAAAAAAA2P////////8A////////////AAAAAAAAAAD/////////MAAAAAAAAACQ/////////wD///////////8AAAAAAAAAAP////////+MAAAAAAAAAFj/////////AP///////////wAAAAAAAAAA/////////8gAAAAAAAAAMP////////8A////////////AAAAAAAAAAD/////////5AAAAAAAAAAY/////////wD///////////8AAAAAAAAAAP//////////AAAAAAAAAAD/////////AP///////////wAAAAAAAAAA//////////8AAAAAAAAAAP////////8A////////////AAAAAAAAAAD//////////wAAAAAAAAAA/////////wD///////////8AAAAAAAAAAP/////////wAAAAAAAAABD/////////AP///////////wAAAAAAAAAA/////////9QAAAAAAAAAJP////////8A////////////AAAAAAAAAAD/////////qAAAAAAAAABI/////////wD///////////8AAAAAAAAAAP////////9QAAAAAAAAAHj/////////AP///////////wAAAAAAAAAA////////uAAAAAAAAAAAvP////////8A////////////AAAAAAAAAAD////w0HwEAAAAAAAAACT8/////////wD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAoP//////////AP///////////wAAAAAAAAAAAAAAAAAAAAAAAAAAADz8//////////8A////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAY6P///////////wD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAKNz/////////////AP///////////wAAAAAAAAAAAAAAAAAAAAAACHT0//////////////8A////////////AAAAAAAAAAAAAAAAABg4bKj0/////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'E' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP//////////AAAAAAAAAAD///////////////////////////////8A//////////8AAAAAAAAAAP///////////////////////////////wD//////////wAAAAAAAAAA////////////////////////////////AP//////////AAAAAAAAAAD///////////////////////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////////8A//////////8AAAAAAAAAAP///////////////////////////////wD//////////wAAAAAAAAAA////////////////////////////////AP//////////AAAAAAAAAAD///////////////////////////////8A//////////8AAAAAAAAAAP///////////////////////////////wD//////////wAAAAAAAAAA////////////////////////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'F' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAA////////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAD///////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAP///////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAA////////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAD///////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAP///////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'G' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD//////////////////MB8TCgQAAAACCA4YJzs////////////////AP///////////////JQcAAAAAAAAAAAAAAAAAAhw8P////////////8A/////////////9gwAAAAAAAAAAAAAAAAAAAAAAAk2P///////////wD////////////EDAAAAAAAAAAAAAAAAAAAAAAAAAAc7P//////////AP//////////2AwAAAAAAAAAAAAAAAAAAAAAAAAAAABY//////////8A//////////wwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQ/////////wD/////////kAAAAAAAAAAAEHzQ/P/gmCAAAAAAAAAAAFz/////////AP////////wcAAAAAAAAACjg////////8CwAAAAAAAAgWP////////8A////////vAAAAAAAAAAI2P//////////yBRAcJjI8P///////////wD///////94AAAAAAAAAGD/////////////////////////////////AP///////0AAAAAAAAAAsP////////////////////////////////8A////////IAAAAAAAAADc/////////////////////////////////wD///////8AAAAAAAAAAP///////wAAAAAAAAAAAAAAAAD/////////AP///////wAAAAAAAAAA////////AAAAAAAAAAAAAAAAAP////////8A////////AAAAAAAAAAD///////8AAAAAAAAAAAAAAAAA/////////wD///////8gAAAAAAAAAOD//////wAAAAAAAAAAAAAAAAD/////////AP///////0AAAAAAAAAAtP//////AAAAAAAAAAAAAAAAAP////////8A////////cAAAAAAAAABw//////8AAAAAAAAAAAAAAAAA/////////wD///////+8AAAAAAAAABDs////////////AAAAAAAAAAD/////////AP////////wYAAAAAAAAADz0//////////AAAAAAAAAAAP////////8A/////////5AAAAAAAAAAACCY4P//3KhcCAAAAAAAAAAA/////////wD/////////+CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////AP//////////xAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIP////////8A////////////rAQAAAAAAAAAAAAAAAAAAAAAAAAAAGTw/////////wD/////////////vBQAAAAAAAAAAAAAAAAAAAAAADjI////////////AP//////////////8HAQAAAAAAAAAAAAAAAAAEiw//////////////8A//////////////////iwcEAgBAAABCA4aKDk/////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'H' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////8A/////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////8A/////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'I' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAA////////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAD///////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAP///////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAA////////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAD///////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAP///////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAA////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAD///////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAP///////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAA////////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAD///////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAP///////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAA////////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAD///////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'J' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP///////////////////////////wAAAAAAAAAA//////////////8A////////////////////////////AAAAAAAAAAD//////////////wD///////////////////////////8AAAAAAAAAAP//////////////AP///////////////////////////wAAAAAAAAAA//////////////8A////////////////////////////AAAAAAAAAAD//////////////wD///////////////////////////8AAAAAAAAAAP//////////////AP///////////////////////////wAAAAAAAAAA//////////////8A////////////////////////////AAAAAAAAAAD//////////////wD///////////////////////////8AAAAAAAAAAP//////////////AP///////////////////////////wAAAAAAAAAA//////////////8A////////////////////////////AAAAAAAAAAD//////////////wD///////////////////////////8AAAAAAAAAAP//////////////AP///////////////////////////wAAAAAAAAAA//////////////8A////////////////////////////AAAAAAAAAAD//////////////wD///////////////////////////8AAAAAAAAAAP//////////////AP///////////////////////////wAAAAAAAAAA//////////////8A////////////////////////////AAAAAAAAAAj//////////////wD//////////+zMrIxwUDAQ//////wAAAAAAAAAIP//////////////AP//////////DAAAAAAAAADo////2AAAAAAAAAA0//////////////8A//////////8wAAAAAAAAAKj///+YAAAAAAAAAFj//////////////wD//////////2gAAAAAAAAAIND/yBgAAAAAAAAAkP//////////////AP//////////vAAAAAAAAAAAAAAAAAAAAAAAAADc//////////////8A////////////MAAAAAAAAAAAAAAAAAAAAAAAUP///////////////wD////////////EBAAAAAAAAAAAAAAAAAAAABjk////////////////AP////////////+sBAAAAAAAAAAAAAAAAAAY2P////////////////8A///////////////EMAAAAAAAAAAAAAAAVOj//////////////////wD/////////////////vHBAIAAAABg8fNT/////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'K' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD///////8AAAAAAAAAAP//////////wAQAAAAAAAAAAABw////////AP///////wAAAAAAAAAA/////////9AMAAAAAAAAAAAAcP////////8A////////AAAAAAAAAAD////////cGAAAAAAAAAAAAHD//////////wD///////8AAAAAAAAAAP//////6CgAAAAAAAAAAABs////////////AP///////wAAAAAAAAAA//////Q0AAAAAAAAAAAAVPz///////////8A////////AAAAAAAAAAD////8RAAAAAAAAAAAAFT8/////////////wD///////8AAAAAAAAAAP///1gAAAAAAAAAAABU/P//////////////AP///////wAAAAAAAAAA//9wAAAAAAAAAAAASPz///////////////8A////////AAAAAAAAAAD/jAAAAAAAAAAAADz0/////////////////wD///////8AAAAAAAAAAKQAAAAAAAAAAAA89P//////////////////AP///////wAAAAAAAAAABAAAAAAAAAAAFPT///////////////////8A////////AAAAAAAAAAAAAAAAAAAAAAAApP///////////////////wD///////8AAAAAAAAAAAAAAAAAAAAAAAAU8P//////////////////AP///////wAAAAAAAAAAAAAAAAAAAAAAAABk//////////////////8A////////AAAAAAAAAAAAAAAAAAAAAAAAAADE/////////////////wD///////8AAAAAAAAAAAAAAAAoEAAAAAAAACz8////////////////AP///////wAAAAAAAAAAAAAAGNiAAAAAAAAAAIj///////////////8A////////AAAAAAAAAAAAABjY//gYAAAAAAAACOD//////////////wD///////8AAAAAAAAAAAAY2P///5wAAAAAAAAASP//////////////AP///////wAAAAAAAAAAGNj//////CgAAAAAAAAAqP////////////8A////////AAAAAAAAAADI////////sAAAAAAAAAAc8P///////////wD///////8AAAAAAAAAAP//////////QAAAAAAAAABs////////////AP///////wAAAAAAAAAA///////////IAAAAAAAAAATI//////////8A////////AAAAAAAAAAD///////////9YAAAAAAAAADD8/////////wD///////8AAAAAAAAAAP///////////9wEAAAAAAAAAJD/////////AP///////wAAAAAAAAAA/////////////3AAAAAAAAAADOT///////8A////////AAAAAAAAAAD/////////////7BAAAAAAAAAAUP///////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'L' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'M' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A//////8AAAAAAAAAAAAAAHz//////3wAAAAAAAAAAAAAAP///////wD//////wAAAAAAAAAAAAAATP//////UAAAAAAAAAAAAAAA////////AP//////AAAAAAAAAAAAAAAc//////8cAAAAAAAAAAAAAAD///////8A//////8AAAAAAAAAAAAAAADw////8AAAAAAAAAAAAAAAAP///////wD//////wAAAAAAAAAAAAAAALz////AAAAAAAAAAAAAAAAA////////AP//////AAAAAAAAAAAAAAAAkP///5AAAAAAAAAAAAAAAAD///////8A//////8AAAAAAAAAAAAAAABc////ZAAAAAAAAAAAAAAAAP///////wD//////wAAAAAAAAAoAAAAADD///8wAAAAACQAAAAAAAAA////////AP//////AAAAAAAAAFwAAAAABPz//AgAAAAAXAAAAAAAAAD///////8A//////8AAAAAAAAAkAAAAAAA0P/UAAAAAACQAAAAAAAAAP///////wD//////wAAAAAAAADMAAAAAACg/6gAAAAAAMQAAAAAAAAA////////AP//////AAAAAAAAAPgEAAAAAHD/dAAAAAAE+AAAAAAAAAD///////8A//////8AAAAAAAAA/zQAAAAAQP9IAAAAADD/AAAAAAAAAP///////wD//////wAAAAAAAAD/bAAAAAAQ/xQAAAAAaP8AAAAAAAAA////////AP//////AAAAAAAAAP+gAAAAAADQAAAAAACc/wAAAAAAAAD///////8A//////8AAAAAAAAA/9QAAAAAAGgAAAAAAND/AAAAAAAAAP///////wD//////wAAAAAAAAD//wwAAAAAFAAAAAAM/P8AAAAAAAAA////////AP//////AAAAAAAAAP//RAAAAAAAAAAAADz//wAAAAAAAAD///////8A//////8AAAAAAAAA//94AAAAAAAAAAAAcP//AAAAAAAAAP///////wD//////wAAAAAAAAD//7AAAAAAAAAAAACo//8AAAAAAAAA////////AP//////AAAAAAAAAP//5AAAAAAAAAAAANz//wAAAAAAAAD///////8A//////8AAAAAAAAA////HAAAAAAAAAAQ////AAAAAAAAAP///////wD//////wAAAAAAAAD///9QAAAAAAAAAEz///8AAAAAAAAA////////AP//////AAAAAAAAAP///4gAAAAAAAAAfP///wAAAAAAAAD///////8A//////8AAAAAAAAA////vAAAAAAAAACw////AAAAAAAAAP///////wD//////wAAAAAAAAD////wAAAAAAAAAOz///8AAAAAAAAA////////AP//////AAAAAAAAAP////8sAAAAAAAc/////wAAAAAAAAD///////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'N' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////AAAAAAAAALD/////////////AAAAAAAAAP//////////AP////////8AAAAAAAAAFOj///////////8AAAAAAAAA//////////8A/////////wAAAAAAAAAASP///////////wAAAAAAAAD//////////wD/////////AAAAAAAAAAAAkP//////////AAAAAAAAAP//////////AP////////8AAAAAAAAAAAAI1P////////8AAAAAAAAA//////////8A/////////wAAAAAAAAAAAAAw+P///////wAAAAAAAAD//////////wD/////////AAAAAAAAAAAAAABw////////AAAAAAAAAP//////////AP////////8AAAAAAAAAAAAAAAC8//////8AAAAAAAAA//////////8A/////////wAAAAAAAAAAAAAAABzs/////wAAAAAAAAD//////////wD/////////AAAAAAAAAAAAAAAAAFD/////AAAAAAAAAP//////////AP////////8AAAAAAAAAAAAAAAAAAJz///8AAAAAAAAA//////////8A/////////wAAAAAAAAAUAAAAAAAADNz//wAAAAAAAAD//////////wD/////////AAAAAAAAALQAAAAAAAAANPz/AAAAAAAAAP//////////AP////////8AAAAAAAAA/2wAAAAAAAAAfP8AAAAAAAAA//////////8A/////////wAAAAAAAAD/+CwAAAAAAAAExAAAAAAAAAD//////////wD/////////AAAAAAAAAP//0AQAAAAAAAAgAAAAAAAAAP//////////AP////////8AAAAAAAAA////jAAAAAAAAAAAAAAAAAAA//////////8A/////////wAAAAAAAAD/////RAAAAAAAAAAAAAAAAAD//////////wD/////////AAAAAAAAAP/////kFAAAAAAAAAAAAAAAAP//////////AP////////8AAAAAAAAA//////+sAAAAAAAAAAAAAAAA//////////8A/////////wAAAAAAAAD///////9kAAAAAAAAAAAAAAD//////////wD/////////AAAAAAAAAP////////QkAAAAAAAAAAAAAP//////////AP////////8AAAAAAAAA/////////8wEAAAAAAAAAAAA//////////8A/////////wAAAAAAAAD//////////4QAAAAAAAAAAAD//////////wD/////////AAAAAAAAAP///////////DwAAAAAAAAAAP//////////AP////////8AAAAAAAAA////////////4BAAAAAAAAAA//////////8A/////////wAAAAAAAAD/////////////qAAAAAAAAAD//////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'O' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A///////////////////0qGw4HAAAABw4aKT0/////////////////wD////////////////wcAwAAAAAAAAAAAAAAAho6P//////////////AP//////////////uBQAAAAAAAAAAAAAAAAAAAAMoP////////////8A/////////////6AEAAAAAAAAAAAAAAAAAAAAAAAAkP///////////wD///////////+4BAAAAAAAAAAAAAAAAAAAAAAAAAAAoP//////////AP//////////8BQAAAAAAAAAAAAAAAAAAAAAAAAAAAAM5P////////8A//////////9wAAAAAAAAAAAsrPD/7KQsAAAAAAAAAABg/////////wD/////////+BAAAAAAAAAAUPj///////hQAAAAAAAAAAjs////////AP////////+sAAAAAAAAABDw//////////AYAAAAAAAAAKD///////8A/////////2wAAAAAAAAAdP///////////3wAAAAAAAAAYP///////wD/////////OAAAAAAAAAC4////////////xAAAAAAAAAAw////////AP////////8cAAAAAAAAAOD////////////oAAAAAAAAABT///////8A/////////wAAAAAAAAAA//////////////8AAAAAAAAAAP///////wD/////////AAAAAAAAAAD//////////////wAAAAAAAAAA////////AP////////8AAAAAAAAAAP/////////////8AAAAAAAAAAD///////8A/////////xwAAAAAAAAA5P///////////+AAAAAAAAAAHP///////wD/////////NAAAAAAAAAC8////////////uAAAAAAAAAA4////////AP////////9oAAAAAAAAAHj///////////98AAAAAAAAAGT///////8A/////////6gAAAAAAAAAGPD/////////+BgAAAAAAAAApP///////wD/////////9AwAAAAAAAAAUPz///////xcAAAAAAAAAAjs////////AP//////////cAAAAAAAAAAALKjs//CwOAAAAAAAAAAAYP////////8A///////////wFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzk/////////wD///////////+4BAAAAAAAAAAAAAAAAAAAAAAAAAAAoP//////////AP////////////+QAAAAAAAAAAAAAAAAAAAAAAAAAJD///////////8A//////////////+sEAAAAAAAAAAAAAAAAAAAAAyg/////////////wD////////////////oZAgAAAAAAAAAAAAAAARg4P//////////////AP//////////////////9KhsOCAAAAAUMFyc7P////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'P' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP///////////wAAAAAAAAAAAAAAAAAACCxguP////////////////8A////////////AAAAAAAAAAAAAAAAAAAAAAAAOOD//////////////wD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAGOD/////////////AP///////////wAAAAAAAAAAAAAAAAAAAAAAAAAARP////////////8A////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAxP///////////wD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAAABo////////////AP///////////wAAAAAAAAAA////6JwMAAAAAAAAADD///////////8A////////////AAAAAAAAAAD//////6AAAAAAAAAADP///////////wD///////////8AAAAAAAAAAP//////9AAAAAAAAAAA////////////AP///////////wAAAAAAAAAA///////0AAAAAAAAAAD///////////8A////////////AAAAAAAAAAD//////5gAAAAAAAAAHP///////////wD///////////8AAAAAAAAAAP///9iICAAAAAAAAABI////////////AP///////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAJD///////////8A////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAI6P///////////wD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAAIT/////////////AP///////////wAAAAAAAAAAAAAAAAAAAAAAAABU/P////////////8A////////////AAAAAAAAAAAAAAAAAAAAAAAIhPz//////////////wD///////////8AAAAAAAAAAAAAAAAABCRMkOz/////////////////AP///////////wAAAAAAAAAA//////////////////////////////8A////////////AAAAAAAAAAD//////////////////////////////wD///////////8AAAAAAAAAAP//////////////////////////////AP///////////wAAAAAAAAAA//////////////////////////////8A////////////AAAAAAAAAAD//////////////////////////////wD///////////8AAAAAAAAAAP//////////////////////////////AP///////////wAAAAAAAAAA//////////////////////////////8A////////////AAAAAAAAAAD//////////////////////////////wD///////////8AAAAAAAAAAP//////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'Q' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////SoaDQcAAAAHDhoqPT///////////////////8A//////////////BwDAAAAAAAAAAAAAAACHDo/////////////////wD///////////+4FAAAAAAAAAAAAAAAAAAAABCo////////////////AP//////////nAQAAAAAAAAAAAAAAAAAAAAAAACQ//////////////8A/////////7gEAAAAAAAAAAAAAAAAAAAAAAAAAACg/////////////wD////////wFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzo////////////AP///////3AAAAAAAAAAACyo8P/sqCwAAAAAAAAAAGT///////////8A///////4EAAAAAAAAABM+P///////FQAAAAAAAAACPT//////////wD//////7AAAAAAAAAAFPD/////////9BgAAAAAAAAApP//////////AP//////bAAAAAAAAAB4////////////fAAAAAAAAABk//////////8A//////84AAAAAAAAALz///////////+8AAAAAAAAADT//////////wD//////xwAAAAAAAAA6P///////////+QAAAAAAAAAHP//////////AP//////AAAAAAAAAAD//////////////wAAAAAAAAAA//////////8A//////8AAAAAAAAAAP//////////////AAAAAAAAAAD//////////wD//////wAAAAAAAAAA/P////////////8AAAAAAAAAAP//////////AP//////GAAAAAAAAADg////////////4AAAAAAAAAAc//////////8A//////84AAAAAAAAALT////MJHTo//+8AAAAAAAAADT//////////wD//////2wAAAAAAAAAdP///2AAABCg/3wAAAAAAAAAZP//////////AP//////rAAAAAAAAAAY9P/sCAAAAABMGAAAAAAAAACk//////////8A///////4EAAAAAAAAABU/P+0OAAAAAAAAAAAAAAACPT//////////wD///////94AAAAAAAAAAA4sPD/gAAAAAAAAAAAAABk////////////AP////////AcAAAAAAAAAAAAAAAAAAAAAAAAAAAADOT///////////8A/////////7wEAAAAAAAAAAAAAAAAAAAAAAAAAACQ/////////////wD//////////6wEAAAAAAAAAAAAAAAAAAAAAAAAABSs////////////AP///////////7gUAAAAAAAAAAAAAAAAAAAAAAAAAABAwP////////8A//////////////BwDAAAAAAAAAAAAAAABAgAAAAAAAA8/////////wD////////////////0qGg0GAAAABgwXJjkxBgAAAAAALD/////////AP//////////////////////////////////5DQAAAAk/P////////8A////////////////////////////////////+GwAAJD//////////wD//////////////////////////////////////8A49P//////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'R' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////wAAAAAAAAAAAAAAAAAAAAQgOGSk+P///////////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAcuP//////////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAEsP////////////8A/////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQ6P///////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB8////////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAADD///////////8A/////////wAAAAAAAAAA///////svDgAAAAAAAAACP///////////wD/////////AAAAAAAAAAD/////////7AAAAAAAAAAA////////////AP////////8AAAAAAAAAAP/////////cAAAAAAAAABD///////////8A/////////wAAAAAAAAAA//////DQoCQAAAAAAAAAQP///////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAACU////////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAIPj///////////8A/////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAzU/////////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAA02P//////////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAxctPz///////////////8A/////////wAAAAAAAAAAAAAAAAAAAAAAAEDY/////////////////wD/////////AAAAAAAAAAD/9LAsAAAAAAAAAAzc////////////////AP////////8AAAAAAAAAAP///+wkAAAAAAAAADD8//////////////8A/////////wAAAAAAAAAA/////8QAAAAAAAAAAJD//////////////wD/////////AAAAAAAAAAD//////1QAAAAAAAAAFPD/////////////AP////////8AAAAAAAAAAP//////3AQAAAAAAAAAgP////////////8A/////////wAAAAAAAAAA////////aAAAAAAAAAAM6P///////////wD/////////AAAAAAAAAAD////////oCAAAAAAAAABs////////////AP////////8AAAAAAAAAAP////////+AAAAAAAAAAATc//////////8A/////////wAAAAAAAAAA//////////AUAAAAAAAAAFj//////////wD/////////AAAAAAAAAAD//////////5AAAAAAAAAAAND/////////AP////////8AAAAAAAAAAP//////////+CQAAAAAAAAAQP////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'S' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP/////////////////8vHBEIAgAAAQgQHC8/P////////////////8A////////////////pCQAAAAAAAAAAAAAAAAcoP///////////////wD//////////////FwAAAAAAAAAAAAAAAAAAAAAXP//////////////AP////////////9oAAAAAAAAAAAAAAAAAAAAAAAAhP////////////8A////////////zAAAAAAAAAAAAAAAAAAAAAAAAAAI6P///////////wD///////////9cAAAAAAAAAAAAAAAAAAAAAAAAAACA////////////AP///////////xgAAAAAAAAAUOD/8KwkAAAAAAAAADj///////////8A////////////AAAAAAAAAAD0/////8wABCAgICxASP///////////wD///////////8MAAAAAAAAAMz/////////////////////////////AP///////////0AAAAAAAAAACFiQxPT///////////////////////8A////////////oAAAAAAAAAAAAAAAADBwtPT//////////////////wD////////////8QAAAAAAAAAAAAAAAAAAACFTA////////////////AP/////////////oOAAAAAAAAAAAAAAAAAAAAABM6P////////////8A///////////////4fAgAAAAAAAAAAAAAAAAAAAAY2P///////////wD/////////////////7IwwAAAAAAAAAAAAAAAAAAAo+P//////////AP/////////////////////koGw0BAAAAAAAAAAAAACU//////////8A///////////////////////////4uFgAAAAAAAAAADz//////////wD//////////2BgSEA0IBwA6P///////5QAAAAAAAAADP//////////AP//////////JAAAAAAAAACc/////////AAAAAAAAAAA//////////8A//////////9YAAAAAAAAACDo///////AAAAAAAAAABT//////////wD//////////6QAAAAAAAAAACCk7P/snBQAAAAAAAAAUP//////////AP//////////+BAAAAAAAAAAAAAAAAAAAAAAAAAAAACs//////////8A////////////kAAAAAAAAAAAAAAAAAAAAAAAAAAAOP///////////wD////////////8RAAAAAAAAAAAAAAAAAAAAAAAABjc////////////AP/////////////0PAAAAAAAAAAAAAAAAAAAAAAg2P////////////8A///////////////8hBQAAAAAAAAAAAAAAAAMdPT//////////////wD/////////////////+LRwSCAMAAAAHDhoqPT/////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'T' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////////8A/////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////////8A/////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'U' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////JAAAAAAAAADk/////////+gAAAAAAAAAHP//////////AP////////9MAAAAAAAAAJz/////////nAAAAAAAAABE//////////8A/////////4gAAAAAAAAAHOj//////+ggAAAAAAAAAHz//////////wD/////////0AAAAAAAAAAAIJzs/+ykIAAAAAAAAAAA0P//////////AP//////////QAAAAAAAAAAAAAAAAAAAAAAAAAAAAED///////////8A///////////IBAAAAAAAAAAAAAAAAAAAAAAAAAAE0P///////////wD///////////+YAAAAAAAAAAAAAAAAAAAAAAAAAJj/////////////AP////////////+UBAAAAAAAAAAAAAAAAAAAAASU//////////////8A///////////////IPAAAAAAAAAAAAAAAAAAwyP///////////////wD/////////////////0IxYOCAIAAAEIEiAyP//////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'V' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD//////zAAAAAAAAAAYP//////////////ZAAAAAAAAAAw////////AP//////kAAAAAAAAAAU/P////////////8UAAAAAAAAAJD///////8A///////oBAAAAAAAAADE////////////xAAAAAAAAAAE7P///////wD///////9MAAAAAAAAAHD///////////94AAAAAAAAAEz/////////AP///////6gAAAAAAAAAJP///////////yQAAAAAAAAArP////////8A////////+BAAAAAAAAAA1P/////////YAAAAAAAAABT4/////////wD/////////aAAAAAAAAACE/////////4QAAAAAAAAAbP//////////AP/////////EAAAAAAAAADT/////////OAAAAAAAAADM//////////8A//////////8kAAAAAAAAAOT//////+QAAAAAAAAAKP///////////wD//////////4QAAAAAAAAAmP//////nAAAAAAAAACI////////////AP//////////5AAAAAAAAABE//////9EAAAAAAAABOT///////////8A////////////QAAAAAAAAAT0////9AgAAAAAAABI/////////////wD///////////+gAAAAAAAAAKT///+kAAAAAAAAAKj/////////////AP////////////QIAAAAAAAAXP///1wAAAAAAAAM+P////////////8A/////////////1wAAAAAAAAM+P/8DAAAAAAAAGT//////////////wD/////////////vAAAAAAAAAC8/7wAAAAAAAAAxP//////////////AP//////////////HAAAAAAAAGj/aAAAAAAAACT///////////////8A//////////////94AAAAAAAAHP8cAAAAAAAAhP///////////////wD//////////////9gAAAAAAAAAkAAAAAAAAADk////////////////AP///////////////zgAAAAAAAAQAAAAAAAAQP////////////////8A////////////////lAAAAAAAAAAAAAAAAACg/////////////////wD////////////////sCAAAAAAAAAAAAAAADPT/////////////////AP////////////////9QAAAAAAAAAAAAAABg//////////////////8A/////////////////7AAAAAAAAAAAAAAAMD//////////////////wD//////////////////BQAAAAAAAAAAAAc////////////////////AP//////////////////cAAAAAAAAAAAAHz///////////////////8A///////////////////MAAAAAAAAAAAA3P///////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'W' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A//8cAAAAAAAAALz/////4AAAAAAAAAAA6P////+8AAAAAAAAABz//wD//1QAAAAAAAAAjP////+gAAAAAAAAAACo/////4wAAAAAAAAAUP//AP//jAAAAAAAAABU/////2AAAAAAAAAAAGj/////VAAAAAAAAACM//8A///EAAAAAAAAACT/////IAAAAAAAAAAAKP////8kAAAAAAAAAMT//wD///gEAAAAAAAAAPD//+AAAAAAAAAAAAAA6P//8AAAAAAAAAAE9P//AP///zAAAAAAAAAAvP//oAAAAAAAAAAAAACo//+8AAAAAAAAADD///8A////bAAAAAAAAACM//9gAAAAAAAAAAAAAGT//4wAAAAAAAAAaP///wD///+kAAAAAAAAAFT//yAAAAAAAAAAAAAAIP//VAAAAAAAAACc////AP///9gAAAAAAAAAJP/gAAAAAAAAAAAAAAAA4P8kAAAAAAAAANT///8A/////xAAAAAAAAAA8KAAAAAAAAAAAAAAAACg8AAAAAAAAAAQ/////wD/////TAAAAAAAAAC8YAAAAAAAAAAAAAAAAGC8AAAAAAAAAET/////AP////+AAAAAAAAAAIwgAAAAAAAAAAAAAAAAIIwAAAAAAAAAfP////8A/////7gAAAAAAAAANAAAAAAAACwwAAAAAAAANAAAAAAAAACw/////wD/////8AAAAAAAAAAAAAAAAAAAdHgAAAAAAAAAAAAAAAAAAOz/////AP//////KAAAAAAAAAAAAAAAAAC4vAAAAAAAAAAAAAAAAAAg//////8A//////9gAAAAAAAAAAAAAAAACPj4CAAAAAAAAAAAAAAAAFj//////wD//////5QAAAAAAAAAAAAAAABE//9IAAAAAAAAAAAAAAAAkP//////AP//////0AAAAAAAAAAAAAAAAIj//4wAAAAAAAAAAAAAAADI//////8A///////8DAAAAAAAAAAAAAAAzP//1AAAAAAAAAAAAAAABPj//////wD///////88AAAAAAAAAAAAABT/////GAAAAAAAAAAAAAA0////////AP///////3QAAAAAAAAAAAAAWP////9gAAAAAAAAAAAAAHD///////8A////////sAAAAAAAAAAAAACg/////6QAAAAAAAAAAAAApP///////wD////////kAAAAAAAAAAAAAOT/////6AAAAAAAAAAAAADc////////AP////////8cAAAAAAAAAAAo////////MAAAAAAAAAAAEP////////8A/////////1QAAAAAAAAAAHD///////94AAAAAAAAAABM/////////wD/////////jAAAAAAAAAAAtP///////7wAAAAAAAAAAID/////////AP/////////EAAAAAAAAAAT0////////+AgAAAAAAAAAuP////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'X' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD///////9UAAAAAAAAAKz///////////+sAAAAAAAAAFD/////////AP///////+QQAAAAAAAAFOT/////////8BwAAAAAAAAM5P////////8A/////////5gAAAAAAAAATP////////9kAAAAAAAAAJD//////////wD//////////0AAAAAAAAAAoP//////wAAAAAAAAAA0/P//////////AP//////////2AgAAAAAAAAQ4P////gkAAAAAAAABMz///////////8A////////////iAAAAAAAAABA////dAAAAAAAAABw/////////////wD////////////8MAAAAAAAAACU/9AEAAAAAAAAHPD/////////////AP/////////////IBAAAAAAAAAzYMAAAAAAAAACs//////////////8A//////////////90AAAAAAAAABAAAAAAAAAATP///////////////wD///////////////QgAAAAAAAAAAAAAAAAAAzg////////////////AP///////////////7wAAAAAAAAAAAAAAAAAjP////////////////8A/////////////////2AAAAAAAAAAAAAAADD8/////////////////wD/////////////////7BQAAAAAAAAAAAAEyP//////////////////AP/////////////////gDAAAAAAAAAAAAAjY//////////////////8A/////////////////0AAAAAAAAAAAAAAADj8/////////////////wD///////////////+UAAAAAAAAAAAAAAAAAJD/////////////////AP//////////////4AwAAAAAAAAAAAAAAAAADOD///////////////8A//////////////9AAAAAAAAAAAAAAAAAAAAAQP///////////////wD/////////////nAAAAAAAAAAAWAAAAAAAAAAAlP//////////////AP///////////+QQAAAAAAAAAGD/YAAAAAAAAAAM4P////////////8A////////////TAAAAAAAAAAs9P/0LAAAAAAAAABM/////////////wD//////////6AAAAAAAAAADNT////UDAAAAAAAAACg////////////AP/////////kEAAAAAAAAACg//////+gAAAAAAAAABDk//////////8A/////////0wAAAAAAAAAYP////////9gAAAAAAAAAEz//////////wD///////+oAAAAAAAAACz0//////////QsAAAAAAAAAKT/////////AP//////7BQAAAAAAAAM1P///////////9QMAAAAAAAAFOz///////8A//////9UAAAAAAAAAKD//////////////6AAAAAAAAAAVP///////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'Y' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP///////1QAAAAAAAAAAGj//////////2gAAAAAAAAAAFT///////8A////////5BAAAAAAAAAAAMT////////EAAAAAAAAAAAQ5P///////wD/////////mAAAAAAAAAAAKPj/////+CgAAAAAAAAAAJj/////////AP//////////PAAAAAAAAAAAgP////+AAAAAAAAAAAA8//////////8A///////////YCAAAAAAAAAAE2P//2AQAAAAAAAAACNj//////////wD///////////+AAAAAAAAAAAA4//84AAAAAAAAAACA////////////AP////////////woAAAAAAAAAACUlAAAAAAAAAAAKPz///////////8A/////////////8gAAAAAAAAAABAQAAAAAAAAAADI/////////////wD//////////////2wAAAAAAAAAAAAAAAAAAAAAbP//////////////AP//////////////8BwAAAAAAAAAAAAAAAAAABzw//////////////8A////////////////tAAAAAAAAAAAAAAAAAAAtP///////////////wD/////////////////VAAAAAAAAAAAAAAAAFT/////////////////AP/////////////////oEAAAAAAAAAAAAAAQ6P////////////////8A//////////////////+cAAAAAAAAAAAAAJz//////////////////wD///////////////////9AAAAAAAAAAABA////////////////////AP///////////////////9gAAAAAAAAAANj///////////////////8A/////////////////////wAAAAAAAAAA/////////////////////wD/////////////////////AAAAAAAAAAD/////////////////////AP////////////////////8AAAAAAAAAAP////////////////////8A/////////////////////wAAAAAAAAAA/////////////////////wD/////////////////////AAAAAAAAAAD/////////////////////AP////////////////////8AAAAAAAAAAP////////////////////8A/////////////////////wAAAAAAAAAA/////////////////////wD/////////////////////AAAAAAAAAAD/////////////////////AP////////////////////8AAAAAAAAAAP////////////////////8A/////////////////////wAAAAAAAAAA/////////////////////wD/////////////////////AAAAAAAAAAD/////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'Z' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAQ//////////////8A/////////////////////////1AAAAAAAAAABLz//////////////wD///////////////////////98AAAAAAAAAACY////////////////AP//////////////////////pAAAAAAAAAAAaP////////////////8A/////////////////////8QIAAAAAAAAAET8/////////////////wD////////////////////gGAAAAAAAAAAo9P//////////////////AP//////////////////9CwAAAAAAAAAFNz///////////////////8A//////////////////xMAAAAAAAAAATA/////////////////////wD/////////////////eAAAAAAAAAAAnP//////////////////////AP///////////////5wAAAAAAAAAAHT///////////////////////8A///////////////ABAAAAAAAAABM/P///////////////////////wD/////////////3BQAAAAAAAAALPT/////////////////////////AP////////////QoAAAAAAAAABjg//////////////////////////8A///////////8SAAAAAAAAAAExP///////////////////////////wD//////////2wAAAAAAAAAAKD/////////////////////////////AP////////+YAAAAAAAAAAB8//////////////////////////////8A/////////wQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A/////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - ); - } -} diff --git a/phpBB/includes/captcha/plugins/captcha_abstract.php b/phpBB/includes/captcha/plugins/captcha_abstract.php deleted file mode 100644 index 7fd88feeb5..0000000000 --- a/phpBB/includes/captcha/plugins/captcha_abstract.php +++ /dev/null @@ -1,372 +0,0 @@ -<?php -/** -* -* @package VC -* @copyright (c) 2006, 2008 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - - -/** -* This class holds the code shared by the two default 3.0.x CAPTCHAs. -* -* @package VC -*/ -class phpbb_captcha_plugins_captcha_abstract -{ - var $confirm_id; - var $confirm_code; - var $code; - var $seed; - var $attempts = 0; - var $type; - var $solved = 0; - var $captcha_vars = false; - - function init($type) - { - global $config, $db, $user; - - // read input - $this->confirm_id = request_var('confirm_id', ''); - $this->confirm_code = request_var('confirm_code', ''); - $refresh = request_var('refresh_vc', false) && $config['confirm_refresh']; - - $this->type = (int) $type; - - if (!strlen($this->confirm_id) || !$this->load_code()) - { - // we have no confirm ID, better get ready to display something - $this->generate_code(); - } - else if ($refresh) - { - $this->regenerate_code(); - } - } - - function execute_demo() - { - global $user; - - $this->code = gen_rand_string_friendly(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS)); - $this->seed = hexdec(substr(unique_id(), 4, 10)); - - // compute $seed % 0x7fffffff - $this->seed -= 0x7fffffff * floor($this->seed / 0x7fffffff); - - $captcha = new captcha(); - define('IMAGE_OUTPUT', 1); - $captcha->execute($this->code, $this->seed); - } - - function execute() - { - if (empty($this->code)) - { - if (!$this->load_code()) - { - // invalid request, bail out - return false; - } - } - $captcha = new captcha(); - define('IMAGE_OUTPUT', 1); - $captcha->execute($this->code, $this->seed); - } - - function get_template() - { - global $config, $user, $template, $phpEx, $phpbb_root_path; - - if ($this->is_solved()) - { - return false; - } - else - { - $link = append_sid($phpbb_root_path . 'ucp.' . $phpEx, 'mode=confirm&confirm_id=' . $this->confirm_id . '&type=' . $this->type); - $explain = $user->lang(($this->type != CONFIRM_POST) ? 'CONFIRM_EXPLAIN' : 'POST_CONFIRM_EXPLAIN', '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>'); - - $template->assign_vars(array( - 'CONFIRM_IMAGE_LINK' => $link, - 'CONFIRM_IMAGE' => '<img src="' . $link . '" />', - 'CONFIRM_IMG' => '<img src="' . $link . '" />', - 'CONFIRM_ID' => $this->confirm_id, - 'S_CONFIRM_CODE' => true, - 'S_TYPE' => $this->type, - 'S_CONFIRM_REFRESH' => ($config['enable_confirm'] && $config['confirm_refresh'] && $this->type == CONFIRM_REG) ? true : false, - 'L_CONFIRM_EXPLAIN' => $explain, - )); - - return 'captcha_default.html'; - } - } - - function get_demo_template($id) - { - global $config, $user, $template, $phpbb_admin_path, $phpEx; - - $variables = ''; - - if (is_array($this->captcha_vars)) - { - foreach ($this->captcha_vars as $captcha_var => $template_var) - { - $variables .= '&' . rawurlencode($captcha_var) . '=' . request_var($captcha_var, (int) $config[$captcha_var]); - } - } - - // acp_captcha has a delivery function; let's use it - $template->assign_vars(array( - 'CONFIRM_IMAGE' => append_sid($phpbb_admin_path . 'index.' . $phpEx, 'captcha_demo=1&mode=visual&i=' . $id . '&select_captcha=' . $this->get_class_name()) . $variables, - 'CONFIRM_ID' => $this->confirm_id, - )); - - return 'captcha_default_acp_demo.html'; - } - - function get_hidden_fields() - { - $hidden_fields = array(); - - // this is required for posting.php - otherwise we would forget about the captcha being already solved - if ($this->solved) - { - $hidden_fields['confirm_code'] = $this->confirm_code; - } - $hidden_fields['confirm_id'] = $this->confirm_id; - return $hidden_fields; - } - - function garbage_collect($type) - { - global $db, $config; - - $sql = 'SELECT DISTINCT c.session_id - FROM ' . CONFIRM_TABLE . ' c - LEFT JOIN ' . SESSIONS_TABLE . ' s ON (c.session_id = s.session_id) - WHERE s.session_id IS NULL' . - ((empty($type)) ? '' : ' AND c.confirm_type = ' . (int) $type); - $result = $db->sql_query($sql); - - if ($row = $db->sql_fetchrow($result)) - { - $sql_in = array(); - do - { - $sql_in[] = (string) $row['session_id']; - } - while ($row = $db->sql_fetchrow($result)); - - if (sizeof($sql_in)) - { - $sql = 'DELETE FROM ' . CONFIRM_TABLE . ' - WHERE ' . $db->sql_in_set('session_id', $sql_in); - $db->sql_query($sql); - } - } - $db->sql_freeresult($result); - } - - function uninstall() - { - $this->garbage_collect(0); - } - - function install() - { - return; - } - - function validate() - { - global $config, $db, $user; - - if (empty($user->lang)) - { - $user->setup(); - } - - $error = ''; - if (!$this->confirm_id) - { - $error = $user->lang['CONFIRM_CODE_WRONG']; - } - else - { - if ($this->check_code()) - { - $this->solved = true; - } - else - { - $error = $user->lang['CONFIRM_CODE_WRONG']; - } - } - - if (strlen($error)) - { - // okay, incorrect answer. Let's ask a new question. - $this->new_attempt(); - return $error; - } - else - { - return false; - } - } - - /** - * The old way to generate code, suitable for GD and non-GD. Resets the internal state. - */ - function generate_code() - { - global $db, $user; - - $this->code = gen_rand_string_friendly(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS)); - $this->confirm_id = md5(unique_id($user->ip)); - $this->seed = hexdec(substr(unique_id(), 4, 10)); - $this->solved = 0; - // compute $seed % 0x7fffffff - $this->seed -= 0x7fffffff * floor($this->seed / 0x7fffffff); - - $sql = 'INSERT INTO ' . CONFIRM_TABLE . ' ' . $db->sql_build_array('INSERT', array( - 'confirm_id' => (string) $this->confirm_id, - 'session_id' => (string) $user->session_id, - 'confirm_type' => (int) $this->type, - 'code' => (string) $this->code, - 'seed' => (int) $this->seed) - ); - $db->sql_query($sql); - } - - /** - * New Question, if desired. - */ - function regenerate_code() - { - global $db, $user; - - $this->code = gen_rand_string_friendly(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS)); - $this->seed = hexdec(substr(unique_id(), 4, 10)); - $this->solved = 0; - // compute $seed % 0x7fffffff - $this->seed -= 0x7fffffff * floor($this->seed / 0x7fffffff); - - $sql = 'UPDATE ' . CONFIRM_TABLE . ' SET ' . $db->sql_build_array('UPDATE', array( - 'code' => (string) $this->code, - 'seed' => (int) $this->seed)) . ' - WHERE - confirm_id = \'' . $db->sql_escape($this->confirm_id) . '\' - AND session_id = \'' . $db->sql_escape($user->session_id) . '\''; - $db->sql_query($sql); - } - - /** - * New Question, if desired. - */ - function new_attempt() - { - global $db, $user; - - $this->code = gen_rand_string_friendly(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS)); - $this->seed = hexdec(substr(unique_id(), 4, 10)); - $this->solved = 0; - // compute $seed % 0x7fffffff - $this->seed -= 0x7fffffff * floor($this->seed / 0x7fffffff); - - $sql = 'UPDATE ' . CONFIRM_TABLE . ' SET ' . $db->sql_build_array('UPDATE', array( - 'code' => (string) $this->code, - 'seed' => (int) $this->seed)) . ' - , attempts = attempts + 1 - WHERE - confirm_id = \'' . $db->sql_escape($this->confirm_id) . '\' - AND session_id = \'' . $db->sql_escape($user->session_id) . '\''; - $db->sql_query($sql); - } - - /** - * Look up everything we need for painting&checking. - */ - function load_code() - { - global $db, $user; - - $sql = 'SELECT code, seed, attempts - FROM ' . CONFIRM_TABLE . " - WHERE confirm_id = '" . $db->sql_escape($this->confirm_id) . "' - AND session_id = '" . $db->sql_escape($user->session_id) . "' - AND confirm_type = " . $this->type; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if ($row) - { - $this->code = $row['code']; - $this->seed = $row['seed']; - $this->attempts = $row['attempts']; - return true; - } - - return false; - } - - function check_code() - { - return (strcasecmp($this->code, $this->confirm_code) === 0); - } - - function get_attempt_count() - { - return $this->attempts; - } - - function reset() - { - global $db, $user; - - $sql = 'DELETE FROM ' . CONFIRM_TABLE . " - WHERE session_id = '" . $db->sql_escape($user->session_id) . "' - AND confirm_type = " . (int) $this->type; - $db->sql_query($sql); - - // we leave the class usable by generating a new question - $this->generate_code(); - } - - function is_solved() - { - if (request_var('confirm_code', false) && $this->solved === 0) - { - $this->validate(); - } - return (bool) $this->solved; - } - - /** - * API function - */ - function has_config() - { - return false; - } - -} - -/** -* Old class name for legacy use. The new class name is auto loadable. -*/ -class phpbb_default_captcha extends phpbb_captcha_plugins_captcha_abstract -{ -} diff --git a/phpBB/includes/captcha/plugins/phpbb_captcha_gd_plugin.php b/phpBB/includes/captcha/plugins/phpbb_captcha_gd_plugin.php deleted file mode 100644 index 80f5b65967..0000000000 --- a/phpBB/includes/captcha/plugins/phpbb_captcha_gd_plugin.php +++ /dev/null @@ -1,157 +0,0 @@ -<?php -/** -* -* @package VC -* @copyright (c) 2006, 2008 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Placeholder for autoload -*/ -if (!class_exists('phpbb_default_captcha', false)) -{ - include($phpbb_root_path . 'includes/captcha/plugins/captcha_abstract.' . $phpEx); -} - -/** -* @package VC -*/ -class phpbb_captcha_gd extends phpbb_default_captcha -{ - - var $captcha_vars = array( - 'captcha_gd_x_grid' => 'CAPTCHA_GD_X_GRID', - 'captcha_gd_y_grid' => 'CAPTCHA_GD_Y_GRID', - 'captcha_gd_foreground_noise' => 'CAPTCHA_GD_FOREGROUND_NOISE', -// 'captcha_gd' => 'CAPTCHA_GD_PREVIEWED', - 'captcha_gd_wave' => 'CAPTCHA_GD_WAVE', - 'captcha_gd_3d_noise' => 'CAPTCHA_GD_3D_NOISE', - 'captcha_gd_fonts' => 'CAPTCHA_GD_FONTS', - ); - - function phpbb_captcha_gd() - { - global $phpbb_root_path, $phpEx; - - if (!class_exists('captcha')) - { - include($phpbb_root_path . 'includes/captcha/captcha_gd.' . $phpEx); - } - } - - static public function get_instance() - { - $instance = new phpbb_captcha_gd(); - return $instance; - } - - static public function is_available() - { - return @extension_loaded('gd'); - } - - /** - * API function - */ - function has_config() - { - return true; - } - - static public function get_name() - { - return 'CAPTCHA_GD'; - } - - function get_class_name() - { - return 'phpbb_captcha_gd'; - } - - function acp_page($id, &$module) - { - global $db, $user, $auth, $template; - global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; - - $user->add_lang('acp/board'); - - $config_vars = array( - 'enable_confirm' => 'REG_ENABLE', - 'enable_post_confirm' => 'POST_ENABLE', - 'confirm_refresh' => 'CONFIRM_REFRESH', - 'captcha_gd' => 'CAPTCHA_GD', - ); - - $module->tpl_name = 'captcha_gd_acp'; - $module->page_title = 'ACP_VC_SETTINGS'; - $form_key = 'acp_captcha'; - add_form_key($form_key); - - $submit = request_var('submit', ''); - - if ($submit && check_form_key($form_key)) - { - $captcha_vars = array_keys($this->captcha_vars); - foreach ($captcha_vars as $captcha_var) - { - $value = request_var($captcha_var, 0); - if ($value >= 0) - { - set_config($captcha_var, $value); - } - } - - add_log('admin', 'LOG_CONFIG_VISUAL'); - trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($module->u_action)); - } - else if ($submit) - { - trigger_error($user->lang['FORM_INVALID'] . adm_back_link($module->u_action)); - } - else - { - foreach ($this->captcha_vars as $captcha_var => $template_var) - { - $var = (isset($_REQUEST[$captcha_var])) ? request_var($captcha_var, 0) : $config[$captcha_var]; - $template->assign_var($template_var, $var); - } - - $template->assign_vars(array( - 'CAPTCHA_PREVIEW' => $this->get_demo_template($id), - 'CAPTCHA_NAME' => $this->get_class_name(), - 'U_ACTION' => $module->u_action, - )); - } - } - - function execute_demo() - { - global $config; - - $config_old = $config; - - $config = new \phpbb\config\config(array()); - foreach ($config_old as $key => $value) - { - $config->set($key, $value); - } - - foreach ($this->captcha_vars as $captcha_var => $template_var) - { - $config->set($captcha_var, request_var($captcha_var, (int) $config[$captcha_var])); - } - parent::execute_demo(); - $config = $config_old; - } - -} diff --git a/phpBB/includes/captcha/plugins/phpbb_captcha_gd_wave_plugin.php b/phpBB/includes/captcha/plugins/phpbb_captcha_gd_wave_plugin.php deleted file mode 100644 index 0d4b8bd451..0000000000 --- a/phpBB/includes/captcha/plugins/phpbb_captcha_gd_wave_plugin.php +++ /dev/null @@ -1,68 +0,0 @@ -<?php -/** -* -* @package VC -* @copyright (c) 2006, 2008 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Placeholder for autoload -*/ -if (!class_exists('phpbb_default_captcha', false)) -{ - include($phpbb_root_path . 'includes/captcha/plugins/captcha_abstract.' . $phpEx); -} - -/** -* @package VC -*/ -class phpbb_captcha_gd_wave extends phpbb_default_captcha -{ - - function phpbb_captcha_gd_wave() - { - global $phpbb_root_path, $phpEx; - - if (!class_exists('captcha')) - { - include_once($phpbb_root_path . 'includes/captcha/captcha_gd_wave.' . $phpEx); - } - } - - static public function get_instance() - { - return new phpbb_captcha_gd_wave(); - } - - static public function is_available() - { - return @extension_loaded('gd'); - } - - static public function get_name() - { - return 'CAPTCHA_GD_3D'; - } - - function get_class_name() - { - return 'phpbb_captcha_gd_wave'; - } - - function acp_page($id, &$module) - { - global $config, $db, $template, $user; - - trigger_error($user->lang['CAPTCHA_NO_OPTIONS'] . adm_back_link($module->u_action)); - } -} diff --git a/phpBB/includes/captcha/plugins/phpbb_captcha_nogd_plugin.php b/phpBB/includes/captcha/plugins/phpbb_captcha_nogd_plugin.php deleted file mode 100644 index c5ef8c78b0..0000000000 --- a/phpBB/includes/captcha/plugins/phpbb_captcha_nogd_plugin.php +++ /dev/null @@ -1,69 +0,0 @@ -<?php -/** -* -* @package VC -* @copyright (c) 2006, 2008 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Placeholder for autoload -*/ -if (!class_exists('phpbb_default_captcha', false)) -{ - include($phpbb_root_path . 'includes/captcha/plugins/captcha_abstract.' . $phpEx); -} - -/** -* @package VC -*/ -class phpbb_captcha_nogd extends phpbb_default_captcha -{ - - function phpbb_captcha_nogd() - { - global $phpbb_root_path, $phpEx; - - if (!class_exists('captcha')) - { - include_once($phpbb_root_path . 'includes/captcha/captcha_non_gd.' . $phpEx); - } - } - - static public function get_instance() - { - $instance = new phpbb_captcha_nogd(); - return $instance; - } - - static public function is_available() - { - return true; - } - - static public function get_name() - { - return 'CAPTCHA_NO_GD'; - } - - function get_class_name() - { - return 'phpbb_captcha_nogd'; - } - - function acp_page($id, &$module) - { - global $user; - - trigger_error($user->lang['CAPTCHA_NO_OPTIONS'] . adm_back_link($module->u_action)); - } -} diff --git a/phpBB/includes/captcha/plugins/phpbb_captcha_qa_plugin.php b/phpBB/includes/captcha/plugins/phpbb_captcha_qa_plugin.php deleted file mode 100644 index 82333f739e..0000000000 --- a/phpBB/includes/captcha/plugins/phpbb_captcha_qa_plugin.php +++ /dev/null @@ -1,996 +0,0 @@ -<?php -/** -* -* @package VC -* @copyright (c) 2006, 2008 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -global $table_prefix; - -define('CAPTCHA_QUESTIONS_TABLE', $table_prefix . 'captcha_questions'); -define('CAPTCHA_ANSWERS_TABLE', $table_prefix . 'captcha_answers'); -define('CAPTCHA_QA_CONFIRM_TABLE', $table_prefix . 'qa_confirm'); - -/** -* And now to something completely different. Let's make a captcha without extending the abstract class. -* QA CAPTCHA sample implementation -* -* @package VC -*/ -class phpbb_captcha_qa -{ - var $confirm_id; - var $answer; - var $question_ids; - var $question_text; - var $question_lang; - var $question_strict; - var $attempts = 0; - var $type; - // dirty trick: 0 is false, but can still encode that the captcha is not yet validated - var $solved = 0; - - /** - * @param int $type as per the CAPTCHA API docs, the type - */ - function init($type) - { - global $config, $db, $user; - - // load our language file - $user->add_lang('captcha_qa'); - - // read input - $this->confirm_id = request_var('qa_confirm_id', ''); - $this->answer = utf8_normalize_nfc(request_var('qa_answer', '', true)); - - $this->type = (int) $type; - $this->question_lang = $user->lang_name; - - // we need all defined questions - shouldn't be too many, so we can just grab them - // try the user's lang first - $sql = 'SELECT question_id - FROM ' . CAPTCHA_QUESTIONS_TABLE . " - WHERE lang_iso = '" . $db->sql_escape($user->lang_name) . "'"; - $result = $db->sql_query($sql, 3600); - - while ($row = $db->sql_fetchrow($result)) - { - $this->question_ids[$row['question_id']] = $row['question_id']; - } - $db->sql_freeresult($result); - - // fallback to the board default lang - if (!sizeof($this->question_ids)) - { - $this->question_lang = $config['default_lang']; - - $sql = 'SELECT question_id - FROM ' . CAPTCHA_QUESTIONS_TABLE . " - WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'"; - $result = $db->sql_query($sql, 7200); - - while ($row = $db->sql_fetchrow($result)) - { - $this->question_ids[$row['question_id']] = $row['question_id']; - } - $db->sql_freeresult($result); - } - - // okay, if there is a confirm_id, we try to load that confirm's state. If not, we try to find one - if (!$this->load_answer() && (!$this->load_confirm_id() || !$this->load_answer())) - { - // we have no valid confirm ID, better get ready to ask something - $this->select_question(); - } - } - - /** - * API function - */ - static public function get_instance() - { - $instance = new phpbb_captcha_qa(); - - return $instance; - } - - /** - * See if the captcha has created its tables. - */ - static public function is_installed() - { - global $db; - - $db_tool = new \phpbb\db\tools($db); - - return $db_tool->sql_table_exists(CAPTCHA_QUESTIONS_TABLE); - } - - /** - * API function - for the captcha to be available, it must have installed itself and there has to be at least one question in the board's default lang - */ - static public function is_available() - { - global $config, $db, $phpbb_root_path, $phpEx, $user; - - // load language file for pretty display in the ACP dropdown - $user->add_lang('captcha_qa'); - - if (!self::is_installed()) - { - return false; - } - - $sql = 'SELECT COUNT(question_id) AS question_count - FROM ' . CAPTCHA_QUESTIONS_TABLE . " - WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'"; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - return ((bool) $row['question_count']); - } - - /** - * API function - */ - function has_config() - { - return true; - } - - /** - * API function - */ - static public function get_name() - { - return 'CAPTCHA_QA'; - } - - /** - * API function - */ - function get_class_name() - { - return 'phpbb_captcha_qa'; - } - - /** - * API function - not needed as we don't display an image - */ - function execute_demo() - { - } - - /** - * API function - not needed as we don't display an image - */ - function execute() - { - } - - /** - * API function - send the question to the template - */ - function get_template() - { - global $template; - - if ($this->is_solved()) - { - return false; - } - else - { - $template->assign_vars(array( - 'QA_CONFIRM_QUESTION' => $this->question_text, - 'QA_CONFIRM_ID' => $this->confirm_id, - 'S_CONFIRM_CODE' => true, - 'S_TYPE' => $this->type, - )); - - return 'captcha_qa.html'; - } - } - - /** - * API function - we just display a mockup so that the captcha doesn't need to be installed - */ - function get_demo_template() - { - global $config, $db, $template; - - if ($this->is_available()) - { - $sql = 'SELECT question_text - FROM ' . CAPTCHA_QUESTIONS_TABLE . " - WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'"; - $result = $db->sql_query_limit($sql, 1); - if ($row = $db->sql_fetchrow($result)) - { - $template->assign_vars(array( - 'QA_CONFIRM_QUESTION' => $row['question_text'], - )); - } - $db->sql_freeresult($result); - } - return 'captcha_qa_acp_demo.html'; - } - - /** - * API function - */ - function get_hidden_fields() - { - $hidden_fields = array(); - - // this is required - otherwise we would forget about the captcha being already solved - if ($this->solved) - { - $hidden_fields['qa_answer'] = $this->answer; - } - $hidden_fields['qa_confirm_id'] = $this->confirm_id; - - return $hidden_fields; - } - - /** - * API function - */ - function garbage_collect($type = 0) - { - global $db, $config; - - $sql = 'SELECT c.confirm_id - FROM ' . CAPTCHA_QA_CONFIRM_TABLE . ' c - LEFT JOIN ' . SESSIONS_TABLE . ' s - ON (c.session_id = s.session_id) - WHERE s.session_id IS NULL' . - ((empty($type)) ? '' : ' AND c.confirm_type = ' . (int) $type); - $result = $db->sql_query($sql); - - if ($row = $db->sql_fetchrow($result)) - { - $sql_in = array(); - - do - { - $sql_in[] = (string) $row['confirm_id']; - } - while ($row = $db->sql_fetchrow($result)); - - if (sizeof($sql_in)) - { - $sql = 'DELETE FROM ' . CAPTCHA_QA_CONFIRM_TABLE . ' - WHERE ' . $db->sql_in_set('confirm_id', $sql_in); - $db->sql_query($sql); - } - } - $db->sql_freeresult($result); - } - - /** - * API function - we don't drop the tables here, as that would cause the loss of all entered questions. - */ - function uninstall() - { - $this->garbage_collect(0); - } - - /** - * API function - set up shop - */ - function install() - { - global $db; - - $db_tool = new \phpbb\db\tools($db); - - $tables = array(CAPTCHA_QUESTIONS_TABLE, CAPTCHA_ANSWERS_TABLE, CAPTCHA_QA_CONFIRM_TABLE); - - $schemas = array( - CAPTCHA_QUESTIONS_TABLE => array ( - 'COLUMNS' => array( - 'question_id' => array('UINT', Null, 'auto_increment'), - 'strict' => array('BOOL', 0), - 'lang_id' => array('UINT', 0), - 'lang_iso' => array('VCHAR:30', ''), - 'question_text' => array('TEXT_UNI', ''), - ), - 'PRIMARY_KEY' => 'question_id', - 'KEYS' => array( - 'lang' => array('INDEX', 'lang_iso'), - ), - ), - CAPTCHA_ANSWERS_TABLE => array ( - 'COLUMNS' => array( - 'question_id' => array('UINT', 0), - 'answer_text' => array('STEXT_UNI', ''), - ), - 'KEYS' => array( - 'qid' => array('INDEX', 'question_id'), - ), - ), - CAPTCHA_QA_CONFIRM_TABLE => array ( - 'COLUMNS' => array( - 'session_id' => array('CHAR:32', ''), - 'confirm_id' => array('CHAR:32', ''), - 'lang_iso' => array('VCHAR:30', ''), - 'question_id' => array('UINT', 0), - 'attempts' => array('UINT', 0), - 'confirm_type' => array('USINT', 0), - ), - 'KEYS' => array( - 'session_id' => array('INDEX', 'session_id'), - 'lookup' => array('INDEX', array('confirm_id', 'session_id', 'lang_iso')), - ), - 'PRIMARY_KEY' => 'confirm_id', - ), - ); - - foreach($schemas as $table => $schema) - { - if (!$db_tool->sql_table_exists($table)) - { - $db_tool->sql_create_table($table, $schema); - } - } - } - - /** - * API function - see what has to be done to validate - */ - function validate() - { - global $config, $db, $user; - - $error = ''; - - if (!sizeof($this->question_ids)) - { - return false; - } - - if (!$this->confirm_id) - { - $error = $user->lang['CONFIRM_QUESTION_WRONG']; - } - else - { - if ($this->check_answer()) - { - $this->solved = true; - } - else - { - $error = $user->lang['CONFIRM_QUESTION_WRONG']; - } - } - - if (strlen($error)) - { - // okay, incorrect answer. Let's ask a new question. - $this->new_attempt(); - $this->solved = false; - - return $error; - } - else - { - return false; - } - } - - /** - * Select a question - */ - function select_question() - { - global $db, $user; - - if (!sizeof($this->question_ids)) - { - return false; - } - $this->confirm_id = md5(unique_id($user->ip)); - $this->question = (int) array_rand($this->question_ids); - - $sql = 'INSERT INTO ' . CAPTCHA_QA_CONFIRM_TABLE . ' ' . $db->sql_build_array('INSERT', array( - 'confirm_id' => (string) $this->confirm_id, - 'session_id' => (string) $user->session_id, - 'lang_iso' => (string) $this->question_lang, - 'confirm_type' => (int) $this->type, - 'question_id' => (int) $this->question, - )); - $db->sql_query($sql); - - $this->load_answer(); - } - - /** - * New Question, if desired. - */ - function reselect_question() - { - global $db, $user; - - if (!sizeof($this->question_ids)) - { - return false; - } - - $this->question = (int) array_rand($this->question_ids); - $this->solved = 0; - - $sql = 'UPDATE ' . CAPTCHA_QA_CONFIRM_TABLE . ' - SET question_id = ' . (int) $this->question . " - WHERE confirm_id = '" . $db->sql_escape($this->confirm_id) . "' - AND session_id = '" . $db->sql_escape($user->session_id) . "'"; - $db->sql_query($sql); - - $this->load_answer(); - } - - /** - * Wrong answer, so we increase the attempts and use a different question. - */ - function new_attempt() - { - global $db, $user; - - // yah, I would prefer a stronger rand, but this should work - $this->question = (int) array_rand($this->question_ids); - $this->solved = 0; - - $sql = 'UPDATE ' . CAPTCHA_QA_CONFIRM_TABLE . ' - SET question_id = ' . (int) $this->question . ", - attempts = attempts + 1 - WHERE confirm_id = '" . $db->sql_escape($this->confirm_id) . "' - AND session_id = '" . $db->sql_escape($user->session_id) . "'"; - $db->sql_query($sql); - - $this->load_answer(); - } - - - /** - * See if there is already an entry for the current session. - */ - function load_confirm_id() - { - global $db, $user; - - $sql = 'SELECT confirm_id - FROM ' . CAPTCHA_QA_CONFIRM_TABLE . " - WHERE - session_id = '" . $db->sql_escape($user->session_id) . "' - AND lang_iso = '" . $db->sql_escape($this->question_lang) . "' - AND confirm_type = " . $this->type; - $result = $db->sql_query_limit($sql, 1); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if ($row) - { - $this->confirm_id = $row['confirm_id']; - return true; - } - return false; - } - - /** - * Look up everything we need and populate the instance variables. - */ - function load_answer() - { - global $db, $user; - - if (!strlen($this->confirm_id) || !sizeof($this->question_ids)) - { - return false; - } - - $sql = 'SELECT con.question_id, attempts, question_text, strict - FROM ' . CAPTCHA_QA_CONFIRM_TABLE . ' con, ' . CAPTCHA_QUESTIONS_TABLE . " qes - WHERE con.question_id = qes.question_id - AND confirm_id = '" . $db->sql_escape($this->confirm_id) . "' - AND session_id = '" . $db->sql_escape($user->session_id) . "' - AND qes.lang_iso = '" . $db->sql_escape($this->question_lang) . "' - AND confirm_type = " . $this->type; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if ($row) - { - $this->question = $row['question_id']; - - $this->attempts = $row['attempts']; - $this->question_strict = $row['strict']; - $this->question_text = $row['question_text']; - - return true; - } - - return false; - } - - /** - * The actual validation - */ - function check_answer() - { - global $db; - - $answer = ($this->question_strict) ? utf8_normalize_nfc(request_var('qa_answer', '', true)) : utf8_clean_string(utf8_normalize_nfc(request_var('qa_answer', '', true))); - - $sql = 'SELECT answer_text - FROM ' . CAPTCHA_ANSWERS_TABLE . ' - WHERE question_id = ' . (int) $this->question; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - $solution = ($this->question_strict) ? $row['answer_text'] : utf8_clean_string($row['answer_text']); - - if ($solution === $answer) - { - $this->solved = true; - - break; - } - } - $db->sql_freeresult($result); - - return $this->solved; - } - - /** - * API function - */ - function get_attempt_count() - { - return $this->attempts; - } - - /** - * API function - */ - function reset() - { - global $db, $user; - - $sql = 'DELETE FROM ' . CAPTCHA_QA_CONFIRM_TABLE . " - WHERE session_id = '" . $db->sql_escape($user->session_id) . "' - AND confirm_type = " . (int) $this->type; - $db->sql_query($sql); - - // we leave the class usable by generating a new question - $this->select_question(); - } - - /** - * API function - */ - function is_solved() - { - if (request_var('qa_answer', false) && $this->solved === 0) - { - $this->validate(); - } - - return (bool) $this->solved; - } - - /** - * API function - The ACP backend, this marks the end of the easy methods - */ - function acp_page($id, &$module) - { - global $db, $user, $auth, $template; - global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; - - $user->add_lang('acp/board'); - $user->add_lang('captcha_qa'); - - if (!self::is_installed()) - { - $this->install(); - } - - $module->tpl_name = 'captcha_qa_acp'; - $module->page_title = 'ACP_VC_SETTINGS'; - $form_key = 'acp_captcha'; - add_form_key($form_key); - - $submit = request_var('submit', false); - $question_id = request_var('question_id', 0); - $action = request_var('action', ''); - - // we have two pages, so users might want to navigate from one to the other - $list_url = $module->u_action . "&configure=1&select_captcha=" . $this->get_class_name(); - - $template->assign_vars(array( - 'U_ACTION' => $module->u_action, - 'QUESTION_ID' => $question_id , - 'CLASS' => $this->get_class_name(), - )); - - // show the list? - if (!$question_id && $action != 'add') - { - $this->acp_question_list($module); - } - else if ($question_id && $action == 'delete') - { - if ($this->get_class_name() !== $config['captcha_plugin'] || !$this->acp_is_last($question_id)) - { - if (confirm_box(true)) - { - $this->acp_delete_question($question_id); - - trigger_error($user->lang['QUESTION_DELETED'] . adm_back_link($list_url)); - } - else - { - confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( - 'question_id' => $question_id, - 'action' => $action, - 'configure' => 1, - 'select_captcha' => $this->get_class_name(), - )) - ); - } - } - else - { - trigger_error($user->lang['QA_LAST_QUESTION'] . adm_back_link($list_url), E_USER_WARNING); - } - } - else - { - // okay, show the editor - $error = false; - $input_question = request_var('question_text', '', true); - $input_answers = request_var('answers', '', true); - $input_lang = request_var('lang_iso', '', true); - $input_strict = request_var('strict', false); - $langs = $this->get_languages(); - - foreach ($langs as $lang => $entry) - { - $template->assign_block_vars('langs', array( - 'ISO' => $lang, - 'NAME' => $entry['name'], - )); - } - - $template->assign_vars(array( - 'U_LIST' => $list_url, - )); - - if ($question_id) - { - if ($question = $this->acp_get_question_data($question_id)) - { - $answers = (isset($input_answers[$lang])) ? $input_answers[$lang] : implode("\n", $question['answers']); - - $template->assign_vars(array( - 'QUESTION_TEXT' => ($input_question) ? $input_question : $question['question_text'], - 'LANG_ISO' => ($input_lang) ? $input_lang : $question['lang_iso'], - 'STRICT' => (isset($_REQUEST['strict'])) ? $input_strict : $question['strict'], - 'ANSWERS' => $answers, - )); - } - else - { - trigger_error($user->lang['FORM_INVALID'] . adm_back_link($list_url)); - } - } - else - { - $template->assign_vars(array( - 'QUESTION_TEXT' => $input_question, - 'LANG_ISO' => $input_lang, - 'STRICT' => $input_strict, - 'ANSWERS' => $input_answers, - )); - } - - if ($submit && check_form_key($form_key)) - { - $data = $this->acp_get_question_input(); - - if (!$this->validate_input($data)) - { - $template->assign_vars(array( - 'S_ERROR' => true, - )); - } - else - { - if ($question_id) - { - $this->acp_update_question($data, $question_id); - } - else - { - $this->acp_add_question($data); - } - - add_log('admin', 'LOG_CONFIG_VISUAL'); - trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($list_url)); - } - } - else if ($submit) - { - trigger_error($user->lang['FORM_INVALID'] . adm_back_link($list_url), E_USER_WARNING); - } - } - } - - /** - * This handles the list overview - */ - function acp_question_list(&$module) - { - global $db, $template; - - $sql = 'SELECT * - FROM ' . CAPTCHA_QUESTIONS_TABLE; - $result = $db->sql_query($sql); - - $template->assign_vars(array( - 'S_LIST' => true, - )); - - while ($row = $db->sql_fetchrow($result)) - { - $url = $module->u_action . "&question_id={$row['question_id']}&configure=1&select_captcha=" . $this->get_class_name() . '&'; - - $template->assign_block_vars('questions', array( - 'QUESTION_TEXT' => $row['question_text'], - 'QUESTION_ID' => $row['question_id'], - 'QUESTION_LANG' => $row['lang_iso'], - 'U_DELETE' => "{$url}action=delete", - 'U_EDIT' => "{$url}action=edit", - )); - } - $db->sql_freeresult($result); - } - - /** - * Grab a question and bring it into a format the editor understands - */ - function acp_get_question_data($question_id) - { - global $db; - - if ($question_id) - { - $sql = 'SELECT * - FROM ' . CAPTCHA_QUESTIONS_TABLE . ' - WHERE question_id = ' . $question_id; - $result = $db->sql_query($sql); - $question = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if (!$question) - { - return false; - } - - $question['answers'] = array(); - - $sql = 'SELECT * - FROM ' . CAPTCHA_ANSWERS_TABLE . ' - WHERE question_id = ' . $question_id; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - $question['answers'][] = $row['answer_text']; - } - $db->sql_freeresult($result); - - return $question; - } - } - - /** - * Grab a question from input and bring it into a format the editor understands - */ - function acp_get_question_input() - { - $answers = utf8_normalize_nfc(request_var('answers', '', true)); - $question = array( - 'question_text' => request_var('question_text', '', true), - 'strict' => request_var('strict', false), - 'lang_iso' => request_var('lang_iso', ''), - 'answers' => (strlen($answers)) ? explode("\n", $answers) : '', - ); - - return $question; - } - - /** - * Update a question. - * param mixed $data : an array as created from acp_get_question_input or acp_get_question_data - */ - function acp_update_question($data, $question_id) - { - global $db, $cache; - - // easier to delete all answers than to figure out which to update - $sql = 'DELETE FROM ' . CAPTCHA_ANSWERS_TABLE . " WHERE question_id = $question_id"; - $db->sql_query($sql); - - $langs = $this->get_languages(); - $question_ary = $data; - $question_ary['lang_id'] = $langs[$question_ary['lang_iso']]['id']; - unset($question_ary['answers']); - - $sql = 'UPDATE ' . CAPTCHA_QUESTIONS_TABLE . ' - SET ' . $db->sql_build_array('UPDATE', $question_ary) . " - WHERE question_id = $question_id"; - $db->sql_query($sql); - - $this->acp_insert_answers($data, $question_id); - - $cache->destroy('sql', CAPTCHA_QUESTIONS_TABLE); - } - - /** - * Insert a question. - * param mixed $data : an array as created from acp_get_question_input or acp_get_question_data - */ - function acp_add_question($data) - { - global $db, $cache; - - $langs = $this->get_languages(); - $question_ary = $data; - - $question_ary['lang_id'] = $langs[$data['lang_iso']]['id']; - unset($question_ary['answers']); - - $sql = 'INSERT INTO ' . CAPTCHA_QUESTIONS_TABLE . ' ' . $db->sql_build_array('INSERT', $question_ary); - $db->sql_query($sql); - - $question_id = $db->sql_nextid(); - - $this->acp_insert_answers($data, $question_id); - - $cache->destroy('sql', CAPTCHA_QUESTIONS_TABLE); - } - - /** - * Insert the answers. - * param mixed $data : an array as created from acp_get_question_input or acp_get_question_data - */ - function acp_insert_answers($data, $question_id) - { - global $db, $cache; - - foreach ($data['answers'] as $answer) - { - $answer_ary = array( - 'question_id' => $question_id, - 'answer_text' => $answer, - ); - - $sql = 'INSERT INTO ' . CAPTCHA_ANSWERS_TABLE . ' ' . $db->sql_build_array('INSERT', $answer_ary); - $db->sql_query($sql); - } - - $cache->destroy('sql', CAPTCHA_ANSWERS_TABLE); - } - - /** - * Delete a question. - */ - function acp_delete_question($question_id) - { - global $db, $cache; - - $tables = array(CAPTCHA_QUESTIONS_TABLE, CAPTCHA_ANSWERS_TABLE); - - foreach ($tables as $table) - { - $sql = "DELETE FROM $table - WHERE question_id = $question_id"; - $db->sql_query($sql); - } - - $cache->destroy('sql', $tables); - } - - /** - * Check if the entered data can be inserted/used - * param mixed $data : an array as created from acp_get_question_input or acp_get_question_data - */ - function validate_input($question_data) - { - $langs = $this->get_languages(); - - if (!isset($question_data['lang_iso']) || - !isset($question_data['question_text']) || - !isset($question_data['strict']) || - !isset($question_data['answers'])) - { - return false; - } - - if (!isset($langs[$question_data['lang_iso']]) || - !strlen($question_data['question_text']) || - !sizeof($question_data['answers']) || - !is_array($question_data['answers'])) - { - return false; - } - - return true; - } - - /** - * List the installed language packs - */ - function get_languages() - { - global $db; - - $sql = 'SELECT * - FROM ' . LANG_TABLE; - $result = $db->sql_query($sql); - - $langs = array(); - while ($row = $db->sql_fetchrow($result)) - { - $langs[$row['lang_iso']] = array( - 'name' => $row['lang_local_name'], - 'id' => (int) $row['lang_id'], - ); - } - $db->sql_freeresult($result); - - return $langs; - } - - - - /** - * See if there is a question other than the one we have - */ - function acp_is_last($question_id) - { - global $config, $db; - - if ($question_id) - { - $sql = 'SELECT question_id - FROM ' . CAPTCHA_QUESTIONS_TABLE . " - WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "' - AND question_id <> " . (int) $question_id; - $result = $db->sql_query_limit($sql, 1); - $question = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if (!$question) - { - return true; - } - return false; - } - } -} diff --git a/phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php b/phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php deleted file mode 100644 index cb21b04ec5..0000000000 --- a/phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php +++ /dev/null @@ -1,343 +0,0 @@ -<?php -/** -* -* @package VC -* @copyright (c) 2006, 2008 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -if (!class_exists('phpbb_default_captcha', false)) -{ - // we need the classic captcha code for tracking solutions and attempts - include($phpbb_root_path . 'includes/captcha/plugins/captcha_abstract.' . $phpEx); -} - -/** -* @package VC -*/ -class phpbb_recaptcha extends phpbb_default_captcha -{ - var $recaptcha_server = 'http://www.google.com/recaptcha/api'; - var $recaptcha_server_secure = 'https://www.google.com/recaptcha/api'; // class constants :( - - // We are opening a socket to port 80 of this host and send - // the POST request asking for verification to the path specified here. - var $recaptcha_verify_server = 'www.google.com'; - var $recaptcha_verify_path = '/recaptcha/api/verify'; - - var $challenge; - var $response; - - // PHP4 Constructor - function phpbb_recaptcha() - { - global $request; - $this->recaptcha_server = $request->is_secure() ? $this->recaptcha_server_secure : $this->recaptcha_server; - } - - function init($type) - { - global $config, $db, $user; - - $user->add_lang('captcha_recaptcha'); - parent::init($type); - $this->challenge = request_var('recaptcha_challenge_field', ''); - $this->response = request_var('recaptcha_response_field', ''); - } - - static public function get_instance() - { - $instance = new phpbb_recaptcha(); - return $instance; - } - - static public function is_available() - { - global $config, $user; - $user->add_lang('captcha_recaptcha'); - return (isset($config['recaptcha_pubkey']) && !empty($config['recaptcha_pubkey'])); - } - - /** - * API function - */ - function has_config() - { - return true; - } - - static public function get_name() - { - return 'CAPTCHA_RECAPTCHA'; - } - - function get_class_name() - { - return 'phpbb_recaptcha'; - } - - function acp_page($id, &$module) - { - global $config, $db, $template, $user; - - $captcha_vars = array( - 'recaptcha_pubkey' => 'RECAPTCHA_PUBKEY', - 'recaptcha_privkey' => 'RECAPTCHA_PRIVKEY', - ); - - $module->tpl_name = 'captcha_recaptcha_acp'; - $module->page_title = 'ACP_VC_SETTINGS'; - $form_key = 'acp_captcha'; - add_form_key($form_key); - - $submit = request_var('submit', ''); - - if ($submit && check_form_key($form_key)) - { - $captcha_vars = array_keys($captcha_vars); - foreach ($captcha_vars as $captcha_var) - { - $value = request_var($captcha_var, ''); - if ($value) - { - set_config($captcha_var, $value); - } - } - - add_log('admin', 'LOG_CONFIG_VISUAL'); - trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($module->u_action)); - } - else if ($submit) - { - trigger_error($user->lang['FORM_INVALID'] . adm_back_link($module->u_action)); - } - else - { - foreach ($captcha_vars as $captcha_var => $template_var) - { - $var = (isset($_REQUEST[$captcha_var])) ? request_var($captcha_var, '') : ((isset($config[$captcha_var])) ? $config[$captcha_var] : ''); - $template->assign_var($template_var, $var); - } - - $template->assign_vars(array( - 'CAPTCHA_PREVIEW' => $this->get_demo_template($id), - 'CAPTCHA_NAME' => $this->get_class_name(), - 'U_ACTION' => $module->u_action, - )); - - } - } - - // not needed - function execute_demo() - { - } - - // not needed - function execute() - { - } - - function get_template() - { - global $config, $user, $template; - - if ($this->is_solved()) - { - return false; - } - else - { - $explain = $user->lang(($this->type != CONFIRM_POST) ? 'CONFIRM_EXPLAIN' : 'POST_CONFIRM_EXPLAIN', '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>'); - - $template->assign_vars(array( - 'RECAPTCHA_SERVER' => $this->recaptcha_server, - 'RECAPTCHA_PUBKEY' => isset($config['recaptcha_pubkey']) ? $config['recaptcha_pubkey'] : '', - 'RECAPTCHA_ERRORGET' => '', - 'S_RECAPTCHA_AVAILABLE' => self::is_available(), - 'S_CONFIRM_CODE' => true, - 'S_TYPE' => $this->type, - 'L_CONFIRM_EXPLAIN' => $explain, - )); - - return 'captcha_recaptcha.html'; - } - } - - function get_demo_template($id) - { - return $this->get_template(); - } - - function get_hidden_fields() - { - $hidden_fields = array(); - - // this is required for posting.php - otherwise we would forget about the captcha being already solved - if ($this->solved) - { - $hidden_fields['confirm_code'] = $this->code; - } - $hidden_fields['confirm_id'] = $this->confirm_id; - return $hidden_fields; - } - - function uninstall() - { - $this->garbage_collect(0); - } - - function install() - { - return; - } - - function validate() - { - if (!parent::validate()) - { - return false; - } - else - { - return $this->recaptcha_check_answer(); - } - } - -// Code from here on is based on recaptchalib.php -/* - * This is a PHP library that handles calling reCAPTCHA. - * - Documentation and latest version - * http://recaptcha.net/plugins/php/ - * - Get a reCAPTCHA API Key - * http://recaptcha.net/api/getkey - * - Discussion group - * http://groups.google.com/group/recaptcha - * - * Copyright (c) 2007 reCAPTCHA -- http://recaptcha.net - * AUTHORS: - * Mike Crawford - * Ben Maurer - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - - /** - * Submits an HTTP POST to a reCAPTCHA server - * @param string $host - * @param string $path - * @param array $data - * @param int port - * @return array response - */ - function _recaptcha_http_post($host, $path, $data, $port = 80) - { - $req = $this->_recaptcha_qsencode ($data); - - $http_request = "POST $path HTTP/1.0\r\n"; - $http_request .= "Host: $host\r\n"; - $http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n"; - $http_request .= "Content-Length: " . strlen($req) . "\r\n"; - $http_request .= "User-Agent: reCAPTCHA/PHP/phpBB\r\n"; - $http_request .= "\r\n"; - $http_request .= $req; - - $response = ''; - if (false == ($fs = @fsockopen($host, $port, $errno, $errstr, 10))) - { - trigger_error('RECAPTCHA_SOCKET_ERROR', E_USER_ERROR); - } - - fwrite($fs, $http_request); - - while (!feof($fs)) - { - // One TCP-IP packet - $response .= fgets($fs, 1160); - } - fclose($fs); - $response = explode("\r\n\r\n", $response, 2); - - return $response; - } - - /** - * Calls an HTTP POST function to verify if the user's guess was correct - * @param array $extra_params an array of extra variables to post to the server - * @return ReCaptchaResponse - */ - function recaptcha_check_answer($extra_params = array()) - { - global $config, $user; - - //discard spam submissions - if ($this->challenge == null || strlen($this->challenge) == 0 || $this->response == null || strlen($this->response) == 0) - { - return $user->lang['RECAPTCHA_INCORRECT']; - } - - $response = $this->_recaptcha_http_post($this->recaptcha_verify_server, $this->recaptcha_verify_path, - array( - 'privatekey' => $config['recaptcha_privkey'], - 'remoteip' => $user->ip, - 'challenge' => $this->challenge, - 'response' => $this->response - ) + $extra_params - ); - - $answers = explode("\n", $response[1]); - - if (trim($answers[0]) === 'true') - { - $this->solved = true; - return false; - } - else - { - return $user->lang['RECAPTCHA_INCORRECT']; - } - } - - /** - * Encodes the given data into a query string format - * @param $data - array of string elements to be encoded - * @return string - encoded request - */ - function _recaptcha_qsencode($data) - { - $req = ''; - foreach ($data as $key => $value) - { - $req .= $key . '=' . urlencode(stripslashes($value)) . '&'; - } - - // Cut the last '&' - $req = substr($req, 0, strlen($req) - 1); - return $req; - } -} diff --git a/phpBB/includes/compatibility_globals.php b/phpBB/includes/compatibility_globals.php new file mode 100644 index 0000000000..ae532c0f13 --- /dev/null +++ b/phpBB/includes/compatibility_globals.php @@ -0,0 +1,79 @@ +<?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; +} + +/** + * Sets compatibility globals in the global scope + * + * This function registers compatibility variables to the global + * variable scope. This is required to make it possible to include this file + * in a service. + */ +function register_compatibility_globals() +{ + global $phpbb_container; + + global $cache, $phpbb_dispatcher, $request, $user, $auth, $db, $config, $phpbb_log; + global $symfony_request, $phpbb_filesystem, $phpbb_path_helper, $phpbb_extension_manager, $template; + + // 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'); + + // Grab global variables, re-cache if necessary + /* @var $config phpbb\config\db */ + $config = $phpbb_container->get('config'); + + /* @var $phpbb_log \phpbb\log\log_interface */ + $phpbb_log = $phpbb_container->get('log'); + + /* @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'); + + // load extensions + /* @var $phpbb_extension_manager \phpbb\extension\manager */ + $phpbb_extension_manager = $phpbb_container->get('ext.manager'); + + /* @var $template \phpbb\template\template */ + $template = $phpbb_container->get('template'); +} + +register_compatibility_globals(); diff --git a/phpBB/includes/constants.php b/phpBB/includes/constants.php index c2c7ca0abd..8056abef00 100644 --- a/phpBB/includes/constants.php +++ b/phpBB/includes/constants.php @@ -1,9 +1,13 @@ <?php /** * -* @package phpBB3 -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -24,7 +28,7 @@ if (!defined('IN_PHPBB')) */ // phpBB Version -define('PHPBB_VERSION', '3.1.0-a4-dev'); +@define('PHPBB_VERSION', '3.2.0-a3-dev'); // QA-related // define('PHPBB_QA', 1); @@ -46,10 +50,10 @@ define('USER_INACTIVE', 1); define('USER_IGNORE', 2); define('USER_FOUNDER', 3); -define('INACTIVE_REGISTER', 1); -define('INACTIVE_PROFILE', 2); -define('INACTIVE_MANUAL', 3); -define('INACTIVE_REMIND', 4); +define('INACTIVE_REGISTER', 1); // Newly registered account +define('INACTIVE_PROFILE', 2); // Profile details changed +define('INACTIVE_MANUAL', 3); // Account deactivated by administrator +define('INACTIVE_REMIND', 4); // Forced user account reactivation // ACL define('ACL_NEVER', 0); @@ -91,6 +95,7 @@ define('ITEM_MOVED', 2); define('ITEM_UNAPPROVED', 0); // => has not yet been approved define('ITEM_APPROVED', 1); // => has been approved, and has not been soft deleted define('ITEM_DELETED', 2); // => has been soft deleted +define('ITEM_REAPPROVE', 3); // => has been edited and needs to be re-approved // Forum Flags define('FORUM_FLAG_LINK_TRACK', 1); @@ -166,11 +171,11 @@ define('CONFIRM_REPORT', 4); // Categories - Attachments define('ATTACHMENT_CATEGORY_NONE', 0); define('ATTACHMENT_CATEGORY_IMAGE', 1); // Inline Images -define('ATTACHMENT_CATEGORY_WM', 2); // Windows Media Files - Streaming -define('ATTACHMENT_CATEGORY_RM', 3); // Real Media Files - Streaming +define('ATTACHMENT_CATEGORY_WM', 2); // Windows Media Files - Streaming - @deprecated 3.2 +define('ATTACHMENT_CATEGORY_RM', 3); // Real Media Files - Streaming - @deprecated 3.2 define('ATTACHMENT_CATEGORY_THUMB', 4); // Not used within the database, only while displaying posts define('ATTACHMENT_CATEGORY_FLASH', 5); // Flash/SWF files -define('ATTACHMENT_CATEGORY_QUICKTIME', 6); // Quicktime/Mov files +define('ATTACHMENT_CATEGORY_QUICKTIME', 6); // Quicktime/Mov files - @deprecated 3.2 // BBCode UID length define('BBCODE_UID_LEN', 8); @@ -216,6 +221,9 @@ define('CAPTCHA_MAX_CHARS', 7); // Additional constants define('VOTE_CONVERTED', 127); +// BC global FTW +global $table_prefix; + // Table names define('ACL_GROUPS_TABLE', $table_prefix . 'acl_groups'); define('ACL_OPTIONS_TABLE', $table_prefix . 'acl_options'); @@ -227,7 +235,8 @@ define('BANLIST_TABLE', $table_prefix . 'banlist'); define('BBCODES_TABLE', $table_prefix . 'bbcodes'); define('BOOKMARKS_TABLE', $table_prefix . 'bookmarks'); define('BOTS_TABLE', $table_prefix . 'bots'); -define('CONFIG_TABLE', $table_prefix . 'config'); +@define('CONFIG_TABLE', $table_prefix . 'config'); +define('CONFIG_TEXT_TABLE', $table_prefix . 'config_text'); define('CONFIRM_TABLE', $table_prefix . 'confirm'); define('DISALLOW_TABLE', $table_prefix . 'disallow'); define('DRAFTS_TABLE', $table_prefix . 'drafts'); diff --git a/phpBB/includes/db/index.htm b/phpBB/includes/db/index.htm deleted file mode 100644 index ee1f723a7d..0000000000 --- a/phpBB/includes/db/index.htm +++ /dev/null @@ -1,10 +0,0 @@ -<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/includes/db/schema_data.php b/phpBB/includes/db/schema_data.php deleted file mode 100644 index dc85ff327b..0000000000 --- a/phpBB/includes/db/schema_data.php +++ /dev/null @@ -1,1221 +0,0 @@ -<?php -/** -* -* @package dbal -* @copyright (c) 2013 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -$schema_data = array(); - -/** -* Define the basic structure -* The format: -* array('{TABLE_NAME}' => {TABLE_DATA}) -* {TABLE_DATA}: -* COLUMNS = array({column_name} = array({column_type}, {default}, {auto_increment})) -* PRIMARY_KEY = {column_name(s)} -* KEYS = array({key_name} = array({key_type}, {column_name(s)})), -* -* Column Types: -* INT:x => SIGNED int(x) -* BINT => BIGINT -* ULINT => UNSIGNED int(10) -* UINT => mediumint(8) UNSIGNED -* UINT:x => int(x) UNSIGNED -* TINT:x => tinyint(x) -* USINT => smallint(4) UNSIGNED (for _order columns) -* BOOL => tinyint(1) UNSIGNED -* VCHAR => varchar(255) -* CHAR:x => char(x) -* XSTEXT_UNI => text for storing 100 characters (topic_title for example) -* STEXT_UNI => text for storing 255 characters (normal input field with a max of 255 single-byte chars) - same as VCHAR_UNI -* TEXT_UNI => text for storing 3000 characters (short text, descriptions, comments, etc.) -* MTEXT_UNI => mediumtext (post text, large text) -* VCHAR:x => varchar(x) -* TIMESTAMP => int(11) UNSIGNED -* DECIMAL => decimal number (5,2) -* DECIMAL: => decimal number (x,2) -* PDECIMAL => precision decimal number (6,3) -* PDECIMAL: => precision decimal number (x,3) -* VCHAR_UNI => varchar(255) BINARY -* VCHAR_CI => varchar_ci for postgresql, others VCHAR -*/ -$schema_data['phpbb_attachments'] = array( - 'COLUMNS' => array( - 'attach_id' => array('UINT', NULL, 'auto_increment'), - 'post_msg_id' => array('UINT', 0), - 'topic_id' => array('ULINT', 0), - 'in_message' => array('BOOL', 0), - 'poster_id' => array('UINT', 0), - 'is_orphan' => array('BOOL', 1), - 'physical_filename' => array('VCHAR', ''), - 'real_filename' => array('VCHAR', ''), - 'download_count' => array('UINT', 0), - 'attach_comment' => array('TEXT_UNI', ''), - 'extension' => array('VCHAR:100', ''), - 'mimetype' => array('VCHAR:100', ''), - 'filesize' => array('UINT:20', 0), - 'filetime' => array('TIMESTAMP', 0), - 'thumbnail' => array('BOOL', 0), - ), - 'PRIMARY_KEY' => 'attach_id', - 'KEYS' => array( - 'filetime' => array('INDEX', 'filetime'), - 'post_msg_id' => array('INDEX', 'post_msg_id'), - 'topic_id' => array('INDEX', 'topic_id'), - 'poster_id' => array('INDEX', 'poster_id'), - 'is_orphan' => array('INDEX', 'is_orphan'), - ), -); - -$schema_data['phpbb_acl_groups'] = array( - 'COLUMNS' => array( - 'group_id' => array('UINT', 0), - 'forum_id' => array('UINT', 0), - 'auth_option_id' => array('UINT', 0), - 'auth_role_id' => array('UINT', 0), - 'auth_setting' => array('TINT:2', 0), - ), - 'KEYS' => array( - 'group_id' => array('INDEX', 'group_id'), - 'auth_opt_id' => array('INDEX', 'auth_option_id'), - 'auth_role_id' => array('INDEX', 'auth_role_id'), - ), -); - -$schema_data['phpbb_acl_options'] = array( - 'COLUMNS' => array( - 'auth_option_id' => array('UINT', NULL, 'auto_increment'), - 'auth_option' => array('VCHAR:50', ''), - 'is_global' => array('BOOL', 0), - 'is_local' => array('BOOL', 0), - 'founder_only' => array('BOOL', 0), - ), - 'PRIMARY_KEY' => 'auth_option_id', - 'KEYS' => array( - 'auth_option' => array('UNIQUE', 'auth_option'), - ), -); - -$schema_data['phpbb_acl_roles'] = array( - 'COLUMNS' => array( - 'role_id' => array('UINT', NULL, 'auto_increment'), - 'role_name' => array('VCHAR_UNI', ''), - 'role_description' => array('TEXT_UNI', ''), - 'role_type' => array('VCHAR:10', ''), - 'role_order' => array('USINT', 0), - ), - 'PRIMARY_KEY' => 'role_id', - 'KEYS' => array( - 'role_type' => array('INDEX', 'role_type'), - 'role_order' => array('INDEX', 'role_order'), - ), -); - -$schema_data['phpbb_acl_roles_data'] = array( - 'COLUMNS' => array( - 'role_id' => array('UINT', 0), - 'auth_option_id' => array('UINT', 0), - 'auth_setting' => array('TINT:2', 0), - ), - 'PRIMARY_KEY' => array('role_id', 'auth_option_id'), - 'KEYS' => array( - 'ath_op_id' => array('INDEX', 'auth_option_id'), - ), -); - -$schema_data['phpbb_acl_users'] = array( - 'COLUMNS' => array( - 'user_id' => array('ULINT', 0), - 'forum_id' => array('UINT', 0), - 'auth_option_id' => array('UINT', 0), - 'auth_role_id' => array('UINT', 0), - 'auth_setting' => array('TINT:2', 0), - ), - 'KEYS' => array( - 'user_id' => array('INDEX', 'user_id'), - 'auth_option_id' => array('INDEX', 'auth_option_id'), - 'auth_role_id' => array('INDEX', 'auth_role_id'), - ), -); - -$schema_data['phpbb_banlist'] = array( - 'COLUMNS' => array( - 'ban_id' => array('UINT', NULL, 'auto_increment'), - 'ban_userid' => array('UINT', 0), - 'ban_ip' => array('VCHAR:40', ''), - 'ban_email' => array('VCHAR_UNI:100', ''), - 'ban_start' => array('TIMESTAMP', 0), - 'ban_end' => array('TIMESTAMP', 0), - 'ban_exclude' => array('BOOL', 0), - 'ban_reason' => array('VCHAR_UNI', ''), - 'ban_give_reason' => array('VCHAR_UNI', ''), - ), - 'PRIMARY_KEY' => 'ban_id', - 'KEYS' => array( - 'ban_end' => array('INDEX', 'ban_end'), - 'ban_user' => array('INDEX', array('ban_userid', 'ban_exclude')), - 'ban_email' => array('INDEX', array('ban_email', 'ban_exclude')), - 'ban_ip' => array('INDEX', array('ban_ip', 'ban_exclude')), - ), -); - -$schema_data['phpbb_bbcodes'] = array( - 'COLUMNS' => array( - 'bbcode_id' => array('USINT', 0), - 'bbcode_tag' => array('VCHAR:16', ''), - 'bbcode_helpline' => array('VCHAR_UNI', ''), - 'display_on_posting' => array('BOOL', 0), - 'bbcode_match' => array('TEXT_UNI', ''), - 'bbcode_tpl' => array('MTEXT_UNI', ''), - 'first_pass_match' => array('MTEXT_UNI', ''), - 'first_pass_replace' => array('MTEXT_UNI', ''), - 'second_pass_match' => array('MTEXT_UNI', ''), - 'second_pass_replace' => array('MTEXT_UNI', ''), - ), - 'PRIMARY_KEY' => 'bbcode_id', - 'KEYS' => array( - 'display_on_post' => array('INDEX', 'display_on_posting'), - ), -); - -$schema_data['phpbb_bookmarks'] = array( - 'COLUMNS' => array( - 'topic_id' => array('ULINT', 0), - 'user_id' => array('ULINT', 0), - ), - 'PRIMARY_KEY' => array('topic_id', 'user_id'), -); - -$schema_data['phpbb_bots'] = array( - 'COLUMNS' => array( - 'bot_id' => array('UINT', NULL, 'auto_increment'), - 'bot_active' => array('BOOL', 1), - 'bot_name' => array('STEXT_UNI', ''), - 'user_id' => array('ULINT', 0), - 'bot_agent' => array('VCHAR', ''), - 'bot_ip' => array('VCHAR', ''), - ), - 'PRIMARY_KEY' => 'bot_id', - 'KEYS' => array( - 'bot_active' => array('INDEX', 'bot_active'), - ), -); - -$schema_data['phpbb_config'] = array( - 'COLUMNS' => array( - 'config_name' => array('VCHAR', ''), - 'config_value' => array('VCHAR_UNI', ''), - 'is_dynamic' => array('BOOL', 0), - ), - 'PRIMARY_KEY' => 'config_name', - 'KEYS' => array( - 'is_dynamic' => array('INDEX', 'is_dynamic'), - ), -); - -$schema_data['phpbb_config_text'] = array( - 'COLUMNS' => array( - 'config_name' => array('VCHAR', ''), - 'config_value' => array('MTEXT', ''), - ), - 'PRIMARY_KEY' => 'config_name', -); - -$schema_data['phpbb_confirm'] = array( - 'COLUMNS' => array( - 'confirm_id' => array('CHAR:32', ''), - 'session_id' => array('CHAR:32', ''), - 'confirm_type' => array('TINT:3', 0), - 'code' => array('VCHAR:8', ''), - 'seed' => array('UINT:10', 0), - 'attempts' => array('UINT', 0), - ), - 'PRIMARY_KEY' => array('session_id', 'confirm_id'), - 'KEYS' => array( - 'confirm_type' => array('INDEX', 'confirm_type'), - ), -); - -$schema_data['phpbb_disallow'] = array( - 'COLUMNS' => array( - 'disallow_id' => array('UINT', NULL, 'auto_increment'), - 'disallow_username' => array('VCHAR_UNI:255', ''), - ), - 'PRIMARY_KEY' => 'disallow_id', -); - -$schema_data['phpbb_drafts'] = array( - 'COLUMNS' => array( - 'draft_id' => array('UINT', NULL, 'auto_increment'), - 'user_id' => array('ULINT', 0), - 'topic_id' => array('ULINT', 0), - 'forum_id' => array('UINT', 0), - 'save_time' => array('TIMESTAMP', 0), - 'draft_subject' => array('STEXT_UNI', ''), - 'draft_message' => array('MTEXT_UNI', ''), - ), - 'PRIMARY_KEY' => 'draft_id', - 'KEYS' => array( - 'save_time' => array('INDEX', 'save_time'), - ), -); - -$schema_data['phpbb_ext'] = array( - 'COLUMNS' => array( - 'ext_name' => array('VCHAR', ''), - 'ext_active' => array('BOOL', 0), - 'ext_state' => array('TEXT', ''), - ), - 'KEYS' => array( - 'ext_name' => array('UNIQUE', 'ext_name'), - ), -); - -$schema_data['phpbb_extensions'] = array( - 'COLUMNS' => array( - 'extension_id' => array('UINT', NULL, 'auto_increment'), - 'group_id' => array('UINT', 0), - 'extension' => array('VCHAR:100', ''), - ), - 'PRIMARY_KEY' => 'extension_id', -); - -$schema_data['phpbb_extension_groups'] = array( - 'COLUMNS' => array( - 'group_id' => array('UINT', NULL, 'auto_increment'), - 'group_name' => array('VCHAR_UNI', ''), - 'cat_id' => array('TINT:2', 0), - 'allow_group' => array('BOOL', 0), - 'download_mode' => array('BOOL', 1), - 'upload_icon' => array('VCHAR', ''), - 'max_filesize' => array('UINT:20', 0), - 'allowed_forums' => array('TEXT', ''), - 'allow_in_pm' => array('BOOL', 0), - ), - 'PRIMARY_KEY' => 'group_id', -); - -$schema_data['phpbb_forums'] = array( - 'COLUMNS' => array( - 'forum_id' => array('UINT', NULL, 'auto_increment'), - 'parent_id' => array('UINT', 0), - 'left_id' => array('UINT', 0), - 'right_id' => array('UINT', 0), - 'forum_parents' => array('MTEXT', ''), - 'forum_name' => array('STEXT_UNI', ''), - 'forum_desc' => array('TEXT_UNI', ''), - 'forum_desc_bitfield' => array('VCHAR:255', ''), - 'forum_desc_options' => array('UINT:11', 7), - 'forum_desc_uid' => array('VCHAR:8', ''), - 'forum_link' => array('VCHAR_UNI', ''), - 'forum_password' => array('VCHAR_UNI', ''), - 'forum_style' => array('UINT', 0), - 'forum_image' => array('VCHAR', ''), - 'forum_rules' => array('TEXT_UNI', ''), - 'forum_rules_link' => array('VCHAR_UNI', ''), - 'forum_rules_bitfield' => array('VCHAR:255', ''), - 'forum_rules_options' => array('UINT:11', 7), - 'forum_rules_uid' => array('VCHAR:8', ''), - 'forum_topics_per_page' => array('TINT:4', 0), - 'forum_type' => array('TINT:4', 0), - 'forum_status' => array('TINT:4', 0), - 'forum_posts_approved' => array('UINT', 0), - 'forum_posts_unapproved' => array('UINT', 0), - 'forum_posts_softdeleted' => array('UINT', 0), - 'forum_topics_approved' => array('UINT', 0), - 'forum_topics_unapproved' => array('UINT', 0), - 'forum_topics_softdeleted' => array('UINT', 0), - 'forum_last_post_id' => array('UINT', 0), - 'forum_last_poster_id' => array('UINT', 0), - 'forum_last_post_subject' => array('STEXT_UNI', ''), - 'forum_last_post_time' => array('TIMESTAMP', 0), - 'forum_last_poster_name'=> array('VCHAR_UNI', ''), - 'forum_last_poster_colour'=> array('VCHAR:6', ''), - 'forum_flags' => array('TINT:4', 32), - 'forum_options' => array('UINT:20', 0), - 'display_subforum_list' => array('BOOL', 1), - 'display_on_index' => array('BOOL', 1), - 'enable_indexing' => array('BOOL', 1), - 'enable_icons' => array('BOOL', 1), - 'enable_prune' => array('BOOL', 0), - 'prune_next' => array('TIMESTAMP', 0), - 'prune_days' => array('UINT', 0), - 'prune_viewed' => array('UINT', 0), - 'prune_freq' => array('UINT', 0), - ), - 'PRIMARY_KEY' => 'forum_id', - 'KEYS' => array( - 'left_right_id' => array('INDEX', array('left_id', 'right_id')), - 'forum_lastpost_id' => array('INDEX', 'forum_last_post_id'), - ), -); - -$schema_data['phpbb_forums_access'] = array( - 'COLUMNS' => array( - 'forum_id' => array('UINT', 0), - 'user_id' => array('ULINT', 0), - 'session_id' => array('CHAR:32', ''), - ), - 'PRIMARY_KEY' => array('forum_id', 'user_id', 'session_id'), -); - -$schema_data['phpbb_forums_track'] = array( - 'COLUMNS' => array( - 'user_id' => array('ULINT', 0), - 'forum_id' => array('UINT', 0), - 'mark_time' => array('TIMESTAMP', 0), - ), - 'PRIMARY_KEY' => array('user_id', 'forum_id'), -); - -$schema_data['phpbb_forums_watch'] = array( - 'COLUMNS' => array( - 'forum_id' => array('UINT', 0), - 'user_id' => array('ULINT', 0), - 'notify_status' => array('BOOL', 0), - ), - 'KEYS' => array( - 'forum_id' => array('INDEX', 'forum_id'), - 'user_id' => array('INDEX', 'user_id'), - 'notify_stat' => array('INDEX', 'notify_status'), - ), -); - -$schema_data['phpbb_groups'] = array( - 'COLUMNS' => array( - 'group_id' => array('UINT', NULL, 'auto_increment'), - 'group_type' => array('TINT:4', 1), - 'group_founder_manage' => array('BOOL', 0), - 'group_skip_auth' => array('BOOL', 0), - 'group_name' => array('VCHAR_CI', ''), - 'group_desc' => array('TEXT_UNI', ''), - 'group_desc_bitfield' => array('VCHAR:255', ''), - 'group_desc_options' => array('UINT:11', 7), - 'group_desc_uid' => array('VCHAR:8', ''), - 'group_display' => array('BOOL', 0), - 'group_avatar' => array('VCHAR', ''), - 'group_avatar_type' => array('VCHAR:255', ''), - 'group_avatar_width' => array('USINT', 0), - 'group_avatar_height' => array('USINT', 0), - 'group_rank' => array('UINT', 0), - 'group_colour' => array('VCHAR:6', ''), - 'group_sig_chars' => array('UINT', 0), - 'group_receive_pm' => array('BOOL', 0), - 'group_message_limit' => array('UINT', 0), - 'group_max_recipients' => array('UINT', 0), - 'group_legend' => array('UINT', 0), - ), - 'PRIMARY_KEY' => 'group_id', - 'KEYS' => array( - 'group_legend_name' => array('INDEX', array('group_legend', 'group_name')), - ), -); - -$schema_data['phpbb_icons'] = array( - 'COLUMNS' => array( - 'icons_id' => array('UINT', NULL, 'auto_increment'), - 'icons_url' => array('VCHAR', ''), - 'icons_width' => array('TINT:4', 0), - 'icons_height' => array('TINT:4', 0), - 'icons_order' => array('UINT', 0), - 'display_on_posting' => array('BOOL', 1), - ), - 'PRIMARY_KEY' => 'icons_id', - 'KEYS' => array( - 'display_on_posting' => array('INDEX', 'display_on_posting'), - ), -); - -$schema_data['phpbb_lang'] = array( - 'COLUMNS' => array( - 'lang_id' => array('TINT:4', NULL, 'auto_increment'), - 'lang_iso' => array('VCHAR:30', ''), - 'lang_dir' => array('VCHAR:30', ''), - 'lang_english_name' => array('VCHAR_UNI:100', ''), - 'lang_local_name' => array('VCHAR_UNI:255', ''), - 'lang_author' => array('VCHAR_UNI:255', ''), - ), - 'PRIMARY_KEY' => 'lang_id', - 'KEYS' => array( - 'lang_iso' => array('INDEX', 'lang_iso'), - ), -); - -$schema_data['phpbb_log'] = array( - 'COLUMNS' => array( - 'log_id' => array('UINT', NULL, 'auto_increment'), - 'log_type' => array('TINT:4', 0), - 'user_id' => array('ULINT', 0), - 'forum_id' => array('UINT', 0), - 'topic_id' => array('ULINT', 0), - 'reportee_id' => array('UINT', 0), - 'log_ip' => array('VCHAR:40', ''), - 'log_time' => array('TIMESTAMP', 0), - 'log_operation' => array('TEXT_UNI', ''), - 'log_data' => array('MTEXT_UNI', ''), - ), - 'PRIMARY_KEY' => 'log_id', - 'KEYS' => array( - 'log_type' => array('INDEX', 'log_type'), - 'log_time' => array('INDEX', 'log_time'), - 'forum_id' => array('INDEX', 'forum_id'), - 'topic_id' => array('INDEX', 'topic_id'), - 'reportee_id' => array('INDEX', 'reportee_id'), - 'user_id' => array('INDEX', 'user_id'), - ), -); - -$schema_data['phpbb_login_attempts'] = array( - 'COLUMNS' => array( - 'attempt_ip' => array('VCHAR:40', ''), - 'attempt_browser' => array('VCHAR:150', ''), - 'attempt_forwarded_for' => array('VCHAR:255', ''), - 'attempt_time' => array('TIMESTAMP', 0), - 'user_id' => array('ULINT', 0), - 'username' => array('VCHAR_UNI:255', 0), - 'username_clean' => array('VCHAR_CI', 0), - ), - 'KEYS' => array( - 'att_ip' => array('INDEX', array('attempt_ip', 'attempt_time')), - 'att_for' => array('INDEX', array('attempt_forwarded_for', 'attempt_time')), - 'att_time' => array('INDEX', array('attempt_time')), - 'user_id' => array('INDEX', 'user_id'), - ), -); - -$schema_data['phpbb_moderator_cache'] = array( - 'COLUMNS' => array( - 'forum_id' => array('UINT', 0), - 'user_id' => array('ULINT', 0), - 'username' => array('VCHAR_UNI:255', ''), - 'group_id' => array('UINT', 0), - 'group_name' => array('VCHAR_UNI', ''), - 'display_on_index' => array('BOOL', 1), - ), - 'KEYS' => array( - 'disp_idx' => array('INDEX', 'display_on_index'), - 'forum_id' => array('INDEX', 'forum_id'), - ), -); - -$schema_data['phpbb_migrations'] = array( - 'COLUMNS' => array( - 'migration_name' => array('VCHAR', ''), - 'migration_depends_on' => array('TEXT', ''), - 'migration_schema_done' => array('BOOL', 0), - 'migration_data_done' => array('BOOL', 0), - 'migration_data_state' => array('TEXT', ''), - 'migration_start_time' => array('TIMESTAMP', 0), - 'migration_end_time' => array('TIMESTAMP', 0), - ), - 'PRIMARY_KEY' => 'migration_name', -); - -$schema_data['phpbb_modules'] = array( - 'COLUMNS' => array( - 'module_id' => array('UINT', NULL, 'auto_increment'), - 'module_enabled' => array('BOOL', 1), - 'module_display' => array('BOOL', 1), - 'module_basename' => array('VCHAR', ''), - 'module_class' => array('VCHAR:10', ''), - 'parent_id' => array('UINT', 0), - 'left_id' => array('UINT', 0), - 'right_id' => array('UINT', 0), - 'module_langname' => array('VCHAR', ''), - 'module_mode' => array('VCHAR', ''), - 'module_auth' => array('VCHAR', ''), - ), - 'PRIMARY_KEY' => 'module_id', - 'KEYS' => array( - 'left_right_id' => array('INDEX', array('left_id', 'right_id')), - 'module_enabled' => array('INDEX', 'module_enabled'), - 'class_left_id' => array('INDEX', array('module_class', 'left_id')), - ), -); - -$schema_data['phpbb_notification_types'] = array( - 'COLUMNS' => array( - 'notification_type_id' => array('USINT', NULL, 'auto_increment'), - 'notification_type_name' => array('VCHAR:255', ''), - 'notification_type_enabled' => array('BOOL', 1), - ), - 'PRIMARY_KEY' => array('notification_type_id'), - 'KEYS' => array( - 'type' => array('UNIQUE', array('notification_type_name')), - ), -); - -$schema_data['phpbb_notifications'] = array( - 'COLUMNS' => array( - 'notification_id' => array('UINT:10', NULL, 'auto_increment'), - 'notification_type_id' => array('USINT', 0), - 'item_id' => array('UINT', 0), - 'item_parent_id' => array('UINT', 0), - 'user_id' => array('ULINT', 0), - 'notification_read' => array('BOOL', 0), - 'notification_time' => array('TIMESTAMP', 1), - 'notification_data' => array('TEXT_UNI', ''), - ), - 'PRIMARY_KEY' => 'notification_id', - 'KEYS' => array( - 'item_ident' => array('INDEX', array('notification_type_id', 'item_id')), - 'user' => array('INDEX', array('user_id', 'notification_read')), - ), -); - -$schema_data['phpbb_oauth_accounts'] = array( - 'COLUMNS' => array( - 'user_id' => array('ULINT', 0), - 'provider' => array('VCHAR', ''), - 'oauth_provider_id' => array('TEXT_UNI', ''), - ), - 'PRIMARY_KEY' => array( - 'user_id', - 'provider', - ), -); - -$schema_data['phpbb_oauth_tokens'] = array( - 'COLUMNS' => array( - 'user_id' => array('ULINT', 0), // phpbb_users.user_id - 'session_id' => array('CHAR:32', ''), // phpbb_sessions.session_id used only when user_id not set - 'provider' => array('VCHAR', ''), // Name of the OAuth provider - 'oauth_token' => array('MTEXT', ''), // Serialized token - ), - 'KEYS' => array( - 'user_id' => array('INDEX', 'user_id'), - 'provider' => array('INDEX', 'provider'), - ), -); - -$schema_data['phpbb_poll_options'] = array( - 'COLUMNS' => array( - 'poll_option_id' => array('TINT:4', 0), - 'topic_id' => array('ULINT', 0), - 'poll_option_text' => array('TEXT_UNI', ''), - 'poll_option_total' => array('UINT', 0), - ), - 'KEYS' => array( - 'poll_opt_id' => array('INDEX', 'poll_option_id'), - 'topic_id' => array('INDEX', 'topic_id'), - ), -); - -$schema_data['phpbb_poll_votes'] = array( - 'COLUMNS' => array( - 'topic_id' => array('ULINT', 0), - 'poll_option_id' => array('TINT:4', 0), - 'vote_user_id' => array('UINT', 0), - 'vote_user_ip' => array('VCHAR:40', ''), - ), - 'KEYS' => array( - 'topic_id' => array('INDEX', 'topic_id'), - 'vote_user_id' => array('INDEX', 'vote_user_id'), - 'vote_user_ip' => array('INDEX', 'vote_user_ip'), - ), -); - -$schema_data['phpbb_posts'] = array( - 'COLUMNS' => array( - 'post_id' => array('ULINT', NULL, 'auto_increment'), - 'topic_id' => array('ULINT', 0), - 'forum_id' => array('UINT', 0), - 'poster_id' => array('UINT', 0), - 'icon_id' => array('UINT', 0), - 'poster_ip' => array('VCHAR:40', ''), - 'post_time' => array('TIMESTAMP', 0), - 'post_visibility' => array('TINT:3', 0), - 'post_reported' => array('BOOL', 0), - 'enable_bbcode' => array('BOOL', 1), - 'enable_smilies' => array('BOOL', 1), - 'enable_magic_url' => array('BOOL', 1), - 'enable_sig' => array('BOOL', 1), - 'post_username' => array('VCHAR_UNI:255', ''), - 'post_subject' => array('STEXT_UNI', '', 'true_sort'), - 'post_text' => array('MTEXT_UNI', ''), - 'post_checksum' => array('VCHAR:32', ''), - 'post_attachment' => array('BOOL', 0), - 'bbcode_bitfield' => array('VCHAR:255', ''), - 'bbcode_uid' => array('VCHAR:8', ''), - 'post_postcount' => array('BOOL', 1), - 'post_edit_time' => array('TIMESTAMP', 0), - 'post_edit_reason' => array('STEXT_UNI', ''), - 'post_edit_user' => array('UINT', 0), - 'post_edit_count' => array('USINT', 0), - 'post_edit_locked' => array('BOOL', 0), - 'post_delete_time' => array('TIMESTAMP', 0), - 'post_delete_reason' => array('STEXT_UNI', ''), - 'post_delete_user' => array('UINT', 0), - ), - 'PRIMARY_KEY' => 'post_id', - 'KEYS' => array( - 'forum_id' => array('INDEX', 'forum_id'), - 'topic_id' => array('INDEX', 'topic_id'), - 'poster_ip' => array('INDEX', 'poster_ip'), - 'poster_id' => array('INDEX', 'poster_id'), - 'post_visibility' => array('INDEX', 'post_visibility'), - 'post_username' => array('INDEX', 'post_username'), - 'tid_post_time' => array('INDEX', array('topic_id', 'post_time')), - ), -); - -$schema_data['phpbb_privmsgs'] = array( - 'COLUMNS' => array( - 'msg_id' => array('UINT', NULL, 'auto_increment'), - 'root_level' => array('UINT', 0), - 'author_id' => array('UINT', 0), - 'icon_id' => array('UINT', 0), - 'author_ip' => array('VCHAR:40', ''), - 'message_time' => array('TIMESTAMP', 0), - 'enable_bbcode' => array('BOOL', 1), - 'enable_smilies' => array('BOOL', 1), - 'enable_magic_url' => array('BOOL', 1), - 'enable_sig' => array('BOOL', 1), - 'message_subject' => array('STEXT_UNI', ''), - 'message_text' => array('MTEXT_UNI', ''), - 'message_edit_reason' => array('STEXT_UNI', ''), - 'message_edit_user' => array('UINT', 0), - 'message_attachment' => array('BOOL', 0), - 'bbcode_bitfield' => array('VCHAR:255', ''), - 'bbcode_uid' => array('VCHAR:8', ''), - 'message_edit_time' => array('TIMESTAMP', 0), - 'message_edit_count' => array('USINT', 0), - 'to_address' => array('TEXT_UNI', ''), - 'bcc_address' => array('TEXT_UNI', ''), - 'message_reported' => array('BOOL', 0), - ), - 'PRIMARY_KEY' => 'msg_id', - 'KEYS' => array( - 'author_ip' => array('INDEX', 'author_ip'), - 'message_time' => array('INDEX', 'message_time'), - 'author_id' => array('INDEX', 'author_id'), - 'root_level' => array('INDEX', 'root_level'), - ), -); - -$schema_data['phpbb_privmsgs_folder'] = array( - 'COLUMNS' => array( - 'folder_id' => array('UINT', NULL, 'auto_increment'), - 'user_id' => array('ULINT', 0), - 'folder_name' => array('VCHAR_UNI', ''), - 'pm_count' => array('UINT', 0), - ), - 'PRIMARY_KEY' => 'folder_id', - 'KEYS' => array( - 'user_id' => array('INDEX', 'user_id'), - ), -); - -$schema_data['phpbb_privmsgs_rules'] = array( - 'COLUMNS' => array( - 'rule_id' => array('UINT', NULL, 'auto_increment'), - 'user_id' => array('ULINT', 0), - 'rule_check' => array('UINT', 0), - 'rule_connection' => array('UINT', 0), - 'rule_string' => array('VCHAR_UNI', ''), - 'rule_user_id' => array('UINT', 0), - 'rule_group_id' => array('UINT', 0), - 'rule_action' => array('UINT', 0), - 'rule_folder_id' => array('INT:11', 0), - ), - 'PRIMARY_KEY' => 'rule_id', - 'KEYS' => array( - 'user_id' => array('INDEX', 'user_id'), - ), -); - -$schema_data['phpbb_privmsgs_to'] = array( - 'COLUMNS' => array( - 'msg_id' => array('UINT', 0), - 'user_id' => array('ULINT', 0), - 'author_id' => array('UINT', 0), - 'pm_deleted' => array('BOOL', 0), - 'pm_new' => array('BOOL', 1), - 'pm_unread' => array('BOOL', 1), - 'pm_replied' => array('BOOL', 0), - 'pm_marked' => array('BOOL', 0), - 'pm_forwarded' => array('BOOL', 0), - 'folder_id' => array('INT:11', 0), - ), - 'KEYS' => array( - 'msg_id' => array('INDEX', 'msg_id'), - 'author_id' => array('INDEX', 'author_id'), - 'usr_flder_id' => array('INDEX', array('user_id', 'folder_id')), - ), -); - -$schema_data['phpbb_profile_fields'] = array( - 'COLUMNS' => array( - 'field_id' => array('UINT', NULL, 'auto_increment'), - 'field_name' => array('VCHAR_UNI', ''), - 'field_type' => array('VCHAR:100', ''), - 'field_ident' => array('VCHAR:20', ''), - 'field_length' => array('VCHAR:20', ''), - 'field_minlen' => array('VCHAR', ''), - 'field_maxlen' => array('VCHAR', ''), - 'field_novalue' => array('VCHAR_UNI', ''), - 'field_default_value' => array('VCHAR_UNI', ''), - 'field_validation' => array('VCHAR_UNI:20', ''), - 'field_required' => array('BOOL', 0), - 'field_show_novalue' => array('BOOL', 0), - 'field_show_on_reg' => array('BOOL', 0), - 'field_show_on_pm' => array('BOOL', 0), - 'field_show_on_vt' => array('BOOL', 0), - 'field_show_on_ml' => array('BOOL', 0), - 'field_show_profile' => array('BOOL', 0), - 'field_hide' => array('BOOL', 0), - 'field_no_view' => array('BOOL', 0), - 'field_active' => array('BOOL', 0), - 'field_order' => array('UINT', 0), - ), - 'PRIMARY_KEY' => 'field_id', - 'KEYS' => array( - 'fld_type' => array('INDEX', 'field_type'), - 'fld_ordr' => array('INDEX', 'field_order'), - ), -); - -$schema_data['phpbb_profile_fields_data'] = array( - 'COLUMNS' => array( - 'user_id' => array('ULINT', 0), - 'pf_phpbb_location' => array('VCHAR', ''), - 'pf_phpbb_interests' => array('TEXT_UNI', ''), - 'pf_phpbb_occupation' => array('TEXT_UNI', ''), - ), - 'PRIMARY_KEY' => 'user_id', -); - -$schema_data['phpbb_profile_fields_lang'] = array( - 'COLUMNS' => array( - 'field_id' => array('UINT', 0), - 'lang_id' => array('UINT', 0), - 'option_id' => array('UINT', 0), - 'field_type' => array('VCHAR:100', ''), - 'lang_value' => array('VCHAR_UNI', ''), - ), - 'PRIMARY_KEY' => array('field_id', 'lang_id', 'option_id'), -); - -$schema_data['phpbb_profile_lang'] = array( - 'COLUMNS' => array( - 'field_id' => array('UINT', 0), - 'lang_id' => array('UINT', 0), - 'lang_name' => array('VCHAR_UNI', ''), - 'lang_explain' => array('TEXT_UNI', ''), - 'lang_default_value' => array('VCHAR_UNI', ''), - ), - 'PRIMARY_KEY' => array('field_id', 'lang_id'), -); - -$schema_data['phpbb_ranks'] = array( - 'COLUMNS' => array( - 'rank_id' => array('UINT', NULL, 'auto_increment'), - 'rank_title' => array('VCHAR_UNI', ''), - 'rank_min' => array('UINT', 0), - 'rank_special' => array('BOOL', 0), - 'rank_image' => array('VCHAR', ''), - ), - 'PRIMARY_KEY' => 'rank_id', -); - -$schema_data['phpbb_reports'] = array( - 'COLUMNS' => array( - 'report_id' => array('UINT', NULL, 'auto_increment'), - 'reason_id' => array('USINT', 0), - 'post_id' => array('ULINT', 0), - 'pm_id' => array('UINT', 0), - 'user_id' => array('ULINT', 0), - 'user_notify' => array('BOOL', 0), - 'report_closed' => array('BOOL', 0), - 'report_time' => array('TIMESTAMP', 0), - 'report_text' => array('MTEXT_UNI', ''), - 'reported_post_text' => array('MTEXT_UNI', ''), - 'reported_post_uid' => array('VCHAR:8', ''), - 'reported_post_bitfield' => array('VCHAR:255', ''), - 'reported_post_enable_magic_url' => array('BOOL', 1), - 'reported_post_enable_smilies' => array('BOOL', 1), - 'reported_post_enable_bbcode' => array('BOOL', 1) - ), - 'PRIMARY_KEY' => 'report_id', - 'KEYS' => array( - 'post_id' => array('INDEX', 'post_id'), - 'pm_id' => array('INDEX', 'pm_id'), - ), -); - -$schema_data['phpbb_reports_reasons'] = array( - 'COLUMNS' => array( - 'reason_id' => array('USINT', NULL, 'auto_increment'), - 'reason_title' => array('VCHAR_UNI', ''), - 'reason_description' => array('MTEXT_UNI', ''), - 'reason_order' => array('USINT', 0), - ), - 'PRIMARY_KEY' => 'reason_id', -); - -$schema_data['phpbb_search_results'] = array( - 'COLUMNS' => array( - 'search_key' => array('VCHAR:32', ''), - 'search_time' => array('TIMESTAMP', 0), - 'search_keywords' => array('MTEXT_UNI', ''), - 'search_authors' => array('MTEXT', ''), - ), - 'PRIMARY_KEY' => 'search_key', -); - -$schema_data['phpbb_search_wordlist'] = array( - 'COLUMNS' => array( - 'word_id' => array('UINT', NULL, 'auto_increment'), - 'word_text' => array('VCHAR_UNI', ''), - 'word_common' => array('BOOL', 0), - 'word_count' => array('UINT', 0), - ), - 'PRIMARY_KEY' => 'word_id', - 'KEYS' => array( - 'wrd_txt' => array('UNIQUE', 'word_text'), - 'wrd_cnt' => array('INDEX', 'word_count'), - ), -); - -$schema_data['phpbb_search_wordmatch'] = array( - 'COLUMNS' => array( - 'post_id' => array('ULINT', 0), - 'word_id' => array('UINT', 0), - 'title_match' => array('BOOL', 0), - ), - 'KEYS' => array( - 'unq_mtch' => array('UNIQUE', array('word_id', 'post_id', 'title_match')), - 'word_id' => array('INDEX', 'word_id'), - 'post_id' => array('INDEX', 'post_id'), - ), -); - -$schema_data['phpbb_sessions'] = array( - 'COLUMNS' => array( - 'session_id' => array('CHAR:32', ''), - 'session_user_id' => array('UINT', 0), - 'session_forum_id' => array('UINT', 0), - 'session_last_visit' => array('TIMESTAMP', 0), - 'session_start' => array('TIMESTAMP', 0), - 'session_time' => array('TIMESTAMP', 0), - 'session_ip' => array('VCHAR:40', ''), - 'session_browser' => array('VCHAR:150', ''), - 'session_forwarded_for' => array('VCHAR:255', ''), - 'session_page' => array('VCHAR_UNI', ''), - 'session_viewonline' => array('BOOL', 1), - 'session_autologin' => array('BOOL', 0), - 'session_admin' => array('BOOL', 0), - ), - 'PRIMARY_KEY' => 'session_id', - 'KEYS' => array( - 'session_time' => array('INDEX', 'session_time'), - 'session_user_id' => array('INDEX', 'session_user_id'), - 'session_fid' => array('INDEX', 'session_forum_id'), - ), -); - -$schema_data['phpbb_sessions_keys'] = array( - 'COLUMNS' => array( - 'key_id' => array('CHAR:32', ''), - 'user_id' => array('ULINT', 0), - 'last_ip' => array('VCHAR:40', ''), - 'last_login' => array('TIMESTAMP', 0), - ), - 'PRIMARY_KEY' => array('key_id', 'user_id'), - 'KEYS' => array( - 'last_login' => array('INDEX', 'last_login'), - ), -); - -$schema_data['phpbb_sitelist'] = array( - 'COLUMNS' => array( - 'site_id' => array('UINT', NULL, 'auto_increment'), - 'site_ip' => array('VCHAR:40', ''), - 'site_hostname' => array('VCHAR', ''), - 'ip_exclude' => array('BOOL', 0), - ), - 'PRIMARY_KEY' => 'site_id', -); - -$schema_data['phpbb_smilies'] = array( - 'COLUMNS' => array( - 'smiley_id' => array('UINT', NULL, 'auto_increment'), - // We may want to set 'code' to VCHAR:50 or check if unicode support is possible... at the moment only ASCII characters are allowed. - 'code' => array('VCHAR_UNI:50', ''), - 'emotion' => array('VCHAR_UNI:50', ''), - 'smiley_url' => array('VCHAR:50', ''), - 'smiley_width' => array('USINT', 0), - 'smiley_height' => array('USINT', 0), - 'smiley_order' => array('UINT', 0), - 'display_on_posting'=> array('BOOL', 1), - ), - 'PRIMARY_KEY' => 'smiley_id', - 'KEYS' => array( - 'display_on_post' => array('INDEX', 'display_on_posting'), - ), -); - -$schema_data['phpbb_styles'] = array( - 'COLUMNS' => array( - 'style_id' => array('UINT', NULL, 'auto_increment'), - 'style_name' => array('VCHAR_UNI:255', ''), - 'style_copyright' => array('VCHAR_UNI', ''), - 'style_active' => array('BOOL', 1), - 'style_path' => array('VCHAR:100', ''), - 'bbcode_bitfield' => array('VCHAR:255', 'kNg='), - 'style_parent_id' => array('UINT:4', 0), - 'style_parent_tree' => array('TEXT', ''), - ), - 'PRIMARY_KEY' => 'style_id', - 'KEYS' => array( - 'style_name' => array('UNIQUE', 'style_name'), - ), -); - -$schema_data['phpbb_teampage'] = array( - 'COLUMNS' => array( - 'teampage_id' => array('UINT', NULL, 'auto_increment'), - 'group_id' => array('UINT', 0), - 'teampage_name' => array('VCHAR_UNI:255', ''), - 'teampage_position' => array('UINT', 0), - 'teampage_parent' => array('UINT', 0), - ), - 'PRIMARY_KEY' => 'teampage_id', -); - -$schema_data['phpbb_topics'] = array( - 'COLUMNS' => array( - 'topic_id' => array('ULINT', NULL, 'auto_increment'), - 'forum_id' => array('UINT', 0), - 'icon_id' => array('UINT', 0), - 'topic_attachment' => array('BOOL', 0), - 'topic_visibility' => array('TINT:3', 0), - 'topic_reported' => array('BOOL', 0), - 'topic_title' => array('STEXT_UNI', '', 'true_sort'), - 'topic_poster' => array('UINT', 0), - 'topic_time' => array('TIMESTAMP', 0), - 'topic_time_limit' => array('TIMESTAMP', 0), - 'topic_views' => array('UINT', 0), - 'topic_posts_approved' => array('UINT', 0), - 'topic_posts_unapproved' => array('UINT', 0), - 'topic_posts_softdeleted' => array('UINT', 0), - 'topic_status' => array('TINT:3', 0), - 'topic_type' => array('TINT:3', 0), - 'topic_first_post_id' => array('UINT', 0), - 'topic_first_poster_name' => array('VCHAR_UNI', ''), - 'topic_first_poster_colour' => array('VCHAR:6', ''), - 'topic_last_post_id' => array('UINT', 0), - 'topic_last_poster_id' => array('UINT', 0), - 'topic_last_poster_name' => array('VCHAR_UNI', ''), - 'topic_last_poster_colour' => array('VCHAR:6', ''), - 'topic_last_post_subject' => array('STEXT_UNI', ''), - 'topic_last_post_time' => array('TIMESTAMP', 0), - 'topic_last_view_time' => array('TIMESTAMP', 0), - 'topic_moved_id' => array('UINT', 0), - 'topic_bumped' => array('BOOL', 0), - 'topic_bumper' => array('UINT', 0), - 'poll_title' => array('STEXT_UNI', ''), - 'poll_start' => array('TIMESTAMP', 0), - 'poll_length' => array('TIMESTAMP', 0), - 'poll_max_options' => array('TINT:4', 1), - 'poll_last_vote' => array('TIMESTAMP', 0), - 'poll_vote_change' => array('BOOL', 0), - 'topic_delete_time' => array('TIMESTAMP', 0), - 'topic_delete_reason' => array('STEXT_UNI', ''), - 'topic_delete_user' => array('UINT', 0), - ), - 'PRIMARY_KEY' => 'topic_id', - 'KEYS' => array( - 'forum_id' => array('INDEX', 'forum_id'), - 'forum_id_type' => array('INDEX', array('forum_id', 'topic_type')), - 'last_post_time' => array('INDEX', 'topic_last_post_time'), - 'topic_visibility' => array('INDEX', 'topic_visibility'), - 'forum_appr_last' => array('INDEX', array('forum_id', 'topic_visibility', 'topic_last_post_id')), - 'fid_time_moved' => array('INDEX', array('forum_id', 'topic_last_post_time', 'topic_moved_id')), - ), -); - -$schema_data['phpbb_topics_track'] = array( - 'COLUMNS' => array( - 'user_id' => array('ULINT', 0), - 'topic_id' => array('ULINT', 0), - 'forum_id' => array('UINT', 0), - 'mark_time' => array('TIMESTAMP', 0), - ), - 'PRIMARY_KEY' => array('user_id', 'topic_id'), - 'KEYS' => array( - 'topic_id' => array('INDEX', 'topic_id'), - 'forum_id' => array('INDEX', 'forum_id'), - ), -); - -$schema_data['phpbb_topics_posted'] = array( - 'COLUMNS' => array( - 'user_id' => array('ULINT', 0), - 'topic_id' => array('ULINT', 0), - 'topic_posted' => array('BOOL', 0), - ), - 'PRIMARY_KEY' => array('user_id', 'topic_id'), -); - -$schema_data['phpbb_topics_watch'] = array( - 'COLUMNS' => array( - 'topic_id' => array('ULINT', 0), - 'user_id' => array('ULINT', 0), - 'notify_status' => array('BOOL', 0), - ), - 'KEYS' => array( - 'topic_id' => array('INDEX', 'topic_id'), - 'user_id' => array('INDEX', 'user_id'), - 'notify_stat' => array('INDEX', 'notify_status'), - ), -); - -$schema_data['phpbb_user_notifications'] = array( - 'COLUMNS' => array( - 'item_type' => array('VCHAR:255', ''), - 'item_id' => array('UINT', 0), - 'user_id' => array('ULINT', 0), - 'method' => array('VCHAR:255', ''), - 'notify' => array('BOOL', 1), - ), -); - -$schema_data['phpbb_user_group'] = array( - 'COLUMNS' => array( - 'group_id' => array('UINT', 0), - 'user_id' => array('ULINT', 0), - 'group_leader' => array('BOOL', 0), - 'user_pending' => array('BOOL', 1), - ), - 'KEYS' => array( - 'group_id' => array('INDEX', 'group_id'), - 'user_id' => array('INDEX', 'user_id'), - 'group_leader' => array('INDEX', 'group_leader'), - ), -); - -$schema_data['phpbb_users'] = array( - 'COLUMNS' => array( - 'user_id' => array('ULINT', NULL, 'auto_increment'), - 'user_type' => array('TINT:2', 0), - 'group_id' => array('UINT', 3), - 'user_permissions' => array('MTEXT', ''), - 'user_perm_from' => array('UINT', 0), - 'user_ip' => array('VCHAR:40', ''), - 'user_regdate' => array('TIMESTAMP', 0), - 'username' => array('VCHAR_CI', ''), - 'username_clean' => array('VCHAR_CI', ''), - 'user_password' => array('VCHAR_UNI', ''), - 'user_passchg' => array('TIMESTAMP', 0), - 'user_pass_convert' => array('BOOL', 0), - 'user_actkey' => array('VCHAR:32', ''), - 'user_newpasswd' => array('VCHAR_UNI', ''), - 'user_email' => array('VCHAR_UNI:100', ''), - 'user_email_hash' => array('BINT', 0), - 'user_birthday' => array('VCHAR:10', ''), - 'user_lastvisit' => array('TIMESTAMP', 0), - 'user_lastmark' => array('TIMESTAMP', 0), - 'user_lastpost_time' => array('TIMESTAMP', 0), - 'user_lastpage' => array('VCHAR_UNI:200', ''), - 'user_last_confirm_key' => array('VCHAR:10', ''), - 'user_last_search' => array('TIMESTAMP', 0), - 'user_warnings' => array('TINT:4', 0), - 'user_last_warning' => array('TIMESTAMP', 0), - 'user_login_attempts' => array('TINT:4', 0), - 'user_inactive_reason' => array('TINT:2', 0), - 'user_inactive_time' => array('TIMESTAMP', 0), - 'user_posts' => array('UINT', 0), - 'user_lang' => array('VCHAR:30', ''), - 'user_timezone' => array('VCHAR:100', 'UTC'), - 'user_dateformat' => array('VCHAR_UNI:30', 'd M Y H:i'), - 'user_style' => array('UINT', 0), - 'user_rank' => array('UINT', 0), - 'user_colour' => array('VCHAR:6', ''), - 'user_new_privmsg' => array('INT:4', 0), - 'user_unread_privmsg' => array('INT:4', 0), - 'user_last_privmsg' => array('TIMESTAMP', 0), - 'user_message_rules' => array('BOOL', 0), - 'user_full_folder' => array('INT:11', -3), - 'user_emailtime' => array('TIMESTAMP', 0), - 'user_topic_show_days' => array('USINT', 0), - 'user_topic_sortby_type' => array('VCHAR:1', 't'), - 'user_topic_sortby_dir' => array('VCHAR:1', 'd'), - 'user_post_show_days' => array('USINT', 0), - 'user_post_sortby_type' => array('VCHAR:1', 't'), - 'user_post_sortby_dir' => array('VCHAR:1', 'a'), - 'user_notify' => array('BOOL', 0), - 'user_notify_pm' => array('BOOL', 1), - 'user_notify_type' => array('TINT:4', 0), - 'user_allow_pm' => array('BOOL', 1), - 'user_allow_viewonline' => array('BOOL', 1), - 'user_allow_viewemail' => array('BOOL', 1), - 'user_allow_massemail' => array('BOOL', 1), - 'user_options' => array('UINT:11', 230271), - 'user_avatar' => array('VCHAR', ''), - 'user_avatar_type' => array('VCHAR:255', ''), - 'user_avatar_width' => array('USINT', 0), - 'user_avatar_height' => array('USINT', 0), - 'user_sig' => array('MTEXT_UNI', ''), - 'user_sig_bbcode_uid' => array('VCHAR:8', ''), - 'user_sig_bbcode_bitfield' => array('VCHAR:255', ''), - 'user_icq' => array('VCHAR:15', ''), - 'user_aim' => array('VCHAR_UNI', ''), - 'user_yim' => array('VCHAR_UNI', ''), - 'user_msnm' => array('VCHAR_UNI', ''), - 'user_jabber' => array('VCHAR_UNI', ''), - 'user_website' => array('VCHAR_UNI:200', ''), - 'user_form_salt' => array('VCHAR_UNI:32', ''), - 'user_new' => array('BOOL', 1), - 'user_reminded' => array('TINT:4', 0), - 'user_reminded_time' => array('TIMESTAMP', 0), - ), - 'PRIMARY_KEY' => 'user_id', - 'KEYS' => array( - 'user_birthday' => array('INDEX', 'user_birthday'), - 'user_email_hash' => array('INDEX', 'user_email_hash'), - 'user_type' => array('INDEX', 'user_type'), - 'username_clean' => array('UNIQUE', 'username_clean'), - ), -); - -$schema_data['phpbb_warnings'] = array( - 'COLUMNS' => array( - 'warning_id' => array('UINT', NULL, 'auto_increment'), - 'user_id' => array('ULINT', 0), - 'post_id' => array('ULINT', 0), - 'log_id' => array('UINT', 0), - 'warning_time' => array('TIMESTAMP', 0), - ), - 'PRIMARY_KEY' => 'warning_id', -); - -$schema_data['phpbb_words'] = array( - 'COLUMNS' => array( - 'word_id' => array('UINT', NULL, 'auto_increment'), - 'word' => array('VCHAR_UNI', ''), - 'replacement' => array('VCHAR_UNI', ''), - ), - 'PRIMARY_KEY' => 'word_id', -); - -$schema_data['phpbb_zebra'] = array( - 'COLUMNS' => array( - 'user_id' => array('ULINT', 0), - 'zebra_id' => array('UINT', 0), - 'friend' => array('BOOL', 0), - 'foe' => array('BOOL', 0), - ), - 'PRIMARY_KEY' => array('user_id', 'zebra_id'), -); diff --git a/phpBB/includes/diff/diff.php b/phpBB/includes/diff/diff.php index 1ffa3429b5..d307880c4b 100644 --- a/phpBB/includes/diff/diff.php +++ b/phpBB/includes/diff/diff.php @@ -1,9 +1,13 @@ <?php /** * -* @package diff -* @copyright (c) 2006 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -19,7 +23,7 @@ if (!defined('IN_PHPBB')) * Code from pear.php.net, Text_Diff-1.1.0 package * http://pear.php.net/package/Text_Diff/ * -* Modified by phpBB Group to meet our coding standards +* Modified by phpBB Limited to meet our coding standards * and being able to integrate into phpBB * * General API for generating and formatting diffs - the differences between @@ -42,8 +46,9 @@ class diff /** * Computes diffs between sequences of strings. * - * @param array $from_lines An array of strings. Typically these are lines from a file. - * @param array $to_lines An array of strings. + * @param array &$from_content An array of strings. Typically these are lines from a file. + * @param array &$to_content An array of strings. + * @param bool $preserve_cr If true, \r is replaced by a new line in the diff output */ function diff(&$from_content, &$to_content, $preserve_cr = true) { @@ -487,9 +492,11 @@ class diff3 extends diff /** * Computes diff between 3 sequences of strings. * - * @param array $orig The original lines to use. - * @param array $final1 The first version to compare to. - * @param array $final2 The second version to compare to. + * @param array &$orig The original lines to use. + * @param array &$final1 The first version to compare to. + * @param array &$final2 The second version to compare to. + * @param bool $preserve_cr If true, \r\n and bare \r are replaced by a new line + * in the diff output */ function diff3(&$orig, &$final1, &$final2, $preserve_cr = true) { diff --git a/phpBB/includes/diff/engine.php b/phpBB/includes/diff/engine.php index dc1ca5875f..bc21b3b9ba 100644 --- a/phpBB/includes/diff/engine.php +++ b/phpBB/includes/diff/engine.php @@ -1,9 +1,13 @@ <?php /** * -* @package diff -* @copyright (c) 2006 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -19,7 +23,7 @@ if (!defined('IN_PHPBB')) * Code from pear.php.net, Text_Diff-1.1.0 package * http://pear.php.net/package/Text_Diff/ (native engine) * -* Modified by phpBB Group to meet our coding standards +* Modified by phpBB Limited to meet our coding standards * and being able to integrate into phpBB * * Class used internally by Text_Diff to actually compute the diffs. This diff --git a/phpBB/includes/diff/renderer.php b/phpBB/includes/diff/renderer.php index eacd42d760..6b7f07cf9c 100644 --- a/phpBB/includes/diff/renderer.php +++ b/phpBB/includes/diff/renderer.php @@ -1,9 +1,13 @@ <?php /** * -* @package diff -* @copyright (c) 2006 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -19,7 +23,7 @@ if (!defined('IN_PHPBB')) * Code from pear.php.net, Text_Diff-1.1.0 package * http://pear.php.net/package/Text_Diff/ * -* Modified by phpBB Group to meet our coding standards +* Modified by phpBB Limited to meet our coding standards * and being able to integrate into phpBB * * A class to render Diffs in different formats. diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 689a682de3..38879caf5f 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -1,9 +1,13 @@ <?php /** * -* @package phpBB3 -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -17,144 +21,46 @@ if (!defined('IN_PHPBB')) // Common global functions /** -* Casts a variable to the given type. -* -* @deprecated -*/ -function set_var(&$result, $var, $type, $multibyte = false) -{ - // no need for dependency injection here, if you have the object, call the method yourself! - $type_cast_helper = new \phpbb\request\type_cast_helper(); - $type_cast_helper->set_var($result, $var, $type, $multibyte); -} - -/** -* Wrapper function of \phpbb\request\request::variable which exists for backwards compatability. -* See {@link \phpbb\request\request_interface::variable \phpbb\request\request_interface::variable} for -* documentation of this function's use. -* -* @deprecated -* @param mixed $var_name The form variable's name from which data shall be retrieved. -* If the value is an array this may be an array of indizes which will give -* direct access to a value at any depth. E.g. if the value of "var" is array(1 => "a") -* then specifying array("var", 1) as the name will return "a". -* If you pass an instance of {@link \phpbb\request\request_interface phpbb_request_interface} -* as this parameter it will overwrite the current request class instance. If you do -* not do so, it will create its own instance (but leave superglobals enabled). -* @param mixed $default A default value that is returned if the variable was not set. -* This function will always return a value of the same type as the default. -* @param bool $multibyte If $default is a string this paramater has to be true if the variable may contain any UTF-8 characters -* Default is false, causing all bytes outside the ASCII range (0-127) to be replaced with question marks -* @param bool $cookie This param is mapped to \phpbb\request\request_interface::COOKIE as the last param for -* \phpbb\request\request_interface::variable for backwards compatability reasons. -* @param \phpbb\request\request_interface|null|false If an instance of \phpbb\request\request_interface is given the instance is stored in -* a static variable and used for all further calls where this parameters is null. Until -* the function is called with an instance it automatically creates a new \phpbb\request\request -* instance on every call. By passing false this per-call instantiation can be restored -* after having passed in a \phpbb\request\request_interface instance. -* -* @return mixed The value of $_REQUEST[$var_name] run through {@link set_var set_var} to ensure that the type is the -* the same as that of $default. If the variable is not set $default is returned. -*/ -function request_var($var_name, $default, $multibyte = false, $cookie = false, $request = null) -{ - // This is all just an ugly hack to add "Dependency Injection" to a function - // the only real code is the function call which maps this function to a method. - static $static_request = null; - - if ($request instanceof \phpbb\request\request_interface) - { - $static_request = $request; - - if (empty($var_name)) - { - return; - } - } - else if ($request === false) - { - $static_request = null; - - if (empty($var_name)) - { - return; - } - } - - $tmp_request = $static_request; - - // no request class set, create a temporary one ourselves to keep backwards compatability - if ($tmp_request === null) - { - // false param: enable super globals, so the created request class does not - // make super globals inaccessible everywhere outside this function. - $tmp_request = new \phpbb\request\request(new \phpbb\request\type_cast_helper(), false); - } - - return $tmp_request->variable($var_name, $default, $multibyte, ($cookie) ? \phpbb\request\request_interface::COOKIE : \phpbb\request\request_interface::REQUEST); -} - -/** -* Sets a configuration option's value. -* -* Please note that this function does not update the is_dynamic value for -* an already existing config option. -* -* @param string $config_name The configuration option's name -* @param string $config_value New configuration value -* @param bool $is_dynamic Whether this variable should be cached (false) or -* if it changes too frequently (true) to be -* efficiently cached. +* Load the autoloaders added by the extensions. * -* @return null -* -* @deprecated +* @param string $phpbb_root_path Path to the phpbb root directory. */ -function set_config($config_name, $config_value, $is_dynamic = false, \phpbb\config\config $set_config = null) +function phpbb_load_extensions_autoloaders($phpbb_root_path) { - static $config = null; + $iterator = new \RecursiveIteratorIterator( + new \phpbb\recursive_dot_prefix_filter_iterator( + new \RecursiveDirectoryIterator( + $phpbb_root_path . 'ext/', + \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS + ) + ), + \RecursiveIteratorIterator::SELF_FIRST + ); + $iterator->setMaxDepth(2); - if ($set_config !== null) + foreach ($iterator as $file_info) { - $config = $set_config; - - if (empty($config_name)) + if ($file_info->getFilename() === 'vendor' && $iterator->getDepth() === 2) { - return; + $filename = $file_info->getRealPath() . '/autoload.php'; + if (file_exists($filename)) + { + require $filename; + } } } - - $config->set($config_name, $config_value, !$is_dynamic); } /** -* Increments an integer config value directly in the database. -* -* @param string $config_name The configuration option's name -* @param int $increment Amount to increment by -* @param bool $is_dynamic Whether this variable should be cached (false) or -* if it changes too frequently (true) to be -* efficiently cached. -* -* @return null +* Casts a variable to the given type. * * @deprecated */ -function set_config_count($config_name, $increment, $is_dynamic = false, \phpbb\config\config $set_config = null) +function set_var(&$result, $var, $type, $multibyte = false) { - static $config = null; - - if ($set_config !== null) - { - $config = $set_config; - - if (empty($config_name)) - { - return; - } - } - - $config->increment($config_name, $increment, !$is_dynamic); + // no need for dependency injection here, if you have the object, call the method yourself! + $type_cast_helper = new \phpbb\request\type_cast_helper(); + $type_cast_helper->set_var($result, $var, $type, $multibyte); } /** @@ -200,8 +106,8 @@ function unique_id($extra = 'c') if ($dss_seeded !== true && ($config['rand_seed_last_update'] < time() - rand(1,10))) { - set_config('rand_seed_last_update', time(), true); - set_config('rand_seed', $config['rand_seed'], true); + $config->set('rand_seed_last_update', time(), false); + $config->set('rand_seed', $config['rand_seed'], false); $dss_seeded = true; } @@ -254,7 +160,6 @@ function phpbb_gmgetdate($time = false) * @param array $allowed_units only allow these units (data array indexes) * * @return mixed data array if $string_only is false -* @author bantu */ function get_formatted_filesize($value, $string_only = true, $allowed_units = false) { @@ -342,8 +247,7 @@ function still_on_time($extra_time = 15) { static $max_execution_time, $start_time; - $time = explode(' ', microtime()); - $current_time = $time[0] + $time[1]; + $current_time = microtime(true); if (empty($max_execution_time)) { @@ -368,41 +272,6 @@ function still_on_time($extra_time = 15) } /** -* Hash the password -* -* @deprecated 3.1.0-a2 (To be removed: 3.3.0) -* -* @param string $password Password to be hashed -* -* @return string|bool Password hash or false if something went wrong during hashing -*/ -function phpbb_hash($password) -{ - global $phpbb_container; - - $passwords_manager = $phpbb_container->get('passwords.manager'); - return $passwords_manager->hash($password); -} - -/** -* Check for correct password -* -* @deprecated 3.1.0-a2 (To be removed: 3.3.0) -* -* @param string $password The password in plain text -* @param string $hash The stored password hash -* -* @return bool Returns true if the password is correct, false if not. -*/ -function phpbb_check_hash($password, $hash) -{ - global $phpbb_container; - - $passwords_manager = $phpbb_container->get('passwords.manager'); - return $passwords_manager->check($password, $hash); -} - -/** * Hashes an email address to a big integer * * @param string $email Email address @@ -442,489 +311,6 @@ function phpbb_version_compare($version1, $version2, $operator = null) } } -/** -* Global function for chmodding directories and files for internal use -* -* This function determines owner and group whom the file belongs to and user and group of PHP and then set safest possible file permissions. -* The function determines owner and group from common.php file and sets the same to the provided file. -* The function uses bit fields to build the permissions. -* The function sets the appropiate execute bit on directories. -* -* Supported constants representing bit fields are: -* -* CHMOD_ALL - all permissions (7) -* CHMOD_READ - read permission (4) -* CHMOD_WRITE - write permission (2) -* CHMOD_EXECUTE - execute permission (1) -* -* NOTE: The function uses POSIX extension and fileowner()/filegroup() functions. If any of them is disabled, this function tries to build proper permissions, by calling is_readable() and is_writable() functions. -* -* @param string $filename The file/directory to be chmodded -* @param int $perms Permissions to set -* -* @return bool true on success, otherwise false -* @author faw, phpBB Group -*/ -function phpbb_chmod($filename, $perms = CHMOD_READ) -{ - static $_chmod_info; - - // Return if the file no longer exists. - if (!file_exists($filename)) - { - return false; - } - - // Determine some common vars - if (empty($_chmod_info)) - { - if (!function_exists('fileowner') || !function_exists('filegroup')) - { - // No need to further determine owner/group - it is unknown - $_chmod_info['process'] = false; - } - else - { - global $phpbb_root_path, $phpEx; - - // Determine owner/group of common.php file and the filename we want to change here - $common_php_owner = @fileowner($phpbb_root_path . 'common.' . $phpEx); - $common_php_group = @filegroup($phpbb_root_path . 'common.' . $phpEx); - - // And the owner and the groups PHP is running under. - $php_uid = (function_exists('posix_getuid')) ? @posix_getuid() : false; - $php_gids = (function_exists('posix_getgroups')) ? @posix_getgroups() : false; - - // If we are unable to get owner/group, then do not try to set them by guessing - if (!$php_uid || empty($php_gids) || !$common_php_owner || !$common_php_group) - { - $_chmod_info['process'] = false; - } - else - { - $_chmod_info = array( - 'process' => true, - 'common_owner' => $common_php_owner, - 'common_group' => $common_php_group, - 'php_uid' => $php_uid, - 'php_gids' => $php_gids, - ); - } - } - } - - if ($_chmod_info['process']) - { - $file_uid = @fileowner($filename); - $file_gid = @filegroup($filename); - - // Change owner - if (@chown($filename, $_chmod_info['common_owner'])) - { - clearstatcache(); - $file_uid = @fileowner($filename); - } - - // Change group - if (@chgrp($filename, $_chmod_info['common_group'])) - { - clearstatcache(); - $file_gid = @filegroup($filename); - } - - // If the file_uid/gid now match the one from common.php we can process further, else we are not able to change something - if ($file_uid != $_chmod_info['common_owner'] || $file_gid != $_chmod_info['common_group']) - { - $_chmod_info['process'] = false; - } - } - - // Still able to process? - if ($_chmod_info['process']) - { - if ($file_uid == $_chmod_info['php_uid']) - { - $php = 'owner'; - } - else if (in_array($file_gid, $_chmod_info['php_gids'])) - { - $php = 'group'; - } - else - { - // Since we are setting the everyone bit anyway, no need to do expensive operations - $_chmod_info['process'] = false; - } - } - - // We are not able to determine or change something - if (!$_chmod_info['process']) - { - $php = 'other'; - } - - // Owner always has read/write permission - $owner = CHMOD_READ | CHMOD_WRITE; - if (is_dir($filename)) - { - $owner |= CHMOD_EXECUTE; - - // Only add execute bit to the permission if the dir needs to be readable - if ($perms & CHMOD_READ) - { - $perms |= CHMOD_EXECUTE; - } - } - - switch ($php) - { - case 'owner': - $result = @chmod($filename, ($owner << 6) + (0 << 3) + (0 << 0)); - - clearstatcache(); - - if (is_readable($filename) && phpbb_is_writable($filename)) - { - break; - } - - case 'group': - $result = @chmod($filename, ($owner << 6) + ($perms << 3) + (0 << 0)); - - clearstatcache(); - - if ((!($perms & CHMOD_READ) || is_readable($filename)) && (!($perms & CHMOD_WRITE) || phpbb_is_writable($filename))) - { - break; - } - - case 'other': - $result = @chmod($filename, ($owner << 6) + ($perms << 3) + ($perms << 0)); - - clearstatcache(); - - if ((!($perms & CHMOD_READ) || is_readable($filename)) && (!($perms & CHMOD_WRITE) || phpbb_is_writable($filename))) - { - break; - } - - default: - return false; - break; - } - - return $result; -} - -/** -* Test if a file/directory is writable -* -* This function calls the native is_writable() when not running under -* Windows and it is not disabled. -* -* @param string $file Path to perform write test on -* @return bool True when the path is writable, otherwise false. -*/ -function phpbb_is_writable($file) -{ - if (strtolower(substr(PHP_OS, 0, 3)) === 'win' || !function_exists('is_writable')) - { - if (file_exists($file)) - { - // Canonicalise path to absolute path - $file = phpbb_realpath($file); - - if (is_dir($file)) - { - // Test directory by creating a file inside the directory - $result = @tempnam($file, 'i_w'); - - if (is_string($result) && file_exists($result)) - { - unlink($result); - - // Ensure the file is actually in the directory (returned realpathed) - return (strpos($result, $file) === 0) ? true : false; - } - } - else - { - $handle = @fopen($file, 'r+'); - - if (is_resource($handle)) - { - fclose($handle); - return true; - } - } - } - else - { - // file does not exist test if we can write to the directory - $dir = dirname($file); - - if (file_exists($dir) && is_dir($dir) && phpbb_is_writable($dir)) - { - return true; - } - } - - return false; - } - else - { - return is_writable($file); - } -} - -/** -* Checks if a path ($path) is absolute or relative -* -* @param string $path Path to check absoluteness of -* @return boolean -*/ -function phpbb_is_absolute($path) -{ - return (isset($path[0]) && $path[0] == '/' || preg_match('#^[a-z]:[/\\\]#i', $path)) ? true : false; -} - -/** -* @author Chris Smith <chris@project-minerva.org> -* @copyright 2006 Project Minerva Team -* @param string $path The path which we should attempt to resolve. -* @return mixed -*/ -function phpbb_own_realpath($path) -{ - global $request; - - // Now to perform funky shizzle - - // Switch to use UNIX slashes - $path = str_replace(DIRECTORY_SEPARATOR, '/', $path); - $path_prefix = ''; - - // Determine what sort of path we have - if (phpbb_is_absolute($path)) - { - $absolute = true; - - if ($path[0] == '/') - { - // Absolute path, *NIX style - $path_prefix = ''; - } - else - { - // Absolute path, Windows style - // Remove the drive letter and colon - $path_prefix = $path[0] . ':'; - $path = substr($path, 2); - } - } - else - { - // Relative Path - // Prepend the current working directory - if (function_exists('getcwd')) - { - // This is the best method, hopefully it is enabled! - $path = str_replace(DIRECTORY_SEPARATOR, '/', getcwd()) . '/' . $path; - $absolute = true; - if (preg_match('#^[a-z]:#i', $path)) - { - $path_prefix = $path[0] . ':'; - $path = substr($path, 2); - } - else - { - $path_prefix = ''; - } - } - else if ($request->server('SCRIPT_FILENAME')) - { - // Warning: If chdir() has been used this will lie! - // Warning: This has some problems sometime (CLI can create them easily) - $filename = htmlspecialchars_decode($request->server('SCRIPT_FILENAME')); - $path = str_replace(DIRECTORY_SEPARATOR, '/', dirname($filename)) . '/' . $path; - $absolute = true; - $path_prefix = ''; - } - else - { - // We have no way of getting the absolute path, just run on using relative ones. - $absolute = false; - $path_prefix = '.'; - } - } - - // Remove any repeated slashes - $path = preg_replace('#/{2,}#', '/', $path); - - // Remove the slashes from the start and end of the path - $path = trim($path, '/'); - - // Break the string into little bits for us to nibble on - $bits = explode('/', $path); - - // Remove any . in the path, renumber array for the loop below - $bits = array_values(array_diff($bits, array('.'))); - - // Lets get looping, run over and resolve any .. (up directory) - for ($i = 0, $max = sizeof($bits); $i < $max; $i++) - { - // @todo Optimise - if ($bits[$i] == '..' ) - { - if (isset($bits[$i - 1])) - { - if ($bits[$i - 1] != '..') - { - // We found a .. and we are able to traverse upwards, lets do it! - unset($bits[$i]); - unset($bits[$i - 1]); - $i -= 2; - $max -= 2; - $bits = array_values($bits); - } - } - else if ($absolute) // ie. !isset($bits[$i - 1]) && $absolute - { - // We have an absolute path trying to descend above the root of the filesystem - // ... Error! - return false; - } - } - } - - // Prepend the path prefix - array_unshift($bits, $path_prefix); - - $resolved = ''; - - $max = sizeof($bits) - 1; - - // Check if we are able to resolve symlinks, Windows cannot. - $symlink_resolve = (function_exists('readlink')) ? true : false; - - foreach ($bits as $i => $bit) - { - if (@is_dir("$resolved/$bit") || ($i == $max && @is_file("$resolved/$bit"))) - { - // Path Exists - if ($symlink_resolve && is_link("$resolved/$bit") && ($link = readlink("$resolved/$bit"))) - { - // Resolved a symlink. - $resolved = $link . (($i == $max) ? '' : '/'); - continue; - } - } - else - { - // Something doesn't exist here! - // This is correct realpath() behaviour but sadly open_basedir and safe_mode make this problematic - // return false; - } - $resolved .= $bit . (($i == $max) ? '' : '/'); - } - - // @todo If the file exists fine and open_basedir only has one path we should be able to prepend it - // because we must be inside that basedir, the question is where... - // @internal The slash in is_dir() gets around an open_basedir restriction - if (!@file_exists($resolved) || (!@is_dir($resolved . '/') && !is_file($resolved))) - { - return false; - } - - // Put the slashes back to the native operating systems slashes - $resolved = str_replace('/', DIRECTORY_SEPARATOR, $resolved); - - // Check for DIRECTORY_SEPARATOR at the end (and remove it!) - if (substr($resolved, -1) == DIRECTORY_SEPARATOR) - { - return substr($resolved, 0, -1); - } - - return $resolved; // We got here, in the end! -} - -if (!function_exists('realpath')) -{ - /** - * A wrapper for realpath - * @ignore - */ - function phpbb_realpath($path) - { - return phpbb_own_realpath($path); - } -} -else -{ - /** - * A wrapper for realpath - */ - function phpbb_realpath($path) - { - $realpath = realpath($path); - - // Strangely there are provider not disabling realpath but returning strange values. :o - // We at least try to cope with them. - if ($realpath === $path || $realpath === false) - { - return phpbb_own_realpath($path); - } - - // Check for DIRECTORY_SEPARATOR at the end (and remove it!) - if (substr($realpath, -1) == DIRECTORY_SEPARATOR) - { - $realpath = substr($realpath, 0, -1); - } - - return $realpath; - } -} - -/** -* Eliminates useless . and .. components from specified path. -* -* Deprecated, use filesystem class instead -* -* @param string $path Path to clean -* @return string Cleaned path -* -* @deprecated -*/ -function phpbb_clean_path($path) -{ - global $phpbb_path_helper, $phpbb_container; - - if (!$phpbb_path_helper && $phpbb_container) - { - $phpbb_path_helper = $phpbb_container->get('path_helper'); - } - else if (!$phpbb_path_helper) - { - // The container is not yet loaded, use a new instance - if (!class_exists('\phpbb\path_helper')) - { - global $phpbb_root_path, $phpEx; - require($phpbb_root_path . 'phpbb/path_helper.' . $phpEx); - } - - $phpbb_path_helper = new phpbb\path_helper( - new phpbb\symfony_request( - new phpbb\request\request() - ), - new phpbb\filesystem(), - $phpbb_root_path, - $phpEx - ); - } - - return $phpbb_path_helper->clean_path($path); -} - // functions used for building option fields /** @@ -979,14 +365,20 @@ function style_select($default = '', $all = false) * Format the timezone offset with hours and minutes * * @param int $tz_offset Timezone offset in seconds +* @param bool $show_null Whether null offsets should be shown * @return string Normalized offset string: -7200 => -02:00 * 16200 => +04:30 */ -function phpbb_format_timezone_offset($tz_offset) +function phpbb_format_timezone_offset($tz_offset, $show_null = false) { $sign = ($tz_offset < 0) ? '-' : '+'; $time_offset = abs($tz_offset); + if ($time_offset == 0 && $show_null == false) + { + return ''; + } + $offset_seconds = $time_offset % 3600; $offset_minutes = $offset_seconds / 60; $offset_hours = ($time_offset - $offset_seconds) / 3600; @@ -1071,7 +463,7 @@ function phpbb_get_timezone_identifiers($selected_timezone) $validate_timezone = new DateTimeZone($selected_timezone); $timezones[] = $selected_timezone; } - catch (Exception $e) + catch (\Exception $e) { } } @@ -1080,33 +472,16 @@ function phpbb_get_timezone_identifiers($selected_timezone) } /** -* Pick a timezone -* -* @param string $default A timezone to select -* @param boolean $truncate Shall we truncate the options text -* -* @return string Returns the options for timezone selector only -* -* @deprecated -*/ -function tz_select($default = '', $truncate = false) -{ - global $user; - - $timezone_select = phpbb_timezone_select($user, $default, $truncate); - return $timezone_select['tz_select']; -} - -/** * Options to pick a timezone and date/time * +* @param \phpbb\template\template $template phpBB template object * @param \phpbb\user $user Object of the current user * @param string $default A timezone to select * @param boolean $truncate Shall we truncate the options text * -* @return array Returns an array, also containing the options for the time selector. +* @return array Returns an array containing the options for the time selector. */ -function phpbb_timezone_select($user, $default = '', $truncate = false) +function phpbb_timezone_select($template, $user, $default = '', $truncate = false) { static $timezones; @@ -1119,18 +494,18 @@ function phpbb_timezone_select($user, $default = '', $truncate = false) foreach ($unsorted_timezones as $timezone) { $tz = new DateTimeZone($timezone); - $dt = new \phpbb\datetime($user, 'now', $tz); + $dt = $user->create_datetime('now', $tz); $offset = $dt->getOffset(); $current_time = $dt->format($user->lang['DATETIME_FORMAT'], true); - $offset_string = phpbb_format_timezone_offset($offset); - $timezones['GMT' . $offset_string . ' - ' . $timezone] = array( + $offset_string = phpbb_format_timezone_offset($offset, true); + $timezones['UTC' . $offset_string . ' - ' . $timezone] = array( 'tz' => $timezone, - 'offest' => 'GMT' . $offset_string, + 'offset' => $offset_string, 'current' => $current_time, ); if ($timezone === $default) { - $default_offset = 'GMT' . $offset_string; + $default_offset = 'UTC' . $offset_string; } } unset($unsorted_timezones); @@ -1138,18 +513,27 @@ function phpbb_timezone_select($user, $default = '', $truncate = false) uksort($timezones, 'phpbb_tz_select_compare'); } - $tz_select = $tz_dates = $opt_group = ''; + $tz_select = $opt_group = ''; - foreach ($timezones as $timezone) + foreach ($timezones as $key => $timezone) { - if ($opt_group != $timezone['offest']) + if ($opt_group != $timezone['offset']) { + // Generate tz_select for backwards compatibility $tz_select .= ($opt_group) ? '</optgroup>' : ''; - $tz_select .= '<optgroup label="' . $timezone['offest'] . ' - ' . $timezone['current'] . '">'; - $opt_group = $timezone['offest']; + $tz_select .= '<optgroup label="' . $user->lang(array('timezones', 'UTC_OFFSET_CURRENT'), $timezone['offset'], $timezone['current']) . '">'; + $opt_group = $timezone['offset']; + $template->assign_block_vars('timezone_select', array( + 'LABEL' => $user->lang(array('timezones', 'UTC_OFFSET_CURRENT'), $timezone['offset'], $timezone['current']), + 'VALUE' => $key . ' - ' . $timezone['current'], + )); - $selected = ($default_offset == $timezone['offest']) ? ' selected="selected"' : ''; - $tz_dates .= '<option value="' . $timezone['offest'] . ' - ' . $timezone['current'] . '"' . $selected . '>' . $timezone['offest'] . ' - ' . $timezone['current'] . '</option>'; + $selected = (!empty($default_offset) && strpos($key, $default_offset) !== false) ? ' selected="selected"' : ''; + $template->assign_block_vars('timezone_date', array( + 'VALUE' => $key . ' - ' . $timezone['current'], + 'SELECTED' => !empty($selected), + 'TITLE' => $user->lang(array('timezones', 'UTC_OFFSET_CURRENT'), $timezone['offset'], $timezone['current']), + )); } $label = $timezone['tz']; @@ -1157,22 +541,26 @@ function phpbb_timezone_select($user, $default = '', $truncate = false) { $label = $user->lang['timezones'][$label]; } - $title = $timezone['offest'] . ' - ' . $label; + $title = $user->lang(array('timezones', 'UTC_OFFSET_CURRENT'), $timezone['offset'], $label); if ($truncate) { $label = truncate_string($label, 50, 255, false, '...'); } + // Also generate timezone_select for backwards compatibility $selected = ($timezone['tz'] === $default) ? ' selected="selected"' : ''; $tz_select .= '<option title="' . $title . '" value="' . $timezone['tz'] . '"' . $selected . '>' . $label . '</option>'; + $template->assign_block_vars('timezone_select.timezone_options', array( + 'TITLE' => $title, + 'VALUE' => $timezone['tz'], + 'SELECTED' => !empty($selected), + 'LABEL' => $label, + )); } $tz_select .= '</optgroup>'; - return array( - 'tz_select' => $tz_select, - 'tz_dates' => $tz_dates, - ); + return $tz_select; } // Functions handling topic/post tracking/marking @@ -1190,26 +578,59 @@ function phpbb_timezone_select($user, $default = '', $truncate = false) function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $user_id = 0) { global $db, $user, $config; - global $request, $phpbb_container; + global $request, $phpbb_container, $phpbb_dispatcher; $post_time = ($post_time === 0 || $post_time > time()) ? time() : (int) $post_time; + $should_markread = true; + + /** + * This event is used for performing actions directly before marking forums, + * topics or posts as read. + * + * It is also possible to prevent the marking. For that, the $should_markread parameter + * should be set to FALSE. + * + * @event core.markread_before + * @var string mode Variable containing marking mode value + * @var mixed forum_id Variable containing forum id, or false + * @var mixed topic_id Variable containing topic id, or false + * @var int post_time Variable containing post time + * @var int user_id Variable containing the user id + * @var bool should_markread Flag indicating if the markread should be done or not. + * @since 3.1.4-RC1 + */ + $vars = array( + 'mode', + 'forum_id', + 'topic_id', + 'post_time', + 'user_id', + 'should_markread', + ); + extract($phpbb_dispatcher->trigger_event('core.markread_before', compact($vars))); + + if (!$should_markread) + { + return; + } + if ($mode == 'all') { if ($forum_id === false || !sizeof($forum_id)) { // Mark all forums read (index page) - + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); // Mark all topic notifications read for this user - $phpbb_notifications->mark_notifications_read(array( - 'topic', - 'quote', - 'bookmark', - 'post', - 'approve_topic', - 'approve_post', + $phpbb_notifications->mark_notifications(array( + 'notification.type.topic', + 'notification.type.quote', + 'notification.type.bookmark', + 'notification.type.post', + 'notification.type.approve_topic', + 'notification.type.approve_post', ), false, $user->data['user_id'], $post_time); if ($config['load_db_lastread'] && $user->data['is_registered']) @@ -1265,12 +686,17 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $ { $forum_id = array($forum_id); } + else + { + $forum_id = array_unique($forum_id); + } + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); - $phpbb_notifications->mark_notifications_read_by_parent(array( - 'topic', - 'approve_topic', + $phpbb_notifications->mark_notifications_by_parent(array( + 'notification.type.topic', + 'notification.type.approve_topic', ), $forum_id, $user->data['user_id'], $post_time); // Mark all post/quote notifications read for this user in this forum @@ -1285,11 +711,11 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $ } $db->sql_freeresult($result); - $phpbb_notifications->mark_notifications_read_by_parent(array( - 'quote', - 'bookmark', - 'post', - 'approve_post', + $phpbb_notifications->mark_notifications_by_parent(array( + 'notification.type.quote', + 'notification.type.bookmark', + 'notification.type.post', + 'notification.type.approve_post', ), $topic_ids, $user->data['user_id'], $post_time); // Add 0 to forums array to mark global announcements correctly @@ -1388,19 +814,20 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $ return; } + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); // Mark post notifications read for this user in this topic - $phpbb_notifications->mark_notifications_read(array( - 'topic', - 'approve_topic', + $phpbb_notifications->mark_notifications(array( + 'notification.type.topic', + 'notification.type.approve_topic', ), $topic_id, $user->data['user_id'], $post_time); - $phpbb_notifications->mark_notifications_read_by_parent(array( - 'quote', - 'bookmark', - 'post', - 'approve_post', + $phpbb_notifications->mark_notifications_by_parent(array( + 'notification.type.quote', + 'notification.type.bookmark', + 'notification.type.post', + 'notification.type.approve_post', ), $topic_id, $user->data['user_id'], $post_time); if ($config['load_db_lastread'] && $user->data['is_registered']) @@ -1528,7 +955,7 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $ */ function get_topic_tracking($forum_id, $topic_ids, &$rowset, $forum_mark_time, $global_announce_list = false) { - global $config, $user; + global $user; $last_read = array(); @@ -1687,7 +1114,8 @@ function get_complete_topic_tracking($forum_id, $topic_ids, $global_announce_lis */ function get_unread_topics($user_id = false, $sql_extra = '', $sql_sort = '', $sql_limit = 1001, $sql_limit_offset = 0) { - global $config, $db, $user; + global $config, $db, $user, $request; + global $phpbb_dispatcher; $user_id = ($user_id === false) ? (int) $user->data['user_id'] : (int) $user_id; @@ -1696,7 +1124,7 @@ function get_unread_topics($user_id = false, $sql_extra = '', $sql_sort = '', $s if (empty($sql_sort)) { - $sql_sort = 'ORDER BY t.topic_last_post_time DESC'; + $sql_sort = 'ORDER BY t.topic_last_post_time DESC, t.topic_last_post_id DESC'; } if ($config['load_db_lastread'] && $user->data['is_registered']) @@ -1731,6 +1159,24 @@ function get_unread_topics($user_id = false, $sql_extra = '', $sql_sort = '', $s $sql_sort", ); + /** + * Change SQL query for fetching unread topics data + * + * @event core.get_unread_topics_modify_sql + * @var array sql_array Fully assembled SQL query with keys SELECT, FROM, LEFT_JOIN, WHERE + * @var int last_mark User's last_mark time + * @var string sql_extra Extra WHERE SQL statement + * @var string sql_sort ORDER BY SQL sorting statement + * @since 3.1.4-RC1 + */ + $vars = array( + 'sql_array', + 'last_mark', + 'sql_extra', + 'sql_sort', + ); + extract($phpbb_dispatcher->trigger_event('core.get_unread_topics_modify_sql', compact($vars))); + $sql = $db->sql_build_query('SELECT', $sql_array); $result = $db->sql_query_limit($sql, $sql_limit, $sql_limit_offset); @@ -1747,7 +1193,7 @@ function get_unread_topics($user_id = false, $sql_extra = '', $sql_sort = '', $s if (empty($tracking_topics)) { - $tracking_topics = request_var($config['cookie_name'] . '_track', '', false, true); + $tracking_topics = $request->variable($config['cookie_name'] . '_track', '', false, \phpbb\request\request_interface::COOKIE); $tracking_topics = ($tracking_topics) ? tracking_unserialize($tracking_topics) : array(); } @@ -1814,7 +1260,7 @@ function get_unread_topics($user_id = false, $sql_extra = '', $sql_sort = '', $s */ function update_forum_tracking_info($forum_id, $forum_last_post_time, $f_mark_time = false, $mark_time_forum = false) { - global $db, $tracking_topics, $user, $config, $auth, $request, $phpbb_container; + global $db, $tracking_topics, $user, $config, $request, $phpbb_container; // Determine the users last forum mark time if not given. if ($mark_time_forum === false) @@ -1839,6 +1285,7 @@ function update_forum_tracking_info($forum_id, $forum_last_post_time, $f_mark_ti // Handle update of unapproved topics info. // Only update for moderators having m_approve permission for the forum. + /* @var $phpbb_content_visibility \phpbb\content_visibility */ $phpbb_content_visibility = $phpbb_container->get('content.visibility'); // Check the forum for any left unread topics. @@ -1871,8 +1318,6 @@ function update_forum_tracking_info($forum_id, $forum_last_post_time, $f_mark_ti else if ($config['load_anon_lastread'] || $user->data['is_registered']) { // Get information from cookie - $row = false; - if (!isset($tracking_topics['tf'][$forum_id])) { // We do not need to mark read, this happened before. Therefore setting this to true @@ -2049,6 +1494,9 @@ function tracking_unserialize($string, $max_depth = 3) * @param mixed $params String or array of additional url parameters * @param bool $is_amp Is url using & (true) or & (false) * @param string $session_id Possibility to use a custom session id instead of the global one +* @param bool $is_route Is url generated by a route. +* +* @return string The corrected url. * * Examples: * <code> @@ -2059,7 +1507,7 @@ function tracking_unserialize($string, $max_depth = 3) * </code> * */ -function append_sid($url, $params = false, $is_amp = true, $session_id = false) +function append_sid($url, $params = false, $is_amp = true, $session_id = false, $is_route = false) { global $_SID, $_EXTRA_URL, $phpbb_hook, $phpbb_path_helper; global $phpbb_dispatcher; @@ -2071,7 +1519,7 @@ function append_sid($url, $params = false, $is_amp = true, $session_id = false) } // Update the root path with the correct relative web path - if ($phpbb_path_helper instanceof \phpbb\path_helper) + if (!$is_route && $phpbb_path_helper instanceof \phpbb\path_helper) { $url = $phpbb_path_helper->update_web_root_path($url); } @@ -2097,9 +1545,10 @@ function append_sid($url, $params = false, $is_amp = true, $session_id = false) * the global one (false) * @var bool|string append_sid_overwrite Overwrite function (string * URL) or not (false) - * @since 3.1-A1 + * @var bool is_route Is url generated by a route. + * @since 3.1.0-a1 */ - $vars = array('url', 'params', 'is_amp', 'session_id', 'append_sid_overwrite'); + $vars = array('url', 'params', 'is_amp', 'session_id', 'append_sid_overwrite', 'is_route'); extract($phpbb_dispatcher->trigger_event('core.append_sid', compact($vars))); if ($append_sid_overwrite) @@ -2268,20 +1717,13 @@ function generate_board_url($without_script_path = false) */ function redirect($url, $return = false, $disable_cd_check = false) { - global $db, $cache, $config, $user, $phpbb_root_path, $phpbb_filesystem, $phpbb_path_helper, $phpEx; - - $failover_flag = false; + global $user, $phpbb_path_helper, $phpbb_dispatcher; - if (empty($user->lang)) + if (!$user->is_setup()) { $user->add_lang('common'); } - if (!$return) - { - garbage_collection(); - } - // Make sure no &'s are in, this will break the redirect $url = str_replace('&', '&', $url); @@ -2298,7 +1740,7 @@ function redirect($url, $return = false, $disable_cd_check = false) // Attention: only able to redirect within the same domain if $disable_cd_check is false (yourdomain.com -> www.yourdomain.com will not work) if (!$disable_cd_check && $url_parts['host'] !== $user->host) { - $url = generate_board_url(); + trigger_error('INSECURE_REDIRECT', E_USER_ERROR); } } else if ($url[0] == '/') @@ -2336,7 +1778,7 @@ function redirect($url, $return = false, $disable_cd_check = false) // Clean URL and check if we go outside the forum directory $url = $phpbb_path_helper->clean_url($url); - if (!$disable_cd_check && strpos($url, generate_board_url(true)) === false) + if (!$disable_cd_check && strpos($url, generate_board_url(true) . '/') !== 0) { trigger_error('INSECURE_REDIRECT', E_USER_ERROR); } @@ -2356,13 +1798,29 @@ function redirect($url, $return = false, $disable_cd_check = false) trigger_error('INSECURE_REDIRECT', E_USER_ERROR); } + /** + * Execute code and/or overwrite redirect() + * + * @event core.functions.redirect + * @var string url The url + * @var bool return If true, do not redirect but return the sanitized URL. + * @var bool disable_cd_check If true, redirect() will redirect to an external domain. If false, the redirect point to the boards url if it does not match the current domain. + * @since 3.1.0-RC3 + */ + $vars = array('url', 'return', 'disable_cd_check'); + extract($phpbb_dispatcher->trigger_event('core.functions.redirect', compact($vars))); + if ($return) { return $url; } + else + { + garbage_collection(); + } // Redirect via an HTML form for PITA webservers - if (@preg_match('#Microsoft|WebSTAR|Xitami#', getenv('SERVER_SOFTWARE'))) + if (@preg_match('#WebSTAR|Xitami#', getenv('SERVER_SOFTWARE'))) { header('Refresh: 0; URL=' . $url); @@ -2419,79 +1877,23 @@ function reapply_sid($url) */ function build_url($strip_vars = false) { - global $user, $phpbb_root_path; - - $page = $user->page['page']; - - // We need to be cautious here. - // On some situations, the redirect path is an absolute URL, sometimes a relative path - // For a relative path, let's prefix it with $phpbb_root_path to point to the correct location, - // else we use the URL directly. - $url_parts = parse_url($page); + global $config, $user, $phpbb_path_helper; - // URL - if ($url_parts === false || empty($url_parts['scheme']) || empty($url_parts['host'])) - { - $page = $phpbb_root_path . $page; - } + $page = $phpbb_path_helper->get_valid_page($user->page['page'], $config['enable_mod_rewrite']); // Append SID $redirect = append_sid($page, false, false); - // Add delimiter if not there... - if (strpos($redirect, '?') === false) + if ($strip_vars !== false) { - $redirect .= '?'; + $redirect = $phpbb_path_helper->strip_url_params($redirect, $strip_vars, false); } - - // Strip vars... - if ($strip_vars !== false && strpos($redirect, '?') !== false) + else { - if (!is_array($strip_vars)) - { - $strip_vars = array($strip_vars); - } - - $query = $_query = array(); - - $args = substr($redirect, strpos($redirect, '?') + 1); - $args = ($args) ? explode('&', $args) : array(); - $redirect = substr($redirect, 0, strpos($redirect, '?')); - - foreach ($args as $argument) - { - $arguments = explode('=', $argument); - $key = $arguments[0]; - unset($arguments[0]); - - if ($key === '') - { - continue; - } - - $query[$key] = implode('=', $arguments); - } - - // Strip the vars off - foreach ($strip_vars as $strip) - { - if (isset($query[$strip])) - { - unset($query[$strip]); - } - } - - // Glue the remaining parts together... already urlencoded - foreach ($query as $key => $value) - { - $_query[] = $key . '=' . $value; - } - $query = implode('&', $_query); - - $redirect .= ($query) ? '?' . $query : ''; + $redirect = str_replace('&', '&', $redirect); } - return str_replace('&', '&', $redirect); + return $redirect . ((strpos($redirect, '?') === false) ? '?' : ''); } /** @@ -2506,19 +1908,19 @@ function meta_refresh($time, $url, $disable_cd_check = false) { global $template, $refresh_data, $request; + $url = redirect($url, true, $disable_cd_check); if ($request->is_ajax()) { $refresh_data = array( 'time' => $time, - 'url' => str_replace('&', '&', $url) + 'url' => $url, ); } else { - $url = redirect($url, true, $disable_cd_check); + // For XHTML compatibility we change back & to & $url = str_replace('&', '&', $url); - // For XHTML compatibility we change back & to & $template->assign_vars(array( 'META' => '<meta http-equiv="refresh" content="' . $time . '; url=' . $url . '" />') ); @@ -2573,13 +1975,19 @@ function phpbb_request_http_version() { global $request; + $version = ''; if ($request && $request->server('SERVER_PROTOCOL')) { - return $request->server('SERVER_PROTOCOL'); + $version = $request->server('SERVER_PROTOCOL'); } else if (isset($_SERVER['SERVER_PROTOCOL'])) { - return $_SERVER['SERVER_PROTOCOL']; + $version = $_SERVER['SERVER_PROTOCOL']; + } + + if (!empty($version) && is_string($version) && preg_match('#^HTTP/[0-9]\.[0-9]$#', $version)) + { + return $version; } return 'HTTP/1.0'; @@ -2624,7 +2032,7 @@ function check_link_hash($token, $link_name) */ function add_form_key($form_name) { - global $config, $template, $user; + global $config, $template, $user, $phpbb_dispatcher; $now = time(); $token_sid = ($user->data['user_id'] == ANONYMOUS && !empty($config['form_token_sid_guests'])) ? $user->session_id : ''; @@ -2635,21 +2043,44 @@ function add_form_key($form_name) 'form_token' => $token, )); + /** + * Perform additional actions on creation of the form token + * + * @event core.add_form_key + * @var string form_name The form name + * @var int now Current time timestamp + * @var string s_fields Generated hidden fields + * @var string token Form token + * @var string token_sid User session ID + * + * @since 3.1.0-RC3 + */ + $vars = array( + 'form_name', + 'now', + 's_fields', + 'token', + 'token_sid', + ); + extract($phpbb_dispatcher->trigger_event('core.add_form_key', compact($vars))); + $template->assign_vars(array( 'S_FORM_TOKEN' => $s_fields, )); } /** -* Check the form key. Required for all altering actions not secured by confirm_box -* @param string $form_name The name of the form; has to match the name used in add_form_key, otherwise no restrictions apply -* @param int $timespan The maximum acceptable age for a submitted form in seconds. Defaults to the config setting. -* @param string $return_page The address for the return link -* @param bool $trigger If true, the function will triger an error when encountering an invalid form -*/ -function check_form_key($form_name, $timespan = false, $return_page = '', $trigger = false) + * Check the form key. Required for all altering actions not secured by confirm_box + * + * @param string $form_name The name of the form; has to match the name used + * in add_form_key, otherwise no restrictions apply + * @param int $timespan The maximum acceptable age for a submitted form + * in seconds. Defaults to the config setting. + * @return bool True, if the form key was valid, false otherwise + */ +function check_form_key($form_name, $timespan = false) { - global $config, $user; + global $config, $request, $user; if ($timespan === false) { @@ -2657,10 +2088,10 @@ function check_form_key($form_name, $timespan = false, $return_page = '', $trigg $timespan = ($config['form_token_lifetime'] == -1) ? -1 : max(30, $config['form_token_lifetime']); } - if (isset($_POST['creation_time']) && isset($_POST['form_token'])) + if ($request->is_set_post('creation_time') && $request->is_set_post('form_token')) { - $creation_time = abs(request_var('creation_time', 0)); - $token = request_var('form_token', ''); + $creation_time = abs($request->variable('creation_time', 0)); + $token = $request->variable('form_token', ''); $diff = time() - $creation_time; @@ -2677,11 +2108,6 @@ function check_form_key($form_name, $timespan = false, $return_page = '', $trigg } } - if ($trigger) - { - trigger_error($user->lang['FORM_INVALID'] . $return_page); - } - return false; } @@ -2701,7 +2127,7 @@ function check_form_key($form_name, $timespan = false, $return_page = '', $trigg function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_body.html', $u_action = '') { global $user, $template, $db, $request; - global $phpEx, $phpbb_root_path, $request; + global $config, $phpbb_path_helper; if (isset($_POST['cancel'])) { @@ -2712,9 +2138,9 @@ function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_bo if ($check && $confirm) { - $user_id = request_var('confirm_uid', 0); - $session_id = request_var('sess', ''); - $confirm_key = request_var('confirm_key', ''); + $user_id = $request->variable('confirm_uid', 0); + $session_id = $request->variable('sess', ''); + $confirm_key = $request->variable('confirm_key', ''); if ($user_id != $user->data['user_id'] || $session_id != $user->session_id || !$confirm_key || !$user->data['user_last_confirm_key'] || $confirm_key != $user->data['user_last_confirm_key']) { @@ -2748,7 +2174,7 @@ function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_bo } else { - page_header(((!isset($user->lang[$title])) ? $user->lang['CONFIRM'] : $user->lang[$title]), false); + page_header((!isset($user->lang[$title])) ? $user->lang['CONFIRM'] : $user->lang[$title]); } $template->set_filenames(array( @@ -2756,15 +2182,15 @@ function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_bo ); // If activation key already exist, we better do not re-use the key (something very strange is going on...) - if (request_var('confirm_key', '')) + if ($request->variable('confirm_key', '')) { // This should not occur, therefore we cancel the operation to safe the user return false; } // re-add sid / transform & to & for user->page (user->page is always using &) - $use_page = ($u_action) ? $phpbb_root_path . $u_action : $phpbb_root_path . str_replace('&', '&', $user->page['page']); - $u_action = reapply_sid($use_page); + $use_page = ($u_action) ? $u_action : str_replace('&', '&', $user->page['page']); + $u_action = reapply_sid($phpbb_path_helper->get_valid_page($use_page, $config['enable_mod_rewrite'])); $u_action .= ((strpos($u_action, '?') === false) ? '?' : '&') . 'confirm_key=' . $confirm_key; $template->assign_vars(array( @@ -2781,7 +2207,6 @@ function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_bo WHERE user_id = " . $user->data['user_id']; $db->sql_query($sql); - if ($request->is_ajax()) { $u_action .= '&confirm_uid=' . $user->data['user_id'] . '&sess=' . $user->session_id . '&sid=' . $user->session_id; @@ -2812,18 +2237,13 @@ function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_bo */ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = false, $s_display = true) { - global $db, $user, $template, $auth, $phpEx, $phpbb_root_path, $config; - global $request, $phpbb_container; - - if (!class_exists('phpbb_captcha_factory', false)) - { - include($phpbb_root_path . 'includes/captcha/captcha_factory.' . $phpEx); - } + global $user, $template, $auth, $phpEx, $phpbb_root_path, $config; + global $request, $phpbb_container, $phpbb_dispatcher, $phpbb_log; $err = ''; // Make sure user->setup() has been called - if (empty($user->lang)) + if (!$user->is_setup()) { $user->setup(); } @@ -2835,7 +2255,7 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa // anonymous/inactive users are never able to go to the ACP even if they have the relevant permissions if ($user->data['is_registered']) { - add_log('admin', 'LOG_ADMIN_AUTH_FAIL'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ADMIN_AUTH_FAIL'); } trigger_error('NO_AUTH_ADMIN'); } @@ -2845,13 +2265,13 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa // Get credential if ($admin) { - $credential = request_var('credential', ''); + $credential = $request->variable('credential', ''); if (strspn($credential, 'abcdef0123456789') !== strlen($credential) || strlen($credential) != 32) { if ($user->data['is_registered']) { - add_log('admin', 'LOG_ADMIN_AUTH_FAIL'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ADMIN_AUTH_FAIL'); } trigger_error('NO_AUTH_ADMIN'); } @@ -2863,7 +2283,7 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa $password = $request->untrimmed_variable('password', '', true); } - $username = request_var('username', '', true); + $username = $request->variable('username', '', true); $autologin = $request->is_set_post('autologin'); $viewonline = (int) !$request->is_set_post('viewonline'); $admin = ($admin) ? 1 : 0; @@ -2873,7 +2293,7 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa if ($admin && utf8_clean_string($username) != utf8_clean_string($user->data['username'])) { // We log the attempt to use a different username... - add_log('admin', 'LOG_ADMIN_AUTH_FAIL'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ADMIN_AUTH_FAIL'); trigger_error('NO_AUTH_ADMIN_USER_DIFFER'); } @@ -2886,7 +2306,7 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa { if ($result['status'] == LOGIN_SUCCESS) { - add_log('admin', 'LOG_ADMIN_AUTH_SUCCESS'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ADMIN_AUTH_SUCCESS'); } else { @@ -2894,7 +2314,7 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa // anonymous/inactive users are never able to go to the ACP even if they have the relevant permissions if ($user->data['is_registered']) { - add_log('admin', 'LOG_ADMIN_AUTH_FAIL'); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ADMIN_AUTH_FAIL'); } } } @@ -2902,9 +2322,19 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa // The result parameter is always an array, holding the relevant information... if ($result['status'] == LOGIN_SUCCESS) { - $redirect = request_var('redirect', "{$phpbb_root_path}index.$phpEx"); - $message = ($l_success) ? $l_success : $user->lang['LOGIN_REDIRECT']; - $l_redirect = ($admin) ? $user->lang['PROCEED_TO_ACP'] : (($redirect === "{$phpbb_root_path}index.$phpEx" || $redirect === "index.$phpEx") ? $user->lang['RETURN_INDEX'] : $user->lang['RETURN_PAGE']); + $redirect = $request->variable('redirect', "{$phpbb_root_path}index.$phpEx"); + + /** + * This event allows an extension to modify the redirection when a user successfully logs in + * + * @event core.login_box_redirect + * @var string redirect Redirect string + * @var boolean admin Is admin? + * @var bool return If true, do not redirect but return the sanitized URL. + * @since 3.1.0-RC5 + */ + $vars = array('redirect', 'admin', 'return'); + extract($phpbb_dispatcher->trigger_event('core.login_box_redirect', compact($vars))); // append/replace SID (may change during the session for AOL users) $redirect = reapply_sid($redirect); @@ -2927,28 +2357,26 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa // Special cases... determine switch ($result['status']) { + case LOGIN_ERROR_PASSWORD_CONVERT: + $err = sprintf( + $user->lang[$result['error_msg']], + ($config['email_enable']) ? '<a href="' . append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=sendpassword') . '">' : '', + ($config['email_enable']) ? '</a>' : '', + '<a href="' . phpbb_get_board_contact_link($config, $phpbb_root_path, $phpEx) . '">', + '</a>' + ); + break; + case LOGIN_ERROR_ATTEMPTS: - $captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']); + $captcha = $phpbb_container->get('captcha.factory')->get_instance($config['captcha_plugin']); $captcha->init(CONFIRM_LOGIN); // $captcha->reset(); $template->assign_vars(array( 'CAPTCHA_TEMPLATE' => $captcha->get_template(), )); - - $err = $user->lang[$result['error_msg']]; - break; - - case LOGIN_ERROR_PASSWORD_CONVERT: - $err = sprintf( - $user->lang[$result['error_msg']], - ($config['email_enable']) ? '<a href="' . append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=sendpassword') . '">' : '', - ($config['email_enable']) ? '</a>' : '', - ($config['board_contact']) ? '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">' : '', - ($config['board_contact']) ? '</a>' : '' - ); - break; + // no break; // Username, password, etc... default: @@ -2957,11 +2385,24 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa // Assign admin contact to some error messages if ($result['error_msg'] == 'LOGIN_ERROR_USERNAME' || $result['error_msg'] == 'LOGIN_ERROR_PASSWORD') { - $err = (!$config['board_contact']) ? sprintf($user->lang[$result['error_msg']], '', '') : sprintf($user->lang[$result['error_msg']], '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>'); + $err = sprintf($user->lang[$result['error_msg']], '<a href="' . append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=contactadmin') . '">', '</a>'); } break; } + + /** + * This event allows an extension to process when a user fails a login attempt + * + * @event core.login_box_failed + * @var array result Login result data + * @var string username User name used to login + * @var string password Password used to login + * @var string err Error message + * @since 3.1.3-RC1 + */ + $vars = array('result', 'username', 'password', 'err'); + extract($phpbb_dispatcher->trigger_event('core.login_box_failed', compact($vars))); } // Assign credential for username/password pair @@ -2981,7 +2422,9 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa $s_hidden_fields['credential'] = $credential; } - $auth_provider = $phpbb_container->get('auth.provider.' . $config['auth_method']); + /* @var $provider_collection \phpbb\auth\provider_collection */ + $provider_collection = $phpbb_container->get('auth.provider_collection'); + $auth_provider = $provider_collection->get_provider(); $auth_provider_data = $auth_provider->get_login_data(); if ($auth_provider_data) @@ -3025,7 +2468,7 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa 'PASSWORD_CREDENTIAL' => ($admin) ? 'password_' . $credential : 'password', )); - page_header($user->lang['LOGIN'], false); + page_header($user->lang['LOGIN']); $template->set_filenames(array( 'body' => 'login_body.html') @@ -3040,7 +2483,7 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa */ function login_forum_box($forum_data) { - global $db, $phpbb_container, $request, $template, $user; + global $db, $phpbb_container, $request, $template, $user, $phpbb_dispatcher; $password = $request->variable('password', '', true); @@ -3083,6 +2526,7 @@ function login_forum_box($forum_data) } $db->sql_freeresult($result); + /* @var $passwords_manager \phpbb\passwords\manager */ $passwords_manager = $phpbb_container->get('passwords.manager'); if ($passwords_manager->check($password, $forum_data['forum_password'])) @@ -3101,7 +2545,18 @@ function login_forum_box($forum_data) $template->assign_var('LOGIN_ERROR', $user->lang['WRONG_PASSWORD']); } - page_header($user->lang['LOGIN'], false); + /** + * Performing additional actions, load additional data on forum login + * + * @event core.login_forum_box + * @var array forum_data Array with forum data + * @var string password Password entered + * @since 3.1.0-RC3 + */ + $vars = array('forum_data', 'password'); + extract($phpbb_dispatcher->trigger_event('core.login_forum_box', compact($vars))); + + page_header($user->lang['LOGIN']); $template->assign_vars(array( 'FORUM_NAME' => isset($forum_data['forum_name']) ? $forum_data['forum_name'] : '', @@ -3192,7 +2647,7 @@ function parse_cfg_file($filename, $lines = false) } // Determine first occurrence, since in values the equal sign is allowed - $key = strtolower(trim(substr($line, 0, $delim_pos))); + $key = htmlspecialchars(strtolower(trim(substr($line, 0, $delim_pos)))); $value = trim(substr($line, $delim_pos + 1)); if (in_array($value, array('off', 'false', '0'))) @@ -3209,7 +2664,11 @@ function parse_cfg_file($filename, $lines = false) } else if (($value[0] == "'" && $value[sizeof($value) - 1] == "'") || ($value[0] == '"' && $value[sizeof($value) - 1] == '"')) { - $value = substr($value, 1, sizeof($value)-2); + $value = htmlspecialchars(substr($value, 1, sizeof($value)-2)); + } + else + { + $value = htmlspecialchars($value); } $parsed_items[$key] = $value; @@ -3224,52 +2683,6 @@ function parse_cfg_file($filename, $lines = false) } /** -* Add log entry -* -* @param string $mode The mode defines which log_type is used and from which log the entry is retrieved -* @param int $forum_id Mode 'mod' ONLY: forum id of the related item, NOT INCLUDED otherwise -* @param int $topic_id Mode 'mod' ONLY: topic id of the related item, NOT INCLUDED otherwise -* @param int $reportee_id Mode 'user' ONLY: user id of the reportee, NOT INCLUDED otherwise -* @param string $log_operation Name of the operation -* @param array $additional_data More arguments can be added, depending on the log_type -* -* @return int|bool Returns the log_id, if the entry was added to the database, false otherwise. -* -* @deprecated Use $phpbb_log->add() instead -*/ -function add_log() -{ - global $phpbb_log, $user; - - $args = func_get_args(); - $mode = array_shift($args); - - // This looks kind of dirty, but add_log has some additional data before the log_operation - $additional_data = array(); - switch ($mode) - { - case 'admin': - case 'critical': - break; - case 'mod': - $additional_data['forum_id'] = array_shift($args); - $additional_data['topic_id'] = array_shift($args); - break; - case 'user': - $additional_data['reportee_id'] = array_shift($args); - break; - } - - $log_operation = array_shift($args); - $additional_data = array_merge($additional_data, $args); - - $user_id = (empty($user->data)) ? ANONYMOUS : $user->data['user_id']; - $user_ip = (empty($user->ip)) ? '' : $user->ip; - - return $phpbb_log->add($mode, $user_id, $user_ip, $log_operation, time(), $additional_data); -} - -/** * Return a nicely formatted backtrace. * * Turns the array returned by debug_backtrace() into HTML markup. @@ -3325,14 +2738,14 @@ function get_preg_expression($mode) case 'email': // Regex written by James Watts and Francisco Jose Martin Moreno // http://fightingforalostcause.net/misc/2006/compare-email-regex.php - return '([\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*(?:[\w\!\#$\%\'\*\+\-\/\=\?\^\`{\|\}\~]|&)+@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,63})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)'; + return '((?:[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*(?:[\w\!\#$\%\'\*\+\-\/\=\?\^\`{\|\}\~]|&)+)@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,63})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)'; break; case 'bbcode_htm': return array( '#<!\-\- e \-\-><a href="mailto:(.*?)">.*?</a><!\-\- e \-\->#', '#<!\-\- l \-\-><a (?:class="[\w-]+" )?href="(.*?)(?:(&|\?)sid=[0-9a-f]{32})?">.*?</a><!\-\- l \-\->#', - '#<!\-\- ([mw]) \-\-><a (?:class="[\w-]+" )?href="(.*?)">.*?</a><!\-\- \1 \-\->#', + '#<!\-\- ([mw]) \-\-><a (?:class="[\w-]+" )?href="(.*?)">(.*?)</a><!\-\- \1 \-\->#', '#<!\-\- s(.*?) \-\-><img src="\{SMILIES_PATH\}\/.*? \/><!\-\- s\1 \-\->#', '#<!\-\- .*? \-\->#s', '#<.*?>#s', @@ -3351,28 +2764,43 @@ function get_preg_expression($mode) break; case 'url': + // generated with regex_idn.php file in the develop folder + return "[a-z][a-z\d+\-.]*:/{2}(?:(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'()*+,;=:@|]+|%[\dA-F]{2})+|[0-9.]+|\[[a-z0-9.]+:[a-z0-9.]+:[a-z0-9.:]+\])(?::\d*)?(?:/(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'()*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'()*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'()*+,;=:@/?|]+|%[\dA-F]{2})*)?"; + break; + case 'url_inline': - $inline = ($mode == 'url') ? ')' : ''; - $scheme = ($mode == 'url') ? '[a-z\d+\-.]' : '[a-z\d+]'; // avoid automatic parsing of "word" in "last word.http://..." - // generated with regex generation file in the develop folder - return "[a-z]$scheme*:/{2}(?:(?:[a-z0-9\-._~!$&'($inline*+,;=:@|]+|%[\dA-F]{2})+|[0-9.]+|\[[a-z0-9.]+:[a-z0-9.]+:[a-z0-9.:]+\])(?::\d*)?(?:/(?:[a-z0-9\-._~!$&'($inline*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[a-z0-9\-._~!$&'($inline*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[a-z0-9\-._~!$&'($inline*+,;=:@/?|]+|%[\dA-F]{2})*)?"; + // generated with regex_idn.php file in the develop folder + return "[a-z][a-z\d+]*:/{2}(?:(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@|]+|%[\dA-F]{2})+|[0-9.]+|\[[a-z0-9.]+:[a-z0-9.]+:[a-z0-9.:]+\])(?::\d*)?(?:/(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@/?|]+|%[\dA-F]{2})*)?"; break; case 'www_url': + // generated with regex_idn.php file in the develop folder + return "www\.(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'()*+,;=:@|]+|%[\dA-F]{2})+(?::\d*)?(?:/(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'()*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'()*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'()*+,;=:@/?|]+|%[\dA-F]{2})*)?"; + break; + case 'www_url_inline': - $inline = ($mode == 'www_url') ? ')' : ''; - return "www\.(?:[a-z0-9\-._~!$&'($inline*+,;=:@|]+|%[\dA-F]{2})+(?::\d*)?(?:/(?:[a-z0-9\-._~!$&'($inline*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[a-z0-9\-._~!$&'($inline*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[a-z0-9\-._~!$&'($inline*+,;=:@/?|]+|%[\dA-F]{2})*)?"; + // generated with regex_idn.php file in the develop folder + return "www\.(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@|]+|%[\dA-F]{2})+(?::\d*)?(?:/(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@/?|]+|%[\dA-F]{2})*)?"; break; case 'relative_url': + // generated with regex_idn.php file in the develop folder + return "(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'()*+,;=:@|]+|%[\dA-F]{2})*(?:/(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'()*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'()*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'()*+,;=:@/?|]+|%[\dA-F]{2})*)?"; + break; + case 'relative_url_inline': - $inline = ($mode == 'relative_url') ? ')' : ''; - return "(?:[a-z0-9\-._~!$&'($inline*+,;=:@|]+|%[\dA-F]{2})*(?:/(?:[a-z0-9\-._~!$&'($inline*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[a-z0-9\-._~!$&'($inline*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[a-z0-9\-._~!$&'($inline*+,;=:@/?|]+|%[\dA-F]{2})*)?"; + // generated with regex_idn.php file in the develop folder + return "(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@|]+|%[\dA-F]{2})*(?:/(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@/?|]+|%[\dA-F]{2})*)?"; break; case 'table_prefix': return '#^[a-zA-Z][a-zA-Z0-9_]*$#'; break; + + // Matches the predecing dot + case 'path_remove_dot_trailing_slash': + return '#^(?:(\.)?)+(?:(.+)?)+(?:([\\/\\\])$)#'; + break; } return ''; @@ -3383,31 +2811,19 @@ function get_preg_expression($mode) * Depends on whether installed PHP version supports unicode properties * * @param string $word word template to be replaced -* @param bool $use_unicode whether or not to take advantage of PCRE supporting unicode * * @return string $preg_expr regex to use with word censor */ -function get_censor_preg_expression($word, $use_unicode = true) +function get_censor_preg_expression($word) { // Unescape the asterisk to simplify further conversions $word = str_replace('\*', '*', preg_quote($word, '#')); - if ($use_unicode && phpbb_pcre_utf8_support()) - { - // Replace asterisk(s) inside the pattern, at the start and at the end of it with regexes - $word = preg_replace(array('#(?<=[\p{Nd}\p{L}_])\*+(?=[\p{Nd}\p{L}_])#iu', '#^\*+#', '#\*+$#'), array('([\x20]*?|[\p{Nd}\p{L}_-]*?)', '[\p{Nd}\p{L}_-]*?', '[\p{Nd}\p{L}_-]*?'), $word); - - // Generate the final substitution - $preg_expr = '#(?<![\p{Nd}\p{L}_-])(' . $word . ')(?![\p{Nd}\p{L}_-])#iu'; - } - else - { - // Replace the asterisk inside the pattern, at the start and at the end of it with regexes - $word = preg_replace(array('#(?<=\S)\*+(?=\S)#iu', '#^\*+#', '#\*+$#'), array('(\x20*?\S*?)', '\S*?', '\S*?'), $word); + // Replace asterisk(s) inside the pattern, at the start and at the end of it with regexes + $word = preg_replace(array('#(?<=[\p{Nd}\p{L}_])\*+(?=[\p{Nd}\p{L}_])#iu', '#^\*+#', '#\*+$#'), array('([\x20]*?|[\p{Nd}\p{L}_-]*?)', '[\p{Nd}\p{L}_-]*?', '[\p{Nd}\p{L}_-]*?'), $word); - // Generate the final substitution - $preg_expr = '#(?<!\S)(' . $word . ')(?!\S)#iu'; - } + // Generate the final substitution + $preg_expr = '#(?<![\p{Nd}\p{L}_-])(' . $word . ')(?![\p{Nd}\p{L}_-])#iu'; return $preg_expr; } @@ -3457,8 +2873,6 @@ function short_ipv6($ip, $length) * * @return mixed false if specified address is not valid, * string otherwise -* -* @author bantu */ function phpbb_ip_normalise($address) { @@ -3487,8 +2901,6 @@ function phpbb_ip_normalise($address) * * @return mixed false on failure, * string otherwise -* -* @author APTX */ function phpbb_inet_ntop($in_addr) { @@ -3558,8 +2970,6 @@ function phpbb_inet_ntop($in_addr) * * @return mixed false if address is invalid, * in_addr representation of the given address otherwise (string) -* -* @author APTX */ function phpbb_inet_pton($address) { @@ -3639,8 +3049,6 @@ function phpbb_inet_pton($address) * * Since null can also be returned, you probably want to compare the result * with === true or === false, -* -* @author bantu */ function phpbb_checkdnsrr($host, $type = 'MX') { @@ -3663,38 +3071,12 @@ function phpbb_checkdnsrr($host, $type = 'MX') return (@gethostbyname($host_fqdn) == $host_fqdn) ? false : true; } - // checkdnsrr() is available on Windows since PHP 5.3, - // but until 5.3.3 it only works for MX records - // See: http://bugs.php.net/bug.php?id=51844 - - // Call checkdnsrr() if - // we're looking for an MX record or - // we're not on Windows or - // we're running a PHP version where #51844 has been fixed - - // checkdnsrr() supports AAAA since 5.0.0 - // checkdnsrr() supports TXT since 5.2.4 - if ( - ($type == 'MX' || DIRECTORY_SEPARATOR != '\\' || version_compare(PHP_VERSION, '5.3.3', '>=')) && - ($type != 'AAAA' || version_compare(PHP_VERSION, '5.0.0', '>=')) && - ($type != 'TXT' || version_compare(PHP_VERSION, '5.2.4', '>=')) && - function_exists('checkdnsrr') - ) + if (function_exists('checkdnsrr')) { return checkdnsrr($host_fqdn, $type); } - // dns_get_record() is available since PHP 5; since PHP 5.3 also on Windows, - // but on Windows it does not work reliable for AAAA records before PHP 5.3.1 - - // Call dns_get_record() if - // we're not looking for an AAAA record or - // we're not on Windows or - // we're running a PHP version where AAAA lookups work reliable - if ( - ($type != 'AAAA' || DIRECTORY_SEPARATOR != '\\' || version_compare(PHP_VERSION, '5.3.1', '>=')) && - function_exists('dns_get_record') - ) + if (function_exists('dns_get_record')) { // dns_get_record() expects an integer as second parameter // We have to convert the string $type to the corresponding integer constant. @@ -3827,7 +3209,7 @@ function phpbb_checkdnsrr($host, $type = 'MX') function msg_handler($errno, $msg_text, $errfile, $errline) { global $cache, $db, $auth, $template, $config, $user, $request; - global $phpEx, $phpbb_root_path, $msg_title, $msg_long_text; + global $phpbb_root_path, $msg_title, $msg_long_text, $phpbb_log; // Do not display notices if we suppress them via @ if (error_reporting() == 0 && $errno != E_USER_ERROR && $errno != E_USER_WARNING && $errno != E_USER_NOTICE) @@ -3841,11 +3223,6 @@ function msg_handler($errno, $msg_text, $errfile, $errline) $msg_text = $msg_long_text; } - if (!defined('E_DEPRECATED')) - { - define('E_DEPRECATED', 8192); - } - switch ($errno) { case E_NOTICE: @@ -3868,7 +3245,7 @@ function msg_handler($errno, $msg_text, $errfile, $errline) // we are writing an image - the user won't see the debug, so let's place it in the log if (defined('IMAGE_OUTPUT') || defined('IN_CRON')) { - add_log('critical', 'LOG_IMAGE_GENERATION_ERROR', $errfile, $errline, $msg_text); + $phpbb_log->add('critical', $user->data['user_id'], $user->ip, 'LOG_IMAGE_GENERATION_ERROR', false, array($errfile, $errline, $msg_text)); } // echo '<br /><br />BACKTRACE<br />' . get_backtrace() . '<br />' . "\n"; } @@ -3879,7 +3256,7 @@ function msg_handler($errno, $msg_text, $errfile, $errline) case E_USER_ERROR: - if (!empty($user) && !empty($user->lang)) + if (!empty($user) && $user->is_setup()) { $msg_text = (!empty($user->lang[$msg_text])) ? $user->lang[$msg_text] : $msg_text; $msg_title = (!isset($msg_title)) ? $user->lang['GENERAL_ERROR'] : ((!empty($user->lang[$msg_title])) ? $user->lang[$msg_title] : $msg_title); @@ -3914,13 +3291,23 @@ function msg_handler($errno, $msg_text, $errfile, $errline) if (defined('IN_INSTALL') || defined('DEBUG') || isset($auth) && $auth->acl_get('a_')) { $msg_text = $log_text; + + // If this is defined there already was some output + // So let's not break it + if (defined('IN_DB_UPDATE')) + { + echo '<div class="errorbox">' . $msg_text . '</div>'; + + $db->sql_return_on_error(true); + phpbb_end_update($cache, $config); + } } if ((defined('IN_CRON') || defined('IMAGE_OUTPUT')) && isset($db)) { // let's avoid loops $db->sql_return_on_error(true); - add_log('critical', 'LOG_GENERAL_ERROR', $msg_title, $log_text); + $phpbb_log->add('critical', $user->data['user_id'], $user->ip, 'LOG_GENERAL_ERROR', false, array($msg_title, $log_text)); $db->sql_return_on_error(false); } @@ -3964,7 +3351,7 @@ function msg_handler($errno, $msg_text, $errfile, $errline) echo ' </div>'; echo ' </div>'; echo ' <div id="page-footer">'; - echo ' Powered by <a href="https://www.phpbb.com/">phpBB</a>® Forum Software © phpBB Group'; + echo ' Powered by <a href="https://www.phpbb.com/">phpBB</a>® Forum Software © phpBB Limited'; echo ' </div>'; echo '</div>'; echo '</body>'; @@ -3989,7 +3376,7 @@ function msg_handler($errno, $msg_text, $errfile, $errline) // We re-init the auth array to get correct results on login/logout $auth->acl($user->data); - if (empty($user->lang)) + if (!$user->is_setup()) { $user->setup(); } @@ -4010,7 +3397,7 @@ function msg_handler($errno, $msg_text, $errfile, $errline) } else { - page_header($msg_title, false); + page_header($msg_title); } } @@ -4078,11 +3465,21 @@ function msg_handler($errno, $msg_text, $errfile, $errline) */ function phpbb_filter_root_path($errfile) { + global $phpbb_filesystem; + static $root_path; if (empty($root_path)) { - $root_path = phpbb_realpath(dirname(__FILE__) . '/../'); + if ($phpbb_filesystem) + { + $root_path = $phpbb_filesystem->realpath(dirname(__FILE__) . '/../'); + } + else + { + $filesystem = new \phpbb\filesystem\filesystem(); + $root_path = $filesystem->realpath(dirname(__FILE__) . '/../'); + } } return str_replace(array($root_path, '\\'), array('[ROOT]', '/'), $errfile); @@ -4110,7 +3507,7 @@ function obtain_guest_count($item_id = 0, $item = 'forum') // Get number of online guests - if ($db->sql_layer === 'sqlite') + if ($db->get_sql_layer() === 'sqlite' || $db->get_sql_layer() === 'sqlite3') { $sql = 'SELECT COUNT(session_ip) as num_guests FROM ( @@ -4144,7 +3541,7 @@ function obtain_guest_count($item_id = 0, $item = 'forum') */ function obtain_users_online($item_id = 0, $item = 'forum') { - global $db, $config, $user; + global $db, $config; $reading_sql = ''; if ($item_id !== 0) @@ -4208,21 +3605,45 @@ function obtain_users_online($item_id = 0, $item = 'forum') */ function obtain_users_online_string($online_users, $item_id = 0, $item = 'forum') { - global $config, $db, $user, $auth; + global $config, $db, $user, $auth, $phpbb_dispatcher; - $user_online_link = $online_userlist = ''; + $user_online_link = $rowset = array(); // Need caps version of $item for language-strings $item_caps = strtoupper($item); if (sizeof($online_users['online_users'])) { - $sql = 'SELECT username, username_clean, user_id, user_type, user_allow_viewonline, user_colour - FROM ' . USERS_TABLE . ' - WHERE ' . $db->sql_in_set('user_id', $online_users['online_users']) . ' - ORDER BY username_clean ASC'; - $result = $db->sql_query($sql); + $sql_ary = array( + 'SELECT' => 'u.username, u.username_clean, u.user_id, u.user_type, u.user_allow_viewonline, u.user_colour', + 'FROM' => array( + USERS_TABLE => 'u', + ), + 'WHERE' => $db->sql_in_set('u.user_id', $online_users['online_users']), + 'ORDER_BY' => 'u.username_clean ASC', + ); - while ($row = $db->sql_fetchrow($result)) + /** + * Modify SQL query to obtain online users data + * + * @event core.obtain_users_online_string_sql + * @var array online_users Array with online users data + * from obtain_users_online() + * @var int item_id Restrict online users to item id + * @var string item Restrict online users to a certain + * session item, e.g. forum for + * session_forum_id + * @var string sql_ary SQL query to obtain users online data + * @since 3.1.4-RC1 + * @changed 3.1.7-RC1 Change sql query into array and adjust var accordingly. Allows extension authors the ability to adjust the sql_ary. + */ + $vars = array('online_users', 'item_id', 'item', 'sql_ary'); + extract($phpbb_dispatcher->trigger_event('core.obtain_users_online_string_sql', compact($vars))); + + $result = $db->sql_query($db->sql_build_query('SELECT', $sql_ary)); + $rowset = $db->sql_fetchrowset($result); + $db->sql_freeresult($result); + + foreach ($rowset as $row) { // User is logged in and therefore not a guest if ($row['user_id'] != ANONYMOUS) @@ -4232,15 +3653,14 @@ function obtain_users_online_string($online_users, $item_id = 0, $item = 'forum' $row['username'] = '<em>' . $row['username'] . '</em>'; } - if (!isset($online_users['hidden_users'][$row['user_id']]) || $auth->acl_get('u_viewonline')) + if (!isset($online_users['hidden_users'][$row['user_id']]) || $auth->acl_get('u_viewonline') || $row['user_id'] === $user->data['user_id']) { - $user_online_link = get_username_string(($row['user_type'] <> USER_IGNORE) ? 'full' : 'no_profile', $row['user_id'], $row['username'], $row['user_colour']); - $online_userlist .= ($online_userlist != '') ? ', ' . $user_online_link : $user_online_link; + $user_online_link[$row['user_id']] = get_username_string(($row['user_type'] <> USER_IGNORE) ? 'full' : 'no_profile', $row['user_id'], $row['username'], $row['user_colour']); } } } - $db->sql_freeresult($result); } + $online_userlist = implode(', ', $user_online_link); if (!$online_userlist) { @@ -4273,6 +3693,33 @@ function obtain_users_online_string($online_users, $item_id = 0, $item = 'forum' $l_online_users = $user->lang('ONLINE_USERS_TOTAL', (int) $online_users['total_online'], $visible_online, $hidden_online); } + /** + * Modify online userlist data + * + * @event core.obtain_users_online_string_modify + * @var array online_users Array with online users data + * from obtain_users_online() + * @var int item_id Restrict online users to item id + * @var string item Restrict online users to a certain + * session item, e.g. forum for + * session_forum_id + * @var array rowset Array with online users data + * @var array user_online_link Array with online users items (usernames) + * @var string online_userlist String containing users online list + * @var string l_online_users String with total online users count info + * @since 3.1.4-RC1 + */ + $vars = array( + 'online_users', + 'item_id', + 'item', + 'rowset', + 'user_online_link', + 'online_userlist', + 'l_online_users', + ); + extract($phpbb_dispatcher->trigger_event('core.obtain_users_online_string_modify', compact($vars))); + return array( 'online_userlist' => $online_userlist, 'l_online_users' => $l_online_users, @@ -4315,178 +3762,6 @@ function phpbb_optionset($bit, $set, $data) } /** -* Determine which plural form we should use. -* For some languages this is not as simple as for English. -* -* @param $rule int ID of the plural rule we want to use, see http://wiki.phpbb.com/Plural_Rules#Plural_Rules -* @param $number int|float The number we want to get the plural case for. Float numbers are floored. -* @return int The plural-case we need to use for the number plural-rule combination -*/ -function phpbb_get_plural_form($rule, $number) -{ - $number = (int) $number; - - if ($rule > 15 || $rule < 0) - { - trigger_error('INVALID_PLURAL_RULE'); - } - - /** - * The following plural rules are based on a list published by the Mozilla Developer Network - * https://developer.mozilla.org/en/Localization_and_Plurals - */ - switch ($rule) - { - case 0: - /** - * Families: Asian (Chinese, Japanese, Korean, Vietnamese), Persian, Turkic/Altaic (Turkish), Thai, Lao - * 1 - everything: 0, 1, 2, ... - */ - return 1; - - case 1: - /** - * Families: Germanic (Danish, Dutch, English, Faroese, Frisian, German, Norwegian, Swedish), Finno-Ugric (Estonian, Finnish, Hungarian), Language isolate (Basque), Latin/Greek (Greek), Semitic (Hebrew), Romanic (Italian, Portuguese, Spanish, Catalan) - * 1 - 1 - * 2 - everything else: 0, 2, 3, ... - */ - return ($number == 1) ? 1 : 2; - - case 2: - /** - * Families: Romanic (French, Brazilian Portuguese) - * 1 - 0, 1 - * 2 - everything else: 2, 3, ... - */ - return (($number == 0) || ($number == 1)) ? 1 : 2; - - case 3: - /** - * Families: Baltic (Latvian) - * 1 - 0 - * 2 - ends in 1, not 11: 1, 21, ... 101, 121, ... - * 3 - everything else: 2, 3, ... 10, 11, 12, ... 20, 22, ... - */ - return ($number == 0) ? 1 : ((($number % 10 == 1) && ($number % 100 != 11)) ? 2 : 3); - - case 4: - /** - * Families: Celtic (Scottish Gaelic) - * 1 - is 1 or 11: 1, 11 - * 2 - is 2 or 12: 2, 12 - * 3 - others between 3 and 19: 3, 4, ... 10, 13, ... 18, 19 - * 4 - everything else: 0, 20, 21, ... - */ - return ($number == 1 || $number == 11) ? 1 : (($number == 2 || $number == 12) ? 2 : (($number >= 3 && $number <= 19) ? 3 : 4)); - - case 5: - /** - * Families: Romanic (Romanian) - * 1 - 1 - * 2 - is 0 or ends in 01-19: 0, 2, 3, ... 19, 101, 102, ... 119, 201, ... - * 3 - everything else: 20, 21, ... - */ - return ($number == 1) ? 1 : ((($number == 0) || (($number % 100 > 0) && ($number % 100 < 20))) ? 2 : 3); - - case 6: - /** - * Families: Baltic (Lithuanian) - * 1 - ends in 1, not 11: 1, 21, 31, ... 101, 121, ... - * 2 - ends in 0 or ends in 10-20: 0, 10, 11, 12, ... 19, 20, 30, 40, ... - * 3 - everything else: 2, 3, ... 8, 9, 22, 23, ... 29, 32, 33, ... - */ - return (($number % 10 == 1) && ($number % 100 != 11)) ? 1 : ((($number % 10 < 2) || (($number % 100 >= 10) && ($number % 100 < 20))) ? 2 : 3); - - case 7: - /** - * Families: Slavic (Croatian, Serbian, Russian, Ukrainian) - * 1 - ends in 1, not 11: 1, 21, 31, ... 101, 121, ... - * 2 - ends in 2-4, not 12-14: 2, 3, 4, 22, 23, 24, 32, ... - * 3 - everything else: 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 25, 26, ... - */ - return (($number % 10 == 1) && ($number % 100 != 11)) ? 1 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 2 : 3); - - case 8: - /** - * Families: Slavic (Slovak, Czech) - * 1 - 1 - * 2 - 2, 3, 4 - * 3 - everything else: 0, 5, 6, 7, ... - */ - return ($number == 1) ? 1 : ((($number >= 2) && ($number <= 4)) ? 2 : 3); - - case 9: - /** - * Families: Slavic (Polish) - * 1 - 1 - * 2 - ends in 2-4, not 12-14: 2, 3, 4, 22, 23, 24, 32, ... 104, 122, ... - * 3 - everything else: 0, 5, 6, ... 11, 12, 13, 14, 15, ... 20, 21, 25, ... - */ - return ($number == 1) ? 1 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 12) || ($number % 100 > 14))) ? 2 : 3); - - case 10: - /** - * Families: Slavic (Slovenian, Sorbian) - * 1 - ends in 01: 1, 101, 201, ... - * 2 - ends in 02: 2, 102, 202, ... - * 3 - ends in 03-04: 3, 4, 103, 104, 203, 204, ... - * 4 - everything else: 0, 5, 6, 7, 8, 9, 10, 11, ... - */ - return ($number % 100 == 1) ? 1 : (($number % 100 == 2) ? 2 : ((($number % 100 == 3) || ($number % 100 == 4)) ? 3 : 4)); - - case 11: - /** - * Families: Celtic (Irish Gaeilge) - * 1 - 1 - * 2 - 2 - * 3 - is 3-6: 3, 4, 5, 6 - * 4 - is 7-10: 7, 8, 9, 10 - * 5 - everything else: 0, 11, 12, ... - */ - return ($number == 1) ? 1 : (($number == 2) ? 2 : (($number >= 3 && $number <= 6) ? 3 : (($number >= 7 && $number <= 10) ? 4 : 5))); - - case 12: - /** - * Families: Semitic (Arabic) - * 1 - 1 - * 2 - 2 - * 3 - ends in 03-10: 3, 4, ... 10, 103, 104, ... 110, 203, 204, ... - * 4 - ends in 11-99: 11, ... 99, 111, 112, ... - * 5 - everything else: 100, 101, 102, 200, 201, 202, ... - * 6 - 0 - */ - return ($number == 1) ? 1 : (($number == 2) ? 2 : ((($number % 100 >= 3) && ($number % 100 <= 10)) ? 3 : ((($number % 100 >= 11) && ($number % 100 <= 99)) ? 4 : (($number != 0) ? 5 : 6)))); - - case 13: - /** - * Families: Semitic (Maltese) - * 1 - 1 - * 2 - is 0 or ends in 01-10: 0, 2, 3, ... 9, 10, 101, 102, ... - * 3 - ends in 11-19: 11, 12, ... 18, 19, 111, 112, ... - * 4 - everything else: 20, 21, ... - */ - return ($number == 1) ? 1 : ((($number == 0) || (($number % 100 > 1) && ($number % 100 < 11))) ? 2 : ((($number % 100 > 10) && ($number % 100 < 20)) ? 3 : 4)); - - case 14: - /** - * Families: Slavic (Macedonian) - * 1 - ends in 1: 1, 11, 21, ... - * 2 - ends in 2: 2, 12, 22, ... - * 3 - everything else: 0, 3, 4, ... 10, 13, 14, ... 20, 23, ... - */ - return ($number % 10 == 1) ? 1 : (($number % 10 == 2) ? 2 : 3); - - case 15: - /** - * Families: Icelandic - * 1 - ends in 1, not 11: 1, 21, 31, ... 101, 121, 131, ... - * 2 - everything else: 0, 2, 3, ... 10, 11, 12, ... 20, 22, ... - */ - return (($number % 10 == 1) && ($number % 100 != 11)) ? 1 : 2; - } -} - -/** * Login using http authenticate. * * @param array $param Parameter array, see $param_defaults array. @@ -4685,9 +3960,133 @@ function phpbb_build_hidden_fields_for_query_params($request, $exclude = null) } /** +* Get user avatar +* +* @param array $user_row Row from the users table +* @param string $alt Optional language string for alt tag within image, can be a language key or text +* @param bool $ignore_config Ignores the config-setting, to be still able to view the avatar in the UCP +* @param bool $lazy If true, will be lazy loaded (requires JS) +* +* @return string Avatar html +*/ +function phpbb_get_user_avatar($user_row, $alt = 'USER_AVATAR', $ignore_config = false, $lazy = false) +{ + $row = \phpbb\avatar\manager::clean_row($user_row, 'user'); + return phpbb_get_avatar($row, $alt, $ignore_config, $lazy); +} + +/** +* Get group avatar +* +* @param array $group_row Row from the groups table +* @param string $alt Optional language string for alt tag within image, can be a language key or text +* @param bool $ignore_config Ignores the config-setting, to be still able to view the avatar in the UCP +* @param bool $lazy If true, will be lazy loaded (requires JS) +* +* @return string Avatar html +*/ +function phpbb_get_group_avatar($user_row, $alt = 'GROUP_AVATAR', $ignore_config = false, $lazy = false) +{ + $row = \phpbb\avatar\manager::clean_row($user_row, 'group'); + return phpbb_get_avatar($row, $alt, $ignore_config, $lazy); +} + +/** +* Get avatar +* +* @param array $row Row cleaned by \phpbb\avatar\manager::clean_row +* @param string $alt Optional language string for alt tag within image, can be a language key or text +* @param bool $ignore_config Ignores the config-setting, to be still able to view the avatar in the UCP +* @param bool $lazy If true, will be lazy loaded (requires JS) +* +* @return string Avatar html +*/ +function phpbb_get_avatar($row, $alt, $ignore_config = false, $lazy = false) +{ + global $user, $config; + global $phpbb_container, $phpbb_dispatcher; + + if (!$config['allow_avatar'] && !$ignore_config) + { + return ''; + } + + $avatar_data = array( + 'src' => $row['avatar'], + 'width' => $row['avatar_width'], + 'height' => $row['avatar_height'], + ); + + /* @var $phpbb_avatar_manager \phpbb\avatar\manager */ + $phpbb_avatar_manager = $phpbb_container->get('avatar.manager'); + $driver = $phpbb_avatar_manager->get_driver($row['avatar_type'], !$ignore_config); + $html = ''; + + if ($driver) + { + $html = $driver->get_custom_html($user, $row, $alt); + if (!empty($html)) + { + return $html; + } + + $avatar_data = $driver->get_data($row); + } + else + { + $avatar_data['src'] = ''; + } + + if (!empty($avatar_data['src'])) + { + if ($lazy) + { + // Determine board url - we may need it later + $board_url = generate_board_url() . '/'; + // This path is sent with the base template paths in the assign_vars() + // call below. We need to correct it in case we are accessing from a + // controller because the web paths will be incorrect otherwise. + $phpbb_path_helper = $phpbb_container->get('path_helper'); + $corrected_path = $phpbb_path_helper->get_web_root_path(); + + $web_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? $board_url : $corrected_path; + + $theme = "{$web_path}styles/" . rawurlencode($user->style['style_path']) . '/theme'; + + $src = 'src="' . $theme . '/images/no_avatar.gif" data-src="' . $avatar_data['src'] . '"'; + } + else + { + $src = 'src="' . $avatar_data['src'] . '"'; + } + + $html = '<img class="avatar" ' . $src . ' ' . + ($avatar_data['width'] ? ('width="' . $avatar_data['width'] . '" ') : '') . + ($avatar_data['height'] ? ('height="' . $avatar_data['height'] . '" ') : '') . + 'alt="' . ((!empty($user->lang[$alt])) ? $user->lang[$alt] : $alt) . '" />'; + } + + /** + * Event to modify HTML <img> tag of avatar + * + * @event core.get_avatar_after + * @var array row Row cleaned by \phpbb\avatar\manager::clean_row + * @var string alt Optional language string for alt tag within image, can be a language key or text + * @var bool ignore_config Ignores the config-setting, to be still able to view the avatar in the UCP + * @var array avatar_data The HTML attributes for avatar <img> tag + * @var string html The HTML <img> tag of generated avatar + * @since 3.1.6-RC1 + */ + $vars = array('row', 'alt', 'ignore_config', 'avatar_data', 'html'); + extract($phpbb_dispatcher->trigger_event('core.get_avatar_after', compact($vars))); + + return $html; +} + +/** * Generate page header */ -function page_header($page_title = '', $display_online_list = true, $item_id = 0, $item = 'forum') +function page_header($page_title = '', $display_online_list = false, $item_id = 0, $item = 'forum') { global $db, $config, $template, $SID, $_SID, $_EXTRA_URL, $user, $auth, $phpEx, $phpbb_root_path; global $phpbb_dispatcher, $request, $phpbb_container, $phpbb_admin_path; @@ -4714,7 +4113,7 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0 * @var int item_id Restrict online users to item id * @var bool page_header_override Shall we return instead of running * the rest of page_header() - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('page_title', 'display_online_list', 'item_id', 'item', 'page_header_override'); extract($phpbb_dispatcher->trigger_event('core.page_header', compact($vars))); @@ -4751,7 +4150,7 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0 if ($user->data['user_id'] != ANONYMOUS) { $u_login_logout = append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=logout', true, $user->session_id); - $l_login_logout = sprintf($user->lang['LOGOUT_USER'], $user->data['username']); + $l_login_logout = $user->lang['LOGOUT']; } else { @@ -4782,8 +4181,8 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0 if ($total_online_users > $config['record_online_users']) { - set_config('record_online_users', $total_online_users, true); - set_config('record_online_date', time(), true); + $config->set('record_online_users', $total_online_users, false); + $config->set('record_online_date', time(), false); } $l_online_record = $user->lang('RECORD_ONLINE_USERS', (int) $config['record_online_users'], $user->format_date($config['record_online_date'], false, true)); @@ -4818,8 +4217,8 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0 } } - $forum_id = request_var('f', 0); - $topic_id = request_var('t', 0); + $forum_id = $request->variable('f', 0); + $topic_id = $request->variable('t', 0); $s_feed_news = false; @@ -4839,6 +4238,7 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0 // This path is sent with the base template paths in the assign_vars() // call below. We need to correct it in case we are accessing from a // controller because the web paths will be incorrect otherwise. + /* @var $phpbb_path_helper \phpbb\path_helper */ $phpbb_path_helper = $phpbb_container->get('path_helper'); $corrected_path = $phpbb_path_helper->get_web_root_path(); $web_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? $board_url : $corrected_path; @@ -4865,8 +4265,8 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0 } } - $dt = new \phpbb\datetime($user, 'now', $user->timezone); - $timezone_offset = 'GMT' . phpbb_format_timezone_offset($dt->getOffset()); + $dt = $user->create_datetime(); + $timezone_offset = $user->lang(array('timezones', 'UTC_OFFSET'), phpbb_format_timezone_offset($dt->getOffset())); $timezone_name = $user->timezone->getName(); if (isset($user->lang['timezones'][$timezone_name])) { @@ -4875,11 +4275,12 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0 // Output the notifications $notifications = false; - if ($config['load_notifications'] && $user->data['user_id'] != ANONYMOUS && $user->data['user_type'] != USER_IGNORE) + if ($config['load_notifications'] && $config['allow_board_notifications'] && $user->data['user_id'] != ANONYMOUS && $user->data['user_type'] != USER_IGNORE) { + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); - $notifications = $phpbb_notifications->load_notifications(array( + $notifications = $phpbb_notifications->load_notifications('notification.method.board', array( 'all_unread' => true, 'limit' => 5, )); @@ -4890,7 +4291,8 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0 } } - $hidden_fields_for_jumpbox = phpbb_build_hidden_fields_for_query_params($request, array('f')); + /** @var \phpbb\controller\helper $controller_helper */ + $controller_helper = $phpbb_container->get('controller.helper'); $notification_mark_hash = generate_link_hash('mark_all_notifications_read'); // The following assigns all _common_ variables that may be used at any point in a template. @@ -4905,15 +4307,17 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0 'TOTAL_USERS_ONLINE' => $l_online_users, 'LOGGED_IN_USER_LIST' => $online_userlist, 'RECORD_USERS' => $l_online_record, - 'PRIVATE_MESSAGE_COUNT' => (!empty($user->data['user_unread_privmsg'])) ? $user->data['user_unread_privmsg'] : 0, - 'HIDDEN_FIELDS_FOR_JUMPBOX' => $hidden_fields_for_jumpbox, + 'PRIVATE_MESSAGE_COUNT' => (!empty($user->data['user_unread_privmsg'])) ? $user->data['user_unread_privmsg'] : 0, + 'CURRENT_USER_AVATAR' => phpbb_get_user_avatar($user->data), + 'CURRENT_USERNAME_SIMPLE' => get_username_string('no_profile', $user->data['user_id'], $user->data['username'], $user->data['user_colour']), + 'CURRENT_USERNAME_FULL' => get_username_string('full', $user->data['user_id'], $user->data['username'], $user->data['user_colour']), 'UNREAD_NOTIFICATIONS_COUNT' => ($notifications !== false) ? $notifications['unread_count'] : '', 'NOTIFICATIONS_COUNT' => ($notifications !== false) ? $notifications['unread_count'] : '', 'U_VIEW_ALL_NOTIFICATIONS' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=ucp_notifications'), 'U_MARK_ALL_NOTIFICATIONS' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=ucp_notifications&mode=notification_list&mark=all&token=' . $notification_mark_hash), 'U_NOTIFICATION_SETTINGS' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=ucp_notifications&mode=notification_options'), - 'S_NOTIFICATIONS_DISPLAY' => $config['load_notifications'], + 'S_NOTIFICATIONS_DISPLAY' => $config['load_notifications'] && $config['allow_board_notifications'], 'S_USER_NEW_PRIVMSG' => $user->data['user_new_privmsg'], 'S_USER_UNREAD_PRIVMSG' => $user->data['user_unread_privmsg'], @@ -4940,19 +4344,21 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0 'U_SITE_HOME' => $config['site_home_url'], 'U_REGISTER' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=register'), 'U_PROFILE' => append_sid("{$phpbb_root_path}ucp.$phpEx"), + 'U_USER_PROFILE' => get_username_string('profile', $user->data['user_id'], $user->data['username'], $user->data['user_colour']), 'U_MODCP' => append_sid("{$phpbb_root_path}mcp.$phpEx", false, true, $user->session_id), - 'U_FAQ' => append_sid("{$phpbb_root_path}faq.$phpEx"), + 'U_FAQ' => $controller_helper->route('phpbb_help_faq_controller'), 'U_SEARCH_SELF' => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=egosearch'), 'U_SEARCH_NEW' => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=newposts'), 'U_SEARCH_UNANSWERED' => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=unanswered'), 'U_SEARCH_UNREAD' => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=unreadposts'), 'U_SEARCH_ACTIVE_TOPICS'=> append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=active_topics'), 'U_DELETE_COOKIES' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=delete_cookies'), - 'U_TEAM' => ($user->data['user_id'] != ANONYMOUS && !$auth->acl_get('u_viewprofile')) ? '' : append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=leaders'), + 'U_CONTACT_US' => ($config['contact_admin_form_enable'] && $config['email_enable']) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=contactadmin') : '', + 'U_TEAM' => ($user->data['user_id'] != ANONYMOUS && !$auth->acl_get('u_viewprofile')) ? '' : append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=team'), 'U_TERMS_USE' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=terms'), 'U_PRIVACY' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=privacy'), 'U_RESTORE_PERMISSIONS' => ($user->data['user_perm_from'] && $auth->acl_get('a_switchperm')) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=restore_perm') : '', - 'U_FEED' => generate_board_url() . "/feed.$phpEx", + 'U_FEED' => $controller_helper->route('phpbb_feed_index'), 'S_USER_LOGGED_IN' => ($user->data['user_id'] != ANONYMOUS) ? true : false, 'S_AUTOLOGIN_ENABLED' => ($config['allow_autologin']) ? true : false, @@ -4977,7 +4383,7 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0 'S_TOPIC_ID' => $topic_id, 'S_LOGIN_ACTION' => ((!defined('ADMIN_START')) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=login') : append_sid("{$phpbb_admin_path}index.$phpEx", false, true, $user->session_id)), - 'S_LOGIN_REDIRECT' => build_hidden_fields(array('redirect' => build_url())), + 'S_LOGIN_REDIRECT' => build_hidden_fields(array('redirect' => $phpbb_path_helper->remove_web_root_path(build_url()))), 'S_ENABLE_FEEDS' => ($config['feed_enable']) ? true : false, 'S_ENABLE_FEEDS_OVERALL' => ($config['feed_overall']) ? true : false, @@ -5003,8 +4409,9 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0 'T_RANKS_PATH' => "{$web_path}{$config['ranks_path']}/", 'T_UPLOAD_PATH' => "{$web_path}{$config['upload_path']}/", 'T_STYLESHEET_LINK' => "{$web_path}styles/" . rawurlencode($user->style['style_path']) . '/theme/stylesheet.css?assets_version=' . $config['assets_version'], - 'T_STYLESHEET_LANG_LINK' => "{$web_path}styles/" . rawurlencode($user->style['style_path']) . '/theme/' . $user->lang_name . '/stylesheet.css?assets_version=' . $config['assets_version'], - 'T_JQUERY_LINK' => !empty($config['allow_cdn']) && !empty($config['load_jquery_url']) ? $config['load_jquery_url'] : "{$web_path}assets/javascript/jquery.js?assets_version=" . $config['assets_version'], + 'T_STYLESHEET_LANG_LINK'=> "{$web_path}styles/" . rawurlencode($user->style['style_path']) . '/theme/' . $user->lang_name . '/stylesheet.css?assets_version=' . $config['assets_version'], + 'T_FONT_AWESOME_LINK' => !empty($config['allow_cdn']) && !empty($config['load_font_awesome_url']) ? $config['load_font_awesome_url'] : "{$web_path}assets/css/font-awesome.min.css?assets_version=" . $config['assets_version'], + 'T_JQUERY_LINK' => !empty($config['allow_cdn']) && !empty($config['load_jquery_url']) ? $config['load_jquery_url'] : "{$web_path}assets/javascript/jquery.min.js?assets_version=" . $config['assets_version'], 'S_ALLOW_CDN' => !empty($config['allow_cdn']), 'T_THEME_NAME' => rawurlencode($user->style['style_path']), @@ -5022,23 +4429,123 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0 'SITE_LOGO_IMG' => $user->img('site_logo'), )); - // application/xhtml+xml not used because of IE - header('Content-type: text/html; charset=UTF-8'); - - header('Cache-Control: private, no-cache="set-cookie"'); - header('Expires: 0'); - header('Pragma: no-cache'); - + // An array of http headers that phpbb will set. The following event may override these. + $http_headers = array( + // application/xhtml+xml not used because of IE + 'Content-type' => 'text/html; charset=UTF-8', + 'Cache-Control' => 'private, no-cache="set-cookie"', + 'Expires' => gmdate('D, d M Y H:i:s', time()) . ' GMT', + ); if (!empty($user->data['is_bot'])) { // Let reverse proxies know we detected a bot. - header('X-PHPBB-IS-BOT: yes'); + $http_headers['X-PHPBB-IS-BOT'] = 'yes'; + } + + /** + * Execute code and/or overwrite _common_ template variables after they have been assigned. + * + * @event core.page_header_after + * @var string page_title Page title + * @var bool display_online_list Do we display online users list + * @var string item Restrict online users to a certain + * session item, e.g. forum for + * session_forum_id + * @var int item_id Restrict online users to item id + * @var array http_headers HTTP headers that should be set by phpbb + * + * @since 3.1.0-b3 + */ + $vars = array('page_title', 'display_online_list', 'item_id', 'item', 'http_headers'); + extract($phpbb_dispatcher->trigger_event('core.page_header_after', compact($vars))); + + foreach ($http_headers as $hname => $hval) + { + header((string) $hname . ': ' . (string) $hval); } return; } /** +* Check and display the SQL report if requested. +* +* @param \phpbb\request\request_interface $request Request object +* @param \phpbb\auth\auth $auth Auth object +* @param \phpbb\db\driver\driver_interface $db Database connection +*/ +function phpbb_check_and_display_sql_report(\phpbb\request\request_interface $request, \phpbb\auth\auth $auth, \phpbb\db\driver\driver_interface $db) +{ + if ($request->variable('explain', false) && $auth->acl_get('a_') && defined('DEBUG')) + { + $db->sql_report('display'); + } +} + +/** +* Generate the debug output string +* +* @param \phpbb\db\driver\driver_interface $db Database connection +* @param \phpbb\config\config $config Config object +* @param \phpbb\auth\auth $auth Auth object +* @param \phpbb\user $user User object +* @param \phpbb\event\dispatcher_interface $phpbb_dispatcher Event dispatcher +* @return string +*/ +function phpbb_generate_debug_output(\phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, \phpbb\auth\auth $auth, \phpbb\user $user, \phpbb\event\dispatcher_interface $phpbb_dispatcher) +{ + $debug_info = array(); + + // Output page creation time + if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + if (isset($GLOBALS['starttime'])) + { + $totaltime = microtime(true) - $GLOBALS['starttime']; + $debug_info[] = sprintf('<span title="SQL time: %.3fs / PHP time: %.3fs">Time: %.3fs</span>', $db->get_sql_time(), ($totaltime - $db->get_sql_time()), $totaltime); + } + + $debug_info[] = sprintf('<span title="Cached: %d">Queries: %d</span>', $db->sql_num_queries(true), $db->sql_num_queries()); + + $memory_usage = memory_get_peak_usage(); + if ($memory_usage) + { + $memory_usage = get_formatted_filesize($memory_usage); + + $debug_info[] = 'Peak Memory Usage: ' . $memory_usage; + } + } + + if (defined('DEBUG')) + { + $debug_info[] = 'GZIP: ' . (($config['gzip_compress'] && @extension_loaded('zlib')) ? 'On' : 'Off'); + + if ($user->load) + { + $debug_info[] = 'Load: ' . $user->load; + } + + if ($auth->acl_get('a_')) + { + $debug_info[] = '<a href="' . build_url() . '&explain=1">SQL Explain</a>'; + } + } + + /** + * Modify debug output information + * + * @event core.phpbb_generate_debug_output + * @var array debug_info Array of strings with debug information + * + * @since 3.1.0-RC3 + */ + $vars = array('debug_info'); + extract($phpbb_dispatcher->trigger_event('core.phpbb_generate_debug_output', compact($vars))); + + return implode(' | ', $debug_info); +} + +/** * Generate page footer * * @param bool $run_cron Whether or not to run the cron @@ -5047,7 +4554,7 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0 */ function page_footer($run_cron = true, $display_template = true, $exit_handler = true) { - global $db, $config, $template, $user, $auth, $cache, $starttime, $phpbb_root_path, $phpEx; + global $db, $config, $template, $user, $auth, $cache, $phpEx; global $request, $phpbb_dispatcher, $phpbb_admin_path; // A listener can set this variable to `true` when it overrides this function @@ -5060,7 +4567,7 @@ function page_footer($run_cron = true, $display_template = true, $exit_handler = * @var bool run_cron Shall we run cron tasks * @var bool page_footer_override Shall we return instead of running * the rest of page_footer() - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('run_cron', 'page_footer_override'); extract($phpbb_dispatcher->trigger_event('core.page_footer', compact($vars))); @@ -5070,46 +4577,21 @@ function page_footer($run_cron = true, $display_template = true, $exit_handler = return; } - // Output page creation time - if (defined('DEBUG')) - { - $mtime = explode(' ', microtime()); - $totaltime = $mtime[0] + $mtime[1] - $starttime; - - if ($request->variable('explain', false) && $auth->acl_get('a_') && defined('DEBUG') && method_exists($db, 'sql_report')) - { - $db->sql_report('display'); - } + $user->update_session_infos(); - $debug_output = sprintf('Time : %.3fs | ' . $db->sql_num_queries() . ' Queries | GZIP : ' . (($config['gzip_compress'] && @extension_loaded('zlib')) ? 'On' : 'Off') . (($user->load) ? ' | Load : ' . $user->load : ''), $totaltime); - - if ($auth->acl_get('a_') && defined('DEBUG')) - { - if (function_exists('memory_get_peak_usage')) - { - if ($memory_usage = memory_get_peak_usage()) - { - $memory_usage = get_formatted_filesize($memory_usage); - - $debug_output .= ' | Peak Memory Usage: ' . $memory_usage; - } - } - - $debug_output .= ' | <a href="' . build_url() . '&explain=1">Explain</a>'; - } - } + phpbb_check_and_display_sql_report($request, $auth, $db); $template->assign_vars(array( - 'DEBUG_OUTPUT' => (defined('DEBUG')) ? $debug_output : '', + 'DEBUG_OUTPUT' => phpbb_generate_debug_output($db, $config, $auth, $user, $phpbb_dispatcher), 'TRANSLATION_INFO' => (!empty($user->lang['TRANSLATION_INFO'])) ? $user->lang['TRANSLATION_INFO'] : '', - 'CREDIT_LINE' => $user->lang('POWERED_BY', '<a href="https://www.phpbb.com/">phpBB</a>® Forum Software © phpBB Group'), + 'CREDIT_LINE' => $user->lang('POWERED_BY', '<a href="https://www.phpbb.com/">phpBB</a>® Forum Software © phpBB Limited'), 'U_ACP' => ($auth->acl_get('a_') && !empty($user->data['is_registered'])) ? append_sid("{$phpbb_admin_path}index.$phpEx", false, true, $user->session_id) : '') ); // Call cron-type script $call_cron = false; - if (!defined('IN_CRON') && !$config['use_system_cron'] && $run_cron && !$config['board_disable'] && !$user->data['is_bot']) + if (!defined('IN_CRON') && !$config['use_system_cron'] && $run_cron && !$config['board_disable'] && !$user->data['is_bot'] && !$cache->get('_cron.lock_check')) { $call_cron = true; $time_now = (!empty($user->time_now) && is_int($user->time_now)) ? $user->time_now : time(); @@ -5130,7 +4612,10 @@ function page_footer($run_cron = true, $display_template = true, $exit_handler = // Call cron job? if ($call_cron) { - global $cron; + global $phpbb_container; + + /* @var $cron \phpbb\cron\manager */ + $cron = $phpbb_container->get('cron.manager'); $task = $cron->find_one_ready_task(); if ($task) @@ -5138,8 +4623,24 @@ function page_footer($run_cron = true, $display_template = true, $exit_handler = $url = $task->get_url(); $template->assign_var('RUN_CRON_TASK', '<img src="' . $url . '" width="1" height="1" alt="cron" />'); } + else + { + $cache->put('_cron.lock_check', true, 60); + } } + /** + * Execute code and/or modify output before displaying the template. + * + * @event core.page_footer_after + * @var bool display_template Whether or not to display the template + * @var bool exit_handler Whether or not to run the exit_handler() + * + * @since 3.1.0-RC5 + */ + $vars = array('display_template', 'exit_handler'); + extract($phpbb_dispatcher->trigger_event('core.page_footer_after', compact($vars))); + if ($display_template) { $template->display('body'); @@ -5168,7 +4669,7 @@ function garbage_collection() * Unload some objects, to free some memory, before we finish our task * * @event core.garbage_collection - * @since 3.1-A1 + * @since 3.1.0-a1 */ $phpbb_dispatcher->dispatch('core.garbage_collection'); } @@ -5194,7 +4695,7 @@ function garbage_collection() */ function exit_handler() { - global $phpbb_hook, $config; + global $phpbb_hook; if (!empty($phpbb_hook) && $phpbb_hook->call_hook(__FUNCTION__)) { @@ -5230,22 +4731,6 @@ function phpbb_user_session_handler() } /** -* Check if PCRE has UTF-8 support -* PHP may not be linked with the bundled PCRE lib and instead with an older version -* -* @return bool Returns true if PCRE (the regular expressions library) supports UTF-8 encoding -*/ -function phpbb_pcre_utf8_support() -{ - static $utf8_pcre_properties = null; - if (is_null($utf8_pcre_properties)) - { - $utf8_pcre_properties = (@preg_match('/\p{L}/u', 'a') !== false); - } - return $utf8_pcre_properties; -} - -/** * Casts a numeric string $input to an appropriate numeric type (i.e. integer or float) * * @param string $input A numeric string. @@ -5259,47 +4744,40 @@ function phpbb_to_numeric($input) } /** -* Convert either 3.0 dbms or 3.1 db driver class name to 3.1 db driver class name. -* -* If $dbms is a valid 3.1 db driver class name, returns it unchanged. -* Otherwise prepends phpbb\db\driver\ to the dbms to convert a 3.0 dbms -* to 3.1 db driver class name. +* Get the board contact details (e.g. for emails) * -* @param string $dbms dbms parameter -* @return db driver class +* @param \phpbb\config\config $config +* @param string $phpEx +* @return string */ -function phpbb_convert_30_dbms_to_31($dbms) +function phpbb_get_board_contact(\phpbb\config\config $config, $phpEx) { - // Note: this check is done first because mysqli extension - // supplies a mysqli class, and class_exists($dbms) would return - // true for mysqli class. - // However, per the docblock any valid 3.1 driver name should be - // recognized by this function, and have priority over 3.0 dbms. - if (class_exists('phpbb\db\driver\\' . $dbms)) + if ($config['contact_admin_form_enable']) { - return 'phpbb\db\driver\\' . $dbms; + return generate_board_url() . '/memberlist.' . $phpEx . '?mode=contactadmin'; } - - if (class_exists($dbms)) + else { - // Additionally we could check that $dbms extends phpbb\db\driver\driver. - // http://php.net/manual/en/class.reflectionclass.php - // Beware of possible performance issues: - // http://stackoverflow.com/questions/294582/php-5-reflection-api-performance - // We could check for interface implementation in all paths or - // only when we do not prepend phpbb\db\driver\. - - /* - $reflection = new \ReflectionClass($dbms); - - if ($reflection->isSubclassOf('phpbb\db\driver\driver')) - { - return $dbms; - } - */ - - return $dbms; + return $config['board_contact']; } +} - throw new \RuntimeException("You have specified an invalid dbms driver: $dbms"); +/** +* Get a clickable board contact details link +* +* @param \phpbb\config\config $config +* @param string $phpbb_root_path +* @param string $phpEx +* @return string +*/ +function phpbb_get_board_contact_link(\phpbb\config\config $config, $phpbb_root_path, $phpEx) +{ + if ($config['contact_admin_form_enable'] && $config['email_enable']) + { + return append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=contactadmin'); + } + else + { + return 'mailto:' . htmlspecialchars($config['board_contact']); + } } diff --git a/phpBB/includes/functions_acp.php b/phpBB/includes/functions_acp.php index cb44ed2794..3f64bc19f9 100644 --- a/phpBB/includes/functions_acp.php +++ b/phpBB/includes/functions_acp.php @@ -1,9 +1,13 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -20,7 +24,7 @@ if (!defined('IN_PHPBB')) */ function adm_page_header($page_title) { - global $config, $db, $user, $template; + global $config, $user, $template; global $phpbb_root_path, $phpbb_admin_path, $phpEx, $SID, $_SID; global $phpbb_dispatcher; @@ -41,7 +45,7 @@ function adm_page_header($page_title) * @var string page_title Page title * @var bool adm_page_header_override Shall we return instead of * running the rest of adm_page_header() - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('page_title', 'adm_page_header_override'); extract($phpbb_dispatcher->trigger_event('core.adm_page_header', compact($vars))); @@ -103,12 +107,30 @@ function adm_page_header($page_title) 'S_CONTENT_FLOW_END' => ($user->lang['DIRECTION'] == 'ltr') ? 'right' : 'left', )); - // application/xhtml+xml not used because of IE - header('Content-type: text/html; charset=UTF-8'); + // An array of http headers that phpbb will set. The following event may override these. + $http_headers = array( + // application/xhtml+xml not used because of IE + 'Content-type' => 'text/html; charset=UTF-8', + 'Cache-Control' => 'private, no-cache="set-cookie"', + 'Expires' => gmdate('D, d M Y H:i:s', time()) . ' GMT', + ); - header('Cache-Control: private, no-cache="set-cookie"'); - header('Expires: 0'); - header('Pragma: no-cache'); + /** + * Execute code and/or overwrite _common_ template variables after they have been assigned. + * + * @event core.adm_page_header_after + * @var string page_title Page title + * @var array http_headers HTTP headers that should be set by phpbb + * + * @since 3.1.0-RC3 + */ + $vars = array('page_title', 'http_headers'); + extract($phpbb_dispatcher->trigger_event('core.adm_page_header_after', compact($vars))); + + foreach ($http_headers as $hname => $hval) + { + header((string) $hname . ': ' . (string) $hval); + } return; } @@ -118,8 +140,8 @@ function adm_page_header($page_title) */ function adm_page_footer($copyright_html = true) { - global $db, $config, $template, $user, $auth, $cache; - global $starttime, $phpbb_root_path, $phpbb_admin_path, $phpEx; + global $db, $config, $template, $user, $auth; + global $phpbb_root_path; global $request, $phpbb_dispatcher; // A listener can set this variable to `true` when it overrides this function @@ -132,7 +154,7 @@ function adm_page_footer($copyright_html = true) * @var bool copyright_html Shall we display the copyright? * @var bool adm_page_footer_override Shall we return instead of * running the rest of adm_page_footer() - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('copyright_html', 'adm_page_footer_override'); extract($phpbb_dispatcher->trigger_event('core.adm_page_footer', compact($vars))); @@ -142,41 +164,16 @@ function adm_page_footer($copyright_html = true) return; } - // Output page creation time - if (defined('DEBUG')) - { - $mtime = explode(' ', microtime()); - $totaltime = $mtime[0] + $mtime[1] - $starttime; - - if ($request->variable('explain', false) && $auth->acl_get('a_') && defined('DEBUG') && method_exists($db, 'sql_report')) - { - $db->sql_report('display'); - } - - $debug_output = sprintf('Time : %.3fs | ' . $db->sql_num_queries() . ' Queries | GZIP : ' . (($config['gzip_compress']) ? 'On' : 'Off') . (($user->load) ? ' | Load : ' . $user->load : ''), $totaltime); + $user->update_session_infos(); - if ($auth->acl_get('a_') && defined('DEBUG')) - { - if (function_exists('memory_get_peak_usage')) - { - if ($memory_usage = memory_get_peak_usage()) - { - $memory_usage = get_formatted_filesize($memory_usage); - - $debug_output .= ' | Peak Memory Usage: ' . $memory_usage; - } - } - - $debug_output .= ' | <a href="' . build_url() . '&explain=1">Explain</a>'; - } - } + phpbb_check_and_display_sql_report($request, $auth, $db); $template->assign_vars(array( - 'DEBUG_OUTPUT' => (defined('DEBUG')) ? $debug_output : '', + 'DEBUG_OUTPUT' => phpbb_generate_debug_output($db, $config, $auth, $user, $phpbb_dispatcher), 'TRANSLATION_INFO' => (!empty($user->lang['TRANSLATION_INFO'])) ? $user->lang['TRANSLATION_INFO'] : '', 'S_COPYRIGHT_HTML' => $copyright_html, - 'CREDIT_LINE' => $user->lang('POWERED_BY', '<a href="https://www.phpbb.com/">phpBB</a>® Forum Software © phpBB Group'), - 'T_JQUERY_LINK' => !empty($config['allow_cdn']) && !empty($config['load_jquery_url']) ? $config['load_jquery_url'] : "{$phpbb_root_path}assets/javascript/jquery.js", + 'CREDIT_LINE' => $user->lang('POWERED_BY', '<a href="https://www.phpbb.com/">phpBB</a>® Forum Software © phpBB Limited'), + 'T_JQUERY_LINK' => !empty($config['allow_cdn']) && !empty($config['load_jquery_url']) ? $config['load_jquery_url'] : "{$phpbb_root_path}assets/javascript/jquery.min.js", 'S_ALLOW_CDN' => !empty($config['allow_cdn']), 'VERSION' => $config['version']) ); @@ -235,7 +232,7 @@ function h_radio($name, $input_ary, $input_default = false, $id = false, $key = /** * Build configuration template for acp configuration pages */ -function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars) +function build_cfg_template($tpl_type, $key, &$new_ary, $config_key, $vars) { global $user, $module, $phpbb_dispatcher; @@ -243,15 +240,20 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars) $name = 'config[' . $config_key . ']'; // Make sure there is no notice printed out for non-existent config options (we simply set them) - if (!isset($new[$config_key])) + if (!isset($new_ary[$config_key])) { - $new[$config_key] = ''; + $new_ary[$config_key] = ''; } switch ($tpl_type[0]) { - case 'text': case 'password': + if ($new_ary[$config_key] !== '') + { + // replace passwords with asterixes + $new_ary[$config_key] = '********'; + } + case 'text': case 'url': case 'email': case 'color': @@ -263,16 +265,15 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars) case 'range': case 'search': case 'tel': - case 'url': case 'week': $size = (int) $tpl_type[1]; $maxlength = (int) $tpl_type[2]; - $tpl = '<input id="' . $key . '" type="' . $tpl_type[0] . '"' . (($size) ? ' size="' . $size . '"' : '') . ' maxlength="' . (($maxlength) ? $maxlength : 255) . '" name="' . $name . '" value="' . $new[$config_key] . '"' . (($tpl_type[0] === 'password') ? ' autocomplete="off"' : '') . ' />'; + $tpl = '<input id="' . $key . '" type="' . $tpl_type[0] . '"' . (($size) ? ' size="' . $size . '"' : '') . ' maxlength="' . (($maxlength) ? $maxlength : 255) . '" name="' . $name . '" value="' . $new_ary[$config_key] . '"' . (($tpl_type[0] === 'password') ? ' autocomplete="off"' : '') . ' />'; break; case 'number': - $min = $max = $maxlength = ''; + $max = $maxlength = ''; $min = ( isset($tpl_type[1]) ) ? (int) $tpl_type[1] : false; if ( isset($tpl_type[2]) ) { @@ -280,11 +281,11 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars) $maxlength = strlen( (string) $max ); } - $tpl = '<input id="' . $key . '" type="number" maxlength="' . (( $maxlength != '' ) ? $maxlength : 255) . '"' . (( $min != '' ) ? ' min="' . $min . '"' : '') . (( $max != '' ) ? ' max="' . $max . '"' : '') . ' name="' . $name . '" value="' . $new[$config_key] . '" />'; + $tpl = '<input id="' . $key . '" type="number" maxlength="' . (( $maxlength != '' ) ? $maxlength : 255) . '"' . (( $min != '' ) ? ' min="' . $min . '"' : '') . (( $max != '' ) ? ' max="' . $max . '"' : '') . ' name="' . $name . '" value="' . $new_ary[$config_key] . '" />'; break; case 'dimension': - $min = $max = $maxlength = $size = ''; + $max = $maxlength = $size = ''; $min = (int) $tpl_type[1]; @@ -294,19 +295,19 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars) $size = $maxlength = strlen( (string) $max ); } - $tpl = '<input id="' . $key . '" type="number"' . (( $size != '' ) ? ' size="' . $size . '"' : '') . ' maxlength="' . (($maxlength != '') ? $maxlength : 255) . '"' . (( $min !== '' ) ? ' min="' . $min . '"' : '') . (( $max != '' ) ? ' max="' . $max . '"' : '') . ' name="config[' . $config_key . '_width]" value="' . $new[$config_key . '_width'] . '" /> x <input type="number"' . (( $size != '' ) ? ' size="' . $size . '"' : '') . ' maxlength="' . (($maxlength != '') ? $maxlength : 255) . '"' . (( $min !== '' ) ? ' min="' . $min . '"' : '') . (( $max != '' ) ? ' max="' . $max . '"' : '') . ' name="config[' . $config_key . '_height]" value="' . $new[$config_key . '_height'] . '" />'; + $tpl = '<input id="' . $key . '" type="number"' . (( $size != '' ) ? ' size="' . $size . '"' : '') . ' maxlength="' . (($maxlength != '') ? $maxlength : 255) . '"' . (( $min !== '' ) ? ' min="' . $min . '"' : '') . (( $max != '' ) ? ' max="' . $max . '"' : '') . ' name="config[' . $config_key . '_width]" value="' . $new_ary[$config_key . '_width'] . '" /> x <input type="number"' . (( $size != '' ) ? ' size="' . $size . '"' : '') . ' maxlength="' . (($maxlength != '') ? $maxlength : 255) . '"' . (( $min !== '' ) ? ' min="' . $min . '"' : '') . (( $max != '' ) ? ' max="' . $max . '"' : '') . ' name="config[' . $config_key . '_height]" value="' . $new_ary[$config_key . '_height'] . '" />'; break; case 'textarea': $rows = (int) $tpl_type[1]; $cols = (int) $tpl_type[2]; - $tpl = '<textarea id="' . $key . '" name="' . $name . '" rows="' . $rows . '" cols="' . $cols . '">' . $new[$config_key] . '</textarea>'; + $tpl = '<textarea id="' . $key . '" name="' . $name . '" rows="' . $rows . '" cols="' . $cols . '">' . $new_ary[$config_key] . '</textarea>'; break; case 'radio': - $key_yes = ($new[$config_key]) ? ' checked="checked"' : ''; - $key_no = (!$new[$config_key]) ? ' checked="checked"' : ''; + $key_yes = ($new_ary[$config_key]) ? ' checked="checked"' : ''; + $key_no = (!$new_ary[$config_key]) ? ' checked="checked"' : ''; $tpl_type_cond = explode('_', $tpl_type[1]); $type_no = ($tpl_type_cond[0] == 'disabled' || $tpl_type_cond[0] == 'enabled') ? false : true; @@ -320,8 +321,6 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars) case 'select': case 'custom': - $return = ''; - if (isset($vars['method'])) { $call = array($module->module, $vars['method']); @@ -343,7 +342,7 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars) switch ($value) { case '{CONFIG_VALUE}': - $value = $new[$config_key]; + $value = $new_ary[$config_key]; break; case '{KEY}': @@ -356,7 +355,7 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars) } else { - $args = array($new[$config_key], $key); + $args = array($new_ary[$config_key], $key); } $return = call_user_func_array($call, $args); @@ -364,8 +363,9 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars) if ($tpl_type[0] == 'select') { $size = (isset($tpl_type[1])) ? (int) $tpl_type[1] : 1; + $data_toggle = (!empty($tpl_type[2])) ? ' data-togglable-settings="true"' : ''; - $tpl = '<select id="' . $key . '" name="' . $name . '"' . (($size > 1) ? ' size="' . $size . '"' : '') . '>' . $return . '</select>'; + $tpl = '<select id="' . $key . '" name="' . $name . '"' . (($size > 1) ? ' size="' . $size . '"' : '') . $data_toggle . '>' . $return . '</select>'; } else { @@ -383,6 +383,7 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars) $tpl .= $vars['append']; } + $new = $new_ary; /** * Overwrite the html code we display for the config value * @@ -396,10 +397,12 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars) * @var string name Should be used for the name attribute * @var array vars Array with the options for the config * @var string tpl The resulting html code we display - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('tpl_type', 'key', 'new', 'name', 'vars', 'tpl'); extract($phpbb_dispatcher->trigger_event('core.build_config_template', compact($vars))); + $new_ary = $new; + unset($new); return $tpl; } @@ -410,7 +413,7 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars) */ function validate_config_vars($config_vars, &$cfg_array, &$error) { - global $phpbb_root_path, $user, $phpbb_dispatcher; + global $phpbb_root_path, $user, $phpbb_dispatcher, $phpbb_filesystem; $type = 0; $min = 1; @@ -555,6 +558,9 @@ function validate_config_vars($config_vars, &$cfg_array, &$error) $cfg_array[$config_name] = trim($destination); + // Absolute file path + case 'absolute_path': + case 'absolute_path_writable': // Path being relative (still prefixed by phpbb_root_path), but with the ability to escape the root dir... case 'path': case 'wpath': @@ -573,20 +579,22 @@ function validate_config_vars($config_vars, &$cfg_array, &$error) break; } - if (!file_exists($phpbb_root_path . $cfg_array[$config_name])) + $path = in_array($config_definition['validate'], array('wpath', 'path', 'rpath', 'rwpath')) ? $phpbb_root_path . $cfg_array[$config_name] : $cfg_array[$config_name]; + + if (!file_exists($path)) { $error[] = sprintf($user->lang['DIRECTORY_DOES_NOT_EXIST'], $cfg_array[$config_name]); } - if (file_exists($phpbb_root_path . $cfg_array[$config_name]) && !is_dir($phpbb_root_path . $cfg_array[$config_name])) + if (file_exists($path) && !is_dir($path)) { $error[] = sprintf($user->lang['DIRECTORY_NOT_DIR'], $cfg_array[$config_name]); } // Check if the path is writable - if ($config_definition['validate'] == 'wpath' || $config_definition['validate'] == 'rwpath') + if ($config_definition['validate'] == 'wpath' || $config_definition['validate'] == 'rwpath' || $config_definition['validate'] === 'absolute_path_writable') { - if (file_exists($phpbb_root_path . $cfg_array[$config_name]) && !phpbb_is_writable($phpbb_root_path . $cfg_array[$config_name])) + if (file_exists($path) && !$phpbb_filesystem->is_writable($path)) { $error[] = sprintf($user->lang['DIRECTORY_NOT_WRITABLE'], $cfg_array[$config_name]); } @@ -606,7 +614,7 @@ function validate_config_vars($config_vars, &$cfg_array, &$error) * @var array error Array of errors, the errors should * be strings only, language keys are * not replaced afterwards - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('cfg_array', 'config_name', 'config_definition', 'error'); extract($phpbb_dispatcher->trigger_event('core.validate_config_variable', compact($vars))); @@ -642,8 +650,6 @@ function validate_range($value_ary, &$error) foreach ($value_ary as $value) { $column = explode(':', $value['column_type']); - $max = $min = 0; - $type = 0; if (!isset($column_types[$column[0]])) { continue; @@ -678,3 +684,30 @@ function validate_range($value_ary, &$error) } } } + +/** +* Inserts new config display_vars into an exisiting display_vars array +* at the given position. +* +* @param array $display_vars An array of existing config display vars +* @param array $add_config_vars An array of new config display vars +* @param array $where Where to place the new config vars, +* before or after an exisiting config, as an array +* of the form: array('after' => 'config_name') or +* array('before' => 'config_name'). +* @return array The array of config display vars +*/ +function phpbb_insert_config_array($display_vars, $add_config_vars, $where) +{ + if (is_array($where) && array_key_exists(current($where), $display_vars)) + { + $position = array_search(current($where), array_keys($display_vars)) + ((key($where) == 'before') ? 0 : 1); + $display_vars = array_merge( + array_slice($display_vars, 0, $position), + $add_config_vars, + array_slice($display_vars, $position) + ); + } + + return $display_vars; +} diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php index 722d3c9c67..1c7e68d358 100644 --- a/phpBB/includes/functions_admin.php +++ b/phpBB/includes/functions_admin.php @@ -1,9 +1,13 @@ <?php /** * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -23,8 +27,6 @@ if (!defined('IN_PHPBB')) * @param string $table constant or fullname of the table * @param int $parent_id parent_id of the current set (default = 0) * @param array $where contains strings to compare closer on the where statement (additional) -* -* @author EXreaction */ function recalc_nested_sets(&$new_id, $pkey, $table, $parent_id = 0, $where = array()) { @@ -63,7 +65,7 @@ function recalc_nested_sets(&$new_id, $pkey, $table, $parent_id = 0, $where = ar */ function make_forum_select($select_id = false, $ignore_id = false, $ignore_acl = false, $ignore_nonpost = false, $ignore_emptycat = true, $only_acl_post = false, $return_array = false) { - global $db, $user, $auth; + global $db, $auth; // This query is identical to the jumpbox one $sql = 'SELECT forum_id, forum_name, parent_id, forum_type, forum_flags, forum_options, left_id, right_id @@ -169,7 +171,10 @@ function size_select_options($size_compare) */ function group_select_options($group_id, $exclude_ids = false, $manage_founder = false) { - global $db, $user, $config; + global $db, $config, $phpbb_container; + + /** @var \phpbb\group\helper $group_helper */ + $group_helper = $phpbb_container->get('group_helper'); $exclude_sql = ($exclude_ids !== false && sizeof($exclude_ids)) ? 'WHERE ' . $db->sql_in_set('group_id', array_map('intval', $exclude_ids), true) : ''; $sql_and = (!$config['coppa_enable']) ? (($exclude_sql) ? ' AND ' : ' WHERE ') . "group_name <> 'REGISTERED_COPPA'" : ''; @@ -187,7 +192,7 @@ function group_select_options($group_id, $exclude_ids = false, $manage_founder = while ($row = $db->sql_fetchrow($result)) { $selected = ($row['group_id'] == $group_id) ? ' selected="selected"' : ''; - $s_group_options .= '<option' . (($row['group_type'] == GROUP_SPECIAL) ? ' class="sep"' : '') . ' value="' . $row['group_id'] . '"' . $selected . '>' . (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']) . '</option>'; + $s_group_options .= '<option' . (($row['group_type'] == GROUP_SPECIAL) ? ' class="sep"' : '') . ' value="' . $row['group_id'] . '"' . $selected . '>' . $group_helper->get_name($row['group_name']) . '</option>'; } $db->sql_freeresult($result); @@ -311,12 +316,10 @@ function get_forum_branch($forum_id, $type = 'all', $order = 'descending', $incl * @param bool $add_log True if log entry should be added * * @return bool False on error -* -* @author bantu */ function copy_forum_permissions($src_forum_id, $dest_forum_ids, $clear_dest_perms = true, $add_log = true) { - global $db; + global $db, $user, $phpbb_log; // Only one forum id specified if (!is_array($dest_forum_ids)) @@ -439,7 +442,7 @@ function copy_forum_permissions($src_forum_id, $dest_forum_ids, $clear_dest_perm if ($add_log) { - add_log('admin', 'LOG_FORUM_COPIED_PERMISSIONS', $src_forum_name, implode(', ', $dest_forum_names)); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_COPIED_PERMISSIONS', false, array($src_forum_name, implode(', ', $dest_forum_names))); } $db->sql_transaction('commit'); @@ -500,7 +503,7 @@ function filelist($rootdir, $dir = '', $type = 'gif|jpg|jpeg|png') */ function move_topics($topic_ids, $forum_id, $auto_sync = true) { - global $db; + global $db, $phpbb_dispatcher; if (empty($topic_ids)) { @@ -534,6 +537,27 @@ function move_topics($topic_ids, $forum_id, $auto_sync = true) } $table_ary = array(TOPICS_TABLE, POSTS_TABLE, LOG_TABLE, DRAFTS_TABLE, TOPICS_TRACK_TABLE); + + /** + * Perform additional actions before topics move + * + * @event core.move_topics_before_query + * @var array table_ary Array of tables from which forum_id will be updated for all rows that hold the moved topics + * @var array topic_ids Array of the moved topic ids + * @var string forum_id The forum id from where the topics are moved + * @var array forum_ids Array of the forums where the topics are moving (includes also forum_id) + * @var bool auto_sync Whether or not to perform auto sync + * @since 3.1.5-RC1 + */ + $vars = array( + 'table_ary', + 'topic_ids', + 'forum_id', + 'forum_ids', + 'auto_sync', + ); + extract($phpbb_dispatcher->trigger_event('core.move_topics_before_query', compact($vars))); + foreach ($table_ary as $table) { $sql = "UPDATE $table @@ -555,7 +579,7 @@ function move_topics($topic_ids, $forum_id, $auto_sync = true) */ function move_posts($post_ids, $topic_id, $auto_sync = true) { - global $db; + global $db, $phpbb_dispatcher; if (!is_array($post_ids)) { @@ -589,6 +613,28 @@ function move_posts($post_ids, $topic_id, $auto_sync = true) trigger_error('NO_TOPIC'); } + /** + * Perform additional actions before moving posts + * + * @event core.move_posts_before + * @var array post_ids Array of post ids to move + * @var string topic_id The topic id the posts are moved to + * @var bool auto_sync Whether or not to perform auto sync + * @var array forum_ids Array of the forum ids the posts are moved from + * @var array topic_ids Array of the topic ids the posts are moved from + * @var array forum_row Array with the forum id of the topic the posts are moved to + * @since 3.1.7-RC1 + */ + $vars = array( + 'post_ids', + 'topic_id', + 'auto_sync', + 'forum_ids', + 'topic_ids', + 'forum_row', + ); + extract($phpbb_dispatcher->trigger_event('core.move_posts_before', compact($vars))); + $sql = 'UPDATE ' . POSTS_TABLE . ' SET forum_id = ' . (int) $forum_row['forum_id'] . ", topic_id = $topic_id WHERE " . $db->sql_in_set('post_id', $post_ids); @@ -599,6 +645,28 @@ function move_posts($post_ids, $topic_id, $auto_sync = true) WHERE " . $db->sql_in_set('post_msg_id', $post_ids); $db->sql_query($sql); + /** + * Perform additional actions after moving posts + * + * @event core.move_posts_after + * @var array post_ids Array of the moved post ids + * @var string topic_id The topic id the posts are moved to + * @var bool auto_sync Whether or not to perform auto sync + * @var array forum_ids Array of the forum ids the posts are moved from + * @var array topic_ids Array of the topic ids the posts are moved from + * @var array forum_row Array with the forum id of the topic the posts are moved to + * @since 3.1.7-RC1 + */ + $vars = array( + 'post_ids', + 'topic_id', + 'auto_sync', + 'forum_ids', + 'topic_ids', + 'forum_row', + ); + extract($phpbb_dispatcher->trigger_event('core.move_posts_after', compact($vars))); + if ($auto_sync) { $forum_ids[] = (int) $forum_row['forum_id']; @@ -618,7 +686,7 @@ function move_posts($post_ids, $topic_id, $auto_sync = true) */ function delete_topics($where_type, $where_ids, $auto_sync = true, $post_count_sync = true, $call_delete_posts = true) { - global $db, $config, $phpbb_container; + global $db, $config, $phpbb_container, $phpbb_dispatcher; $approved_topics = 0; $forum_ids = $topic_ids = array(); @@ -672,6 +740,20 @@ function delete_topics($where_type, $where_ids, $auto_sync = true, $post_count_s $table_ary = array(BOOKMARKS_TABLE, TOPICS_TRACK_TABLE, TOPICS_POSTED_TABLE, POLL_VOTES_TABLE, POLL_OPTIONS_TABLE, TOPICS_WATCH_TABLE, TOPICS_TABLE); + /** + * Perform additional actions before topic(s) deletion + * + * @event core.delete_topics_before_query + * @var array table_ary Array of tables from which all rows will be deleted that hold a topic_id occuring in topic_ids + * @var array topic_ids Array of topic ids to delete + * @since 3.1.4-RC1 + */ + $vars = array( + 'table_ary', + 'topic_ids', + ); + extract($phpbb_dispatcher->trigger_event('core.delete_topics_before_query', compact($vars))); + foreach ($table_ary as $table) { $sql = "DELETE FROM $table @@ -680,6 +762,18 @@ function delete_topics($where_type, $where_ids, $auto_sync = true, $post_count_s } unset($table_ary); + /** + * Perform additional actions after topic(s) deletion + * + * @event core.delete_topics_after_query + * @var array topic_ids Array of topic ids that were deleted + * @since 3.1.4-RC1 + */ + $vars = array( + 'topic_ids', + ); + extract($phpbb_dispatcher->trigger_event('core.delete_topics_after_query', compact($vars))); + $moved_topic_ids = array(); // update the other forums @@ -712,15 +806,16 @@ function delete_topics($where_type, $where_ids, $auto_sync = true, $post_count_s if ($approved_topics) { - set_config_count('num_topics', $approved_topics * (-1), true); + $config->increment('num_topics', $approved_topics * (-1), false); } + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); $phpbb_notifications->delete_notifications(array( - 'topic', - 'approve_topic', - 'topic_in_queue', + 'notification.type.topic', + 'notification.type.approve_topic', + 'notification.type.topic_in_queue', ), $topic_ids); return $return; @@ -731,7 +826,39 @@ function delete_topics($where_type, $where_ids, $auto_sync = true, $post_count_s */ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = true, $post_count_sync = true, $call_delete_topics = true) { - global $db, $config, $phpbb_root_path, $phpEx, $auth, $user, $phpbb_container; + global $db, $config, $phpbb_root_path, $phpEx, $auth, $user, $phpbb_container, $phpbb_dispatcher; + + // Notifications types to delete + $delete_notifications_types = array( + 'notification.type.quote', + 'notification.type.approve_post', + 'notification.type.post_in_queue', + 'notification.type.report_post', + ); + + /** + * Perform additional actions before post(s) deletion + * + * @event core.delete_posts_before + * @var string where_type Variable containing posts deletion mode + * @var mixed where_ids Array or comma separated list of posts ids to delete + * @var bool auto_sync Flag indicating if topics/forums should be synchronized + * @var bool posted_sync Flag indicating if topics_posted table should be resynchronized + * @var bool post_count_sync Flag indicating if posts count should be resynchronized + * @var bool call_delete_topics Flag indicating if topics having no posts should be deleted + * @var array delete_notifications_types Array with notifications types to delete + * @since 3.1.0-a4 + */ + $vars = array( + 'where_type', + 'where_ids', + 'auto_sync', + 'posted_sync', + 'post_count_sync', + 'call_delete_topics', + 'delete_notifications_types', + ); + extract($phpbb_dispatcher->trigger_event('core.delete_posts_before', compact($vars))); if ($where_type === 'range') { @@ -808,6 +935,32 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = $table_ary = array(POSTS_TABLE, REPORTS_TABLE); + /** + * Perform additional actions during post(s) deletion before running the queries + * + * @event core.delete_posts_in_transaction_before + * @var array post_ids Array with deleted posts' ids + * @var array poster_ids Array with deleted posts' author ids + * @var array topic_ids Array with deleted posts' topic ids + * @var array forum_ids Array with deleted posts' forum ids + * @var string where_type Variable containing posts deletion mode + * @var mixed where_ids Array or comma separated list of post ids to delete + * @var array delete_notifications_types Array with notifications types to delete + * @var array table_ary Array with table names to delete data from + * @since 3.1.7-RC1 + */ + $vars = array( + 'post_ids', + 'poster_ids', + 'topic_ids', + 'forum_ids', + 'where_type', + 'where_ids', + 'delete_notifications_types', + 'table_ary', + ); + extract($phpbb_dispatcher->trigger_event('core.delete_posts_in_transaction_before', compact($vars))); + foreach ($table_ary as $table) { $sql = "DELETE FROM $table @@ -863,7 +1016,7 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = } $error = false; - $search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user); + $search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher); if ($error) { @@ -872,10 +1025,61 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = $search->index_remove($post_ids, $poster_ids, $forum_ids); - delete_attachments('post', $post_ids, false); + /** @var \phpbb\attachment\manager $attachment_manager */ + $attachment_manager = $phpbb_container->get('attachment.manager'); + $attachment_manager->delete('post', $post_ids, false); + unset($attachment_manager); + + /** + * Perform additional actions during post(s) deletion + * + * @event core.delete_posts_in_transaction + * @var array post_ids Array with deleted posts' ids + * @var array poster_ids Array with deleted posts' author ids + * @var array topic_ids Array with deleted posts' topic ids + * @var array forum_ids Array with deleted posts' forum ids + * @var string where_type Variable containing posts deletion mode + * @var mixed where_ids Array or comma separated list of posts ids to delete + * @var array delete_notifications_types Array with notifications types to delete + * @since 3.1.0-a4 + */ + $vars = array( + 'post_ids', + 'poster_ids', + 'topic_ids', + 'forum_ids', + 'where_type', + 'where_ids', + 'delete_notifications_types', + ); + extract($phpbb_dispatcher->trigger_event('core.delete_posts_in_transaction', compact($vars))); $db->sql_transaction('commit'); + /** + * Perform additional actions after post(s) deletion + * + * @event core.delete_posts_after + * @var array post_ids Array with deleted posts' ids + * @var array poster_ids Array with deleted posts' author ids + * @var array topic_ids Array with deleted posts' topic ids + * @var array forum_ids Array with deleted posts' forum ids + * @var string where_type Variable containing posts deletion mode + * @var mixed where_ids Array or comma separated list of posts ids to delete + * @var array delete_notifications_types Array with notifications types to delete + * @since 3.1.0-a4 + */ + $vars = array( + 'post_ids', + 'poster_ids', + 'topic_ids', + 'forum_ids', + 'where_type', + 'where_ids', + 'delete_notifications_types', + ); + extract($phpbb_dispatcher->trigger_event('core.delete_posts_after', compact($vars))); + // Resync topics_posted table if ($posted_sync) { @@ -891,7 +1095,7 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = if ($approved_posts && $post_count_sync) { - set_config_count('num_posts', $approved_posts * (-1), true); + $config->increment('num_posts', $approved_posts * (-1), false); } // We actually remove topics now to not be inconsistent (the delete_topics function calls this function too) @@ -900,15 +1104,10 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = delete_topics('topic_id', $remove_topics, $auto_sync, $post_count_sync, false); } + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); - $phpbb_notifications->delete_notifications(array( - 'quote', - 'bookmark', - 'post', - 'approve_post', - 'post_in_queue', - ), $post_ids); + $phpbb_notifications->delete_notifications($delete_notifications_types, $post_ids); return sizeof($post_ids); } @@ -916,225 +1115,21 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = /** * Delete Attachments * +* @deprecated 3.2.0-a1 (To be removed: 3.4.0) +* * @param string $mode can be: post|message|topic|attach|user * @param mixed $ids can be: post_ids, message_ids, topic_ids, attach_ids, user_ids * @param bool $resync set this to false if you are deleting posts or topics */ function delete_attachments($mode, $ids, $resync = true) { - global $db, $config; - - // 0 is as bad as an empty array - if (empty($ids)) - { - return false; - } - - if (is_array($ids)) - { - $ids = array_unique($ids); - $ids = array_map('intval', $ids); - } - else - { - $ids = array((int) $ids); - } - - $sql_where = ''; - - switch ($mode) - { - case 'post': - case 'message': - $sql_id = 'post_msg_id'; - $sql_where = ' AND in_message = ' . ($mode == 'message' ? 1 : 0); - break; - - case 'topic': - $sql_id = 'topic_id'; - break; - - case 'user': - $sql_id = 'poster_id'; - break; - - case 'attach': - default: - $sql_id = 'attach_id'; - $mode = 'attach'; - break; - } - - $post_ids = $message_ids = $topic_ids = $physical = array(); - - // Collect post and topic ids for later use if we need to touch remaining entries (if resync is enabled) - $sql = 'SELECT post_msg_id, topic_id, in_message, physical_filename, thumbnail, filesize, is_orphan - FROM ' . ATTACHMENTS_TABLE . ' - WHERE ' . $db->sql_in_set($sql_id, $ids); - - $sql .= $sql_where; - - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - // We only need to store post/message/topic ids if resync is enabled and the file is not orphaned - if ($resync && !$row['is_orphan']) - { - if (!$row['in_message']) - { - $post_ids[] = $row['post_msg_id']; - $topic_ids[] = $row['topic_id']; - } - else - { - $message_ids[] = $row['post_msg_id']; - } - } + global $phpbb_container; - $physical[] = array('filename' => $row['physical_filename'], 'thumbnail' => $row['thumbnail'], 'filesize' => $row['filesize'], 'is_orphan' => $row['is_orphan']); - } - $db->sql_freeresult($result); + /** @var \phpbb\attachment\manager $attachment_manager */ + $attachment_manager = $phpbb_container->get('attachment.manager'); + $num_deleted = $attachment_manager->delete($mode, $ids, $resync); - // Delete attachments - $sql = 'DELETE FROM ' . ATTACHMENTS_TABLE . ' - WHERE ' . $db->sql_in_set($sql_id, $ids); - - $sql .= $sql_where; - - $db->sql_query($sql); - $num_deleted = $db->sql_affectedrows(); - - if (!$num_deleted) - { - return 0; - } - - // Delete attachments from filesystem - $space_removed = $files_removed = 0; - foreach ($physical as $file_ary) - { - if (phpbb_unlink($file_ary['filename'], 'file', true) && !$file_ary['is_orphan']) - { - // Only non-orphaned files count to the file size - $space_removed += $file_ary['filesize']; - $files_removed++; - } - - if ($file_ary['thumbnail']) - { - phpbb_unlink($file_ary['filename'], 'thumbnail', true); - } - } - - if ($space_removed || $files_removed) - { - set_config_count('upload_dir_size', $space_removed * (-1), true); - set_config_count('num_files', $files_removed * (-1), true); - } - - // If we do not resync, we do not need to adjust any message, post, topic or user entries - if (!$resync) - { - return $num_deleted; - } - - // No more use for the original ids - unset($ids); - - // Now, we need to resync posts, messages, topics. We go through every one of them - $post_ids = array_unique($post_ids); - $message_ids = array_unique($message_ids); - $topic_ids = array_unique($topic_ids); - - // Update post indicators for posts now no longer having attachments - if (sizeof($post_ids)) - { - // Just check which posts are still having an assigned attachment not orphaned by querying the attachments table - $sql = 'SELECT post_msg_id - FROM ' . ATTACHMENTS_TABLE . ' - WHERE ' . $db->sql_in_set('post_msg_id', $post_ids) . ' - AND in_message = 0 - AND is_orphan = 0'; - $result = $db->sql_query($sql); - - $remaining_ids = array(); - while ($row = $db->sql_fetchrow($result)) - { - $remaining_ids[] = $row['post_msg_id']; - } - $db->sql_freeresult($result); - - // Now only unset those ids remaining - $post_ids = array_diff($post_ids, $remaining_ids); - - if (sizeof($post_ids)) - { - $sql = 'UPDATE ' . POSTS_TABLE . ' - SET post_attachment = 0 - WHERE ' . $db->sql_in_set('post_id', $post_ids); - $db->sql_query($sql); - } - } - - // Update message table if messages are affected - if (sizeof($message_ids)) - { - // Just check which messages are still having an assigned attachment not orphaned by querying the attachments table - $sql = 'SELECT post_msg_id - FROM ' . ATTACHMENTS_TABLE . ' - WHERE ' . $db->sql_in_set('post_msg_id', $message_ids) . ' - AND in_message = 1 - AND is_orphan = 0'; - $result = $db->sql_query($sql); - - $remaining_ids = array(); - while ($row = $db->sql_fetchrow($result)) - { - $remaining_ids[] = $row['post_msg_id']; - } - $db->sql_freeresult($result); - - // Now only unset those ids remaining - $message_ids = array_diff($message_ids, $remaining_ids); - - if (sizeof($message_ids)) - { - $sql = 'UPDATE ' . PRIVMSGS_TABLE . ' - SET message_attachment = 0 - WHERE ' . $db->sql_in_set('msg_id', $message_ids); - $db->sql_query($sql); - } - } - - // Now update the topics. This is a bit trickier, because there could be posts still having attachments within the topic - if (sizeof($topic_ids)) - { - // Just check which topics are still having an assigned attachment not orphaned by querying the attachments table (much less entries expected) - $sql = 'SELECT topic_id - FROM ' . ATTACHMENTS_TABLE . ' - WHERE ' . $db->sql_in_set('topic_id', $topic_ids) . ' - AND is_orphan = 0'; - $result = $db->sql_query($sql); - - $remaining_ids = array(); - while ($row = $db->sql_fetchrow($result)) - { - $remaining_ids[] = $row['topic_id']; - } - $db->sql_freeresult($result); - - // Now only unset those ids remaining - $topic_ids = array_diff($topic_ids, $remaining_ids); - - if (sizeof($topic_ids)) - { - $sql = 'UPDATE ' . TOPICS_TABLE . ' - SET topic_attachment = 0 - WHERE ' . $db->sql_in_set('topic_id', $topic_ids); - $db->sql_query($sql); - } - } + unset($attachment_manager); return $num_deleted; } @@ -1147,8 +1142,6 @@ function delete_attachments($mode, $ids, $resync = true) * @param bool $auto_sync Will call sync() if this is true * * @return array Array with affected forums -* -* @author bantu */ function delete_topic_shadows($forum_id, $sql_more = '', $auto_sync = true) { @@ -1254,27 +1247,19 @@ function update_posted_info(&$topic_ids) /** * Delete attached file +* +* @deprecated 3.2.0-a1 (To be removed: 3.4.0) */ function phpbb_unlink($filename, $mode = 'file', $entry_removed = false) { - global $db, $phpbb_root_path, $config; + global $phpbb_container; - // Because of copying topics or modifications a physical filename could be assigned more than once. If so, do not remove the file itself. - $sql = 'SELECT COUNT(attach_id) AS num_entries - FROM ' . ATTACHMENTS_TABLE . " - WHERE physical_filename = '" . $db->sql_escape(utf8_basename($filename)) . "'"; - $result = $db->sql_query($sql); - $num_entries = (int) $db->sql_fetchfield('num_entries'); - $db->sql_freeresult($result); + /** @var \phpbb\attachment\manager $attachment_manager */ + $attachment_manager = $phpbb_container->get('attachment.manager'); + $unlink = $attachment_manager->unlink($filename, $mode, $entry_removed); + unset($attachment_manager); - // Do not remove file if at least one additional entry with the same name exist. - if (($entry_removed && $num_entries > 0) || (!$entry_removed && $num_entries > 1)) - { - return false; - } - - $filename = ($mode == 'thumbnail') ? 'thumb_' . utf8_basename($filename) : utf8_basename($filename); - return @unlink($phpbb_root_path . $config['upload_path'] . '/' . $filename); + return $unlink; } /** @@ -1358,7 +1343,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, { case 'topic_moved': $db->sql_transaction('begin'); - switch ($db->sql_layer) + switch ($db->get_sql_layer()) { case 'mysql4': case 'mysqli': @@ -1438,7 +1423,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, ITEM_DELETED => (!empty($topics_softdeleted)) ? ' WHERE ' . $db->sql_in_set('topic_id', $topics_softdeleted) : '', ); - foreach ($topic_visiblities as $visibility => $sql_where) + foreach ($update_ary as $visibility => $sql_where) { if ($sql_where) { @@ -1727,7 +1712,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, { $forum_data[$forum_id]['topics_approved'] = $row['total_topics']; } - else if ($row['topic_visibility'] == ITEM_UNAPPROVED) + else if ($row['topic_visibility'] == ITEM_UNAPPROVED || $row['topic_visibility'] == ITEM_REAPPROVE) { $forum_data[$forum_id]['topics_unapproved'] = $row['total_topics']; } @@ -1950,7 +1935,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, { $topic_data[$topic_id]['posts_approved'] = $row['total_posts']; } - else if ($row['post_visibility'] == ITEM_UNAPPROVED) + else if ($row['post_visibility'] == ITEM_UNAPPROVED || $row['post_visibility'] == ITEM_REAPPROVE) { $topic_data[$topic_id]['posts_unapproved'] = $row['total_posts']; } @@ -1972,7 +1957,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, $topic_data[$topic_id]['first_post_id'] = (!empty($topic_data[$topic_id]['first_post_id'])) ? min($topic_data[$topic_id]['first_post_id'], $row['first_post_id']) : $row['first_post_id']; $topic_data[$topic_id]['last_post_id'] = max($topic_data[$topic_id]['last_post_id'], $row['last_post_id']); - if ($topic_data[$topic_id]['visibility'] == ITEM_UNAPPROVED) + if ($topic_data[$topic_id]['visibility'] == ITEM_UNAPPROVED || $topic_data[$topic_id]['visibility'] == ITEM_REAPPROVE) { // Soft delete status is stronger than unapproved. $topic_data[$topic_id]['visibility'] = $row['post_visibility']; @@ -2024,7 +2009,6 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, AND u.user_id = p.poster_id'; $result = $db->sql_query($sql); - $post_ids = array(); while ($row = $db->sql_fetchrow($result)) { $topic_id = intval($row['topic_id']); @@ -2097,7 +2081,6 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, AND u.user_id = p.poster_id'; $result = $db->sql_query($sql); - $post_ids = array(); while ($row = $db->sql_fetchrow($result)) { $topic_id = (int) $row['topic_id']; @@ -2240,7 +2223,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, */ function prune($forum_id, $prune_mode, $prune_date, $prune_flags = 0, $auto_sync = true) { - global $db; + global $db, $phpbb_dispatcher; if (!is_array($forum_id)) { @@ -2275,6 +2258,26 @@ function prune($forum_id, $prune_mode, $prune_date, $prune_flags = 0, $auto_sync $sql_and .= " AND topic_last_view_time < $prune_date"; } + if ($prune_mode == 'shadow') + { + $sql_and .= ' AND topic_status = ' . ITEM_MOVED . " AND topic_last_post_time < $prune_date"; + } + + /** + * Use this event to modify the SQL that selects topics to be pruned + * + * @event core.prune_sql + * @var string forum_id The forum id + * @var string prune_mode The prune mode + * @var string prune_date The prune date + * @var int prune_flags The prune flags + * @var bool auto_sync Whether or not to perform auto sync + * @var string sql_and SQL text appended to where clause + * @since 3.1.3-RC1 + */ + $vars = array('forum_id', 'prune_mode', 'prune_date', 'prune_flags', 'auto_sync', 'sql_and'); + extract($phpbb_dispatcher->trigger_event('core.prune_sql', compact($vars))); + $sql = 'SELECT topic_id FROM ' . TOPICS_TABLE . ' WHERE ' . $db->sql_in_set('forum_id', $forum_id) . " @@ -2316,7 +2319,7 @@ function prune($forum_id, $prune_mode, $prune_date, $prune_flags = 0, $auto_sync */ function auto_prune($forum_id, $prune_mode, $prune_flags, $prune_days, $prune_freq) { - global $db; + global $db, $user, $phpbb_log; $sql = 'SELECT forum_name FROM ' . FORUMS_TABLE . " @@ -2337,7 +2340,7 @@ function auto_prune($forum_id, $prune_mode, $prune_flags, $prune_days, $prune_fr WHERE forum_id = $forum_id"; $db->sql_query($sql); - add_log('admin', 'LOG_AUTO_PRUNE', $row['forum_name']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_AUTO_PRUNE', false, array($row['forum_name'])); } return; @@ -2348,7 +2351,7 @@ function auto_prune($forum_id, $prune_mode, $prune_flags, $prune_days, $prune_fr * via admin_permissions. Changes of usernames and group names * must be carried through for the moderators table. * -* @param \phpbb\db\driver\driver $db Database connection +* @param \phpbb\db\driver\driver_interface $db Database connection * @param \phpbb\cache\driver\driver_interface Cache driver * @param \phpbb\auth\auth $auth Authentication object * @return null @@ -2359,10 +2362,10 @@ function phpbb_cache_moderators($db, $cache, $auth) $cache->destroy('sql', MODERATOR_CACHE_TABLE); // Clear table - switch ($db->sql_layer) + switch ($db->get_sql_layer()) { case 'sqlite': - case 'firebird': + case 'sqlite3': $db->sql_query('DELETE FROM ' . MODERATOR_CACHE_TABLE); break; @@ -2372,7 +2375,7 @@ function phpbb_cache_moderators($db, $cache, $auth) } // We add moderators who have forum moderator permissions without an explicit ACL_NEVER setting - $hold_ary = $ug_id_ary = $sql_ary = array(); + $sql_ary = array(); // Grab all users having moderative options... $hold_ary = $auth->acl_user_raw_data(false, 'm_%', false); @@ -2409,7 +2412,7 @@ function phpbb_cache_moderators($db, $cache, $auth) AND NOT (ug.group_leader = 1 AND g.group_skip_auth = 1) AND ' . $db->sql_in_set('ug.user_id', $ug_id_ary) . " AND ug.user_pending = 0 - AND o.auth_option " . $db->sql_like_expression('m_' . $db->any_char), + AND o.auth_option " . $db->sql_like_expression('m_' . $db->get_any_char()), ); $sql = $db->sql_build_query('SELECT', $sql_ary_deny); $result = $db->sql_query($sql); @@ -2436,6 +2439,7 @@ function phpbb_cache_moderators($db, $cache, $auth) { $usernames_ary[$row['user_id']] = $row['username']; } + $db->sql_freeresult($result); foreach ($hold_ary as $user_id => $forum_id_ary) { @@ -2525,20 +2529,6 @@ function phpbb_cache_moderators($db, $cache, $auth) } /** -* Cache moderators. Called whenever permissions are changed -* via admin_permissions. Changes of usernames and group names -* must be carried through for the moderators table. -* -* @deprecated 3.1 -* @return null -*/ -function cache_moderators() -{ - global $db, $cache, $auth; - return phpbb_cache_moderators($db, $cache, $auth); -} - -/** * View log * * @param string $mode The mode defines which log_type is used and from which log the entry is retrieved @@ -2571,7 +2561,7 @@ function view_log($mode, &$log, &$log_count, $limit = 0, $offset = 0, $forum_id /** * Removes moderators and administrators from foe lists. * -* @param \phpbb\db\driver\driver $db Database connection +* @param \phpbb\db\driver\driver_interface $db Database connection * @param \phpbb\auth\auth $auth Authentication object * @param array|bool $group_id If an array, remove all members of this group from foe lists, or false to ignore * @param array|bool $user_id If an array, remove this user from foe lists, or false to ignore @@ -2629,11 +2619,11 @@ function phpbb_update_foes($db, $auth, $group_id = false, $user_id = false) return; } - switch ($db->sql_layer) + switch ($db->get_sql_layer()) { case 'mysqli': case 'mysql4': - $sql = 'DELETE ' . (($db->sql_layer === 'mysqli' || version_compare($db->sql_server_info(true), '4.1', '>=')) ? 'z.*' : ZEBRA_TABLE) . ' + $sql = 'DELETE ' . (($db->get_sql_layer() === 'mysqli' || version_compare($db->sql_server_info(true), '4.1', '>=')) ? 'z.*' : ZEBRA_TABLE) . ' FROM ' . ZEBRA_TABLE . ' z, ' . USER_GROUP_TABLE . ' ug WHERE z.zebra_id = ug.user_id AND z.foe = 1 @@ -2688,20 +2678,6 @@ function phpbb_update_foes($db, $auth, $group_id = false, $user_id = false) } /** -* Removes moderators and administrators from foe lists. -* -* @deprecated 3.1 -* @param array|bool $group_id If an array, remove all members of this group from foe lists, or false to ignore -* @param array|bool $user_id If an array, remove this user from foe lists, or false to ignore -* @return null -*/ -function update_foes($group_id = false, $user_id = false) -{ - global $db, $auth; - return phpbb_update_foes($db, $auth, $group_id, $user_id); -} - -/** * Lists inactive users */ function view_inactive_users(&$users, &$user_count, $limit = 0, $offset = 0, $limit_days = 0, $sort_by = 'user_inactive_time DESC') @@ -2758,6 +2734,7 @@ function view_inactive_users(&$users, &$user_count, $limit = 0, $offset = 0, $li $users[] = $row; } + $db->sql_freeresult($result); return $offset; } @@ -2800,7 +2777,7 @@ function get_database_size() $database_size = false; // This code is heavily influenced by a similar routine in phpMyAdmin 2.2.0 - switch ($db->sql_layer) + switch ($db->get_sql_layer()) { case 'mysql': case 'mysql4': @@ -2816,7 +2793,7 @@ function get_database_size() if (preg_match('#(3\.23|[45]\.)#', $version)) { - $db_name = (preg_match('#^(?:3\.23\.(?:[6-9]|[1-9]{2}))|[45]\.#', $version)) ? "`{$db->dbname}`" : $db->dbname; + $db_name = (preg_match('#^(?:3\.23\.(?:[6-9]|[1-9]{2}))|[45]\.#', $version)) ? "`{$db->get_db_name()}`" : $db->get_db_name(); $sql = 'SHOW TABLE STATUS FROM ' . $db_name; @@ -2845,18 +2822,8 @@ function get_database_size() } break; - case 'firebird': - global $dbname; - - // if it on the local machine, we can get lucky - if (file_exists($dbname)) - { - $database_size = filesize($dbname); - } - - break; - case 'sqlite': + case 'sqlite3': global $dbhost; if (file_exists($dbhost)) @@ -2869,8 +2836,24 @@ function get_database_size() case 'mssql': case 'mssql_odbc': case 'mssqlnative': + $sql = 'SELECT @@VERSION AS mssql_version'; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + $sql = 'SELECT ((SUM(size) * 8.0) * 1024.0) as dbsize FROM sysfiles'; + + if ($row) + { + // Azure stats are stored elsewhere + if (strpos($row['mssql_version'], 'SQL Azure') !== false) + { + $sql = 'SELECT ((SUM(reserved_page_count) * 8.0) * 1024.0) as dbsize + FROM sys.dm_db_partition_stats'; + } + } + $result = $db->sql_query($sql, 7200); $database_size = ($row = $db->sql_fetchrow($result)) ? $row['dbsize'] : false; $db->sql_freeresult($result); @@ -2886,7 +2869,7 @@ function get_database_size() if ($row['proname'] == 'pg_database_size') { - $database = $db->dbname; + $database = $db->get_db_name(); if (strpos($database, '.') !== false) { list($database, ) = explode('.', $database); @@ -2924,73 +2907,7 @@ function get_database_size() return $database_size; } -/** -* Retrieve contents from remotely stored file -*/ -function get_remote_file($host, $directory, $filename, &$errstr, &$errno, $port = 80, $timeout = 6) -{ - global $user; - - if ($fsock = @fsockopen($host, $port, $errno, $errstr, $timeout)) - { - @fputs($fsock, "GET $directory/$filename HTTP/1.0\r\n"); - @fputs($fsock, "HOST: $host\r\n"); - @fputs($fsock, "Connection: close\r\n\r\n"); - - $timer_stop = time() + $timeout; - stream_set_timeout($fsock, $timeout); - - $file_info = ''; - $get_info = false; - - while (!@feof($fsock)) - { - if ($get_info) - { - $file_info .= @fread($fsock, 1024); - } - else - { - $line = @fgets($fsock, 1024); - if ($line == "\r\n") - { - $get_info = true; - } - else if (stripos($line, '404 not found') !== false) - { - $errstr = $user->lang['FILE_NOT_FOUND'] . ': ' . $filename; - return false; - } - } - - $stream_meta_data = stream_get_meta_data($fsock); - - if (!empty($stream_meta_data['timed_out']) || time() >= $timer_stop) - { - $errstr = $user->lang['FSOCK_TIMEOUT']; - return false; - } - } - @fclose($fsock); - } - else - { - if ($errstr) - { - $errstr = utf8_convert_message($errstr); - return false; - } - else - { - $errstr = $user->lang['FSOCK_DISABLED']; - return false; - } - } - - return $file_info; -} - -/** +/* * Tidy Warnings * Remove all warnings which have now expired from the database * The duration of a warning can be defined by the administrator @@ -3033,7 +2950,7 @@ function tidy_warnings() $db->sql_transaction('commit'); } - set_config('warnings_last_gc', time(), true); + $config->set('warnings_last_gc', time(), false); } /** @@ -3041,7 +2958,7 @@ function tidy_warnings() */ function tidy_database() { - global $db; + global $config, $db; // Here we check permission consistency @@ -3066,7 +2983,7 @@ function tidy_database() WHERE ' . $db->sql_in_set('forum_id', $forum_ids, true); $db->sql_query($sql); - set_config('database_last_gc', time(), true); + $config->set('database_last_gc', time(), false); } /** @@ -3100,45 +3017,6 @@ function add_permission_language() } /** - * Obtains the latest version information - * - * @param bool $force_update Ignores cached data. Defaults to false. - * @param bool $warn_fail Trigger a warning if obtaining the latest version information fails. Defaults to false. - * @param int $ttl Cache version information for $ttl seconds. Defaults to 86400 (24 hours). - * - * @return string | false Version info on success, false on failure. - */ -function obtain_latest_version_info($force_update = false, $warn_fail = false, $ttl = 86400) -{ - global $cache; - - $info = $cache->get('versioncheck'); - - if ($info === false || $force_update) - { - $errstr = ''; - $errno = 0; - - $info = get_remote_file('version.phpbb.com', '/phpbb', - ((defined('PHPBB_QA')) ? '30x_qa.txt' : '30x.txt'), $errstr, $errno); - - if (empty($info)) - { - $cache->destroy('versioncheck'); - if ($warn_fail) - { - trigger_error($errstr, E_USER_WARNING); - } - return false; - } - - $cache->put('versioncheck', $info, $ttl); - } - - return $info; -} - -/** * Enables a particular flag in a bitfield column of a given table. * * @param string $table_name The table to update diff --git a/phpBB/includes/functions_compatibility.php b/phpBB/includes/functions_compatibility.php index 2197815087..4b085a6050 100644 --- a/phpBB/includes/functions_compatibility.php +++ b/phpBB/includes/functions_compatibility.php @@ -1,9 +1,13 @@ <?php /** * -* @package phpBB3 -* @copyright (c) 2013 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -26,10 +30,11 @@ if (!defined('IN_PHPBB')) * @param string $avatar_height Height of users avatar * @param string $alt Optional language string for alt tag within image, can be a language key or text * @param bool $ignore_config Ignores the config-setting, to be still able to view the avatar in the UCP +* @param bool $lazy If true, will be lazy loaded (requires JS) * * @return string Avatar image */ -function get_user_avatar($avatar, $avatar_type, $avatar_width, $avatar_height, $alt = 'USER_AVATAR', $ignore_config = false) +function get_user_avatar($avatar, $avatar_type, $avatar_width, $avatar_height, $alt = 'USER_AVATAR', $ignore_config = false, $lazy = false) { // map arguments to new function phpbb_get_avatar() $row = array( @@ -39,12 +44,470 @@ function get_user_avatar($avatar, $avatar_type, $avatar_width, $avatar_height, $ 'avatar_height' => $avatar_height, ); - if (!function_exists('phpbb_get_avatar')) + return phpbb_get_avatar($row, $alt, $ignore_config, $lazy); +} + +/** +* Hash the password +* +* @deprecated 3.1.0-a2 (To be removed: 3.3.0) +* +* @param string $password Password to be hashed +* +* @return string|bool Password hash or false if something went wrong during hashing +*/ +function phpbb_hash($password) +{ + global $phpbb_container; + + /* @var $passwords_manager \phpbb\passwords\manager */ + $passwords_manager = $phpbb_container->get('passwords.manager'); + return $passwords_manager->hash($password); +} + +/** +* Check for correct password +* +* @deprecated 3.1.0-a2 (To be removed: 3.3.0) +* +* @param string $password The password in plain text +* @param string $hash The stored password hash +* +* @return bool Returns true if the password is correct, false if not. +*/ +function phpbb_check_hash($password, $hash) +{ + global $phpbb_container; + + /* @var $passwords_manager \phpbb\passwords\manager */ + $passwords_manager = $phpbb_container->get('passwords.manager'); + return $passwords_manager->check($password, $hash); +} + +/** +* Eliminates useless . and .. components from specified path. +* +* Deprecated, use filesystem class instead +* +* @param string $path Path to clean +* @return string Cleaned path +* +* @deprecated 3.1.0 (To be removed: 3.3.0) +*/ +function phpbb_clean_path($path) +{ + global $phpbb_path_helper, $phpbb_container; + + if (!$phpbb_path_helper && $phpbb_container) + { + /* @var $phpbb_path_helper \phpbb\path_helper */ + $phpbb_path_helper = $phpbb_container->get('path_helper'); + } + else if (!$phpbb_path_helper) { global $phpbb_root_path, $phpEx; + // The container is not yet loaded, use a new instance + if (!class_exists('\phpbb\path_helper')) + { + require($phpbb_root_path . 'phpbb/path_helper.' . $phpEx); + } + + $request = new phpbb\request\request(); + $phpbb_path_helper = new phpbb\path_helper( + new phpbb\symfony_request( + $request + ), + new phpbb\filesystem\filesystem(), + $request, + $phpbb_root_path, + $phpEx + ); + } + + return $phpbb_path_helper->clean_path($path); +} + +/** +* Pick a timezone +* +* @param string $default A timezone to select +* @param boolean $truncate Shall we truncate the options text +* +* @return string Returns the options for timezone selector only +* +* @deprecated 3.1.0 (To be removed: 3.3.0) +*/ +function tz_select($default = '', $truncate = false) +{ + global $template, $user; + + return phpbb_timezone_select($template, $user, $default, $truncate); +} + +/** +* Cache moderators. Called whenever permissions are changed +* via admin_permissions. Changes of usernames and group names +* must be carried through for the moderators table. +* +* @deprecated 3.1.0 (To be removed: 3.3.0) +* @return null +*/ +function cache_moderators() +{ + global $db, $cache, $auth; + return phpbb_cache_moderators($db, $cache, $auth); +} + +/** +* Removes moderators and administrators from foe lists. +* +* @deprecated 3.1.0 (To be removed: 3.3.0) +* @param array|bool $group_id If an array, remove all members of this group from foe lists, or false to ignore +* @param array|bool $user_id If an array, remove this user from foe lists, or false to ignore +* @return null +*/ +function update_foes($group_id = false, $user_id = false) +{ + global $db, $auth; + return phpbb_update_foes($db, $auth, $group_id, $user_id); +} + +/** +* Get user rank title and image +* +* @param int $user_rank the current stored users rank id +* @param int $user_posts the users number of posts +* @param string &$rank_title the rank title will be stored here after execution +* @param string &$rank_img the rank image as full img tag is stored here after execution +* @param string &$rank_img_src the rank image source is stored here after execution +* +* @deprecated 3.1.0-RC5 (To be removed: 3.3.0) +* +* Note: since we do not want to break backwards-compatibility, this function will only properly assign ranks to guests if you call it for them with user_posts == false +*/ +function get_user_rank($user_rank, $user_posts, &$rank_title, &$rank_img, &$rank_img_src) +{ + global $phpbb_root_path, $phpEx; + if (!function_exists('phpbb_get_user_rank')) + { include($phpbb_root_path . 'includes/functions_display.' . $phpEx); } - return phpbb_get_avatar($row, $alt, $ignore_config); + $rank_data = phpbb_get_user_rank(array('user_rank' => $user_rank), $user_posts); + $rank_title = $rank_data['title']; + $rank_img = $rank_data['img']; + $rank_img_src = $rank_data['img_src']; +} + +/** + * Retrieve contents from remotely stored file + * + * @deprecated 3.1.2 Use file_downloader instead + */ +function get_remote_file($host, $directory, $filename, &$errstr, &$errno, $port = 80, $timeout = 6) +{ + global $phpbb_container; + + // Get file downloader and assign $errstr and $errno + /* @var $file_downloader \phpbb\file_downloader */ + $file_downloader = $phpbb_container->get('file_downloader'); + + $file_data = $file_downloader->get($host, $directory, $filename, $port, $timeout); + $errstr = $file_downloader->get_error_string(); + $errno = $file_downloader->get_error_number(); + + return $file_data; +} + +/** + * Add log entry + * + * @param string $mode The mode defines which log_type is used and from which log the entry is retrieved + * @param int $forum_id Mode 'mod' ONLY: forum id of the related item, NOT INCLUDED otherwise + * @param int $topic_id Mode 'mod' ONLY: topic id of the related item, NOT INCLUDED otherwise + * @param int $reportee_id Mode 'user' ONLY: user id of the reportee, NOT INCLUDED otherwise + * @param string $log_operation Name of the operation + * @param array $additional_data More arguments can be added, depending on the log_type + * + * @return int|bool Returns the log_id, if the entry was added to the database, false otherwise. + * + * @deprecated 3.1.0 (To be removed: 3.3.0) + */ +function add_log() +{ + global $phpbb_log, $user; + + $args = func_get_args(); + $mode = array_shift($args); + + // This looks kind of dirty, but add_log has some additional data before the log_operation + $additional_data = array(); + switch ($mode) + { + case 'admin': + case 'critical': + break; + case 'mod': + $additional_data['forum_id'] = array_shift($args); + $additional_data['topic_id'] = array_shift($args); + break; + case 'user': + $additional_data['reportee_id'] = array_shift($args); + break; + } + + $log_operation = array_shift($args); + $additional_data = array_merge($additional_data, $args); + + $user_id = (empty($user->data)) ? ANONYMOUS : $user->data['user_id']; + $user_ip = (empty($user->ip)) ? '' : $user->ip; + + return $phpbb_log->add($mode, $user_id, $user_ip, $log_operation, time(), $additional_data); +} + +/** + * Sets a configuration option's value. + * + * Please note that this function does not update the is_dynamic value for + * an already existing config option. + * + * @param string $config_name The configuration option's name + * @param string $config_value New configuration value + * @param bool $is_dynamic Whether this variable should be cached (false) or + * if it changes too frequently (true) to be + * efficiently cached. + * + * @return null + * + * @deprecated 3.1.0 (To be removed: 3.3.0) + */ +function set_config($config_name, $config_value, $is_dynamic = false, \phpbb\config\config $set_config = null) +{ + static $config = null; + + if ($set_config !== null) + { + $config = $set_config; + + if (empty($config_name)) + { + return; + } + } + + $config->set($config_name, $config_value, !$is_dynamic); +} + +/** + * Increments an integer config value directly in the database. + * + * @param string $config_name The configuration option's name + * @param int $increment Amount to increment by + * @param bool $is_dynamic Whether this variable should be cached (false) or + * if it changes too frequently (true) to be + * efficiently cached. + * + * @return null + * + * @deprecated 3.1.0 (To be removed: 3.3.0) + */ +function set_config_count($config_name, $increment, $is_dynamic = false, \phpbb\config\config $set_config = null) +{ + static $config = null; + if ($set_config !== null) + { + $config = $set_config; + if (empty($config_name)) + { + return; + } + } + $config->increment($config_name, $increment, !$is_dynamic); +} + +/** + * Wrapper function of \phpbb\request\request::variable which exists for backwards compatability. + * See {@link \phpbb\request\request_interface::variable \phpbb\request\request_interface::variable} for + * documentation of this function's use. + * + * @deprecated 3.1.0 (To be removed: 3.3.0) + * @param mixed $var_name The form variable's name from which data shall be retrieved. + * If the value is an array this may be an array of indizes which will give + * direct access to a value at any depth. E.g. if the value of "var" is array(1 => "a") + * then specifying array("var", 1) as the name will return "a". + * If you pass an instance of {@link \phpbb\request\request_interface phpbb_request_interface} + * as this parameter it will overwrite the current request class instance. If you do + * not do so, it will create its own instance (but leave superglobals enabled). + * @param mixed $default A default value that is returned if the variable was not set. + * This function will always return a value of the same type as the default. + * @param bool $multibyte If $default is a string this paramater has to be true if the variable may contain any UTF-8 characters + * Default is false, causing all bytes outside the ASCII range (0-127) to be replaced with question marks + * @param bool $cookie This param is mapped to \phpbb\request\request_interface::COOKIE as the last param for + * \phpbb\request\request_interface::variable for backwards compatability reasons. + * @param \phpbb\request\request_interface|null|false If an instance of \phpbb\request\request_interface is given the instance is stored in + * a static variable and used for all further calls where this parameters is null. Until + * the function is called with an instance it automatically creates a new \phpbb\request\request + * instance on every call. By passing false this per-call instantiation can be restored + * after having passed in a \phpbb\request\request_interface instance. + * + * @return mixed The value of $_REQUEST[$var_name] run through {@link set_var set_var} to ensure that the type is the + * the same as that of $default. If the variable is not set $default is returned. + */ +function request_var($var_name, $default, $multibyte = false, $cookie = false, $request = null) +{ + // This is all just an ugly hack to add "Dependency Injection" to a function + // the only real code is the function call which maps this function to a method. + static $static_request = null; + if ($request instanceof \phpbb\request\request_interface) + { + $static_request = $request; + if (empty($var_name)) + { + return; + } + } + else if ($request === false) + { + $static_request = null; + if (empty($var_name)) + { + return; + } + } + $tmp_request = $static_request; + // no request class set, create a temporary one ourselves to keep backwards compatibility + if ($tmp_request === null) + { + // false param: enable super globals, so the created request class does not + // make super globals inaccessible everywhere outside this function. + $tmp_request = new \phpbb\request\request(new \phpbb\request\type_cast_helper(), false); + } + return $tmp_request->variable($var_name, $default, $multibyte, ($cookie) ? \phpbb\request\request_interface::COOKIE : \phpbb\request\request_interface::REQUEST); +} + +/** + * Get tables of a database + * + * @deprecated 3.1.0 (To be removed: 3.3.0) + */ +function get_tables(&$db) +{ + $db_tools_factory = new \phpbb\db\tools\factory(); + $db_tools = $db_tools_factory->get($db); + + return $db_tools->sql_list_tables(); +} + +/** + * Global function for chmodding directories and files for internal use + * + * This function determines owner and group whom the file belongs to and user and group of PHP and then set safest possible file permissions. + * The function determines owner and group from common.php file and sets the same to the provided file. + * The function uses bit fields to build the permissions. + * The function sets the appropiate execute bit on directories. + * + * Supported constants representing bit fields are: + * + * CHMOD_ALL - all permissions (7) + * CHMOD_READ - read permission (4) + * CHMOD_WRITE - write permission (2) + * CHMOD_EXECUTE - execute permission (1) + * + * NOTE: The function uses POSIX extension and fileowner()/filegroup() functions. If any of them is disabled, this function tries to build proper permissions, by calling is_readable() and is_writable() functions. + * + * @param string $filename The file/directory to be chmodded + * @param int $perms Permissions to set + * + * @return bool true on success, otherwise false + * + * @deprecated 3.2.0-dev use \phpbb\filesystem\filesystem::phpbb_chmod() instead + */ +function phpbb_chmod($filename, $perms = CHMOD_READ) +{ + global $phpbb_filesystem; + + try + { + $phpbb_filesystem->phpbb_chmod($filename, $perms); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + return false; + } + + return true; +} + +/** + * Test if a file/directory is writable + * + * This function calls the native is_writable() when not running under + * Windows and it is not disabled. + * + * @param string $file Path to perform write test on + * @return bool True when the path is writable, otherwise false. + * + * @deprecated 3.2.0-dev use \phpbb\filesystem\filesystem::is_writable() instead + */ +function phpbb_is_writable($file) +{ + global $phpbb_filesystem; + + return $phpbb_filesystem->is_writable($file); +} + +/** + * Checks if a path ($path) is absolute or relative + * + * @param string $path Path to check absoluteness of + * @return boolean + * + * @deprecated 3.2.0-dev use \phpbb\filesystem\filesystem::is_absolute_path() instead + */ +function phpbb_is_absolute($path) +{ + global $phpbb_filesystem; + + return $phpbb_filesystem->is_absolute_path($path); +} + +/** + * A wrapper for realpath + * + * @deprecated 3.2.0-dev use \phpbb\filesystem\filesystem::realpath() instead + */ +function phpbb_realpath($path) +{ + global $phpbb_filesystem; + + return $phpbb_filesystem->realpath($path); +} + +/** + * Determine which plural form we should use. + * For some languages this is not as simple as for English. + * + * @param $rule int ID of the plural rule we want to use, see http://wiki.phpbb.com/Plural_Rules#Plural_Rules + * @param $number int|float The number we want to get the plural case for. Float numbers are floored. + * @return int The plural-case we need to use for the number plural-rule combination + * + * @deprecated 3.2.0-dev (To be removed: 3.3.0) + */ +function phpbb_get_plural_form($rule, $number) +{ + global $phpbb_container; + + /** @var \phpbb\language\language $language */ + $language = $phpbb_container->get('language'); + return $language->get_plural_form($number, $rule); +} + +/** +* @return bool Always true +* @deprecated 3.2.0-dev +*/ +function phpbb_pcre_utf8_support() +{ + return true; } diff --git a/phpBB/includes/functions_compress.php b/phpBB/includes/functions_compress.php index 39a1b2ad21..910708f502 100644 --- a/phpBB/includes/functions_compress.php +++ b/phpBB/includes/functions_compress.php @@ -1,9 +1,13 @@ <?php /** * -* @package phpBB3 -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -17,7 +21,6 @@ if (!defined('IN_PHPBB')) /** * Class for handling archives (compression/decompression) -* @package phpBB3 */ class compress { @@ -53,7 +56,6 @@ class compress // Clean up path, add closing / if not present $src_path = ($src_path && substr($src_path, -1) != '/') ? $src_path . '/' : $src_path; - $filelist = array(); $filelist = filelist("$phpbb_root_path$src", '', '*'); krsort($filelist); @@ -181,17 +183,15 @@ class compress } /** -* Zip creation class from phpMyAdmin 2.3.0 (c) Tobias Ratschiller, Olivier Müller, Loïc Chapeaux, +* Zip creation class from phpMyAdmin 2.3.0 (c) Tobias Ratschiller, Olivier Müller, Loïc Chapeaux, * Marc Delisle, http://www.phpmyadmin.net/ * * Zip extraction function by Alexandre Tedeschi, alexandrebr at gmail dot com * -* Modified extensively by psoTFX and DavidMJ, (c) phpBB Group, 2003 +* Modified extensively by psoTFX and DavidMJ, (c) phpBB Limited, 2003 * * Based on work by Eric Mueller and Denis125 * Official ZIP file format: http://www.pkware.com/appnote.txt -* -* @package phpBB3 */ class compress_zip extends compress { @@ -203,11 +203,19 @@ class compress_zip extends compress var $datasec_len = 0; /** + * @var \phpbb\filesystem\filesystem_interface + */ + protected $filesystem; + + /** * Constructor */ function compress_zip($mode, $file) { + global $phpbb_filesystem; + $this->fp = @fopen($file, $mode . 'b'); + $this->filesystem = ($phpbb_filesystem instanceof \phpbb\filesystem\filesystem_interface) ? $phpbb_filesystem : new \phpbb\filesystem\filesystem(); if (!$this->fp) { @@ -285,7 +293,15 @@ class compress_zip extends compress { trigger_error("Could not create directory $folder"); } - phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE); + + try + { + $this->filesystem->phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } } } } @@ -314,7 +330,15 @@ class compress_zip extends compress { trigger_error("Could not create directory $folder"); } - phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE); + + try + { + $this->filesystem->phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } } } } @@ -508,7 +532,7 @@ class compress_zip extends compress $mimetype = 'application/zip'; - header('Pragma: no-cache'); + header('Cache-Control: private, no-cache'); header("Content-Type: $mimetype; name=\"$download_name.zip\""); header("Content-disposition: attachment; filename=$download_name.zip"); @@ -527,8 +551,6 @@ class compress_zip extends compress /** * Tar/tar.gz compression routine * Header/checksum creation derived from tarfile.pl, (c) Tom Horsley, 1994 -* -* @package phpBB3 */ class compress_tar extends compress { @@ -540,10 +562,17 @@ class compress_tar extends compress var $wrote = false; /** + * @var \phpbb\filesystem\filesystem_interface + */ + protected $filesystem; + + /** * Constructor */ function compress_tar($mode, $file, $type = '') { + global $phpbb_filesystem; + $type = (!$type) ? $file : $type; $this->isgz = preg_match('#(\.tar\.gz|\.tgz)$#', $type); $this->isbz = preg_match('#\.tar\.bz2$#', $type); @@ -552,6 +581,8 @@ class compress_tar extends compress $this->file = &$file; $this->type = &$type; $this->open(); + + $this->filesystem = ($phpbb_filesystem instanceof \phpbb\filesystem\filesystem_interface) ? $phpbb_filesystem : new \phpbb\filesystem\filesystem(); } /** @@ -602,7 +633,15 @@ class compress_tar extends compress { trigger_error("Could not create directory $folder"); } - phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE); + + try + { + $this->filesystem->phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } } } } @@ -629,7 +668,15 @@ class compress_tar extends compress { trigger_error("Could not create directory $folder"); } - phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE); + + try + { + $this->filesystem->phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } } } @@ -638,7 +685,15 @@ class compress_tar extends compress { trigger_error("Couldn't create file $filename"); } - phpbb_chmod($target_filename, CHMOD_READ); + + try + { + $this->filesystem->phpbb_chmod($target_filename, CHMOD_READ); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } // Grab the file contents fwrite($fp, ($filesize) ? $fzread($this->fp, ($filesize + 511) &~ 511) : '', $filesize); @@ -758,7 +813,7 @@ class compress_tar extends compress break; } - header('Pragma: no-cache'); + header('Cache-Control: private, no-cache'); header("Content-Type: $mimetype; name=\"$download_name$this->type\""); header("Content-disposition: attachment; filename=$download_name$this->type"); diff --git a/phpBB/includes/functions_container.php b/phpBB/includes/functions_container.php deleted file mode 100644 index 667d27fd20..0000000000 --- a/phpBB/includes/functions_container.php +++ /dev/null @@ -1,287 +0,0 @@ -<?php -/** -* -* @package phpBB3 -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 -* -*/ - -use Symfony\Component\Config\FileLocator; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Dumper\PhpDumper; -use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Get DB connection from config.php. -* -* Used to bootstrap the container. -* -* @param string $config_file -* @return \phpbb\db\driver\driver -*/ -function phpbb_bootstrap_db_connection($config_file) -{ - require($config_file); - $dbal_driver_class = phpbb_convert_30_dbms_to_31($dbms); - - $db = new $dbal_driver_class(); - $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, defined('PHPBB_DB_NEW_LINK')); - - return $db; -} - -/** -* Get table prefix from config.php. -* -* Used to bootstrap the container. -* -* @param string $config_file -* @return string table prefix -*/ -function phpbb_bootstrap_table_prefix($config_file) -{ - require($config_file); - return $table_prefix; -} - -/** -* Get enabled extensions. -* -* Used to bootstrap the container. -* -* @param string $config_file -* @param string $phpbb_root_path -* @return array enabled extensions -*/ -function phpbb_bootstrap_enabled_exts($config_file, $phpbb_root_path) -{ - $db = phpbb_bootstrap_db_connection($config_file); - $table_prefix = phpbb_bootstrap_table_prefix($config_file); - $extension_table = $table_prefix.'ext'; - - $sql = 'SELECT * - FROM ' . $extension_table . ' - WHERE ext_active = 1'; - - $result = $db->sql_query($sql); - $rows = $db->sql_fetchrowset($result); - $db->sql_freeresult($result); - - $exts = array(); - foreach ($rows as $row) - { - $exts[$row['ext_name']] = $phpbb_root_path . 'ext/' . $row['ext_name'] . '/'; - } - - return $exts; -} - -/** -* Create the ContainerBuilder object -* -* @param array $extensions Array of Container extension objects -* @param string $phpbb_root_path Root path -* @param string $php_ext PHP Extension -* @return ContainerBuilder object -*/ -function phpbb_create_container(array $extensions, $phpbb_root_path, $php_ext) -{ - $container = new ContainerBuilder(); - - foreach ($extensions as $extension) - { - $container->registerExtension($extension); - $container->loadFromExtension($extension->getAlias()); - } - - $container->setParameter('core.root_path', $phpbb_root_path); - $container->setParameter('core.php_ext', $php_ext); - - return $container; -} - -/** -* Create installer container -* -* @param string $phpbb_root_path Root path -* @param string $php_ext PHP Extension -* @return ContainerBuilder object -*/ -function phpbb_create_install_container($phpbb_root_path, $php_ext) -{ - $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/'; - - $core = new \phpbb\di\extension\core($config_path); - $container = phpbb_create_container(array($core), $phpbb_root_path, $php_ext); - - $container->setParameter('core.root_path', $phpbb_root_path); - $container->setParameter('core.adm_relative_path', $phpbb_adm_relative_path); - $container->setParameter('core.php_ext', $php_ext); - $container->setParameter('core.table_prefix', ''); - - $container->register('dbal.conn')->setSynthetic(true); - - $container->setAlias('cache.driver', 'cache.driver.install'); - - $container->compile(); - - return $container; -} - -/** -* Create updater container -* -* @param string $phpbb_root_path Root path -* @param string $php_ext PHP Extension -* @param array $config_path Path to config directory -* @return ContainerBuilder object (compiled) -*/ -function phpbb_create_update_container($phpbb_root_path, $php_ext, $config_path) -{ - $config_file = $phpbb_root_path . 'config.' . $php_ext; - return phpbb_create_compiled_container( - $config_file, - array( - new phpbb\di\extension\config($config_file), - new phpbb\di\extension\core($config_path), - ), - array( - new phpbb\di\pass\collection_pass(), - new phpbb\di\pass\kernel_pass(), - ), - $phpbb_root_path, - $php_ext - ); -} - -/** -* Create a compiled ContainerBuilder object -* -* @param array $extensions Array of Container extension objects -* @param array $passes Array of Compiler Pass objects -* @param string $phpbb_root_path Root path -* @param string $php_ext PHP Extension -* @return ContainerBuilder object (compiled) -*/ -function phpbb_create_compiled_container($config_file, array $extensions, array $passes, $phpbb_root_path, $php_ext) -{ - // Create the final container to be compiled and cached - $container = phpbb_create_container($extensions, $phpbb_root_path, $php_ext); - - // Compile the container - foreach ($passes as $pass) - { - $container->addCompilerPass($pass); - } - $container->compile(); - - return $container; -} - -/** -* Create a compiled and dumped ContainerBuilder object -* -* @param array $extensions Array of Container extension objects -* @param array $passes Array of Compiler Pass objects -* @param string $phpbb_root_path Root path -* @param string $php_ext PHP Extension -* @return ContainerBuilder object (compiled) -*/ -function phpbb_create_dumped_container($config_file, array $extensions, array $passes, $phpbb_root_path, $php_ext) -{ - // Check for our cached container; if it exists, use it - $container_filename = phpbb_container_filename($phpbb_root_path, $php_ext); - if (file_exists($container_filename)) - { - require($container_filename); - return new phpbb_cache_container(); - } - - $container = phpbb_create_compiled_container($config_file, $extensions, $passes, $phpbb_root_path, $php_ext); - - // Lastly, we create our cached container class - $dumper = new PhpDumper($container); - $cached_container_dump = $dumper->dump(array( - 'class' => 'phpbb_cache_container', - 'base_class' => 'Symfony\\Component\\DependencyInjection\\ContainerBuilder', - )); - - file_put_contents($container_filename, $cached_container_dump); - - return $container; -} - -/** -* Create an environment-specific ContainerBuilder object -* -* If debug is enabled, the container is re-compiled every time. -* This ensures that the latest changes will always be reflected -* during development. -* -* Otherwise it will get the existing dumped container and use -* that one instead. -* -* @param array $extensions Array of Container extension objects -* @param array $passes Array of Compiler Pass objects -* @param string $phpbb_root_path Root path -* @param string $php_ext PHP Extension -* @return ContainerBuilder object (compiled) -*/ -function phpbb_create_dumped_container_unless_debug($config_file, array $extensions, array $passes, $phpbb_root_path, $php_ext) -{ - $container_factory = defined('DEBUG') ? 'phpbb_create_compiled_container' : 'phpbb_create_dumped_container'; - return $container_factory($config_file, $extensions, $passes, $phpbb_root_path, $php_ext); -} - -/** -* Create a default ContainerBuilder object -* -* Contains the default configuration of the phpBB container. -* -* @param array $extensions Array of Container extension objects -* @param array $passes Array of Compiler Pass objects -* @return ContainerBuilder object (compiled) -*/ -function phpbb_create_default_container($phpbb_root_path, $php_ext) -{ - $config_file = $phpbb_root_path . 'config.' . $php_ext; - $installed_exts = phpbb_bootstrap_enabled_exts($config_file, $phpbb_root_path); - - return phpbb_create_dumped_container_unless_debug( - $config_file, - array( - new \phpbb\di\extension\config($config_file), - new \phpbb\di\extension\core($phpbb_root_path . 'config'), - new \phpbb\di\extension\ext($installed_exts), - ), - array( - new \phpbb\di\pass\collection_pass(), - new \phpbb\di\pass\kernel_pass(), - ), - $phpbb_root_path, - $php_ext - ); -} - -/** -* Get the filename under which the dumped container will be stored. -* -* @param string $phpbb_root_path Root path -* @param string $php_ext PHP Extension -* @return Path for dumped container -*/ -function phpbb_container_filename($phpbb_root_path, $php_ext) -{ - $filename = str_replace(array('/', '.'), array('slash', 'dot'), $phpbb_root_path); - return $phpbb_root_path . 'cache/container_' . $filename . '.' . $php_ext; -} diff --git a/phpBB/includes/functions_content.php b/phpBB/includes/functions_content.php index 8122b87e4b..df25451266 100644 --- a/phpBB/includes/functions_content.php +++ b/phpBB/includes/functions_content.php @@ -1,9 +1,13 @@ <?php /** * -* @package phpBB3 -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -20,6 +24,7 @@ if (!defined('IN_PHPBB')) * make_jumpbox() * bump_topic_allowed() * get_context() +* phpbb_clean_search_string() * decode_message() * strip_bbcode() * generate_text_for_display() @@ -73,7 +78,7 @@ function gen_sort_selects(&$limit_days, &$sort_by_text, &$sort_days, &$sort_key, foreach ($sorts as $name => $sort_ary) { $key = $sort_ary['key']; - $selected = $$sort_ary['key']; + $selected = ${$sort_ary['key']}; // Check if the key is selectable. If not, we reset to the default or first key found. // This ensures the values are always valid. We also set $sort_dir/sort_key/etc. to the @@ -82,12 +87,12 @@ function gen_sort_selects(&$limit_days, &$sort_by_text, &$sort_days, &$sort_key, { if ($sort_ary['default'] !== false) { - $selected = $$key = $sort_ary['default']; + $selected = ${$key} = $sort_ary['default']; } else { @reset($sort_ary['options']); - $selected = $$key = key($sort_ary['options']); + $selected = ${$key} = key($sort_ary['options']); } } @@ -109,7 +114,7 @@ function gen_sort_selects(&$limit_days, &$sort_by_text, &$sort_days, &$sort_key, */ function make_jumpbox($action, $forum_id = false, $select_all = false, $acl_list = false, $force_display = false) { - global $config, $auth, $template, $user, $db; + global $config, $auth, $template, $user, $db, $phpbb_path_helper; // We only return if the jumpbox is not forced to be displayed (in case it is needed for functionality) if (!$config['load_jumpbox'] && $force_display === false) @@ -169,8 +174,9 @@ function make_jumpbox($action, $forum_id = false, $select_all = false, $acl_list $template->assign_block_vars('jumpbox_forums', array( 'FORUM_ID' => ($select_all) ? 0 : -1, 'FORUM_NAME' => ($select_all) ? $user->lang['ALL_FORUMS'] : $user->lang['SELECT_FORUM'], - 'S_FORUM_COUNT' => $iteration) - ); + 'S_FORUM_COUNT' => $iteration, + 'LINK' => $phpbb_path_helper->append_url_params($action, array('f' => $forum_id)), + )); $iteration++; $display_jumpbox = true; @@ -183,8 +189,9 @@ function make_jumpbox($action, $forum_id = false, $select_all = false, $acl_list 'S_FORUM_COUNT' => $iteration, 'S_IS_CAT' => ($row['forum_type'] == FORUM_CAT) ? true : false, 'S_IS_LINK' => ($row['forum_type'] == FORUM_LINK) ? true : false, - 'S_IS_POST' => ($row['forum_type'] == FORUM_POST) ? true : false) - ); + 'S_IS_POST' => ($row['forum_type'] == FORUM_POST) ? true : false, + 'LINK' => $phpbb_path_helper->append_url_params($action, array('f' => $row['forum_id'])), + )); for ($i = 0; $i < $padding; $i++) { @@ -195,10 +202,13 @@ function make_jumpbox($action, $forum_id = false, $select_all = false, $acl_list $db->sql_freeresult($result); unset($padding_store); + $url_parts = $phpbb_path_helper->get_url_parts($action); + $template->assign_vars(array( - 'S_DISPLAY_JUMPBOX' => $display_jumpbox, - 'S_JUMPBOX_ACTION' => $action) - ); + 'S_DISPLAY_JUMPBOX' => $display_jumpbox, + 'S_JUMPBOX_ACTION' => $action, + 'HIDDEN_FIELDS_FOR_JUMPBOX' => build_hidden_fields($url_parts['params']), + )); return; } @@ -360,48 +370,87 @@ function get_context($text, $words, $length = 400) } /** +* Cleans a search string by removing single wildcards from it and replacing multiple spaces with a single one. +* +* @param string $search_string The full search string which should be cleaned. +* +* @return string The cleaned search string without any wildcards and multiple spaces. +*/ +function phpbb_clean_search_string($search_string) +{ + // This regular expressions matches every single wildcard. + // That means one after a whitespace or the beginning of the string or one before a whitespace or the end of the string. + $search_string = preg_replace('#(?<=^|\s)\*+(?=\s|$)#', '', $search_string); + $search_string = trim($search_string); + $search_string = preg_replace(array('#\s+#u', '#\*+#u'), array(' ', '*'), $search_string); + return $search_string; +} + +/** * Decode text whereby text is coming from the db and expected to be pre-parsed content * We are placing this outside of the message parser because we are often in need of it... +* +* NOTE: special chars are kept encoded +* +* @param string &$message Original message, passed by reference +* @param string $bbcode_uid BBCode UID +* @return null */ function decode_message(&$message, $bbcode_uid = '') { - global $config; + global $phpbb_container; - if ($bbcode_uid) + if (preg_match('#^<[rt][ >]#', $message)) { - $match = array('<br />', "[/*:m:$bbcode_uid]", ":u:$bbcode_uid", ":o:$bbcode_uid", ":$bbcode_uid"); - $replace = array("\n", '', '', '', ''); + $message = htmlspecialchars($phpbb_container->get('text_formatter.utils')->unparse($message), ENT_COMPAT); } else { - $match = array('<br />'); - $replace = array("\n"); - } + if ($bbcode_uid) + { + $match = array('<br />', "[/*:m:$bbcode_uid]", ":u:$bbcode_uid", ":o:$bbcode_uid", ":$bbcode_uid"); + $replace = array("\n", '', '', '', ''); + } + else + { + $match = array('<br />'); + $replace = array("\n"); + } - $message = str_replace($match, $replace, $message); + $message = str_replace($match, $replace, $message); - $match = get_preg_expression('bbcode_htm'); - $replace = array('\1', '\1', '\2', '\1', '', ''); + $match = get_preg_expression('bbcode_htm'); + $replace = array('\1', '\1', '\3', '\1', '', ''); - $message = preg_replace($match, $replace, $message); + $message = preg_replace($match, $replace, $message); + } } /** -* Strips all bbcode from a text and returns the plain content +* Strips all bbcode from a text in place */ function strip_bbcode(&$text, $uid = '') { - if (!$uid) + global $phpbb_container; + + if (preg_match('#^<[rt][ >]#', $text)) { - $uid = '[0-9a-z]{5,}'; + $text = $phpbb_container->get('text_formatter.utils')->clean_formatting($text); } + else + { + if (!$uid) + { + $uid = '[0-9a-z]{5,}'; + } - $text = preg_replace("#\[\/?[a-z0-9\*\+\-]+(?:=(?:".*"|[^\]]*))?(?::[a-z])?(\:$uid)\]#", ' ', $text); + $text = preg_replace("#\[\/?[a-z0-9\*\+\-]+(?:=(?:".*"|[^\]]*))?(?::[a-z])?(\:$uid)\]#", ' ', $text); - $match = get_preg_expression('bbcode_htm'); - $replace = array('\1', '\1', '\2', '\1', '', ''); + $match = get_preg_expression('bbcode_htm'); + $replace = array('\1', '\1', '\2', '\1', '', ''); - $text = preg_replace($match, $replace, $text); + $text = preg_replace($match, $replace, $text); + } } /** @@ -411,7 +460,7 @@ function strip_bbcode(&$text, $uid = '') function generate_text_for_display($text, $uid, $bitfield, $flags, $censor_text = true) { static $bbcode; - global $phpbb_dispatcher; + global $phpbb_dispatcher, $phpbb_container; if ($text === '') { @@ -427,39 +476,61 @@ function generate_text_for_display($text, $uid, $bitfield, $flags, $censor_text * @var string bitfield The BBCode Bitfield * @var int flags The BBCode Flags * @var bool censor_text Whether or not to apply word censors - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('text', 'uid', 'bitfield', 'flags', 'censor_text'); extract($phpbb_dispatcher->trigger_event('core.modify_text_for_display_before', compact($vars))); - if ($censor_text) - { - $text = censor_text($text); - } - - // Parse bbcode if bbcode uid stored and bbcode enabled - if ($uid && ($flags & OPTION_FLAG_BBCODE)) + if (preg_match('#^<[rt][ >]#', $text)) { - if (!class_exists('bbcode')) + $renderer = $phpbb_container->get('text_formatter.renderer'); + + // Temporarily switch off viewcensors if applicable + $old_censor = $renderer->get_viewcensors(); + if ($old_censor !== $censor_text) { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/bbcode.' . $phpEx); + $renderer->set_viewcensors($censor_text); } - if (empty($bbcode)) + $text = $renderer->render($text); + + // Restore the previous value + if ($old_censor !== $censor_text) { - $bbcode = new bbcode($bitfield); + $renderer->set_viewcensors($old_censor); } - else + } + else + { + if ($censor_text) { - $bbcode->bbcode($bitfield); + $text = censor_text($text); } - $bbcode->bbcode_second_pass($text, $uid); - } + // Parse bbcode if bbcode uid stored and bbcode enabled + if ($uid && ($flags & OPTION_FLAG_BBCODE)) + { + if (!class_exists('bbcode')) + { + global $phpbb_root_path, $phpEx; + include($phpbb_root_path . 'includes/bbcode.' . $phpEx); + } - $text = bbcode_nl2br($text); - $text = smiley_text($text, !($flags & OPTION_FLAG_SMILIES)); + if (empty($bbcode)) + { + $bbcode = new bbcode($bitfield); + } + else + { + $bbcode->bbcode($bitfield); + } + + $bbcode->bbcode_second_pass($text, $uid); + } + + $text = bbcode_nl2br($text); + $text = smiley_text($text, !($flags & OPTION_FLAG_SMILIES)); + } /** * Use this event to modify the text after it is parsed @@ -469,7 +540,7 @@ function generate_text_for_display($text, $uid, $bitfield, $flags, $censor_text * @var string uid The BBCode UID * @var string bitfield The BBCode Bitfield * @var int flags The BBCode Flags - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('text', 'uid', 'bitfield', 'flags'); extract($phpbb_dispatcher->trigger_event('core.modify_text_for_display_after', compact($vars))); @@ -480,8 +551,8 @@ function generate_text_for_display($text, $uid, $bitfield, $flags, $censor_text /** * For parsing custom parsed text to be stored within the database. * This function additionally returns the uid and bitfield that needs to be stored. -* Expects $text to be the value directly from request_var() and in it's non-parsed form -* +* Expects $text to be the value directly from $request->variable() and in it's non-parsed form +* * @param string $text The text to be replaced with the parsed one * @param string $uid The BBCode uid for this parse * @param string $bitfield The BBCode bitfield for this parse @@ -489,10 +560,15 @@ function generate_text_for_display($text, $uid, $bitfield, $flags, $censor_text * @param bool $allow_bbcode If BBCode is allowed (i.e. if BBCode is parsed) * @param bool $allow_urls If urls is allowed * @param bool $allow_smilies If smilies are allowed +* @param bool $allow_img_bbcode +* @param bool $allow_flash_bbcode +* @param bool $allow_quote_bbcode +* @param bool $allow_url_bbcode +* @param string $mode Mode to parse text as, e.g. post or sig * * @return array An array of string with the errors that occurred while parsing */ -function generate_text_for_storage(&$text, &$uid, &$bitfield, &$flags, $allow_bbcode = false, $allow_urls = false, $allow_smilies = false) +function generate_text_for_storage(&$text, &$uid, &$bitfield, &$flags, $allow_bbcode = false, $allow_urls = false, $allow_smilies = false, $allow_img_bbcode = true, $allow_flash_bbcode = true, $allow_quote_bbcode = true, $allow_url_bbcode = true, $mode = 'post') { global $phpbb_root_path, $phpEx, $phpbb_dispatcher; @@ -507,26 +583,40 @@ function generate_text_for_storage(&$text, &$uid, &$bitfield, &$flags, $allow_bb * @var bool allow_bbcode Whether or not to parse BBCode * @var bool allow_urls Whether or not to parse URLs * @var bool allow_smilies Whether or not to parse Smilies - * @since 3.1-A1 + * @var bool allow_img_bbcode Whether or not to parse the [img] BBCode + * @var bool allow_flash_bbcode Whether or not to parse the [flash] BBCode + * @var bool allow_quote_bbcode Whether or not to parse the [quote] BBCode + * @var bool allow_url_bbcode Whether or not to parse the [url] BBCode + * @var string mode Mode to parse text as, e.g. post or sig + * @since 3.1.0-a1 + * @changed 3.2.0-a1 */ - $vars = array('text', 'uid', 'bitfield', 'flags', 'allow_bbcode', 'allow_urls', 'allow_smilies'); + $vars = array( + 'text', + 'uid', + 'bitfield', + 'flags', + 'allow_bbcode', + 'allow_urls', + 'allow_smilies', + 'allow_img_bbcode', + 'allow_flash_bbcode', + 'allow_quote_bbcode', + 'allow_url_bbcode', + 'mode', + ); extract($phpbb_dispatcher->trigger_event('core.modify_text_for_storage_before', compact($vars))); $uid = $bitfield = ''; $flags = (($allow_bbcode) ? OPTION_FLAG_BBCODE : 0) + (($allow_smilies) ? OPTION_FLAG_SMILIES : 0) + (($allow_urls) ? OPTION_FLAG_LINKS : 0); - if ($text === '') - { - return; - } - if (!class_exists('parse_message')) { include($phpbb_root_path . 'includes/message_parser.' . $phpEx); } $message_parser = new parse_message($text); - $message_parser->parse($allow_bbcode, $allow_urls, $allow_smilies); + $message_parser->parse($allow_bbcode, $allow_urls, $allow_smilies, $allow_img_bbcode, $allow_flash_bbcode, $allow_quote_bbcode, $allow_url_bbcode, true, $mode); $text = $message_parser->message; $uid = $message_parser->bbcode_uid; @@ -547,7 +637,7 @@ function generate_text_for_storage(&$text, &$uid, &$bitfield, &$flags, $allow_bb * @var string uid The BBCode UID * @var string bitfield The BBCode Bitfield * @var int flags The BBCode Flags - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('text', 'uid', 'bitfield', 'flags'); extract($phpbb_dispatcher->trigger_event('core.modify_text_for_storage_after', compact($vars))); @@ -561,7 +651,7 @@ function generate_text_for_storage(&$text, &$uid, &$bitfield, &$flags, $allow_bb */ function generate_text_for_edit($text, $uid, $flags) { - global $phpbb_root_path, $phpEx, $phpbb_dispatcher; + global $phpbb_dispatcher; /** * Use this event to modify the text before it is decoded for editing @@ -570,7 +660,7 @@ function generate_text_for_edit($text, $uid, $flags) * @var string text The text to parse * @var string uid The BBCode UID * @var int flags The BBCode Flags - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('text', 'uid', 'flags'); extract($phpbb_dispatcher->trigger_event('core.modify_text_for_edit_before', compact($vars))); @@ -583,7 +673,7 @@ function generate_text_for_edit($text, $uid, $flags) * @event core.modify_text_for_edit_after * @var string text The text to parse * @var int flags The BBCode Flags - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('text', 'flags'); extract($phpbb_dispatcher->trigger_event('core.modify_text_for_edit_after', compact($vars))); @@ -677,7 +767,7 @@ function make_clickable_callback($type, $whitespace, $url, $relative_url, $class break; } - $short_url = (strlen($url) > 55) ? substr($url, 0, 39) . ' ... ' . substr($url, -10) : $url; + $short_url = (utf8_strlen($url) > 55) ? utf8_substr($url, 0, 39) . ' ... ' . utf8_substr($url, -10) : $url; switch ($type) { @@ -740,44 +830,47 @@ function make_clickable($text, $server_url = false, $class = 'postlink') static $static_class; static $magic_url_match_args; - if (!is_array($magic_url_match_args) || $static_class != $class) + if (!isset($magic_url_match_args[$server_url]) || $static_class != $class) { $static_class = $class; $class = ($static_class) ? ' class="' . $static_class . '"' : ''; $local_class = ($static_class) ? ' class="' . $static_class . '-local"' : ''; - $magic_url_match_args = array(); + if (!is_array($magic_url_match_args)) + { + $magic_url_match_args = array(); + } // relative urls for this board - $magic_url_match_args[] = array( - '#(^|[\n\t (>.])(' . preg_quote($server_url, '#') . ')/(' . get_preg_expression('relative_url_inline') . ')#i', + $magic_url_match_args[$server_url][] = array( + '#(^|[\n\t (>.])(' . preg_quote($server_url, '#') . ')/(' . get_preg_expression('relative_url_inline') . ')#iu', MAGIC_URL_LOCAL, $local_class, ); // matches a xxxx://aaaaa.bbb.cccc. ... - $magic_url_match_args[] = array( - '#(^|[\n\t (>.])(' . get_preg_expression('url_inline') . ')#i', + $magic_url_match_args[$server_url][] = array( + '#(^|[\n\t (>.])(' . get_preg_expression('url_inline') . ')#iu', MAGIC_URL_FULL, $class, ); // matches a "www.xxxx.yyyy[/zzzz]" kinda lazy URL thing - $magic_url_match_args[] = array( - '#(^|[\n\t (>])(' . get_preg_expression('www_url_inline') . ')#i', + $magic_url_match_args[$server_url][] = array( + '#(^|[\n\t (>])(' . get_preg_expression('www_url_inline') . ')#iu', MAGIC_URL_WWW, $class, ); // matches an email@domain type address at the start of a line, or after a space or after what might be a BBCode. - $magic_url_match_args[] = array( - '/(^|[\n\t (>])(' . get_preg_expression('email') . ')/i', + $magic_url_match_args[$server_url][] = array( + '/(^|[\n\t (>])(' . get_preg_expression('email') . ')/iu', MAGIC_URL_EMAIL, '', ); } - foreach ($magic_url_match_args as $magic_args) + foreach ($magic_url_match_args[$server_url] as $magic_args) { if (preg_match($magic_args[0], $text, $matches)) { @@ -864,17 +957,17 @@ function smiley_text($text, $force_option = false) * @param mixed $forum_id The forum id the attachments are displayed in (false if in private message) * @param string &$message The post/private message * @param array &$attachments The attachments to parse for (inline) display. The attachments array will hold templated data after parsing. -* @param array &$update_count The attachment counts to be updated - will be filled +* @param array &$update_count_ary The attachment counts to be updated - will be filled * @param bool $preview If set to true the attachments are parsed for preview. Within preview mode the comments are fetched from the given $attachments array and not fetched from the database. */ -function parse_attachments($forum_id, &$message, &$attachments, &$update_count, $preview = false) +function parse_attachments($forum_id, &$message, &$attachments, &$update_count_ary, $preview = false) { if (!sizeof($attachments)) { return; } - global $template, $cache, $user; + global $template, $cache, $user, $phpbb_dispatcher; global $extensions, $config, $phpbb_root_path, $phpEx; // @@ -963,7 +1056,6 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count, // Some basics... $attachment['extension'] = strtolower(trim($attachment['extension'])); $filename = $phpbb_root_path . $config['upload_path'] . '/' . utf8_basename($attachment['physical_filename']); - $thumbnail_filename = $phpbb_root_path . $config['upload_path'] . '/thumb_' . utf8_basename($attachment['physical_filename']); $upload_icon = ''; @@ -1005,7 +1097,6 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count, if (!$denied) { - $l_downloaded_viewed = $download_link = ''; $display_cat = $extensions[$attachment['extension']]['display_cat']; if ($display_cat == ATTACHMENT_CATEGORY_IMAGE) @@ -1066,7 +1157,7 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count, 'U_INLINE_LINK' => $inline_link, ); - $update_count[] = $attachment['attach_id']; + $update_count_ary[] = $attachment['attach_id']; break; // Images, but display Thumbnail @@ -1079,39 +1170,7 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count, 'THUMB_IMAGE' => $thumbnail_link, ); - $update_count[] = $attachment['attach_id']; - break; - - // Windows Media Streams - case ATTACHMENT_CATEGORY_WM: - - // Giving the filename directly because within the wm object all variables are in local context making it impossible - // to validate against a valid session (all params can differ) - // $download_link = $filename; - - $block_array += array( - 'U_FORUM' => generate_board_url(), - 'ATTACH_ID' => $attachment['attach_id'], - 'S_WM_FILE' => true, - ); - - // Viewed/Heared File ... update the download count - $update_count[] = $attachment['attach_id']; - break; - - // Real Media Streams - case ATTACHMENT_CATEGORY_RM: - case ATTACHMENT_CATEGORY_QUICKTIME: - - $block_array += array( - 'S_RM_FILE' => ($display_cat == ATTACHMENT_CATEGORY_RM) ? true : false, - 'S_QUICKTIME_FILE' => ($display_cat == ATTACHMENT_CATEGORY_QUICKTIME) ? true : false, - 'U_FORUM' => generate_board_url(), - 'ATTACH_ID' => $attachment['attach_id'], - ); - - // Viewed/Heared File ... update the download count - $update_count[] = $attachment['attach_id']; + $update_count_ary[] = $attachment['attach_id']; break; // Macromedia Flash Files @@ -1126,7 +1185,7 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count, ); // Viewed/Heared File ... update the download count - $update_count[] = $attachment['attach_id']; + $update_count_ary[] = $attachment['attach_id']; break; default: @@ -1149,6 +1208,37 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count, ); } + $update_count = $update_count_ary; + /** + * Use this event to modify the attachment template data. + * + * This event is triggered once per attachment. + * + * @event core.parse_attachments_modify_template_data + * @var array attachment Array with attachment data + * @var array block_array Template data of the attachment + * @var int display_cat Attachment category data + * @var string download_link Attachment download link + * @var array extensions Array with attachment extensions data + * @var mixed forum_id The forum id the attachments are displayed in (false if in private message) + * @var bool preview Flag indicating if we are in post preview mode + * @var array update_count Array with attachment ids to update download count + * @since 3.1.0-RC5 + */ + $vars = array( + 'attachment', + 'block_array', + 'display_cat', + 'download_link', + 'extensions', + 'forum_id', + 'preview', + 'update_count', + ); + extract($phpbb_dispatcher->trigger_event('core.parse_attachments_modify_template_data', compact($vars))); + $update_count_ary = $update_count; + unset($update_count); + $template->assign_block_vars('_file', $block_array); $compiled_attachments[] = $template->assign_display('attachment_tpl'); @@ -1224,8 +1314,6 @@ function extension_allowed($forum_id, $extension, &$extensions) */ function truncate_string($string, $max_length = 60, $max_store_length = 255, $allow_reply = false, $append = '') { - $chars = array(); - $strip_reply = false; $stripped = false; if ($allow_reply && strpos($string, 'Re: ') === 0) @@ -1285,7 +1373,6 @@ function truncate_string($string, $max_length = 60, $max_store_length = 255, $al * @param string $custom_profile_url optional parameter to specify a profile url. The user id get appended to this url as &u={user_id} * * @return string A string consisting of what is wanted based on $mode. -* @author BartVB, Acyd Burn */ function get_username_string($mode, $user_id, $username, $username_colour = '', $guest_username = false, $custom_profile_url = false) { @@ -1298,9 +1385,9 @@ function get_username_string($mode, $user_id, $username, $username_colour = '', global $phpbb_root_path, $phpEx; $_profile_cache['base_url'] = append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&u={USER_ID}'); - $_profile_cache['tpl_noprofile'] = '{USERNAME}'; + $_profile_cache['tpl_noprofile'] = '<span class="username">{USERNAME}</span>'; $_profile_cache['tpl_noprofile_colour'] = '<span style="color: {USERNAME_COLOUR};" class="username-coloured">{USERNAME}</span>'; - $_profile_cache['tpl_profile'] = '<a href="{PROFILE_URL}">{USERNAME}</a>'; + $_profile_cache['tpl_profile'] = '<a href="{PROFILE_URL}" class="username">{USERNAME}</a>'; $_profile_cache['tpl_profile_colour'] = '<a href="{PROFILE_URL}" style="color: {USERNAME_COLOUR};" class="username-coloured">{USERNAME}</a>'; } @@ -1319,7 +1406,8 @@ function get_username_string($mode, $user_id, $username, $username_colour = '', // Return colour if ($mode == 'colour') { - return $username_colour; + $username_string = $username_colour; + break; } // no break; @@ -1339,7 +1427,8 @@ function get_username_string($mode, $user_id, $username, $username_colour = '', // Return username if ($mode == 'username') { - return $username; + $username_string = $username; + break; } // no break; @@ -1360,21 +1449,25 @@ function get_username_string($mode, $user_id, $username, $username_colour = '', // Return profile if ($mode == 'profile') { - return $profile_url; + $username_string = $profile_url; + break; } // no break; } - if (($mode == 'full' && !$profile_url) || $mode == 'no_profile') - { - $username_string = str_replace(array('{USERNAME_COLOUR}', '{USERNAME}'), array($username_colour, $username), (!$username_colour) ? $_profile_cache['tpl_noprofile'] : $_profile_cache['tpl_noprofile_colour']); - } - else + if (!isset($username_string)) { - $username_string = str_replace(array('{PROFILE_URL}', '{USERNAME_COLOUR}', '{USERNAME}'), array($profile_url, $username_colour, $username), (!$username_colour) ? $_profile_cache['tpl_profile'] : $_profile_cache['tpl_profile_colour']); + if (($mode == 'full' && !$profile_url) || $mode == 'no_profile') + { + $username_string = str_replace(array('{USERNAME_COLOUR}', '{USERNAME}'), array($username_colour, $username), (!$username_colour) ? $_profile_cache['tpl_noprofile'] : $_profile_cache['tpl_noprofile_colour']); + } + else + { + $username_string = str_replace(array('{PROFILE_URL}', '{USERNAME_COLOUR}', '{USERNAME}'), array($profile_url, $username_colour, $username), (!$username_colour) ? $_profile_cache['tpl_profile'] : $_profile_cache['tpl_profile_colour']); + } } - + /** * Use this event to change the output of get_username_string() * @@ -1390,9 +1483,18 @@ function get_username_string($mode, $user_id, $username, $username_colour = '', * profile url. * @var string username_string The string that has been generated * @var array _profile_cache Array of original return templates - * @since 3.1-A1 + * @since 3.1.0-a1 */ - $vars = array('mode', 'user_id', 'username', 'username_colour', 'guest_username', 'custom_profile_url', 'username_string', '_profile_cache'); + $vars = array( + 'mode', + 'user_id', + 'username', + 'username_colour', + 'guest_username', + 'custom_profile_url', + 'username_string', + '_profile_cache', + ); extract($phpbb_dispatcher->trigger_event('core.modify_username_string', compact($vars))); return $username_string; @@ -1401,22 +1503,54 @@ function get_username_string($mode, $user_id, $username, $username_colour = '', /** * Add an option to the quick-mod tools. * + * @param string $url The recepting URL for the quickmod actions. * @param string $option The language key for the value of the option. * @param string $lang_string The language string to use. */ -function phpbb_add_quickmod_option($option, $lang_string) +function phpbb_add_quickmod_option($url, $option, $lang_string) { - global $template, $user; + global $template, $user, $phpbb_path_helper; + $lang_string = $user->lang($lang_string); $template->assign_block_vars('quickmod', array( - 'VALUE' => $option, - 'TITLE' => $lang_string, + 'VALUE' => $option, + 'TITLE' => $lang_string, + 'LINK' => $phpbb_path_helper->append_url_params($url, array('action' => $option)), )); } /** -* @package phpBB3 +* Concatenate an array into a string list. +* +* @param array $items Array of items to concatenate +* @param object $user The phpBB $user object. +* +* @return string String list. Examples: "A"; "A and B"; "A, B, and C" */ +function phpbb_generate_string_list($items, $user) +{ + if (empty($items)) + { + return ''; + } + + $count = sizeof($items); + $last_item = array_pop($items); + $lang_key = 'STRING_LIST_MULTI'; + + if ($count == 1) + { + return $last_item; + } + else if ($count == 2) + { + $lang_key = 'STRING_LIST_SIMPLE'; + } + $list = implode($user->lang['COMMA_SEPARATOR'], $items); + + return $user->lang($lang_key, $list, $last_item); +} + class bitfield { var $data; diff --git a/phpBB/includes/functions_convert.php b/phpBB/includes/functions_convert.php index 1646c79161..3575768782 100644 --- a/phpBB/includes/functions_convert.php +++ b/phpBB/includes/functions_convert.php @@ -1,9 +1,13 @@ <?php /** * -* @package install -* @copyright (c) 2006 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -419,7 +423,7 @@ function remote_avatar_dims() function import_avatar_gallery($gallery_name = '', $subdirs_as_galleries = false) { - global $config, $convert, $phpbb_root_path, $user; + global $config, $convert, $user; $relative_path = empty($convert->convertor['source_path_absolute']); @@ -488,7 +492,7 @@ function import_avatar_gallery($gallery_name = '', $subdirs_as_galleries = false function import_attachment_files($category_name = '') { - global $config, $convert, $phpbb_root_path, $db, $user; + global $config, $convert, $db, $user; $sql = 'SELECT config_value AS upload_path FROM ' . CONFIG_TABLE . " @@ -586,7 +590,7 @@ function import_attachment($source, $use_target = false) return ''; } - global $convert, $phpbb_root_path, $config, $user; + global $convert, $config, $user; // check for trailing slash if (rtrim($convert->convertor['upload_path'], '/') === '') @@ -628,7 +632,7 @@ function import_rank($source, $use_target = false) return ''; } - global $convert, $phpbb_root_path, $config, $user; + global $convert, $user; if (!isset($convert->convertor['ranks_path'])) { @@ -646,7 +650,7 @@ function import_smiley($source, $use_target = false) return ''; } - global $convert, $phpbb_root_path, $config, $user; + global $convert, $user; // check for trailing slash if (rtrim($convert->convertor['smilies_path'], '/') === '') @@ -667,7 +671,7 @@ function import_avatar($source, $use_target = false, $user_id = false) return; } - global $convert, $phpbb_root_path, $config, $user; + global $convert, $config, $user; // check for trailing slash if (rtrim($convert->convertor['avatar_path'], '/') === '') @@ -680,7 +684,7 @@ function import_avatar($source, $use_target = false, $user_id = false) $use_target = $config['avatar_salt'] . '_' . $user_id . '.' . substr(strrchr($source, '.'), 1); } - $result = _import_check('avatar_path', $source, $use_target); + _import_check('avatar_path', $source, $use_target); return ((!empty($user_id)) ? $user_id : $use_target) . '.' . substr(strrchr($source, '.'), 1); } @@ -746,7 +750,7 @@ function get_smiley_dim($source, $axis) return $smiley_cache[$source][$axis]; } - global $convert, $phpbb_root_path, $config, $user; + global $convert, $user; $orig_source = $source; @@ -854,14 +858,12 @@ function get_upload_avatar_dim($source, $axis) return $cachedims[$axis]; } - $orig_source = $source; - if (substr($source, 0, 7) == 'upload:') { $source = substr($source, 7); } - global $convert, $phpbb_root_path, $config, $user; + global $convert, $user; if (!isset($convert->convertor['avatar_path'])) { @@ -903,7 +905,7 @@ function get_gallery_avatar_dim($source, $axis) return $avatar_cache[$source][$axis]; } - global $convert, $phpbb_root_path, $config, $user; + global $convert, $user; $orig_source = $source; @@ -962,7 +964,7 @@ function get_remote_avatar_dim($src, $axis) $protocol = (isset($url_info['scheme'])) ? $url_info['scheme'] : 'http'; if (empty($port)) { - switch(strtolower($protocol)) + switch (strtolower($protocol)) { case 'ftp': $port = 21; @@ -1003,8 +1005,8 @@ function get_remote_avatar_dim($src, $axis) { $bigger = ($remote_avatar_cache[$src][0] > $remote_avatar_cache[$src][1]) ? 0 : 1; $ratio = $default[$bigger] / $remote_avatar_cache[$src][$bigger]; - $remote_avatar_cache[$src][0] = (int)($remote_avatar_cache[$src][0] * $ratio); - $remote_avatar_cache[$src][1] = (int)($remote_avatar_cache[$src][1] * $ratio); + $remote_avatar_cache[$src][0] = (int) ($remote_avatar_cache[$src][0] * $ratio); + $remote_avatar_cache[$src][1] = (int) ($remote_avatar_cache[$src][1] * $ratio); } } @@ -1118,7 +1120,7 @@ function words_unique(&$words) */ function add_user_group($group_id, $user_id, $group_leader = false) { - global $convert, $phpbb_root_path, $config, $user, $db; + global $db; $sql = 'INSERT INTO ' . USER_GROUP_TABLE . ' ' . $db->sql_build_array('INSERT', array( 'group_id' => $group_id, @@ -1138,7 +1140,7 @@ function add_user_group($group_id, $user_id, $group_leader = false) */ function user_group_auth($group, $select_query, $use_src_db) { - global $convert, $phpbb_root_path, $config, $user, $db, $src_db, $same_db; + global $convert, $user, $db, $src_db, $same_db; if (!in_array($group, array('guests', 'registered', 'registered_coppa', 'global_moderators', 'administrators', 'bots'))) { @@ -1194,7 +1196,7 @@ function get_config() return $convert_config; } - global $src_db, $same_db, $phpbb_root_path, $config; + global $src_db, $same_db; global $convert; if ($convert->config_schema['table_format'] != 'file') @@ -1236,7 +1238,7 @@ function get_config() $filename = $convert->options['forum_path'] . '/' . $convert->config_schema['filename']; if (!file_exists($filename)) { - $convert->p_master->error($user->lang['FILE_NOT_FOUND'] . ': ' . $filename, __LINE__, __FILE__); + $convert->p_master->error($user->lang('FILE_NOT_FOUND', $filename), __LINE__, __FILE__); } if (isset($convert->config_schema['array_name'])) @@ -1273,7 +1275,7 @@ function get_config() */ function restore_config($schema) { - global $db, $config; + global $config; $convert_config = get_config(); @@ -1283,7 +1285,9 @@ function restore_config($schema) { $var = (empty($m[2]) || empty($convert_config[$m[2]])) ? "''" : "'" . addslashes($convert_config[$m[2]]) . "'"; $exec = '$config_value = ' . $m[1] . '(' . $var . ');'; + // @codingStandardsIgnoreStart eval($exec); + // @codingStandardsIgnoreEnd } else { @@ -1306,7 +1310,7 @@ function restore_config($schema) $config_value = truncate_string(utf8_htmlspecialchars($config_value), 255, 255, false); } - set_config($config_name, $config_value); + $config->set($config_name, $config_value); } } } @@ -1316,7 +1320,7 @@ function restore_config($schema) */ function update_folder_pm_count() { - global $db, $convert, $user; + global $db; $sql = 'SELECT user_id, folder_id, COUNT(msg_id) as num_messages FROM ' . PRIVMSGS_TO_TABLE . ' @@ -1375,7 +1379,7 @@ function extract_variables_from_file($_filename) function get_path($src_path, $src_url, $test_file) { - global $config, $phpbb_root_path, $phpEx; + global $phpbb_root_path, $phpEx; $board_config = get_config(); @@ -1486,7 +1490,7 @@ function compare_table($tables, $tablename, &$prefixes) */ function mass_auth($ug_type, $forum_id, $ug_id, $acl_list, $setting = ACL_NO) { - global $db, $convert, $user, $config; + global $db; static $acl_option_ids, $group_ids; if (($ug_type == 'group' || $ug_type == 'group_role') && is_string($ug_id)) @@ -1641,7 +1645,7 @@ function mass_auth($ug_type, $forum_id, $ug_id, $acl_list, $setting = ACL_NO) switch ($sql_type) { case 'insert': - switch ($db->sql_layer) + switch ($db->get_sql_layer()) { case 'mysql': case 'mysql4': @@ -1650,6 +1654,7 @@ function mass_auth($ug_type, $forum_id, $ug_id, $acl_list, $setting = ACL_NO) case 'mssql': case 'sqlite': + case 'sqlite3': case 'mssqlnative': $sql = implode(' UNION ALL ', preg_replace('#^(.*?)$#', 'SELECT \1', $sql_subary)); break; @@ -1961,9 +1966,9 @@ function update_dynamic_config() if ($row) { - set_config('newest_user_id', $row['user_id'], true); - set_config('newest_username', $row['username'], true); - set_config('newest_user_colour', $row['user_colour'], true); + $config->set('newest_user_id', $row['user_id'], false); + $config->set('newest_username', $row['username'], false); + $config->set('newest_user_colour', $row['user_colour'], false); } // Also do not reset record online user/date. There will be old data or the fresh data from the schema. @@ -1977,7 +1982,7 @@ function update_dynamic_config() $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); - set_config('num_posts', (int) $row['stat'], true); + $config->set('num_posts', (int) $row['stat'], false); $sql = 'SELECT COUNT(topic_id) AS stat FROM ' . TOPICS_TABLE . ' @@ -1986,7 +1991,7 @@ function update_dynamic_config() $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); - set_config('num_topics', (int) $row['stat'], true); + $config->set('num_topics', (int) $row['stat'], false); $sql = 'SELECT COUNT(user_id) AS stat FROM ' . USERS_TABLE . ' @@ -1995,20 +2000,20 @@ function update_dynamic_config() $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); - set_config('num_users', (int) $row['stat'], true); + $config->set('num_users', (int) $row['stat'], false); $sql = 'SELECT COUNT(attach_id) as stat FROM ' . ATTACHMENTS_TABLE . ' WHERE is_orphan = 0'; $result = $db->sql_query($sql); - set_config('num_files', (int) $db->sql_fetchfield('stat'), true); + $config->set('num_files', (int) $db->sql_fetchfield('stat'), false); $db->sql_freeresult($result); $sql = 'SELECT SUM(filesize) as stat FROM ' . ATTACHMENTS_TABLE . ' WHERE is_orphan = 0'; $result = $db->sql_query($sql); - set_config('upload_dir_size', (float) $db->sql_fetchfield('stat'), true); + $config->set('upload_dir_size', (float) $db->sql_fetchfield('stat'), false); $db->sql_freeresult($result); /** @@ -2032,12 +2037,12 @@ function update_dynamic_config() */ function update_topics_posted() { - global $db, $config; + global $db; - switch ($db->sql_layer) + switch ($db->get_sql_layer()) { case 'sqlite': - case 'firebird': + case 'sqlite3': $db->sql_query('DELETE FROM ' . TOPICS_POSTED_TABLE); break; @@ -2141,6 +2146,7 @@ function fix_empty_primary_groups() } $sql = 'SELECT user_id FROM ' . USER_GROUP_TABLE . ' WHERE group_id = ' . get_group_id('global_moderators'); + $result = $db->sql_query($sql); $user_ids = array(); while ($row = $db->sql_fetchrow($result)) @@ -2172,7 +2178,7 @@ function fix_empty_primary_groups() */ function remove_invalid_users() { - global $convert, $db, $phpEx, $phpbb_root_path; + global $db, $phpEx, $phpbb_root_path; // username_clean is UNIQUE $sql = 'SELECT user_id @@ -2289,7 +2295,7 @@ function convert_bbcode($message, $convert_size = true, $extended_bbcodes = fals $message = preg_replace('#\[size=([0-9]+)\](.*?)\[/size\]#i', '[size=\1]\2[/size]', $message); $message = preg_replace('#\[size=[0-9]{2,}\](.*?)\[/size\]#i', '[size=29]\1[/size]', $message); - for ($i = sizeof($size); $i; ) + for ($i = sizeof($size); $i;) { $i--; $message = str_replace('[size=' . $i . ']', '[size=' . $size[$i] . ']', $message); @@ -2308,7 +2314,10 @@ function convert_bbcode($message, $convert_size = true, $extended_bbcodes = fals function copy_file($src, $trg, $overwrite = false, $die_on_failure = true, $source_relative_path = true) { - global $convert, $phpbb_root_path, $config, $user, $db; + global $convert, $phpbb_root_path, $user, $phpbb_filesystem; + + /** @var \phpbb\filesystem\filesystem_interface $filesystem */ + $filesystem = $phpbb_filesystem; if (substr($trg, -1) == '/') { @@ -2341,7 +2350,7 @@ function copy_file($src, $trg, $overwrite = false, $die_on_failure = true, $sour } } - if (!phpbb_is_writable($path)) + if (!$filesystem->is_writable($path)) { @chmod($path, 0777); } @@ -2362,7 +2371,10 @@ function copy_file($src, $trg, $overwrite = false, $die_on_failure = true, $sour function copy_dir($src, $trg, $copy_subdirs = true, $overwrite = false, $die_on_failure = true, $source_relative_path = true) { - global $convert, $phpbb_root_path, $config, $user, $db; + global $convert, $phpbb_root_path, $config, $user, $phpbb_filesystem; + + /** @var \phpbb\filesystem\filesystem_interface $filesystem */ + $filesystem = $phpbb_filesystem; $dirlist = $filelist = $bad_dirs = array(); $src = path($src, $source_relative_path); @@ -2376,7 +2388,7 @@ function copy_dir($src, $trg, $copy_subdirs = true, $overwrite = false, $die_on_ @chmod($trg_path, 0777); } - if (!phpbb_is_writable($trg_path)) + if (!$filesystem->is_writable($trg_path)) { $bad_dirs[] = path($config['script_path']) . $trg; } @@ -2443,7 +2455,7 @@ function copy_dir($src, $trg, $copy_subdirs = true, $overwrite = false, $die_on_ @chmod($trg_path . $dir, 0777); } - if (!phpbb_is_writable($trg_path . $dir)) + if (!$filesystem->is_writable($trg_path . $dir)) { $bad_dirs[] = $trg . $dir; $bad_dirs[] = $trg_path . $dir; @@ -2471,7 +2483,7 @@ function copy_dir($src, $trg, $copy_subdirs = true, $overwrite = false, $die_on_ function relative_base($path, $is_relative = true, $line = false, $file = false) { - global $convert, $phpbb_root_path, $config, $user, $db; + global $convert, $user; if (!$is_relative) { diff --git a/phpBB/includes/functions_database_helper.php b/phpBB/includes/functions_database_helper.php index 923e542690..8f363d56f3 100644 --- a/phpBB/includes/functions_database_helper.php +++ b/phpBB/includes/functions_database_helper.php @@ -1,9 +1,13 @@ <?php /** * -* @package phpBB3 -* @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -22,14 +26,14 @@ if (!defined('IN_PHPBB')) * * The only supported table is bookmarks. * -* @param \phpbb\db\driver\driver $db Database object +* @param \phpbb\db\driver\driver_interface $db Database object * @param string $table Table on which to perform the update * @param string $column Column whose values to change * @param array $from_values An array of values that should be changed * @param int $to_value The new value * @return null */ -function phpbb_update_rows_avoiding_duplicates(\phpbb\db\driver\driver $db, $table, $column, $from_values, $to_value) +function phpbb_update_rows_avoiding_duplicates(\phpbb\db\driver\driver_interface $db, $table, $column, $from_values, $to_value) { $sql = "SELECT $column, user_id FROM $table @@ -107,14 +111,14 @@ function phpbb_update_rows_avoiding_duplicates(\phpbb\db\driver\driver $db, $tab * * The only supported table is topics_watch. * -* @param \phpbb\db\driver\driver $db Database object +* @param \phpbb\db\driver\driver_interface $db Database object * @param string $table Table on which to perform the update * @param string $column Column whose values to change * @param array $from_values An array of values that should be changed * @param int $to_value The new value * @return null */ -function phpbb_update_rows_avoiding_duplicates_notify_status(\phpbb\db\driver\driver $db, $table, $column, $from_values, $to_value) +function phpbb_update_rows_avoiding_duplicates_notify_status(\phpbb\db\driver\driver_interface $db, $table, $column, $from_values, $to_value) { $sql = "SELECT $column, user_id, notify_status FROM $table diff --git a/phpBB/includes/functions_display.php b/phpBB/includes/functions_display.php index e663ac90c5..afda10ebee 100644 --- a/phpBB/includes/functions_display.php +++ b/phpBB/includes/functions_display.php @@ -1,9 +1,13 @@ <?php /** * -* @package phpBB3 -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -26,10 +30,9 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod $forum_rows = $subforums = $forum_ids = $forum_ids_moderator = $forum_moderators = $active_forum_ary = array(); $parent_id = $visible_forums = 0; - $sql_from = ''; // Mark forums read? - $mark_read = request_var('mark', ''); + $mark_read = $request->variable('mark', ''); if ($mark_read == 'all') { @@ -57,9 +60,9 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod $redirect = build_url(array('mark', 'hash', 'mark_time')); meta_refresh(3, $redirect); - if (check_link_hash(request_var('hash', ''), 'global')) + if (check_link_hash($request->variable('hash', ''), 'global')) { - markread('all', false, false, request_var('mark_time', 0)); + markread('all', false, false, $request->variable('mark_time', 0)); if ($request->is_ajax()) { @@ -138,7 +141,7 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod * * @event core.display_forums_modify_sql * @var array sql_ary The SQL array to get the data of the forums - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('sql_ary'); extract($phpbb_dispatcher->trigger_event('core.display_forums_modify_sql', compact($vars))); @@ -146,9 +149,10 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod $sql = $db->sql_build_query('SELECT', $sql_ary); $result = $db->sql_query($sql); - $forum_tracking_info = array(); + $forum_tracking_info = $valid_categories = array(); $branch_root_id = $root_data['forum_id']; + /* @var $phpbb_content_visibility \phpbb\content_visibility */ $phpbb_content_visibility = $phpbb_container->get('content.visibility'); while ($row = $db->sql_fetchrow($result)) @@ -161,7 +165,7 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod * @event core.display_forums_modify_row * @var int branch_root_id Last top-level forum * @var array row The data of the forum - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('branch_root_id', 'row'); extract($phpbb_dispatcher->trigger_event('core.display_forums_modify_row', compact($vars))); @@ -246,6 +250,12 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod } } + // Fill list of categories with forums + if (isset($forum_rows[$row['parent_id']])) + { + $valid_categories[$row['parent_id']] = true; + } + // if ($row['parent_id'] == $root_data['forum_id'] || $row['parent_id'] == $branch_root_id) { @@ -263,6 +273,7 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod $branch_root_id = $forum_id; } $forum_rows[$parent_id]['forum_id_last_post'] = $row['forum_id']; + $forum_rows[$parent_id]['forum_password_last_post'] = $row['forum_password']; $forum_rows[$parent_id]['orig_forum_last_post_time'] = $row['forum_last_post_time']; } else if ($row['forum_type'] != FORUM_CAT) @@ -304,6 +315,7 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod $forum_rows[$parent_id]['forum_last_poster_name'] = $row['forum_last_poster_name']; $forum_rows[$parent_id]['forum_last_poster_colour'] = $row['forum_last_poster_colour']; $forum_rows[$parent_id]['forum_id_last_post'] = $forum_id; + $forum_rows[$parent_id]['forum_password_last_post'] = $row['forum_password']; } } @@ -318,7 +330,7 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod * @var int branch_root_id Current top-level forum * @var int parent_id Current parent forum * @var array row The data of the forum - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('forum_rows', 'subforums', 'branch_root_id', 'parent_id', 'row'); extract($phpbb_dispatcher->trigger_event('core.display_forums_modify_forum_rows', compact($vars))); @@ -329,10 +341,10 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod if ($mark_read == 'forums') { $redirect = build_url(array('mark', 'hash', 'mark_time')); - $token = request_var('hash', ''); + $token = $request->variable('hash', ''); if (check_link_hash($token, 'global')) { - markread('topics', $forum_ids, false, request_var('mark_time', 0)); + markread('topics', $forum_ids, false, $request->variable('mark_time', 0)); $message = sprintf($user->lang['RETURN_FORUM'], '<a href="' . $redirect . '">', '</a>'); meta_refresh(3, $redirect); @@ -371,14 +383,42 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod get_moderators($forum_moderators, $forum_ids_moderator); } + /** + * Event to perform additional actions before the forum list is being generated + * + * @event core.display_forums_before + * @var array active_forum_ary Array with forum data to display active topics + * @var bool display_moderators Flag indicating if we display forum moderators + * @var array forum_moderators Array with forum moderators list + * @var array forum_rows Data array of all forums we display + * @var bool return_moderators Flag indicating if moderators list should be returned + * @var array root_data Array with the root forum data + * @since 3.1.4-RC1 + */ + $vars = array( + 'active_forum_ary', + 'display_moderators', + 'forum_moderators', + 'forum_rows', + 'return_moderators', + 'root_data', + ); + extract($phpbb_dispatcher->trigger_event('core.display_forums_before', compact($vars))); + // Used to tell whatever we have to create a dummy category or not. $last_catless = true; foreach ($forum_rows as $row) { - // Empty category + // Category if ($row['parent_id'] == $root_data['forum_id'] && $row['forum_type'] == FORUM_CAT) { - $template->assign_block_vars('forumrow', array( + // Do not display categories without any forums to display + if (!isset($valid_categories[$row['forum_id']])) + { + continue; + } + + $cat_row = array( 'S_IS_CAT' => true, 'FORUM_ID' => $row['forum_id'], 'FORUM_NAME' => $row['forum_name'], @@ -387,8 +427,31 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod 'FORUM_FOLDER_IMG_SRC' => '', 'FORUM_IMAGE' => ($row['forum_image']) ? '<img src="' . $phpbb_root_path . $row['forum_image'] . '" alt="' . $user->lang['FORUM_CAT'] . '" />' : '', 'FORUM_IMAGE_SRC' => ($row['forum_image']) ? $phpbb_root_path . $row['forum_image'] : '', - 'U_VIEWFORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $row['forum_id'])) + 'U_VIEWFORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $row['forum_id']), + ); + + /** + * Modify the template data block of the 'category' + * + * This event is triggered once per 'category' + * + * @event core.display_forums_modify_category_template_vars + * @var array cat_row Template data of the 'category' + * @var bool last_catless The flag indicating whether the last forum had a parent category + * @var array root_data Array with the root forum data + * @var array row The data of the 'category' + * @since 3.1.0-RC4 + * @change 3.1.7-RC1 Removed undefined catless variable + */ + $vars = array( + 'cat_row', + 'last_catless', + 'root_data', + 'row', ); + extract($phpbb_dispatcher->trigger_event('core.display_forums_modify_category_template_vars', compact($vars))); + + $template->assign_block_vars('forumrow', $cat_row); continue; } @@ -441,7 +504,7 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod } } - $l_subforums = (sizeof($subforums[$forum_id]) == 1) ? $user->lang['SUBFORUM'] . ': ' : $user->lang['SUBFORUMS'] . ': '; + $l_subforums = (sizeof($subforums[$forum_id]) == 1) ? $user->lang['SUBFORUM'] : $user->lang['SUBFORUMS']; $folder_image = ($forum_unread) ? 'forum_unread_subforum' : 'forum_read_subforum'; } else @@ -472,8 +535,15 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod // Create last post link information, if appropriate if ($row['forum_last_post_id']) { - $last_post_subject = $row['forum_last_post_subject']; - $last_post_subject_truncated = truncate_string(censor_text($last_post_subject), 30, 255, false, $user->lang['ELLIPSIS']); + if ($row['forum_password_last_post'] === '' && $auth->acl_get('f_read', $row['forum_id_last_post'])) + { + $last_post_subject = censor_text($row['forum_last_post_subject']); + $last_post_subject_truncated = truncate_string($last_post_subject, 30, 255, false, $user->lang['ELLIPSIS']); + } + else + { + $last_post_subject = $last_post_subject_truncated = ''; + } $last_post_time = $user->format_date($row['forum_last_post_time']); $last_post_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $row['forum_id_last_post'] . '&p=' . $row['forum_last_post_id']) . '#p' . $row['forum_last_post_id']; } @@ -493,10 +563,15 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod $l_post_click_count = ($row['forum_type'] == FORUM_LINK) ? 'CLICKS' : 'POSTS'; $post_click_count = ($row['forum_type'] != FORUM_LINK || $row['forum_flags'] & FORUM_FLAG_LINK_TRACK) ? $row['forum_posts'] : ''; - $s_subforums_list = array(); + $s_subforums_list = $subforums_row = array(); foreach ($subforums_list as $subforum) { $s_subforums_list[] = '<a href="' . $subforum['link'] . '" class="subforum ' . (($subforum['unread']) ? 'unread' : 'read') . '" title="' . (($subforum['unread']) ? $user->lang['UNREAD_POSTS'] : $user->lang['NO_UNREAD_POSTS']) . '">' . $subforum['name'] . '</a>'; + $subforums_row[] = array( + 'U_SUBFORUM' => $subforum['link'], + 'SUBFORUM_NAME' => $subforum['name'], + 'S_UNREAD' => $subforum['unread'], + ); } $s_subforums_list = (string) implode($user->lang['COMMA_SEPARATOR'], $s_subforums_list); $catless = ($row['parent_id'] == $root_data['forum_id']) ? true : false; @@ -528,7 +603,7 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod 'S_LOCKED_FORUM' => ($row['forum_status'] == ITEM_LOCKED) ? true : false, 'S_LIST_SUBFORUMS' => ($row['display_subforum_list']) ? true : false, 'S_SUBFORUMS' => (sizeof($subforums_list)) ? true : false, - 'S_DISPLAY_SUBJECT' => ($last_post_subject && $config['display_last_subject'] && !$row['forum_password'] && $auth->acl_get('f_read', $row['forum_id'])) ? true : false, + 'S_DISPLAY_SUBJECT' => ($last_post_subject !== '' && $config['display_last_subject']) ? true : false, 'S_FEED_ENABLED' => ($config['feed_forum'] && !phpbb_optionget(FORUM_OPTION_FEED_EXCLUDE, $row['forum_options']) && $row['forum_type'] == FORUM_POST) ? true : false, 'FORUM_ID' => $row['forum_id'], @@ -541,8 +616,8 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod 'FORUM_FOLDER_IMG_ALT' => isset($user->lang[$folder_alt]) ? $user->lang[$folder_alt] : '', 'FORUM_IMAGE' => ($row['forum_image']) ? '<img src="' . $phpbb_root_path . $row['forum_image'] . '" alt="' . $user->lang[$folder_alt] . '" />' : '', 'FORUM_IMAGE_SRC' => ($row['forum_image']) ? $phpbb_root_path . $row['forum_image'] : '', - 'LAST_POST_SUBJECT' => (!$row['forum_password'] && $auth->acl_get('f_read', $row['forum_id'])) ? censor_text($last_post_subject) : "", - 'LAST_POST_SUBJECT_TRUNCATED' => (!$row['forum_password'] && $auth->acl_get('f_read', $row['forum_id'])) ? $last_post_subject_truncated : "", + 'LAST_POST_SUBJECT' => $last_post_subject, + 'LAST_POST_SUBJECT_TRUNCATED' => $last_post_subject_truncated, 'LAST_POST_TIME' => $last_post_time, 'LAST_POSTER' => get_username_string('username', $row['forum_last_poster_id'], $row['forum_last_poster_name'], $row['forum_last_poster_colour']), 'LAST_POSTER_COLOUR' => get_username_string('colour', $row['forum_last_poster_id'], $row['forum_last_poster_name'], $row['forum_last_poster_colour']), @@ -568,22 +643,41 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod * @event core.display_forums_modify_template_vars * @var array forum_row Template data of the forum * @var array row The data of the forum - * @since 3.1-A1 + * @var array subforums_row Template data of subforums + * @since 3.1.0-a1 + * @change 3.1.0-b5 Added var subforums_row */ - $vars = array('forum_row', 'row'); + $vars = array('forum_row', 'row', 'subforums_row'); extract($phpbb_dispatcher->trigger_event('core.display_forums_modify_template_vars', compact($vars))); $template->assign_block_vars('forumrow', $forum_row); // Assign subforums loop for style authors - foreach ($subforums_list as $subforum) - { - $template->assign_block_vars('forumrow.subforum', array( - 'U_SUBFORUM' => $subforum['link'], - 'SUBFORUM_NAME' => $subforum['name'], - 'S_UNREAD' => $subforum['unread']) - ); - } + $template->assign_block_vars_array('forumrow.subforum', $subforums_row); + + /** + * Modify and/or assign additional template data for the forum + * after forumrow loop has been assigned. This can be used + * to create additional forumrow subloops in extensions. + * + * This event is triggered once per forum + * + * @event core.display_forums_add_template_data + * @var array forum_row Template data of the forum + * @var array row The data of the forum + * @var array subforums_list The data of subforums + * @var array subforums_row Template data of subforums + * @var bool catless The flag indicating whether a forum has a parent category + * @since 3.1.0-b5 + */ + $vars = array( + 'forum_row', + 'row', + 'subforums_list', + 'subforums_row', + 'catless', + ); + extract($phpbb_dispatcher->trigger_event('core.display_forums_add_template_data', compact($vars))); $last_catless = $catless; } @@ -594,9 +688,31 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod 'L_SUBFORUM' => ($visible_forums == 1) ? $user->lang['SUBFORUM'] : $user->lang['SUBFORUMS'], 'LAST_POST_IMG' => $user->img('icon_topic_latest', 'VIEW_LATEST_POST'), 'UNAPPROVED_IMG' => $user->img('icon_topic_unapproved', 'TOPICS_UNAPPROVED'), - 'UNAPPROVED_POST_IMG' => $user->img('icon_topic_unapproved', 'POSTS_UNAPPROVED'), + 'UNAPPROVED_POST_IMG' => $user->img('icon_topic_unapproved', 'POSTS_UNAPPROVED_FORUM'), )); + /** + * Event to perform additional actions after the forum list has been generated + * + * @event core.display_forums_after + * @var array active_forum_ary Array with forum data to display active topics + * @var bool display_moderators Flag indicating if we display forum moderators + * @var array forum_moderators Array with forum moderators list + * @var array forum_rows Data array of all forums we display + * @var bool return_moderators Flag indicating if moderators list should be returned + * @var array root_data Array with the root forum data + * @since 3.1.0-RC5 + */ + $vars = array( + 'active_forum_ary', + 'display_moderators', + 'forum_moderators', + 'forum_rows', + 'return_moderators', + 'root_data', + ); + extract($phpbb_dispatcher->trigger_event('core.display_forums_after', compact($vars))); + if ($return_moderators) { return array($active_forum_ary, $forum_moderators); @@ -615,7 +731,7 @@ function generate_forum_rules(&$forum_data) return; } - global $template, $phpbb_root_path, $phpEx; + global $template; if ($forum_data['forum_rules']) { @@ -633,18 +749,22 @@ function generate_forum_rules(&$forum_data) * Create forum navigation links for given forum, create parent * list if currently null, assign basic forum info to template */ -function generate_forum_nav(&$forum_data) +function generate_forum_nav(&$forum_data_ary) { - global $db, $user, $template, $auth, $config; - global $phpEx, $phpbb_root_path; + global $template, $auth, $config; + global $phpEx, $phpbb_root_path, $phpbb_dispatcher; - if (!$auth->acl_get('f_list', $forum_data['forum_id'])) + if (!$auth->acl_get('f_list', $forum_data_ary['forum_id'])) { return; } + $navlinks_parents = $forum_template_data = array(); + // Get forum parents - $forum_parents = get_forum_parents($forum_data); + $forum_parents = get_forum_parents($forum_data_ary); + + $microdata_attr = 'data-forum-id'; // Build navigation links if (!empty($forum_parents)) @@ -659,33 +779,62 @@ function generate_forum_nav(&$forum_data) continue; } - $template->assign_block_vars('navlinks', array( + $navlinks_parents[] = array( 'S_IS_CAT' => ($parent_type == FORUM_CAT) ? true : false, 'S_IS_LINK' => ($parent_type == FORUM_LINK) ? true : false, 'S_IS_POST' => ($parent_type == FORUM_POST) ? true : false, 'FORUM_NAME' => $parent_name, 'FORUM_ID' => $parent_forum_id, - 'U_VIEW_FORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $parent_forum_id)) + 'MICRODATA' => $microdata_attr . '="' . $parent_forum_id . '"', + 'U_VIEW_FORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $parent_forum_id), ); } } - $template->assign_block_vars('navlinks', array( - 'S_IS_CAT' => ($forum_data['forum_type'] == FORUM_CAT) ? true : false, - 'S_IS_LINK' => ($forum_data['forum_type'] == FORUM_LINK) ? true : false, - 'S_IS_POST' => ($forum_data['forum_type'] == FORUM_POST) ? true : false, - 'FORUM_NAME' => $forum_data['forum_name'], - 'FORUM_ID' => $forum_data['forum_id'], - 'U_VIEW_FORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_data['forum_id'])) + $navlinks = array( + 'S_IS_CAT' => ($forum_data_ary['forum_type'] == FORUM_CAT) ? true : false, + 'S_IS_LINK' => ($forum_data_ary['forum_type'] == FORUM_LINK) ? true : false, + 'S_IS_POST' => ($forum_data_ary['forum_type'] == FORUM_POST) ? true : false, + 'FORUM_NAME' => $forum_data_ary['forum_name'], + 'FORUM_ID' => $forum_data_ary['forum_id'], + 'MICRODATA' => $microdata_attr . '="' . $forum_data_ary['forum_id'] . '"', + 'U_VIEW_FORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_data_ary['forum_id']), ); - $template->assign_vars(array( - 'FORUM_ID' => $forum_data['forum_id'], - 'FORUM_NAME' => $forum_data['forum_name'], - 'FORUM_DESC' => generate_text_for_display($forum_data['forum_desc'], $forum_data['forum_desc_uid'], $forum_data['forum_desc_bitfield'], $forum_data['forum_desc_options']), + $forum_template_data = array( + 'FORUM_ID' => $forum_data_ary['forum_id'], + 'FORUM_NAME' => $forum_data_ary['forum_name'], + 'FORUM_DESC' => generate_text_for_display($forum_data_ary['forum_desc'], $forum_data_ary['forum_desc_uid'], $forum_data_ary['forum_desc_bitfield'], $forum_data_ary['forum_desc_options']), - 'S_ENABLE_FEEDS_FORUM' => ($config['feed_forum'] && $forum_data['forum_type'] == FORUM_POST && !phpbb_optionget(FORUM_OPTION_FEED_EXCLUDE, $forum_data['forum_options'])) ? true : false, - )); + 'S_ENABLE_FEEDS_FORUM' => ($config['feed_forum'] && $forum_data_ary['forum_type'] == FORUM_POST && !phpbb_optionget(FORUM_OPTION_FEED_EXCLUDE, $forum_data_ary['forum_options'])) ? true : false, + ); + + $forum_data = $forum_data_ary; + /** + * Event to modify the navlinks text + * + * @event core.generate_forum_nav + * @var array forum_data Array with the forum data + * @var array forum_template_data Array with generic forum template data + * @var string microdata_attr The microdata attribute + * @var array navlinks_parents Array with the forum parents navlinks data + * @var array navlinks Array with the forum navlinks data + * @since 3.1.5-RC1 + */ + $vars = array( + 'forum_data', + 'forum_template_data', + 'microdata_attr', + 'navlinks_parents', + 'navlinks', + ); + extract($phpbb_dispatcher->trigger_event('core.generate_forum_nav', compact($vars))); + $forum_data_ary = $forum_data; + unset($forum_data); + + $template->assign_block_vars_array('navlinks', $navlinks_parents); + $template->assign_block_vars('navlinks', $navlinks); + $template->assign_vars($forum_template_data); return; } @@ -737,7 +886,8 @@ function get_forum_parents(&$forum_data) */ function get_moderators(&$forum_moderators, $forum_id = false) { - global $config, $template, $db, $phpbb_root_path, $phpEx, $user, $auth; + global $db, $phpbb_root_path, $phpEx, $user, $auth; + global $phpbb_container; $forum_id_ary = array(); @@ -773,6 +923,9 @@ function get_moderators(&$forum_moderators, $forum_id = false) 'WHERE' => 'm.display_on_index = 1', ); + /** @var \phpbb\group\helper $group_helper */ + $group_helper = $phpbb_container->get('group_helper'); + // We query every forum here because for caching we should not have any parameter. $sql = $db->sql_build_query('SELECT', $sql_array); $result = $db->sql_query($sql, 3600); @@ -792,7 +945,7 @@ function get_moderators(&$forum_moderators, $forum_id = false) } else { - $group_name = (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']); + $group_name = $group_helper->get_name($row['group_name']); if ($user->data['user_id'] != ANONYMOUS && !$auth->acl_get('u_viewprofile')) { @@ -849,8 +1002,6 @@ function topic_status(&$topic_row, $replies, $unread_topic, &$folder_img, &$fold { global $user, $config; - $folder = $folder_new = ''; - if ($topic_row['topic_status'] == ITEM_MOVED) { $topic_type = $user->lang['VIEW_TOPIC_MOVED']; @@ -900,7 +1051,6 @@ function topic_status(&$topic_row, $replies, $unread_topic, &$folder_img, &$fold $folder_new .= '_locked'; } - $folder_img = ($unread_topic) ? $folder_new : $folder; $folder_alt = ($unread_topic) ? 'UNREAD_POSTS' : (($topic_row['topic_status'] == ITEM_LOCKED) ? 'TOPIC_LOCKED' : 'NO_UNREAD_POSTS'); @@ -962,6 +1112,7 @@ function display_custom_bbcodes() 'BBCODE_NAME' => "'[{$row['bbcode_tag']}]', '[/" . str_replace('=', '', $row['bbcode_tag']) . "]'", 'BBCODE_ID' => $num_predefined_bbcodes + ($i * 2), 'BBCODE_TAG' => $row['bbcode_tag'], + 'BBCODE_TAG_CLEAN' => str_replace('=', '-', $row['bbcode_tag']), 'BBCODE_HELPLINE' => $row['bbcode_helpline'], 'A_BBCODE_HELPLINE' => str_replace(array('&', '"', "'", '<', '>'), array('&', '"', "\'", '<', '>'), $row['bbcode_helpline']), ); @@ -974,7 +1125,7 @@ function display_custom_bbcodes() * @event core.display_custom_bbcodes_modify_row * @var array custom_tags Template data of the bbcode * @var array row The data of the bbcode - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('custom_tags', 'row'); extract($phpbb_dispatcher->trigger_event('core.display_custom_bbcodes_modify_row', compact($vars))); @@ -989,52 +1140,34 @@ function display_custom_bbcodes() * Display custom bbcodes * * @event core.display_custom_bbcodes - * @since 3.1-A1 + * @since 3.1.0-a1 */ $phpbb_dispatcher->dispatch('core.display_custom_bbcodes'); } /** * Display reasons +* +* @deprecated 3.2.0-dev */ function display_reasons($reason_id = 0) { - global $db, $user, $template; - - $sql = 'SELECT * - FROM ' . REPORTS_REASONS_TABLE . ' - ORDER BY reason_order ASC'; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - // If the reason is defined within the language file, we will use the localized version, else just use the database entry... - if (isset($user->lang['report_reasons']['TITLE'][strtoupper($row['reason_title'])]) && isset($user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])])) - { - $row['reason_description'] = $user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])]; - $row['reason_title'] = $user->lang['report_reasons']['TITLE'][strtoupper($row['reason_title'])]; - } + global $phpbb_container; - $template->assign_block_vars('reason', array( - 'ID' => $row['reason_id'], - 'TITLE' => $row['reason_title'], - 'DESCRIPTION' => $row['reason_description'], - 'S_SELECTED' => ($row['reason_id'] == $reason_id) ? true : false) - ); - } - $db->sql_freeresult($result); + $phpbb_container->get('phpbb.report.report_reason_list_provider')->display_reasons($reason_id); } /** * Display user activity (action forum/topic) */ -function display_user_activity(&$userdata) +function display_user_activity(&$userdata_ary) { global $auth, $template, $db, $user; - global $phpbb_root_path, $phpEx, $phpbb_container; + global $phpbb_root_path, $phpEx; + global $phpbb_container, $phpbb_dispatcher; // Do not display user activity for users having more than 5000 posts... - if ($userdata['user_posts'] > 5000) + if ($userdata_ary['user_posts'] > 5000) { return; } @@ -1055,12 +1188,13 @@ function display_user_activity(&$userdata) $active_f_row = $active_t_row = array(); if (!empty($forum_ary)) { + /* @var $phpbb_content_visibility \phpbb\content_visibility */ $phpbb_content_visibility = $phpbb_container->get('content.visibility'); // Obtain active forum $sql = 'SELECT forum_id, COUNT(post_id) AS num_posts FROM ' . POSTS_TABLE . ' - WHERE poster_id = ' . $userdata['user_id'] . ' + WHERE poster_id = ' . $userdata_ary['user_id'] . ' AND post_postcount = 1 AND ' . $phpbb_content_visibility->get_forums_visibility_sql('post', $forum_ary) . ' GROUP BY forum_id @@ -1082,7 +1216,7 @@ function display_user_activity(&$userdata) // Obtain active topic $sql = 'SELECT topic_id, COUNT(post_id) AS num_posts FROM ' . POSTS_TABLE . ' - WHERE poster_id = ' . $userdata['user_id'] . ' + WHERE poster_id = ' . $userdata_ary['user_id'] . ' AND post_postcount = 1 AND ' . $phpbb_content_visibility->get_forums_visibility_sql('post', $forum_ary) . ' GROUP BY topic_id @@ -1102,8 +1236,23 @@ function display_user_activity(&$userdata) } } - $userdata['active_t_row'] = $active_t_row; - $userdata['active_f_row'] = $active_f_row; + $userdata = $userdata_ary; + /** + * Alter list of forums and topics to display as active + * + * @event core.display_user_activity_modify_actives + * @var array userdata User's data + * @var array active_f_row List of active forums + * @var array active_t_row List of active posts + * @since 3.1.0-RC3 + */ + $vars = array('userdata', 'active_f_row', 'active_t_row'); + extract($phpbb_dispatcher->trigger_event('core.display_user_activity_modify_actives', compact($vars))); + $userdata_ary = $userdata; + unset($userdata); + + $userdata_ary['active_t_row'] = $active_t_row; + $userdata_ary['active_f_row'] = $active_f_row; $active_f_name = $active_f_id = $active_f_count = $active_f_pct = ''; if (!empty($active_f_row['num_posts'])) @@ -1111,7 +1260,7 @@ function display_user_activity(&$userdata) $active_f_name = $active_f_row['forum_name']; $active_f_id = $active_f_row['forum_id']; $active_f_count = $active_f_row['num_posts']; - $active_f_pct = ($userdata['user_posts']) ? ($active_f_count / $userdata['user_posts']) * 100 : 0; + $active_f_pct = ($userdata_ary['user_posts']) ? ($active_f_count / $userdata_ary['user_posts']) * 100 : 0; } $active_t_name = $active_t_id = $active_t_count = $active_t_pct = ''; @@ -1120,10 +1269,10 @@ function display_user_activity(&$userdata) $active_t_name = $active_t_row['topic_title']; $active_t_id = $active_t_row['topic_id']; $active_t_count = $active_t_row['num_posts']; - $active_t_pct = ($userdata['user_posts']) ? ($active_t_count / $userdata['user_posts']) * 100 : 0; + $active_t_pct = ($userdata_ary['user_posts']) ? ($active_t_count / $userdata_ary['user_posts']) * 100 : 0; } - $l_active_pct = ($userdata['user_id'] != ANONYMOUS && $userdata['user_id'] == $user->data['user_id']) ? $user->lang['POST_PCT_ACTIVE_OWN'] : $user->lang['POST_PCT_ACTIVE']; + $l_active_pct = ($userdata_ary['user_id'] != ANONYMOUS && $userdata_ary['user_id'] == $user->data['user_id']) ? $user->lang['POST_PCT_ACTIVE_OWN'] : $user->lang['POST_PCT_ACTIVE']; $template->assign_vars(array( 'ACTIVE_FORUM' => $active_f_name, @@ -1143,7 +1292,7 @@ function display_user_activity(&$userdata) */ function watch_topic_forum($mode, &$s_watching, $user_id, $forum_id, $topic_id, $notify_status = 'unset', $start = 0, $item_title = '') { - global $template, $db, $user, $phpEx, $start, $phpbb_root_path; + global $db, $user, $phpEx, $start, $phpbb_root_path; global $request; $table_sql = ($mode == 'forum') ? FORUMS_WATCH_TABLE : TOPICS_WATCH_TABLE; @@ -1153,7 +1302,7 @@ function watch_topic_forum($mode, &$s_watching, $user_id, $forum_id, $topic_id, $u_url .= ($mode == 'forum') ? '&f' : '&f=' . $forum_id . '&t'; $is_watching = 0; - // Is user watching this thread? + // Is user watching this topic? if ($user_id != ANONYMOUS) { $can_watch = true; @@ -1174,8 +1323,8 @@ function watch_topic_forum($mode, &$s_watching, $user_id, $forum_id, $topic_id, { if (isset($_GET['unwatch'])) { - $uid = request_var('uid', 0); - $token = request_var('hash', ''); + $uid = $request->variable('uid', 0); + $token = $request->variable('hash', ''); if ($token && check_link_hash($token, "{$mode}_$match_id") || confirm_box(true)) { @@ -1248,8 +1397,8 @@ function watch_topic_forum($mode, &$s_watching, $user_id, $forum_id, $topic_id, { if (isset($_GET['watch'])) { - $uid = request_var('uid', 0); - $token = request_var('hash', ''); + $uid = $request->variable('uid', 0); + $token = $request->variable('hash', ''); if ($token && check_link_hash($token, "{$mode}_$match_id") || confirm_box(true)) { @@ -1333,17 +1482,34 @@ function watch_topic_forum($mode, &$s_watching, $user_id, $forum_id, $topic_id, /** * Get user rank title and image * -* @param int $user_rank the current stored users rank id +* @param array $user_data the current stored users data * @param int $user_posts the users number of posts -* @param string &$rank_title the rank title will be stored here after execution -* @param string &$rank_img the rank image as full img tag is stored here after execution -* @param string &$rank_img_src the rank image source is stored here after execution +* +* @return array An associative array containing the rank title (title), the rank image as full img tag (img) and the rank image source (img_src) * * Note: since we do not want to break backwards-compatibility, this function will only properly assign ranks to guests if you call it for them with user_posts == false */ -function get_user_rank($user_rank, $user_posts, &$rank_title, &$rank_img, &$rank_img_src) +function phpbb_get_user_rank($user_data, $user_posts) { - global $ranks, $config, $phpbb_root_path; + global $ranks, $config, $phpbb_root_path, $phpbb_path_helper, $phpbb_dispatcher; + + $user_rank_data = array( + 'title' => null, + 'img' => null, + 'img_src' => null, + ); + + /** + * Preparing a user's rank before displaying + * + * @event core.modify_user_rank + * @var array user_data Array with user's data + * @var int user_posts User_posts to change + * @since 3.1.0-RC4 + */ + + $vars = array('user_data', 'user_posts'); + extract($phpbb_dispatcher->trigger_event('core.modify_user_rank', compact($vars))); if (empty($ranks)) { @@ -1351,11 +1517,14 @@ function get_user_rank($user_rank, $user_posts, &$rank_title, &$rank_img, &$rank $ranks = $cache->obtain_ranks(); } - if (!empty($user_rank)) + if (!empty($user_data['user_rank'])) { - $rank_title = (isset($ranks['special'][$user_rank]['rank_title'])) ? $ranks['special'][$user_rank]['rank_title'] : ''; - $rank_img = (!empty($ranks['special'][$user_rank]['rank_image'])) ? '<img src="' . $phpbb_root_path . $config['ranks_path'] . '/' . $ranks['special'][$user_rank]['rank_image'] . '" alt="' . $ranks['special'][$user_rank]['rank_title'] . '" title="' . $ranks['special'][$user_rank]['rank_title'] . '" />' : ''; - $rank_img_src = (!empty($ranks['special'][$user_rank]['rank_image'])) ? $phpbb_root_path . $config['ranks_path'] . '/' . $ranks['special'][$user_rank]['rank_image'] : ''; + + $user_rank_data['title'] = (isset($ranks['special'][$user_data['user_rank']]['rank_title'])) ? $ranks['special'][$user_data['user_rank']]['rank_title'] : ''; + + $user_rank_data['img_src'] = (!empty($ranks['special'][$user_data['user_rank']]['rank_image'])) ? $phpbb_path_helper->update_web_root_path($phpbb_root_path . $config['ranks_path'] . '/' . $ranks['special'][$user_data['user_rank']]['rank_image']) : ''; + + $user_rank_data['img'] = (!empty($ranks['special'][$user_data['user_rank']]['rank_image'])) ? '<img src="' . $user_rank_data['img_src'] . '" alt="' . $ranks['special'][$user_data['user_rank']]['rank_title'] . '" title="' . $ranks['special'][$user_data['user_rank']]['rank_title'] . '" />' : ''; } else if ($user_posts !== false) { @@ -1365,136 +1534,176 @@ function get_user_rank($user_rank, $user_posts, &$rank_title, &$rank_img, &$rank { if ($user_posts >= $rank['rank_min']) { - $rank_title = $rank['rank_title']; - $rank_img = (!empty($rank['rank_image'])) ? '<img src="' . $phpbb_root_path . $config['ranks_path'] . '/' . $rank['rank_image'] . '" alt="' . $rank['rank_title'] . '" title="' . $rank['rank_title'] . '" />' : ''; - $rank_img_src = (!empty($rank['rank_image'])) ? $phpbb_root_path . $config['ranks_path'] . '/' . $rank['rank_image'] : ''; + $user_rank_data['title'] = $rank['rank_title']; + $user_rank_data['img_src'] = (!empty($rank['rank_image'])) ? $phpbb_path_helper->update_web_root_path($phpbb_root_path . $config['ranks_path'] . '/' . $rank['rank_image']) : ''; + $user_rank_data['img'] = (!empty($rank['rank_image'])) ? '<img src="' . $user_rank_data['img_src'] . '" alt="' . $rank['rank_title'] . '" title="' . $rank['rank_title'] . '" />' : ''; break; } } } } -} -/** -* Get user avatar -* -* @param array $user_row Row from the users table -* @param string $alt Optional language string for alt tag within image, can be a language key or text -* @param bool $ignore_config Ignores the config-setting, to be still able to view the avatar in the UCP -* -* @return string Avatar html -*/ -function phpbb_get_user_avatar($user_row, $alt = 'USER_AVATAR', $ignore_config = false) -{ - $row = \phpbb\avatar\manager::clean_row($user_row, 'user'); - return phpbb_get_avatar($row, $alt, $ignore_config); + return $user_rank_data; } /** -* Get group avatar -* -* @param array $group_row Row from the groups table -* @param string $alt Optional language string for alt tag within image, can be a language key or text -* @param bool $ignore_config Ignores the config-setting, to be still able to view the avatar in the UCP -* -* @return string Avatar html +* Prepare profile data */ -function phpbb_get_group_avatar($user_row, $alt = 'GROUP_AVATAR', $ignore_config = false) +function phpbb_show_profile($data, $user_notes_enabled = false, $warn_user_enabled = false, $check_can_receive_pm = true) { - $row = \phpbb\avatar\manager::clean_row($user_row, 'group'); - return phpbb_get_avatar($row, $alt, $ignore_config); -} + global $config, $auth, $user, $phpEx, $phpbb_root_path, $phpbb_dispatcher; -/** -* Get avatar -* -* @param array $row Row cleaned by \phpbb\avatar\driver\driver::clean_row -* @param string $alt Optional language string for alt tag within image, can be a language key or text -* @param bool $ignore_config Ignores the config-setting, to be still able to view the avatar in the UCP -* -* @return string Avatar html -*/ -function phpbb_get_avatar($row, $alt, $ignore_config = false) -{ - global $user, $config, $cache, $phpbb_root_path, $phpEx; - global $request; - global $phpbb_container; + $username = $data['username']; + $user_id = $data['user_id']; - if (!$config['allow_avatar'] && !$ignore_config) + $user_rank_data = phpbb_get_user_rank($data, (($user_id == ANONYMOUS) ? false : $data['user_posts'])); + + if ((!empty($data['user_allow_viewemail']) && $auth->acl_get('u_sendemail')) || $auth->acl_get('a_user')) { - return ''; + $email = ($config['board_email_form'] && $config['email_enable']) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=email&u=' . $user_id) : (($config['board_hide_emails'] && !$auth->acl_get('a_user')) ? '' : 'mailto:' . $data['user_email']); + } + else + { + $email = ''; } - $avatar_data = array( - 'src' => $row['avatar'], - 'width' => $row['avatar_width'], - 'height' => $row['avatar_height'], - ); - - $phpbb_avatar_manager = $phpbb_container->get('avatar.manager'); - $driver = $phpbb_avatar_manager->get_driver($row['avatar_type'], $ignore_config); - $html = ''; - - if ($driver) + if ($config['load_onlinetrack']) { - $html = $driver->get_custom_html($user, $row, $alt); - if (!empty($html)) - { - return $html; - } + $update_time = $config['load_online_time'] * 60; + $online = (time() - $update_time < $data['session_time'] && ((isset($data['session_viewonline']) && $data['session_viewonline']) || $auth->acl_get('u_viewonline'))) ? true : false; + } + else + { + $online = false; + } - $avatar_data = $driver->get_data($row, $ignore_config); + if ($data['user_allow_viewonline'] || $auth->acl_get('u_viewonline')) + { + $last_active = (!empty($data['session_time'])) ? $data['session_time'] : $data['user_lastvisit']; } else { - $avatar_data['src'] = ''; + $last_active = ''; } - if (!empty($avatar_data['src'])) + $age = ''; + + if ($config['allow_birthdays'] && $data['user_birthday']) + { + list($bday_day, $bday_month, $bday_year) = array_map('intval', explode('-', $data['user_birthday'])); + + if ($bday_year) + { + $now = $user->create_datetime(); + $now = phpbb_gmgetdate($now->getTimestamp() + $now->getOffset()); + + $diff = $now['mon'] - $bday_month; + if ($diff == 0) + { + $diff = ($now['mday'] - $bday_day < 0) ? 1 : 0; + } + else + { + $diff = ($diff < 0) ? 1 : 0; + } + + $age = max(0, (int) ($now['year'] - $bday_year - $diff)); + } + } + + if (!function_exists('phpbb_get_banned_user_ids')) { - $html = '<img src="' . $avatar_data['src'] . '" ' . - ($avatar_data['width'] ? ('width="' . $avatar_data['width'] . '" ') : '') . - ($avatar_data['height'] ? ('height="' . $avatar_data['height'] . '" ') : '') . - 'alt="' . ((!empty($user->lang[$alt])) ? $user->lang[$alt] : $alt) . '" />'; + include($phpbb_root_path . 'includes/functions_user.' . $phpEx); } - return $html; + // Can this user receive a Private Message? + $can_receive_pm = $check_can_receive_pm && ( + // They must be a "normal" user + $data['user_type'] != USER_IGNORE && + + // They must not be deactivated by the administrator + ($data['user_type'] != USER_INACTIVE || $data['user_inactive_reason'] != INACTIVE_MANUAL) && + + // They must be able to read PMs + sizeof($auth->acl_get_list($user_id, 'u_readpm')) && + + // They must not be permanently banned + !sizeof(phpbb_get_banned_user_ids($user_id, false)) && + + // They must allow users to contact via PM + (($auth->acl_gets('a_', 'm_') || $auth->acl_getf_global('m_')) || $data['user_allow_pm']) + ); + + // Dump it out to the template + $template_data = array( + 'AGE' => $age, + 'RANK_TITLE' => $user_rank_data['title'], + 'JOINED' => $user->format_date($data['user_regdate']), + 'LAST_ACTIVE' => (empty($last_active)) ? ' - ' : $user->format_date($last_active), + 'POSTS' => ($data['user_posts']) ? $data['user_posts'] : 0, + 'WARNINGS' => isset($data['user_warnings']) ? $data['user_warnings'] : 0, + + 'USERNAME_FULL' => get_username_string('full', $user_id, $username, $data['user_colour']), + 'USERNAME' => get_username_string('username', $user_id, $username, $data['user_colour']), + 'USER_COLOR' => get_username_string('colour', $user_id, $username, $data['user_colour']), + 'U_VIEW_PROFILE' => get_username_string('profile', $user_id, $username, $data['user_colour']), + + 'A_USERNAME' => addslashes(get_username_string('username', $user_id, $username, $data['user_colour'])), + + 'AVATAR_IMG' => phpbb_get_user_avatar($data), + 'ONLINE_IMG' => (!$config['load_onlinetrack']) ? '' : (($online) ? $user->img('icon_user_online', 'ONLINE') : $user->img('icon_user_offline', 'OFFLINE')), + 'S_ONLINE' => ($config['load_onlinetrack'] && $online) ? true : false, + 'RANK_IMG' => $user_rank_data['img'], + 'RANK_IMG_SRC' => $user_rank_data['img_src'], + 'S_JABBER_ENABLED' => ($config['jab_enable']) ? true : false, + + 'S_WARNINGS' => ($auth->acl_getf_global('m_') || $auth->acl_get('m_warn')) ? true : false, + + 'U_SEARCH_USER' => ($auth->acl_get('u_search')) ? append_sid("{$phpbb_root_path}search.$phpEx", "author_id=$user_id&sr=posts") : '', + 'U_NOTES' => ($user_notes_enabled && $auth->acl_getf_global('m_')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=notes&mode=user_notes&u=' . $user_id, true, $user->session_id) : '', + 'U_WARN' => ($warn_user_enabled && $auth->acl_get('m_warn')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=warn&mode=warn_user&u=' . $user_id, true, $user->session_id) : '', + 'U_PM' => ($config['allow_privmsg'] && $auth->acl_get('u_sendpm') && $can_receive_pm) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&mode=compose&u=' . $user_id) : '', + 'U_EMAIL' => $email, + 'U_JABBER' => ($data['user_jabber'] && $auth->acl_get('u_sendim')) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=contact&action=jabber&u=' . $user_id) : '', + + 'USER_JABBER' => ($config['jab_enable']) ? $data['user_jabber'] : '', + 'USER_JABBER_IMG' => ($config['jab_enable'] && $data['user_jabber']) ? $user->img('icon_contact_jabber', $data['user_jabber']) : '', + + 'L_SEND_EMAIL_USER' => $user->lang('SEND_EMAIL_USER', $username), + 'L_CONTACT_USER' => $user->lang('CONTACT_USER', $username), + 'L_VIEWING_PROFILE' => $user->lang('VIEWING_PROFILE', $username), + ); + + /** + * Preparing a user's data before displaying it in profile and memberlist + * + * @event core.memberlist_prepare_profile_data + * @var array data Array with user's data + * @var array template_data Template array with user's data + * @since 3.1.0-a1 + */ + $vars = array('data', 'template_data'); + extract($phpbb_dispatcher->trigger_event('core.memberlist_prepare_profile_data', compact($vars))); + + return $template_data; } -/** -* Generate a list of archive types available for compressing attachments -* -* @param string $param_key Either topic_id or post_id -* @param string $param_val The value of the topic or post id -* @param string $phpbb_root_path The root path of the phpBB installation -* @param string $phpEx The PHP extension -* -* @return array Array containing the link and the type of compression -*/ -function phpbb_gen_download_links($param_key, $param_val, $phpbb_root_path, $phpEx) +function phpbb_sort_last_active($first, $second) { - if (!class_exists('compress')) - { - require $phpbb_root_path . 'includes/functions_compress.' . $phpEx; - } + global $id_cache, $sort_dir; - $methods = compress::methods(); - // Sort by preferred type. - $methods = array_intersect(array('.zip', '.tar.bz2', '.tar.gz', '.tar'), $methods); - $links = array(); + $lesser_than = ($sort_dir === 'd') ? -1 : 1; - foreach ($methods as $method) + if (isset($id_cache[$first]['group_leader']) && $id_cache[$first]['group_leader'] && (!isset($id_cache[$second]['group_leader']) || !$id_cache[$second]['group_leader'])) { - $exploded = explode('.', $method); - $type = array_pop($exploded); - $params = array('archive' => $method); - $params[$param_key] = $param_val; - - $links[] = array( - 'LINK' => append_sid("{$phpbb_root_path}download/file.$phpEx", $params), - 'TYPE' => $type, - ); + return -1; + } + else if (isset($id_cache[$second]['group_leader']) && (!isset($id_cache[$first]['group_leader']) || !$id_cache[$first]['group_leader']) && $id_cache[$second]['group_leader']) + { + return 1; + } + else + { + return $lesser_than * (int) ($id_cache[$first]['last_visit'] - $id_cache[$second]['last_visit']); } - - return $links; } diff --git a/phpBB/includes/functions_download.php b/phpBB/includes/functions_download.php index c895f7b54b..916655e77c 100644 --- a/phpBB/includes/functions_download.php +++ b/phpBB/includes/functions_download.php @@ -1,9 +1,13 @@ <?php /** * -* @package phpBB3 -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -41,28 +45,28 @@ function send_avatar_to_browser($file, $browser) if ((@file_exists($file_path) && @is_readable($file_path)) && !headers_sent()) { - header('Pragma: public'); + header('Cache-Control: public'); $image_data = @getimagesize($file_path); header('Content-Type: ' . image_type_to_mime_type($image_data[2])); - if ((strpos(strtolower($user->browser), 'msie') !== false) && !phpbb_is_greater_ie_version($browser, 7)) + if ((strpos(strtolower($browser), 'msie') !== false) && !phpbb_is_greater_ie_version($browser, 7)) { header('Content-Disposition: attachment; ' . header_filename($file)); if (strpos(strtolower($browser), 'msie 6.0') !== false) { - header('Expires: -1'); + header('Expires: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT'); } else { - header('Expires: ' . gmdate('D, d M Y H:i:s \G\M\T', time() + 31536000)); + header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 31536000) . ' GMT'); } } else { header('Content-Disposition: inline; ' . header_filename($file)); - header('Expires: ' . gmdate('D, d M Y H:i:s \G\M\T', time() + 31536000)); + header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 31536000) . ' GMT'); } $size = @filesize($file_path); @@ -119,7 +123,7 @@ function wrap_img_in_html($src, $title) */ function send_file_to_browser($attachment, $upload_dir, $category) { - global $user, $db, $config, $phpbb_root_path; + global $user, $db, $phpbb_root_path, $request; $filename = $phpbb_root_path . $upload_dir . '/' . $attachment['physical_filename']; @@ -171,7 +175,7 @@ function send_file_to_browser($attachment, $upload_dir, $category) } // Now the tricky part... let's dance - header('Pragma: public'); + header('Cache-Control: public'); // Send out the Headers. Do not set Content-Disposition to inline please, it is a security measure for users using the Internet Explorer. header('Content-Type: ' . $attachment['mimetype']); @@ -181,7 +185,7 @@ function send_file_to_browser($attachment, $upload_dir, $category) header('X-Content-Type-Options: nosniff'); } - if ($category == ATTACHMENT_CATEGORY_FLASH && request_var('view', 0) === 1) + if ($category == ATTACHMENT_CATEGORY_FLASH && $request->variable('view', 0) === 1) { // We use content-disposition: inline for flash files and view=1 to let it correctly play with flash player 10 - any other disposition will fail to play inline header('Content-Disposition: inline'); @@ -193,7 +197,7 @@ function send_file_to_browser($attachment, $upload_dir, $category) header('Content-Disposition: attachment; ' . header_filename(htmlspecialchars_decode($attachment['real_filename']))); if (empty($user->browser) || (strpos(strtolower($user->browser), 'msie 6.0') !== false)) { - header('expires: -1'); + header('Expires: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT'); } } else @@ -206,11 +210,6 @@ function send_file_to_browser($attachment, $upload_dir, $category) } } - if ($size) - { - header("Content-Length: $size"); - } - // Close the db connection before sending the file etc. file_gc(false); @@ -234,6 +233,11 @@ function send_file_to_browser($attachment, $upload_dir, $category) exit; } + if ($size) + { + header("Content-Length: $size"); + } + // Try to deliver in chunks @set_time_limit(0); @@ -416,8 +420,8 @@ function set_modified_headers($stamp, $browser) { send_status_line(304, 'Not Modified'); // seems that we need those too ... browsers - header('Pragma: public'); - header('Expires: ' . gmdate('D, d M Y H:i:s \G\M\T', time() + 31536000)); + header('Cache-Control: public'); + header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 31536000) . ' GMT'); return true; } else @@ -596,7 +600,7 @@ function phpbb_parse_range_request($request_array, $filesize) /** * Increments the download count of all provided attachments * -* @param \phpbb\db\driver\driver $db The database object +* @param \phpbb\db\driver\driver_interface $db The database object * @param array|int $ids The attach_id of each attachment * * @return null @@ -617,7 +621,7 @@ function phpbb_increment_downloads($db, $ids) /** * Handles authentication when downloading attachments from a post or topic * -* @param \phpbb\db\driver\driver $db The database object +* @param \phpbb\db\driver\driver_interface $db The database object * @param \phpbb\auth\auth $auth The authentication object * @param int $topic_id The id of the topic that we are downloading from * @@ -663,7 +667,7 @@ function phpbb_download_handle_forum_auth($db, $auth, $topic_id) /** * Handles authentication when downloading attachments from PMs * -* @param \phpbb\db\driver\driver $db The database object +* @param \phpbb\db\driver\driver_interface $db The database object * @param \phpbb\auth\auth $auth The authentication object * @param int $user_id The user id * @param int $msg_id The id of the PM that we are downloading from @@ -690,7 +694,7 @@ function phpbb_download_handle_pm_auth($db, $auth, $user_id, $msg_id) /** * Checks whether a user can download from a particular PM * -* @param \phpbb\db\driver\driver $db The database object +* @param \phpbb\db\driver\driver_interface $db The database object * @param int $user_id The user id * @param int $msg_id The id of the PM that we are downloading from * @@ -714,27 +718,6 @@ function phpbb_download_check_pm_auth($db, $user_id, $msg_id) } /** -* Cleans a filename of any characters that could potentially cause a problem on -* a user's filesystem. -* -* @param string $filename The filename to clean -* -* @return string The cleaned filename -*/ -function phpbb_download_clean_filename($filename) -{ - $bad_chars = array("'", "\\", ' ', '/', ':', '*', '?', '"', '<', '>', '|'); - - // rawurlencode to convert any potentially 'bad' characters that we missed - $filename = rawurlencode(str_replace($bad_chars, '_', $filename)); - - // Turn the %xx entities created by rawurlencode to _ - $filename = preg_replace("/%(\w{2})/", '_', $filename); - - return $filename; -} - -/** * Check if the browser is internet explorer version 7+ * * @param string $user_agent User agent HTTP header diff --git a/phpBB/includes/functions_install.php b/phpBB/includes/functions_install.php deleted file mode 100644 index deb304b838..0000000000 --- a/phpBB/includes/functions_install.php +++ /dev/null @@ -1,583 +0,0 @@ -<?php -/** -* -* @package install -* @copyright (c) 2006 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Returns an array of available DBMS with some data, if a DBMS is specified it will only -* return data for that DBMS and will load its extension if necessary. -*/ -function get_available_dbms($dbms = false, $return_unavailable = false, $only_20x_options = false) -{ - global $lang; - $available_dbms = array( - 'firebird' => array( - 'LABEL' => 'FireBird', - 'SCHEMA' => 'firebird', - 'MODULE' => 'interbase', - 'DELIM' => ';;', - 'DRIVER' => 'phpbb\db\driver\firebird', - 'AVAILABLE' => true, - '2.0.x' => false, - ), - // Note: php 5.5 alpha 2 deprecated mysql. - // Keep mysqli before mysql in this list. - 'mysqli' => array( - 'LABEL' => 'MySQL with MySQLi Extension', - 'SCHEMA' => 'mysql_41', - 'MODULE' => 'mysqli', - 'DELIM' => ';', - 'DRIVER' => 'phpbb\db\driver\mysqli', - 'AVAILABLE' => true, - '2.0.x' => true, - ), - 'mysql' => array( - 'LABEL' => 'MySQL', - 'SCHEMA' => 'mysql', - 'MODULE' => 'mysql', - 'DELIM' => ';', - 'DRIVER' => 'phpbb\db\driver\mysql', - 'AVAILABLE' => true, - '2.0.x' => true, - ), - 'mssql' => array( - 'LABEL' => 'MS SQL Server 2000+', - 'SCHEMA' => 'mssql', - 'MODULE' => 'mssql', - 'DELIM' => 'GO', - 'DRIVER' => 'phpbb\db\driver\mssql', - 'AVAILABLE' => true, - '2.0.x' => true, - ), - 'mssql_odbc'=> array( - 'LABEL' => 'MS SQL Server [ ODBC ]', - 'SCHEMA' => 'mssql', - 'MODULE' => 'odbc', - 'DELIM' => 'GO', - 'DRIVER' => 'phpbb\db\driver\mssql_odbc', - 'AVAILABLE' => true, - '2.0.x' => true, - ), - 'mssqlnative' => array( - 'LABEL' => 'MS SQL Server 2005+ [ Native ]', - 'SCHEMA' => 'mssql', - 'MODULE' => 'sqlsrv', - 'DELIM' => 'GO', - 'DRIVER' => 'phpbb\db\driver\mssqlnative', - 'AVAILABLE' => true, - '2.0.x' => false, - ), - 'oracle' => array( - 'LABEL' => 'Oracle', - 'SCHEMA' => 'oracle', - 'MODULE' => 'oci8', - 'DELIM' => '/', - 'DRIVER' => 'phpbb\db\driver\oracle', - 'AVAILABLE' => true, - '2.0.x' => false, - ), - 'postgres' => array( - 'LABEL' => 'PostgreSQL 8.3+', - 'SCHEMA' => 'postgres', - 'MODULE' => 'pgsql', - 'DELIM' => ';', - 'DRIVER' => 'phpbb\db\driver\postgres', - 'AVAILABLE' => true, - '2.0.x' => true, - ), - 'sqlite' => array( - 'LABEL' => 'SQLite', - 'SCHEMA' => 'sqlite', - 'MODULE' => 'sqlite', - 'DELIM' => ';', - 'DRIVER' => 'phpbb\db\driver\sqlite', - 'AVAILABLE' => true, - '2.0.x' => false, - ), - ); - - if ($dbms) - { - if (isset($available_dbms[$dbms])) - { - $available_dbms = array($dbms => $available_dbms[$dbms]); - } - else - { - return array(); - } - } - - // now perform some checks whether they are really available - foreach ($available_dbms as $db_name => $db_ary) - { - if ($only_20x_options && !$db_ary['2.0.x']) - { - if ($return_unavailable) - { - $available_dbms[$db_name]['AVAILABLE'] = false; - } - else - { - unset($available_dbms[$db_name]); - } - continue; - } - - $dll = $db_ary['MODULE']; - - if (!@extension_loaded($dll)) - { - if ($return_unavailable) - { - $available_dbms[$db_name]['AVAILABLE'] = false; - } - else - { - unset($available_dbms[$db_name]); - } - continue; - } - $any_db_support = true; - } - - if ($return_unavailable) - { - $available_dbms['ANY_DB_SUPPORT'] = $any_db_support; - } - return $available_dbms; -} - -/** -* Generate the drop down of available database options -*/ -function dbms_select($default = '', $only_20x_options = false) -{ - global $lang; - - $available_dbms = get_available_dbms(false, false, $only_20x_options); - $dbms_options = ''; - foreach ($available_dbms as $dbms_name => $details) - { - $selected = ($dbms_name == $default) ? ' selected="selected"' : ''; - $dbms_options .= '<option value="' . $dbms_name . '"' . $selected .'>' . $lang['DLL_' . strtoupper($dbms_name)] . '</option>'; - } - return $dbms_options; -} - -/** -* Get tables of a database -* -* @deprecated -*/ -function get_tables(&$db) -{ - $db_tools = new \phpbb\db\tools($db); - - return $db_tools->sql_list_tables(); -} - -/** -* Used to test whether we are able to connect to the database the user has specified -* and identify any problems (eg there are already tables with the names we want to use -* @param array $dbms should be of the format of an element of the array returned by {@link get_available_dbms get_available_dbms()} -* necessary extensions should be loaded already -*/ -function connect_check_db($error_connect, &$error, $dbms_details, $table_prefix, $dbhost, $dbuser, $dbpasswd, $dbname, $dbport, $prefix_may_exist = false, $load_dbal = true, $unicode_check = true) -{ - global $phpbb_root_path, $phpEx, $config, $lang; - - $dbms = $dbms_details['DRIVER']; - - // Instantiate it and set return on error true - $db = new $dbms(); - $db->sql_return_on_error(true); - - // Check that we actually have a database name before going any further..... - if ($dbms_details['DRIVER'] != 'phpbb\db\driver\sqlite' && $dbms_details['DRIVER'] != 'phpbb\db\driver\oracle' && $dbname === '') - { - $error[] = $lang['INST_ERR_DB_NO_NAME']; - return false; - } - - // Make sure we don't have a daft user who thinks having the SQLite database in the forum directory is a good idea - if ($dbms_details['DRIVER'] == 'phpbb\db\driver\sqlite' && stripos(phpbb_realpath($dbhost), phpbb_realpath('../')) === 0) - { - $error[] = $lang['INST_ERR_DB_FORUM_PATH']; - return false; - } - - // Check the prefix length to ensure that index names are not too long and does not contain invalid characters - switch ($dbms_details['DRIVER']) - { - case 'phpbb\db\driver\mysql': - case 'phpbb\db\driver\mysqli': - if (strspn($table_prefix, '-./\\') !== 0) - { - $error[] = $lang['INST_ERR_PREFIX_INVALID']; - return false; - } - - // no break; - - case 'phpbb\db\driver\postgres': - $prefix_length = 36; - break; - - case 'phpbb\db\driver\mssql': - case 'phpbb\db\driver\mssql_odbc': - case 'phpbb\db\driver\mssqlnative': - $prefix_length = 90; - break; - - case 'phpbb\db\driver\sqlite': - $prefix_length = 200; - break; - - case 'phpbb\db\driver\firebird': - case 'phpbb\db\driver\oracle': - $prefix_length = 6; - break; - } - - if (strlen($table_prefix) > $prefix_length) - { - $error[] = sprintf($lang['INST_ERR_PREFIX_TOO_LONG'], $prefix_length); - return false; - } - - // Try and connect ... - if (is_array($db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, true))) - { - $db_error = $db->sql_error(); - $error[] = $lang['INST_ERR_DB_CONNECT'] . '<br />' . (($db_error['message']) ? $db_error['message'] : $lang['INST_ERR_DB_NO_ERROR']); - } - else - { - // Likely matches for an existing phpBB installation - if (!$prefix_may_exist) - { - $temp_prefix = strtolower($table_prefix); - $table_ary = array($temp_prefix . 'attachments', $temp_prefix . 'config', $temp_prefix . 'sessions', $temp_prefix . 'topics', $temp_prefix . 'users'); - - $tables = get_tables($db); - $tables = array_map('strtolower', $tables); - $table_intersect = array_intersect($tables, $table_ary); - - if (sizeof($table_intersect)) - { - $error[] = $lang['INST_ERR_PREFIX']; - } - } - - // Make sure that the user has selected a sensible DBAL for the DBMS actually installed - switch ($dbms_details['DRIVER']) - { - case 'phpbb\db\driver\mysqli': - if (version_compare(mysqli_get_server_info($db->db_connect_id), '4.1.3', '<')) - { - $error[] = $lang['INST_ERR_DB_NO_MYSQLI']; - } - break; - - case 'phpbb\db\driver\sqlite': - if (version_compare(sqlite_libversion(), '2.8.2', '<')) - { - $error[] = $lang['INST_ERR_DB_NO_SQLITE']; - } - break; - - case 'phpbb\db\driver\firebird': - // check the version of FB, use some hackery if we can't get access to the server info - if ($db->service_handle !== false && function_exists('ibase_server_info')) - { - $val = @ibase_server_info($db->service_handle, IBASE_SVC_SERVER_VERSION); - preg_match('#V([\d.]+)#', $val, $match); - if ($match[1] < 2) - { - $error[] = $lang['INST_ERR_DB_NO_FIREBIRD']; - } - $db_info = @ibase_db_info($db->service_handle, $dbname, IBASE_STS_HDR_PAGES); - - preg_match('/^\\s*Page size\\s*(\\d+)/m', $db_info, $regs); - $page_size = intval($regs[1]); - if ($page_size < 8192) - { - $error[] = $lang['INST_ERR_DB_NO_FIREBIRD_PS']; - } - } - else - { - $sql = "SELECT * - FROM RDB$FUNCTIONS - WHERE RDB$SYSTEM_FLAG IS NULL - AND RDB$FUNCTION_NAME = 'CHAR_LENGTH'"; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - // if its a UDF, its too old - if ($row) - { - $error[] = $lang['INST_ERR_DB_NO_FIREBIRD']; - } - else - { - $sql = 'SELECT 1 FROM RDB$DATABASE - WHERE BIN_AND(10, 1) = 0'; - $result = $db->sql_query($sql); - if (!$result) // This can only fail if BIN_AND is not defined - { - $error[] = $lang['INST_ERR_DB_NO_FIREBIRD']; - } - $db->sql_freeresult($result); - } - - // Setup the stuff for our random table - $char_array = array_merge(range('A', 'Z'), range('0', '9')); - $char_len = mt_rand(7, 9); - $char_array_len = sizeof($char_array) - 1; - - $final = ''; - - for ($i = 0; $i < $char_len; $i++) - { - $final .= $char_array[mt_rand(0, $char_array_len)]; - } - - // Create some random table - $sql = 'CREATE TABLE ' . $final . " ( - FIELD1 VARCHAR(255) CHARACTER SET UTF8 DEFAULT '' NOT NULL COLLATE UNICODE, - FIELD2 INTEGER DEFAULT 0 NOT NULL);"; - $db->sql_query($sql); - - // Create an index that should fail if the page size is less than 8192 - $sql = 'CREATE INDEX ' . $final . ' ON ' . $final . '(FIELD1, FIELD2);'; - $db->sql_query($sql); - - if (ibase_errmsg() !== false) - { - $error[] = $lang['INST_ERR_DB_NO_FIREBIRD_PS']; - } - else - { - // Kill the old table - $db->sql_query('DROP TABLE ' . $final . ';'); - } - unset($final); - } - break; - - case 'phpbb\db\driver\oracle': - if ($unicode_check) - { - $sql = "SELECT * - FROM NLS_DATABASE_PARAMETERS - WHERE PARAMETER = 'NLS_RDBMS_VERSION' - OR PARAMETER = 'NLS_CHARACTERSET'"; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - $stats[$row['parameter']] = $row['value']; - } - $db->sql_freeresult($result); - - if (version_compare($stats['NLS_RDBMS_VERSION'], '9.2', '<') && $stats['NLS_CHARACTERSET'] !== 'UTF8') - { - $error[] = $lang['INST_ERR_DB_NO_ORACLE']; - } - } - break; - - case 'phpbb\db\driver\postgres': - if ($unicode_check) - { - $sql = "SHOW server_encoding;"; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if ($row['server_encoding'] !== 'UNICODE' && $row['server_encoding'] !== 'UTF8') - { - $error[] = $lang['INST_ERR_DB_NO_POSTGRES']; - } - } - break; - } - - } - - if ($error_connect && (!isset($error) || !sizeof($error))) - { - return true; - } - return false; -} - -/** -* Removes "/* style" as well as "# style" comments from $input. -* -* @param string $input Input string -* -* @return string Input string with comments removed -*/ -function phpbb_remove_comments($input) -{ - // Remove /* */ comments (http://ostermiller.org/findcomment.html) - $input = preg_replace('#/\*(.|[\r\n])*?\*/#', "\n", $input); - - // Remove # style comments - $input = preg_replace('/\n{2,}/', "\n", preg_replace('/^#.*$/m', "\n", $input)); - - return $input; -} - -/** -* split_sql_file will split an uploaded sql file into single sql statements. -* Note: expects trim() to have already been run on $sql. -*/ -function split_sql_file($sql, $delimiter) -{ - $sql = str_replace("\r" , '', $sql); - $data = preg_split('/' . preg_quote($delimiter, '/') . '$/m', $sql); - - $data = array_map('trim', $data); - - // The empty case - $end_data = end($data); - - if (empty($end_data)) - { - unset($data[key($data)]); - } - - return $data; -} - -/** -* For replacing {L_*} strings with preg_replace_callback -*/ -function adjust_language_keys_callback($matches) -{ - if (!empty($matches[1])) - { - global $lang, $db; - - return (!empty($lang[$matches[1]])) ? $db->sql_escape($lang[$matches[1]]) : $db->sql_escape($matches[1]); - } -} - -/** -* Creates the output to be stored in a phpBB config.php file -* -* @param array $data Array containing the database connection information -* @param string $dbms The name of the DBAL class to use -* @param bool $debug If the debug constants should be enabled by default or not -* @param bool $debug_test If the DEBUG_TEST constant should be added -* NOTE: Only for use within the testing framework -* -* @return string The output to write to the file -*/ -function phpbb_create_config_file_data($data, $dbms, $debug = false, $debug_test = false) -{ - $config_data = "<?php\n"; - $config_data .= "// phpBB 3.1.x auto-generated configuration file\n// Do not change anything in this file!\n"; - - $config_data_array = array( - 'dbms' => $dbms, - 'dbhost' => $data['dbhost'], - 'dbport' => $data['dbport'], - 'dbname' => $data['dbname'], - 'dbuser' => $data['dbuser'], - 'dbpasswd' => htmlspecialchars_decode($data['dbpasswd']), - 'table_prefix' => $data['table_prefix'], - - 'phpbb_adm_relative_path' => 'adm/', - - 'acm_type' => 'phpbb\cache\driver\file', - ); - - foreach ($config_data_array as $key => $value) - { - $config_data .= "\${$key} = '" . str_replace("'", "\\'", str_replace('\\', '\\\\', $value)) . "';\n"; - } - - $config_data .= "\n@define('PHPBB_INSTALLED', true);\n"; - - if ($debug) - { - $config_data .= "@define('DEBUG', true);\n"; - } - else - { - $config_data .= "// @define('DEBUG', true);\n"; - } - - if ($debug_test) - { - $config_data .= "@define('DEBUG_TEST', true);\n"; - } - - return $config_data; -} - -/** -* Check whether a file should be ignored on update -* -* We ignore new files in some circumstances: -* 1. The file is a language file, but the language is not installed -* 2. The file is a style file, but the style is not installed -* 3. The file is a style language file, but the language is not installed -* -* @param string $phpbb_root_path phpBB root path -* @param string $file File including path from phpbb root -* @return bool Should we ignore the new file or add it to the board? -*/ -function phpbb_ignore_new_file_on_update($phpbb_root_path, $file) -{ - $ignore_new_file = false; - - // We ignore new files in some circumstances: - // 1. The file is a language file, but the language is not installed - if (!$ignore_new_file && strpos($file, 'language/') === 0) - { - list($language_dir, $language_iso) = explode('/', $file); - $ignore_new_file = !file_exists($phpbb_root_path . $language_dir . '/' . $language_iso); - } - - // 2. The file is a style file, but the style is not installed - if (!$ignore_new_file && strpos($file, 'styles/') === 0) - { - list($styles_dir, $style_name) = explode('/', $file); - $ignore_new_file = !file_exists($phpbb_root_path . $styles_dir . '/' . $style_name); - } - - // 3. The file is a style language file, but the language is not installed - if (!$ignore_new_file && strpos($file, 'styles/') === 0) - { - $dirs = explode('/', $file); - if (sizeof($dirs) >= 5) - { - list($styles_dir, $style_name, $template_component, $language_iso) = explode('/', $file); - if ($template_component == 'theme' && $language_iso !== 'images') - { - $ignore_new_file = !file_exists($phpbb_root_path . 'language/' . $language_iso); - } - } - } - - return $ignore_new_file; -} diff --git a/phpBB/includes/functions_jabber.php b/phpBB/includes/functions_jabber.php index b260ffad6e..a38888a861 100644 --- a/phpBB/includes/functions_jabber.php +++ b/phpBB/includes/functions_jabber.php @@ -1,9 +1,13 @@ <?php /** * -* @package phpBB3 -* @copyright (c) 2007 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -24,8 +28,6 @@ if (!defined('IN_PHPBB')) * @author Florian Schmitz (floele) * * Only slightly modified by Acyd Burn -* -* @package phpBB3 */ class jabber { @@ -85,8 +87,7 @@ class jabber */ static public function can_use_ssl() { - // Will not work with PHP >= 5.2.1 or < 5.2.3RC2 until timeout problem with ssl hasn't been fixed (http://bugs.php.net/41236) - return ((version_compare(PHP_VERSION, '5.2.1', '<') || version_compare(PHP_VERSION, '5.2.3RC2', '>=')) && @extension_loaded('openssl')) ? true : false; + return @extension_loaded('openssl'); } /** diff --git a/phpBB/includes/functions_mcp.php b/phpBB/includes/functions_mcp.php new file mode 100644 index 0000000000..dfe3fefbd0 --- /dev/null +++ b/phpBB/includes/functions_mcp.php @@ -0,0 +1,741 @@ +<?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; +} + +/** +* Functions used to generate additional URL paramters +*/ +function phpbb_module__url($mode, &$module_row) +{ + return phpbb_extra_url(); +} + +function phpbb_module_notes_url($mode, &$module_row) +{ + if ($mode == 'front') + { + return ''; + } + + global $user_id; + return ($user_id) ? "&u=$user_id" : ''; +} + +function phpbb_module_warn_url($mode, &$module_row) +{ + if ($mode == 'front' || $mode == 'list') + { + global $forum_id; + + return ($forum_id) ? "&f=$forum_id" : ''; + } + + if ($mode == 'warn_post') + { + global $forum_id, $post_id; + + $url_extra = ($forum_id) ? "&f=$forum_id" : ''; + $url_extra .= ($post_id) ? "&p=$post_id" : ''; + + return $url_extra; + } + else + { + global $user_id; + + return ($user_id) ? "&u=$user_id" : ''; + } +} + +function phpbb_module_main_url($mode, &$module_row) +{ + return phpbb_extra_url(); +} + +function phpbb_module_logs_url($mode, &$module_row) +{ + return phpbb_extra_url(); +} + +function phpbb_module_ban_url($mode, &$module_row) +{ + return phpbb_extra_url(); +} + +function phpbb_module_queue_url($mode, &$module_row) +{ + return phpbb_extra_url(); +} + +function phpbb_module_reports_url($mode, &$module_row) +{ + return phpbb_extra_url(); +} + +function phpbb_extra_url() +{ + global $forum_id, $topic_id, $post_id, $report_id, $user_id; + + $url_extra = ''; + $url_extra .= ($forum_id) ? "&f=$forum_id" : ''; + $url_extra .= ($topic_id) ? "&t=$topic_id" : ''; + $url_extra .= ($post_id) ? "&p=$post_id" : ''; + $url_extra .= ($user_id) ? "&u=$user_id" : ''; + $url_extra .= ($report_id) ? "&r=$report_id" : ''; + + return $url_extra; +} + +/** +* Get simple topic data +*/ +function phpbb_get_topic_data($topic_ids, $acl_list = false, $read_tracking = false) +{ + global $auth, $db, $config, $user; + static $rowset = array(); + + $topics = array(); + + if (!sizeof($topic_ids)) + { + return array(); + } + + // cache might not contain read tracking info, so we can't use it if read + // tracking information is requested + if (!$read_tracking) + { + $cache_topic_ids = array_intersect($topic_ids, array_keys($rowset)); + $topic_ids = array_diff($topic_ids, array_keys($rowset)); + } + else + { + $cache_topic_ids = array(); + } + + if (sizeof($topic_ids)) + { + $sql_array = array( + 'SELECT' => 't.*, f.*', + + 'FROM' => array( + TOPICS_TABLE => 't', + ), + + 'LEFT_JOIN' => array( + array( + 'FROM' => array(FORUMS_TABLE => 'f'), + 'ON' => 'f.forum_id = t.forum_id' + ) + ), + + 'WHERE' => $db->sql_in_set('t.topic_id', $topic_ids) + ); + + if ($read_tracking && $config['load_db_lastread']) + { + $sql_array['SELECT'] .= ', tt.mark_time, ft.mark_time as forum_mark_time'; + + $sql_array['LEFT_JOIN'][] = array( + 'FROM' => array(TOPICS_TRACK_TABLE => 'tt'), + 'ON' => 'tt.user_id = ' . $user->data['user_id'] . ' AND t.topic_id = tt.topic_id' + ); + + $sql_array['LEFT_JOIN'][] = array( + 'FROM' => array(FORUMS_TRACK_TABLE => 'ft'), + 'ON' => 'ft.user_id = ' . $user->data['user_id'] . ' AND t.forum_id = ft.forum_id' + ); + } + + $sql = $db->sql_build_query('SELECT', $sql_array); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $rowset[$row['topic_id']] = $row; + + if ($acl_list && !$auth->acl_gets($acl_list, $row['forum_id'])) + { + continue; + } + + $topics[$row['topic_id']] = $row; + } + $db->sql_freeresult($result); + } + + foreach ($cache_topic_ids as $id) + { + if (!$acl_list || $auth->acl_gets($acl_list, $rowset[$id]['forum_id'])) + { + $topics[$id] = $rowset[$id]; + } + } + + return $topics; +} + +/** +* Get simple post data +*/ +function phpbb_get_post_data($post_ids, $acl_list = false, $read_tracking = false) +{ + global $db, $auth, $config, $user; + + $rowset = array(); + + if (!sizeof($post_ids)) + { + return array(); + } + + $sql_array = array( + 'SELECT' => 'p.*, u.*, t.*, f.*', + + 'FROM' => array( + USERS_TABLE => 'u', + POSTS_TABLE => 'p', + TOPICS_TABLE => 't', + ), + + 'LEFT_JOIN' => array( + array( + 'FROM' => array(FORUMS_TABLE => 'f'), + 'ON' => 'f.forum_id = t.forum_id' + ) + ), + + 'WHERE' => $db->sql_in_set('p.post_id', $post_ids) . ' + AND u.user_id = p.poster_id + AND t.topic_id = p.topic_id', + ); + + if ($read_tracking && $config['load_db_lastread']) + { + $sql_array['SELECT'] .= ', tt.mark_time, ft.mark_time as forum_mark_time'; + + $sql_array['LEFT_JOIN'][] = array( + 'FROM' => array(TOPICS_TRACK_TABLE => 'tt'), + 'ON' => 'tt.user_id = ' . $user->data['user_id'] . ' AND t.topic_id = tt.topic_id' + ); + + $sql_array['LEFT_JOIN'][] = array( + 'FROM' => array(FORUMS_TRACK_TABLE => 'ft'), + 'ON' => 'ft.user_id = ' . $user->data['user_id'] . ' AND t.forum_id = ft.forum_id' + ); + } + + $sql = $db->sql_build_query('SELECT', $sql_array); + $result = $db->sql_query($sql); + unset($sql_array); + + while ($row = $db->sql_fetchrow($result)) + { + if ($acl_list && !$auth->acl_gets($acl_list, $row['forum_id'])) + { + continue; + } + + if ($row['post_visibility'] != ITEM_APPROVED && !$auth->acl_get('m_approve', $row['forum_id'])) + { + // Moderators without the permission to approve post should at least not see them. ;) + continue; + } + + $rowset[$row['post_id']] = $row; + } + $db->sql_freeresult($result); + + return $rowset; +} + +/** +* Get simple forum data +*/ +function phpbb_get_forum_data($forum_id, $acl_list = 'f_list', $read_tracking = false) +{ + global $auth, $db, $user, $config, $phpbb_container; + + $rowset = array(); + + if (!is_array($forum_id)) + { + $forum_id = array($forum_id); + } + + if (!sizeof($forum_id)) + { + return array(); + } + + if ($read_tracking && $config['load_db_lastread']) + { + $read_tracking_join = ' LEFT JOIN ' . FORUMS_TRACK_TABLE . ' ft ON (ft.user_id = ' . $user->data['user_id'] . ' + AND ft.forum_id = f.forum_id)'; + $read_tracking_select = ', ft.mark_time'; + } + else + { + $read_tracking_join = $read_tracking_select = ''; + } + + $sql = "SELECT f.* $read_tracking_select + FROM " . FORUMS_TABLE . " f$read_tracking_join + WHERE " . $db->sql_in_set('f.forum_id', $forum_id); + $result = $db->sql_query($sql); + + /* @var $phpbb_content_visibility \phpbb\content_visibility */ + $phpbb_content_visibility = $phpbb_container->get('content.visibility'); + + while ($row = $db->sql_fetchrow($result)) + { + if ($acl_list && !$auth->acl_gets($acl_list, $row['forum_id'])) + { + continue; + } + + $row['forum_topics_approved'] = $phpbb_content_visibility->get_count('forum_topics', $row, $row['forum_id']); + + $rowset[$row['forum_id']] = $row; + } + $db->sql_freeresult($result); + + return $rowset; +} + +/** +* Get simple pm data +*/ +function phpbb_get_pm_data($pm_ids) +{ + global $db; + + $rowset = array(); + + if (!sizeof($pm_ids)) + { + return array(); + } + + $sql_array = array( + 'SELECT' => 'p.*, u.*', + + 'FROM' => array( + USERS_TABLE => 'u', + PRIVMSGS_TABLE => 'p', + ), + + 'WHERE' => $db->sql_in_set('p.msg_id', $pm_ids) . ' + AND u.user_id = p.author_id', + ); + + $sql = $db->sql_build_query('SELECT', $sql_array); + $result = $db->sql_query($sql); + unset($sql_array); + + while ($row = $db->sql_fetchrow($result)) + { + $rowset[$row['msg_id']] = $row; + } + $db->sql_freeresult($result); + + return $rowset; +} + +/** +* sorting in mcp +* +* @param string $where_sql should either be WHERE (default if ommited) or end with AND or OR +* +* $mode reports and reports_closed: the $where parameters uses aliases p for posts table and r for report table +* $mode unapproved_posts: the $where parameters uses aliases p for posts table and t for topic table +*/ +function phpbb_mcp_sorting($mode, &$sort_days_val, &$sort_key_val, &$sort_dir_val, &$sort_by_sql_ary, &$sort_order_sql, &$total_val, $forum_id = 0, $topic_id = 0, $where_sql = 'WHERE') +{ + global $db, $user, $auth, $template, $request, $phpbb_dispatcher; + + $sort_days_val = $request->variable('st', 0); + $min_time = ($sort_days_val) ? time() - ($sort_days_val * 86400) : 0; + + switch ($mode) + { + case 'viewforum': + $type = 'topics'; + $default_key = 't'; + $default_dir = 'd'; + + $sql = 'SELECT COUNT(topic_id) AS total + FROM ' . TOPICS_TABLE . " + $where_sql forum_id = $forum_id + AND topic_type NOT IN (" . POST_ANNOUNCE . ', ' . POST_GLOBAL . ") + AND topic_last_post_time >= $min_time"; + + if (!$auth->acl_get('m_approve', $forum_id)) + { + $sql .= ' AND topic_visibility = ' . ITEM_APPROVED; + } + break; + + case 'viewtopic': + $type = 'posts'; + $default_key = 't'; + $default_dir = 'a'; + + $sql = 'SELECT COUNT(post_id) AS total + FROM ' . POSTS_TABLE . " + $where_sql topic_id = $topic_id + AND post_time >= $min_time"; + + if (!$auth->acl_get('m_approve', $forum_id)) + { + $sql .= ' AND post_visibility = ' . ITEM_APPROVED; + } + break; + + case 'unapproved_posts': + case 'deleted_posts': + $visibility_const = ($mode == 'unapproved_posts') ? array(ITEM_UNAPPROVED, ITEM_REAPPROVE) : ITEM_DELETED; + $type = 'posts'; + $default_key = 't'; + $default_dir = 'd'; + $where_sql .= ($topic_id) ? ' p.topic_id = ' . $topic_id . ' AND' : ''; + + $sql = 'SELECT COUNT(p.post_id) AS total + FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . " t + $where_sql " . $db->sql_in_set('p.forum_id', ($forum_id) ? array($forum_id) : array_intersect(get_forum_list('f_read'), get_forum_list('m_approve'))) . ' + AND ' . $db->sql_in_set('p.post_visibility', $visibility_const) .' + AND t.topic_id = p.topic_id + AND t.topic_visibility <> p.post_visibility'; + + if ($min_time) + { + $sql .= ' AND post_time >= ' . $min_time; + } + break; + + case 'unapproved_topics': + case 'deleted_topics': + $visibility_const = ($mode == 'unapproved_topics') ? array(ITEM_UNAPPROVED, ITEM_REAPPROVE) : ITEM_DELETED; + $type = 'topics'; + $default_key = 't'; + $default_dir = 'd'; + + $sql = 'SELECT COUNT(topic_id) AS total + FROM ' . TOPICS_TABLE . " + $where_sql " . $db->sql_in_set('forum_id', ($forum_id) ? array($forum_id) : array_intersect(get_forum_list('f_read'), get_forum_list('m_approve'))) . ' + AND ' . $db->sql_in_set('topic_visibility', $visibility_const); + + if ($min_time) + { + $sql .= ' AND topic_time >= ' . $min_time; + } + break; + + case 'pm_reports': + case 'pm_reports_closed': + case 'reports': + case 'reports_closed': + $pm = (strpos($mode, 'pm_') === 0) ? true : false; + + $type = ($pm) ? 'pm_reports' : 'reports'; + $default_key = 't'; + $default_dir = 'd'; + $limit_time_sql = ($min_time) ? "AND r.report_time >= $min_time" : ''; + + if ($topic_id) + { + $where_sql .= ' p.topic_id = ' . $topic_id . ' AND '; + } + else if ($forum_id) + { + $where_sql .= ' p.forum_id = ' . $forum_id . ' AND '; + } + else if (!$pm) + { + $where_sql .= ' ' . $db->sql_in_set('p.forum_id', get_forum_list(array('!f_read', '!m_report')), true, true) . ' AND '; + } + + if ($mode == 'reports' || $mode == 'pm_reports') + { + $where_sql .= ' r.report_closed = 0 AND '; + } + else + { + $where_sql .= ' r.report_closed = 1 AND '; + } + + if ($pm) + { + $sql = 'SELECT COUNT(r.report_id) AS total + FROM ' . REPORTS_TABLE . ' r, ' . PRIVMSGS_TABLE . " p + $where_sql r.post_id = 0 + AND p.msg_id = r.pm_id + $limit_time_sql"; + } + else + { + $sql = 'SELECT COUNT(r.report_id) AS total + FROM ' . REPORTS_TABLE . ' r, ' . POSTS_TABLE . " p + $where_sql r.pm_id = 0 + AND p.post_id = r.post_id + $limit_time_sql"; + } + break; + + case 'viewlogs': + $type = 'logs'; + $default_key = 't'; + $default_dir = 'd'; + + $sql = 'SELECT COUNT(log_id) AS total + FROM ' . LOG_TABLE . " + $where_sql " . $db->sql_in_set('forum_id', ($forum_id) ? array($forum_id) : array_intersect(get_forum_list('f_read'), get_forum_list('m_'))) . ' + AND log_time >= ' . $min_time . ' + AND log_type = ' . LOG_MOD; + break; + } + + $sort_key_val = $request->variable('sk', $default_key); + $sort_dir_val = $request->variable('sd', $default_dir); + $sort_dir_text = array('a' => $user->lang['ASCENDING'], 'd' => $user->lang['DESCENDING']); + + switch ($type) + { + case 'topics': + $limit_days = array(0 => $user->lang['ALL_TOPICS'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']); + $sort_by_text = array('a' => $user->lang['AUTHOR'], 't' => $user->lang['POST_TIME'], 'tt' => $user->lang['TOPIC_TIME'], 'r' => $user->lang['REPLIES'], 's' => $user->lang['SUBJECT'], 'v' => $user->lang['VIEWS']); + + $sort_by_sql_ary = array('a' => 't.topic_first_poster_name', 't' => array('t.topic_last_post_time', 't.topic_last_post_id'), 'tt' => 't.topic_time', 'r' => (($auth->acl_get('m_approve', $forum_id)) ? 't.topic_posts_approved + t.topic_posts_unapproved + t.topic_posts_softdeleted' : 't.topic_posts_approved'), 's' => 't.topic_title', 'v' => 't.topic_views'); + $limit_time_sql = ($min_time) ? "AND t.topic_last_post_time >= $min_time" : ''; + break; + + case 'posts': + $limit_days = array(0 => $user->lang['ALL_POSTS'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']); + $sort_by_text = array('a' => $user->lang['AUTHOR'], 't' => $user->lang['POST_TIME'], 's' => $user->lang['SUBJECT']); + $sort_by_sql_ary = array('a' => 'u.username_clean', 't' => array('p.post_time', 'p.post_id'), 's' => 'p.post_subject'); + $limit_time_sql = ($min_time) ? "AND p.post_time >= $min_time" : ''; + break; + + case 'reports': + $limit_days = array(0 => $user->lang['ALL_REPORTS'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']); + $sort_by_text = array('a' => $user->lang['AUTHOR'], 'r' => $user->lang['REPORTER'], 'p' => $user->lang['POST_TIME'], 't' => $user->lang['REPORT_TIME'], 's' => $user->lang['SUBJECT']); + $sort_by_sql_ary = array('a' => 'u.username_clean', 'r' => 'ru.username', 'p' => array('p.post_time', 'p.post_id'), 't' => 'r.report_time', 's' => 'p.post_subject'); + break; + + case 'pm_reports': + $limit_days = array(0 => $user->lang['ALL_REPORTS'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']); + $sort_by_text = array('a' => $user->lang['AUTHOR'], 'r' => $user->lang['REPORTER'], 'p' => $user->lang['POST_TIME'], 't' => $user->lang['REPORT_TIME'], 's' => $user->lang['SUBJECT']); + $sort_by_sql_ary = array('a' => 'u.username_clean', 'r' => 'ru.username', 'p' => 'p.message_time', 't' => 'r.report_time', 's' => 'p.message_subject'); + break; + + case 'logs': + $limit_days = array(0 => $user->lang['ALL_ENTRIES'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']); + $sort_by_text = array('u' => $user->lang['SORT_USERNAME'], 't' => $user->lang['SORT_DATE'], 'i' => $user->lang['SORT_IP'], 'o' => $user->lang['SORT_ACTION']); + + $sort_by_sql_ary = array('u' => 'u.username_clean', 't' => 'l.log_time', 'i' => 'l.log_ip', 'o' => 'l.log_operation'); + $limit_time_sql = ($min_time) ? "AND l.log_time >= $min_time" : ''; + break; + } + + // Default total to -1 to allow editing by the event + $total_val = -1; + + $sort_by_sql = $sort_by_sql_ary; + $sort_days = $sort_days_val; + $sort_dir = $sort_dir_val; + $sort_key = $sort_key_val; + $total = $total_val; + /** + * This event allows you to control the SQL query used to get the total number + * of reports the user can access. + * + * This total is used for the pagination and for displaying the total number + * of reports to the user + * + * + * @event core.mcp_sorting_query_before + * @var string sql The current SQL search string + * @var string mode An id related to the module(s) the user is viewing + * @var string type Which kind of information is this being used for displaying. Posts, topics, etc... + * @var int forum_id The forum id of the posts the user is trying to access, if not 0 + * @var int topic_id The topic id of the posts the user is trying to access, if not 0 + * @var int sort_days The max age of the oldest report to be shown, in days + * @var string sort_key The way the user has decided to sort the data. + * The valid values must be in the keys of the sort_by_* variables + * @var string sort_dir Either 'd' for "DESC" or 'a' for 'ASC' in the SQL query + * @var int limit_days The possible max ages of the oldest report for the user to choose, in days. + * @var array sort_by_sql SQL text (values) for the possible names of the ways of sorting data (keys). + * @var array sort_by_text Language text (values) for the possible names of the ways of sorting data (keys). + * @var int min_time Integer with the minimum post time that the user is searching for + * @var int limit_time_sql Time limiting options used in the SQL query. + * @var int total The total number of reports that exist. Only set if you want to override the result + * @var string where_sql Extra information included in the WHERE clause. It must end with "WHERE" or "AND" or "OR". + * Set to "WHERE" and set total above -1 to override the total value + * @since 3.1.4-RC1 + */ + $vars = array( + 'sql', + 'mode', + 'type', + 'forum_id', + 'topic_id', + 'sort_days', + 'sort_key', + 'sort_dir', + 'limit_days', + 'sort_by_sql', + 'sort_by_text', + 'min_time', + 'limit_time_sql', + 'total', + 'where_sql', + ); + extract($phpbb_dispatcher->trigger_event('core.mcp_sorting_query_before', compact($vars))); + $sort_by_sql_ary = $sort_by_sql; + $sort_days_val = $sort_days; + $sort_key_val = $sort_key; + $sort_dir_val = $sort_dir; + $total_val = $total; + unset($sort_by_sql); + unset($sort_days); + unset($sort_key); + unset($sort_dir); + unset($total); + + if (!isset($sort_by_sql_ary[$sort_key_val])) + { + $sort_key_val = $default_key; + } + + $direction = ($sort_dir_val == 'd') ? 'DESC' : 'ASC'; + + if (is_array($sort_by_sql_ary[$sort_key_val])) + { + $sort_order_sql = implode(' ' . $direction . ', ', $sort_by_sql_ary[$sort_key_val]) . ' ' . $direction; + } + else + { + $sort_order_sql = $sort_by_sql_ary[$sort_key_val] . ' ' . $direction; + } + + $s_limit_days = $s_sort_key = $s_sort_dir = $sort_url = ''; + gen_sort_selects($limit_days, $sort_by_text, $sort_days_val, $sort_key_val, $sort_dir_val, $s_limit_days, $s_sort_key, $s_sort_dir, $sort_url); + + $template->assign_vars(array( + 'S_SELECT_SORT_DIR' => $s_sort_dir, + 'S_SELECT_SORT_KEY' => $s_sort_key, + 'S_SELECT_SORT_DAYS' => $s_limit_days) + ); + + if (($sort_days_val && $mode != 'viewlogs') || in_array($mode, array('reports', 'unapproved_topics', 'unapproved_posts', 'deleted_topics', 'deleted_posts')) || $where_sql != 'WHERE') + { + $result = $db->sql_query($sql); + $total_val = (int) $db->sql_fetchfield('total'); + $db->sql_freeresult($result); + } + else if ($total_val < -1) + { + $total_val = -1; + } +} + +/** +* Validate ids +* +* @param array &$ids The relevant ids to check +* @param string $table The table to find the ids in +* @param string $sql_id The ids relevant column name +* @param array $acl_list A list of permissions the user need to have +* @param mixed $singe_forum Limit to one forum id (int) or the first forum found (true) +* +* @return mixed False if no ids were able to be retrieved, true if at least one id left. +* Additionally, this value can be the forum_id assigned if $single_forum was set. +* Therefore checking the result for with !== false is the best method. +*/ +function phpbb_check_ids(&$ids, $table, $sql_id, $acl_list = false, $single_forum = false) +{ + global $db, $auth; + + if (!is_array($ids) || empty($ids)) + { + return false; + } + + $sql = "SELECT $sql_id, forum_id FROM $table + WHERE " . $db->sql_in_set($sql_id, $ids); + $result = $db->sql_query($sql); + + $ids = array(); + $forum_id = false; + + while ($row = $db->sql_fetchrow($result)) + { + if ($acl_list && $row['forum_id'] && !$auth->acl_gets($acl_list, $row['forum_id'])) + { + continue; + } + + if ($acl_list && !$row['forum_id'] && !$auth->acl_getf_global($acl_list)) + { + continue; + } + + // Limit forum? If not, just assign the id. + if ($single_forum === false) + { + $ids[] = $row[$sql_id]; + continue; + } + + // Limit forum to a specific forum id? + // This can get really tricky, because we do not want to create a failure on global topics. :) + if ($row['forum_id']) + { + if ($single_forum !== true && $row['forum_id'] == (int) $single_forum) + { + $forum_id = (int) $single_forum; + } + else if ($forum_id === false) + { + $forum_id = $row['forum_id']; + } + + if ($row['forum_id'] == $forum_id) + { + $ids[] = $row[$sql_id]; + } + } + else + { + // Always add a global topic + $ids[] = $row[$sql_id]; + } + } + $db->sql_freeresult($result); + + if (!sizeof($ids)) + { + return false; + } + + // If forum id is false and ids populated we may have only global announcements selected (returning 0 because of (int) $forum_id) + + return ($single_forum === false) ? true : (int) $forum_id; +} diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php index 6ceeb50330..0aee9dd3cf 100644 --- a/phpBB/includes/functions_messenger.php +++ b/phpBB/includes/functions_messenger.php @@ -1,9 +1,13 @@ <?php /** * -* @package phpBB3 -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -17,7 +21,6 @@ if (!defined('IN_PHPBB')) /** * Messenger -* @package phpBB3 */ class messenger { @@ -30,8 +33,6 @@ class messenger /** @var \phpbb\template\template */ protected $template; - var $eol = "\n"; - /** * Constructor */ @@ -41,10 +42,6 @@ class messenger $this->use_queue = (!$config['email_package_size']) ? false : $use_queue; $this->subject = ''; - - // Determine EOL character (\n for UNIX, \r\n for Windows and \r for Mac) - $this->eol = (!defined('PHP_EOL')) ? (($eol = strtolower(substr(PHP_OS, 0, 3))) == 'win') ? "\r\n" : (($eol == 'mac') ? "\r" : "\n") : PHP_EOL; - $this->eol = (!$this->eol) ? "\n" : $this->eol; } /** @@ -209,7 +206,7 @@ class messenger */ function template($template_file, $template_lang = '', $template_path = '') { - global $config, $phpbb_root_path, $phpEx, $user, $phpbb_extension_manager; + global $config, $phpbb_root_path, $user; $this->setup_template(); @@ -252,7 +249,12 @@ class messenger } } - $this->set_template_paths($template_lang . '_email', $template_paths); + $this->set_template_paths(array( + array( + 'name' => $template_lang . '_email', + 'ext_path' => 'language/' . $template_lang . '/email' + ), + ), $template_paths); $this->template->set_filenames(array( 'body' => $template_file . '.txt', @@ -347,7 +349,7 @@ class messenger */ function error($type, $msg) { - global $user, $phpEx, $phpbb_root_path, $config, $request; + global $user, $config, $request, $phpbb_log; // Session doesn't exist, create it if (!isset($user->session_id) || $user->session_id === '') @@ -357,7 +359,6 @@ class messenger $calling_page = htmlspecialchars_decode($request->server('PHP_SELF')); - $message = ''; switch ($type) { case 'EMAIL': @@ -370,7 +371,7 @@ class messenger } $message .= '<br /><em>' . htmlspecialchars($calling_page) . '</em><br /><br />' . $msg . '<br />'; - add_log('critical', 'LOG_ERROR_' . $type, $message); + $phpbb_log->add('critical', $user->data['user_id'], $user->ip, 'LOG_ERROR_' . $type, false, array($message)); } /** @@ -394,17 +395,9 @@ class messenger */ function generate_message_id() { - global $config; + global $config, $request; - $domain = 'phpbb.generated'; - if ($config['server_name']) - { - $domain = $config['server_name']; - } - else if (!empty($_SERVER['SERVER_NAME'])) - { - $domain = $_SERVER['SERVER_NAME']; - } + $domain = ($config['server_name']) ?: $request->server('SERVER_NAME', 'phpbb.generated'); return md5(unique_id(time())) . '@' . $domain; } @@ -459,7 +452,7 @@ class messenger */ function msg_email() { - global $config, $user; + global $config; if (empty($config['email_enable'])) { @@ -484,17 +477,20 @@ class messenger $use_queue = true; } + $contact_name = htmlspecialchars_decode($config['board_contact_name']); + $board_contact = (($contact_name !== '') ? '"' . mail_encode($contact_name) . '" ' : '') . '<' . $config['board_contact'] . '>'; + if (empty($this->replyto)) { - $this->replyto = '<' . $config['board_contact'] . '>'; + $this->replyto = $board_contact; } if (empty($this->from)) { - $this->from = '<' . $config['board_contact'] . '>'; + $this->from = $board_contact; } - $encode_eol = ($config['smtp_delivery']) ? "\r\n" : $this->eol; + $encode_eol = ($config['smtp_delivery']) ? "\r\n" : PHP_EOL; // Build to, cc and bcc strings $to = $cc = $bcc = ''; @@ -507,7 +503,7 @@ class messenger foreach ($address_ary as $which_ary) { - $$type .= (($$type != '') ? ', ' : '') . (($which_ary['name'] != '') ? mail_encode($which_ary['name'], $encode_eol) . ' <' . $which_ary['email'] . '>' : $which_ary['email']); + ${$type} .= ((${$type} != '') ? ', ' : '') . (($which_ary['name'] != '') ? mail_encode($which_ary['name'], $encode_eol) . ' <' . $which_ary['email'] . '>' : $which_ary['email']); } } @@ -526,7 +522,7 @@ class messenger } else { - $result = phpbb_mail($mail_to, $this->subject, $this->msg, $headers, $this->eol, $err_msg); + $result = phpbb_mail($mail_to, $this->subject, $this->msg, $headers, PHP_EOL, $err_msg); } if (!$result) @@ -554,7 +550,7 @@ class messenger */ function msg_jabber() { - global $config, $db, $user, $phpbb_root_path, $phpEx; + global $config, $user, $phpbb_root_path, $phpEx; if (empty($config['jab_enable']) || empty($config['jab_host']) || empty($config['jab_username']) || empty($config['jab_password'])) { @@ -626,14 +622,33 @@ class messenger */ protected function setup_template() { - global $config, $phpbb_path_helper, $user, $phpbb_extension_manager; + global $phpbb_extension_manager, $phpbb_container, $phpbb_filesystem; if ($this->template instanceof \phpbb\template\template) { return; } - $this->template = new \phpbb\template\twig\twig($phpbb_path_helper, $config, $user, new \phpbb\template\context(), $phpbb_extension_manager); + $this->template = new \phpbb\template\twig\twig( + $phpbb_container->get('path_helper'), + $phpbb_container->get('config'), + new \phpbb\template\context(), + new \phpbb\template\twig\environment( + $phpbb_container->get('config'), + $phpbb_container->get('filesystem'), + $phpbb_container->get('path_helper'), + $phpbb_container, + $phpbb_container->getParameter('core.root_path') . 'cache/', + $phpbb_container->get('ext.manager'), + new \phpbb\template\twig\loader( + $phpbb_filesystem + ) + ), + $phpbb_container->getParameter('core.root_path') . 'cache/', + $phpbb_container->get('user'), + $phpbb_container->get('template.twig.extensions.collection'), + $phpbb_extension_manager + ); } /** @@ -649,7 +664,6 @@ class messenger /** * handling email and jabber queue -* @package phpBB3 */ class queue { @@ -660,18 +674,20 @@ class queue var $eol = "\n"; /** + * @var \phpbb\filesystem\filesystem_interface + */ + protected $filesystem; + + /** * constructor */ function queue() { - global $phpEx, $phpbb_root_path; + global $phpEx, $phpbb_root_path, $phpbb_filesystem; $this->data = array(); $this->cache_file = "{$phpbb_root_path}cache/queue.$phpEx"; - - // Determine EOL character (\n for UNIX, \r\n for Windows and \r for Mac) - $this->eol = (!defined('PHP_EOL')) ? (($eol = strtolower(substr(PHP_OS, 0, 3))) == 'win') ? "\r\n" : (($eol == 'mac') ? "\r" : "\n") : PHP_EOL; - $this->eol = (!$this->eol) ? "\n" : $this->eol; + $this->filesystem = $phpbb_filesystem; } /** @@ -698,7 +714,7 @@ class queue */ function process() { - global $db, $config, $phpEx, $phpbb_root_path, $user; + global $config, $phpEx, $phpbb_root_path, $user; $lock = new \phpbb\lock\flock($this->cache_file); $lock->acquire(); @@ -709,14 +725,14 @@ class queue { if (!$have_cache_file) { - set_config('last_queue_run', time(), true); + $config->set('last_queue_run', time(), false); } $lock->release(); return; } - set_config('last_queue_run', time(), true); + $config->set('last_queue_run', time(), false); include($this->cache_file); @@ -768,13 +784,15 @@ class queue if (!$this->jabber->connect()) { - messenger::error('JABBER', $user->lang['ERR_JAB_CONNECT']); + $messenger = new messenger(); + $messenger->error('JABBER', $user->lang['ERR_JAB_CONNECT']); continue 2; } if (!$this->jabber->login()) { - messenger::error('JABBER', $user->lang['ERR_JAB_AUTH']); + $messenger = new messenger(); + $messenger->error('JABBER', $user->lang['ERR_JAB_AUTH']); continue 2; } @@ -802,12 +820,13 @@ class queue } else { - $result = phpbb_mail($to, $subject, $msg, $headers, $this->eol, $err_msg); + $result = phpbb_mail($to, $subject, $msg, $headers, PHP_EOL, $err_msg); } if (!$result) { - messenger::error('EMAIL', $err_msg); + $messenger = new messenger(); + $messenger->error('EMAIL', $err_msg); continue 2; } break; @@ -817,7 +836,8 @@ class queue { if ($this->jabber->send_message($address, $msg, $subject) === false) { - messenger::error('JABBER', $this->jabber->get_log()); + $messenger = new messenger(); + $messenger->error('JABBER', $this->jabber->get_log()); continue 3; } } @@ -853,7 +873,14 @@ class queue fwrite($fp, "<?php\nif (!defined('IN_PHPBB')) exit;\n\$this->queue_data = unserialize(" . var_export(serialize($this->queue_data), true) . ");\n\n?>"); fclose($fp); - phpbb_chmod($this->cache_file, CHMOD_READ | CHMOD_WRITE); + try + { + $this->filesystem->phpbb_chmod($this->cache_file, CHMOD_READ | CHMOD_WRITE); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } } } @@ -895,7 +922,16 @@ class queue fwrite($fp, "<?php\nif (!defined('IN_PHPBB')) exit;\n\$this->queue_data = unserialize(" . var_export(serialize($this->data), true) . ");\n\n?>"); fclose($fp); - phpbb_chmod($this->cache_file, CHMOD_READ | CHMOD_WRITE); + try + { + $this->filesystem->phpbb_chmod($this->cache_file, CHMOD_READ | CHMOD_WRITE); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } + + $this->data = array(); } $lock->release(); @@ -1125,7 +1161,6 @@ function smtpmail($addresses, $subject, $message, &$err_msg, $headers = false) * SMTP Class * Auth Mechanisms originally taken from the AUTH Modules found within the PHP Extension and Application Repository (PEAR) * See docs/AUTHORS for more details -* @package phpBB3 */ class smtp_class { @@ -1222,8 +1257,6 @@ class smtp_class { global $user; - $err_msg = ''; - // Here we try to determine the *real* hostname (reverse DNS entry preferrably) $local_host = $user->host; @@ -1258,7 +1291,7 @@ class smtp_class $this->server_send("QUIT"); fclose($this->socket); - $result = $this->pop_before_smtp($hostname, $username, $password); + $this->pop_before_smtp($hostname, $username, $password); $username = $password = $default_auth_method = ''; // We need to close the previous session, else the server is not @@ -1700,7 +1733,7 @@ function mail_encode($str, $eol = "\r\n") */ function phpbb_mail($to, $subject, $msg, $headers, $eol, &$err_msg) { - global $config, $phpbb_root_path, $phpEx; + global $phpbb_root_path, $phpEx; // We use the EOL character for the OS here because the PHP mail function does not correctly transform line endings. On Windows SMTP is used (SMTP is \r\n), on UNIX a command is used... // Reference: http://bugs.php.net/bug.php?id=15841 diff --git a/phpBB/includes/functions_module.php b/phpBB/includes/functions_module.php index 53055752f6..7a1991d69a 100644 --- a/phpBB/includes/functions_module.php +++ b/phpBB/includes/functions_module.php @@ -1,9 +1,13 @@ <?php /** * -* @package phpBB3 -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -17,7 +21,6 @@ if (!defined('IN_PHPBB')) /** * Class handling all types of 'plugins' (a future term) -* @package phpBB3 */ class p_master { @@ -79,8 +82,8 @@ class p_master */ function list_modules($p_class) { - global $auth, $db, $user, $cache; - global $config, $phpbb_root_path, $phpEx; + global $db, $user, $cache; + global $phpbb_dispatcher; // Sanitise for future path use, it's escaped as appropriate for queries $this->p_class = str_replace(array('.', '/', '\\'), '', basename($p_class)); @@ -125,8 +128,17 @@ class p_master // Clean up module cache array to only let survive modules the user can access $right_id = false; + + $hide_categories = array(); foreach ($this->module_cache['modules'] as $key => $row) { + // When the module has no mode (category) we check whether it has visible children + // before listing it as well. + if (!$row['module_mode']) + { + $hide_categories[(int) $row['module_id']] = $key; + } + // Not allowed to view module? if (!$this->module_auth_self($row['module_auth'])) { @@ -161,6 +173,22 @@ class p_master $right_id = $row['right_id']; continue; } + + if ($row['module_mode']) + { + // The parent category has a visible child + // So remove it and all its parents from the hide array + unset($hide_categories[(int) $row['parent_id']]); + foreach ($this->module_cache['parents'][$row['module_id']] as $module_id => $row_id) + { + unset($hide_categories[$module_id]); + } + } + } + + foreach ($hide_categories as $module_id => $row_id) + { + unset($this->module_cache['modules'][$row_id]); } // Re-index (this is needed, else we are not able to array_slice later) @@ -222,13 +250,25 @@ class p_master // Function for building 'url_extra' $short_name = $this->get_short_name($row['module_basename']); - $url_func = '_module_' . $short_name . '_url'; + $url_func = 'phpbb_module_' . $short_name . '_url'; + if (!function_exists($url_func)) + { + $url_func = '_module_' . $short_name . '_url'; + } // Function for building the language name - $lang_func = '_module_' . $short_name . '_lang'; + $lang_func = 'phpbb_module_' . $short_name . '_lang'; + if (!function_exists($lang_func)) + { + $lang_func = '_module_' . $short_name . '_lang'; + } // Custom function for calling parameters on module init (for example assigning template variables) - $custom_func = '_module_' . $short_name; + $custom_func = 'phpbb_module_' . $short_name; + if (!function_exists($custom_func)) + { + $custom_func = '_module_' . $short_name; + } $names[$row['module_basename'] . '_' . $row['module_mode']][] = true; @@ -259,6 +299,20 @@ class p_master $custom_func($row['module_mode'], $module_row); } + /** + * This event allows to modify parameters for building modules list + * + * @event core.modify_module_row + * @var string url_func Function for building 'url_extra' + * @var string lang_func Function for building the language name + * @var string custom_func Custom function for calling parameters on module init + * @var array row Array holding the basic module data + * @var array module_row Array holding the module display parameters + * @since 3.1.0-b3 + */ + $vars = array('url_func', 'lang_func', 'custom_func', 'row', 'module_row'); + extract($phpbb_dispatcher->trigger_event('core.modify_module_row', compact($vars))); + $this->module_ary[] = $module_row; } @@ -359,6 +413,7 @@ class p_master 'cfg_([a-z0-9_]+)' => '(int) $config[\'\\1\']', 'request_([a-zA-Z0-9_]+)' => '$request->variable(\'\\1\', false)', 'ext_([a-zA-Z0-9_/]+)' => 'array_key_exists(\'\\1\', $phpbb_extension_manager->all_enabled())', + 'authmethod_([a-z0-9_\\\\]+)' => '($config[\'auth_method\'] === \'\\1\')', ); /** @@ -370,7 +425,7 @@ class p_master * @var string module_auth The module_auth of the current * module * @var int forum_id The current forum_id - * @since 3.1-A3 + * @since 3.1.0-a3 */ $vars = array('valid_tokens', 'module_auth', 'forum_id'); extract($phpbb_dispatcher->trigger_event('core.module_auth', compact($vars))); @@ -413,7 +468,9 @@ class p_master ); $is_auth = false; + // @codingStandardsIgnoreStart eval('$is_auth = (int) (' . $module_auth . ');'); + // @codingStandardsIgnoreEnd return $is_auth; } @@ -423,13 +480,21 @@ class p_master */ function set_active($id = false, $mode = false) { + global $request; + $icat = false; $this->active_module = false; - if (request_var('icat', '')) + if ($request->variable('icat', '')) { $icat = $id; - $id = request_var('icat', ''); + $id = $request->variable('icat', ''); + } + + // Restore the backslashes in class names + if (strpos($id, '-') !== false) + { + $id = str_replace('-', '\\', $id); } if ($id && !is_numeric($id) && !$this->is_full_class($id)) @@ -484,18 +549,20 @@ class p_master * * This method loads a given module, passing it the relevant id and mode. * - * @param string $mode mode, as passed through to the module + * @param string|false $mode mode, as passed through to the module + * @param string|false $module_url If supplied, we use this module url + * @param bool $execute_module If true, at the end we execute the main method for the new instance */ function load_active($mode = false, $module_url = false, $execute_module = true) { - global $phpbb_root_path, $phpbb_admin_path, $phpEx, $user, $template; + global $phpbb_root_path, $phpbb_admin_path, $phpEx, $user, $template, $request; $module_path = $this->include_path . $this->p_class; - $icat = request_var('icat', ''); + $icat = $request->variable('icat', ''); if ($this->active_module === false) { - trigger_error('Module not accessible', E_USER_ERROR); + trigger_error('MODULE_NOT_ACCESS', E_USER_ERROR); } // new modules use the full class names, old ones are always called <type>_<name>, e.g. acp_board @@ -503,14 +570,14 @@ class p_master { if (!file_exists("$module_path/{$this->p_name}.$phpEx")) { - trigger_error("Cannot find module $module_path/{$this->p_name}.$phpEx", E_USER_ERROR); + trigger_error($user->lang('MODULE_NOT_FIND', "$module_path/{$this->p_name}.$phpEx"), E_USER_ERROR); } include("$module_path/{$this->p_name}.$phpEx"); if (!class_exists($this->p_name)) { - trigger_error("Module file $module_path/{$this->p_name}.$phpEx does not contain correct class [{$this->p_name}]", E_USER_ERROR); + trigger_error($user->lang('MODULE_FILE_INCORRECT_CLASS', "$module_path/{$this->p_name}.$phpEx", $this->p_name), E_USER_ERROR); } } @@ -541,7 +608,12 @@ class p_master if (is_dir($module_style_dir)) { - $template->set_custom_style('adm', array($module_style_dir, $phpbb_admin_path . 'style')); + $template->set_custom_style(array( + array( + 'name' => 'adm', + 'ext_path' => 'adm/style/', + ), + ), array($module_style_dir, $phpbb_admin_path . 'style')); } } @@ -552,7 +624,7 @@ class p_master } // Not being able to overwrite ;) - $this->module->u_action = append_sid("{$phpbb_admin_path}index.$phpEx", 'i=' . $this->get_module_identifier($this->p_name, $this->p_id)) . (($icat) ? '&icat=' . $icat : '') . "&mode={$this->p_mode}"; + $this->module->u_action = append_sid("{$phpbb_admin_path}index.$phpEx", 'i=' . $this->get_module_identifier($this->p_name)) . (($icat) ? '&icat=' . $icat : '') . "&mode={$this->p_mode}"; } else { @@ -584,7 +656,7 @@ class p_master $this->module->u_action = $phpbb_root_path . (($user->page['page_dir']) ? $user->page['page_dir'] . '/' : '') . $user->page['page_name']; } - $this->module->u_action = append_sid($this->module->u_action, 'i=' . $this->get_module_identifier($this->p_name, $this->p_id)) . (($icat) ? '&icat=' . $icat : '') . "&mode={$this->p_mode}"; + $this->module->u_action = append_sid($this->module->u_action, 'i=' . $this->get_module_identifier($this->p_name)) . (($icat) ? '&icat=' . $icat : '') . "&mode={$this->p_mode}"; } // Add url_extra parameter to u_action url @@ -657,8 +729,6 @@ class p_master */ function get_parents($parent_id, $left_id, $right_id, &$all_parents) { - global $db; - $parents = array(); if ($parent_id > 0) @@ -750,7 +820,7 @@ class p_master // Make sure the module_url has a question mark set, effectively determining the delimiter to use $delim = (strpos($module_url, '?') === false) ? '?' : '&'; - $current_padding = $current_depth = 0; + $current_depth = 0; $linear_offset = 'l_block1'; $tabular_offset = 't_block2'; @@ -837,7 +907,7 @@ class p_master else { // if the category has a name, then use it. - $u_title .= $this->get_module_identifier($item_ary['name'], $item_ary['id']); + $u_title .= $this->get_module_identifier($item_ary['name']); } // If the item is not a category append the mode if (!$item_ary['cat']) @@ -906,7 +976,7 @@ class p_master * * @param string $class module class (acp/mcp/ucp) * @param string $name module name (class name of the module, or its basename - * phpbb_ext_foo_acp_bar_module, ucp_zebra or zebra) + * phpbb_ext_foo_acp_bar_module, ucp_zebra or zebra) * @param string $mode mode, as passed through to the module * */ @@ -931,7 +1001,7 @@ class p_master /** * Display module */ - function display($page_title, $display_online_list = true) + function display($page_title, $display_online_list = false) { global $template, $user; @@ -978,19 +1048,45 @@ class p_master */ function add_mod_info($module_class) { - global $user, $phpEx; - - global $phpbb_extension_manager; + global $config, $user, $phpEx, $phpbb_extension_manager; $finder = $phpbb_extension_manager->get_finder(); - $lang_files = $finder + // We grab the language files from the default, English and user's language. + // So we can fall back to the other files like we do when using add_lang() + $default_lang_files = $english_lang_files = $user_lang_files = array(); + + // Search for board default language if it's not the user language + if ($config['default_lang'] != $user->lang_name) + { + $default_lang_files = $finder + ->prefix('info_' . strtolower($module_class) . '_') + ->suffix(".$phpEx") + ->extension_directory('/language/' . basename($config['default_lang'])) + ->core_path('language/' . basename($config['default_lang']) . '/mods/') + ->find(); + } + + // Search for english, if its not the default or user language + if ($config['default_lang'] != 'en' && $user->lang_name != 'en') + { + $english_lang_files = $finder + ->prefix('info_' . strtolower($module_class) . '_') + ->suffix(".$phpEx") + ->extension_directory('/language/en') + ->core_path('language/en/mods/') + ->find(); + } + + // Find files in the user's language + $user_lang_files = $finder ->prefix('info_' . strtolower($module_class) . '_') ->suffix(".$phpEx") ->extension_directory('/language/' . $user->lang_name) ->core_path('language/' . $user->lang_name . '/mods/') ->find(); + $lang_files = array_merge($english_lang_files, $default_lang_files, $user_lang_files); foreach ($lang_files as $lang_file => $ext_name) { $user->add_lang_ext($ext_name, $lang_file); @@ -1016,26 +1112,24 @@ class p_master } /** - * If the basename contains a \ we dont use that for the URL. + * If the basename contains a \ we don't use that for the URL. * * Firefox is currently unable to correctly copy a urlencoded \ * so users will be unable to post links to modules. - * However we can still fallback to the id instead of the name, - * so we do that in this case. + * However we can replace them with dashes and re-replace them later * * @param string $basename Basename of the module - * @param int $id Id of the module - * @return mixed Identifier that should be used for + * @return string Identifier that should be used for * module link creation */ - protected function get_module_identifier($basename, $id) + protected function get_module_identifier($basename) { if (strpos($basename, '\\') === false) { return $basename; } - return $id; + return str_replace('\\', '-', $basename); } /** diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php index 8e9cc3a950..56d2408e88 100644 --- a/phpBB/includes/functions_posting.php +++ b/phpBB/includes/functions_posting.php @@ -1,9 +1,13 @@ <?php /** * -* @package phpBB3 -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -20,12 +24,13 @@ if (!defined('IN_PHPBB')) */ function generate_smilies($mode, $forum_id) { - global $db, $user, $config, $template, $phpbb_dispatcher; - global $phpEx, $phpbb_root_path, $phpbb_container; + global $db, $user, $config, $template, $phpbb_dispatcher, $request; + global $phpEx, $phpbb_root_path, $phpbb_container, $phpbb_path_helper; - $base_url = append_sid("{$phpbb_root_path}posting.$phpEx", 'mode=smilies&f=' . $forum_id); + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); - $start = request_var('start', 0); + $base_url = append_sid("{$phpbb_root_path}posting.$phpEx", 'mode=smilies&f=' . $forum_id); + $start = $request->variable('start', 0); if ($mode == 'window') { @@ -111,7 +116,7 @@ function generate_smilies($mode, $forum_id) if (sizeof($smilies)) { - $root_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? generate_board_url() . '/' : $phpbb_root_path; + $root_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? generate_board_url() . '/' : $phpbb_path_helper->get_web_root_path(); foreach ($smilies as $row) { @@ -133,7 +138,7 @@ function generate_smilies($mode, $forum_id) * @var string mode Mode of the smilies: window|inline * @var int forum_id The forum ID we are currently in * @var bool display_link Shall we display the "more smilies" link? - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('mode', 'forum_id', 'display_link'); extract($phpbb_dispatcher->trigger_event('core.generate_smilies_after', compact($vars))); @@ -173,7 +178,6 @@ function update_post_information($type, $ids, $return_update_sql = false) $ids = array($ids); } - $update_sql = $empty_forums = $not_empty_forums = array(); if ($type != 'topic') @@ -310,6 +314,7 @@ function posting_gen_topic_icons($mode, $icon_id) 'ICON_IMG' => $root_path . $config['icons_path'] . '/' . $data['img'], 'ICON_WIDTH' => $data['width'], 'ICON_HEIGHT' => $data['height'], + 'ICON_ALT' => $data['alt'], 'S_CHECKED' => ($id == $icon_id) ? true : false, 'S_ICON_CHECKED' => ($id == $icon_id) ? ' checked="checked"' : '') @@ -328,23 +333,20 @@ function posting_gen_topic_icons($mode, $icon_id) */ function posting_gen_topic_types($forum_id, $cur_topic_type = POST_NORMAL) { - global $auth, $user, $template, $topic_type; + global $auth, $user, $template; $toggle = false; $topic_types = array( - 'sticky' => array('const' => POST_STICKY, 'lang' => 'POST_STICKY'), - 'announce' => array('const' => POST_ANNOUNCE, 'lang' => 'POST_ANNOUNCEMENT'), - 'global' => array('const' => POST_GLOBAL, 'lang' => 'POST_GLOBAL') + 'sticky' => array('const' => POST_STICKY, 'lang' => 'POST_STICKY'), + 'announce' => array('const' => POST_ANNOUNCE, 'lang' => 'POST_ANNOUNCEMENT'), + 'announce_global' => array('const' => POST_GLOBAL, 'lang' => 'POST_GLOBAL') ); $topic_type_array = array(); foreach ($topic_types as $auth_key => $topic_value) { - // We do not have a special post global announcement permission - $auth_key = ($auth_key == 'global') ? 'announce' : $auth_key; - if ($auth->acl_get('f_' . $auth_key, $forum_id)) { $toggle = true; @@ -374,8 +376,8 @@ function posting_gen_topic_types($forum_id, $cur_topic_type = POST_NORMAL) $template->assign_vars(array( 'S_TOPIC_TYPE_STICKY' => ($auth->acl_get('f_sticky', $forum_id)), - 'S_TOPIC_TYPE_ANNOUNCE' => ($auth->acl_get('f_announce', $forum_id))) - ); + 'S_TOPIC_TYPE_ANNOUNCE' => ($auth->acl_gets('f_announce', 'f_announce_global', $forum_id)), + )); } return $toggle; @@ -389,164 +391,27 @@ function posting_gen_topic_types($forum_id, $cur_topic_type = POST_NORMAL) * Upload Attachment - filedata is generated here * Uses upload class * +* @deprecated 3.2.0-a1 (To be removed: 3.4.0) +* * @param string $form_name The form name of the file upload input * @param int $forum_id The id of the forum * @param bool $local Whether the file is local or not * @param string $local_storage The path to the local file * @param bool $is_message Whether it is a PM or not -* @param \filespec $local_filedata A filespec object created for the local file -* @param \phpbb\plupload\plupload $plupload The plupload object if one is being used +* @param array $local_filedata A filespec object created for the local file * -* @return object filespec +* @return array File data array */ -function upload_attachment($form_name, $forum_id, $local = false, $local_storage = '', $is_message = false, $local_filedata = false, \phpbb\plupload\plupload $plupload = null) +function upload_attachment($form_name, $forum_id, $local = false, $local_storage = '', $is_message = false, $local_filedata = false) { - global $auth, $user, $config, $db, $cache; - global $phpbb_root_path, $phpEx; - - $filedata = array( - 'error' => array() - ); - - include_once($phpbb_root_path . 'includes/functions_upload.' . $phpEx); - $upload = new fileupload(); - - if ($config['check_attachment_content'] && isset($config['mime_triggers'])) - { - $upload->set_disallowed_content(explode('|', $config['mime_triggers'])); - } - - $filedata['post_attach'] = $local || $upload->is_valid($form_name); - - if (!$filedata['post_attach']) - { - $filedata['error'][] = $user->lang['NO_UPLOAD_FORM_FOUND']; - return $filedata; - } - - $extensions = $cache->obtain_attach_extensions((($is_message) ? false : (int) $forum_id)); - $upload->set_allowed_extensions(array_keys($extensions['_allowed_'])); - - $file = ($local) ? $upload->local_upload($local_storage, $local_filedata) : $upload->form_upload($form_name, $plupload); - - if ($file->init_error) - { - $filedata['post_attach'] = false; - return $filedata; - } - - // Whether the uploaded file is in the image category - $is_image = (isset($extensions[$file->get('extension')]['display_cat'])) ? $extensions[$file->get('extension')]['display_cat'] == ATTACHMENT_CATEGORY_IMAGE : false; - - if (!$auth->acl_get('a_') && !$auth->acl_get('m_', $forum_id)) - { - // Check Image Size, if it is an image - if ($is_image) - { - $file->upload->set_allowed_dimensions(0, 0, $config['img_max_width'], $config['img_max_height']); - } - - // Admins and mods are allowed to exceed the allowed filesize - if (!empty($extensions[$file->get('extension')]['max_filesize'])) - { - $allowed_filesize = $extensions[$file->get('extension')]['max_filesize']; - } - else - { - $allowed_filesize = ($is_message) ? $config['max_filesize_pm'] : $config['max_filesize']; - } - - $file->upload->set_max_filesize($allowed_filesize); - } - - $file->clean_filename('unique', $user->data['user_id'] . '_'); - - // Are we uploading an image *and* this image being within the image category? - // Only then perform additional image checks. - $file->move_file($config['upload_path'], false, !$is_image); - - // Do we have to create a thumbnail? - $filedata['thumbnail'] = ($is_image && $config['img_create_thumbnail']) ? 1 : 0; - - if (sizeof($file->error)) - { - $file->remove(); - $filedata['error'] = array_merge($filedata['error'], $file->error); - $filedata['post_attach'] = false; - - return $filedata; - } - - // Make sure the image category only holds valid images... - if ($is_image && !$file->is_image()) - { - $file->remove(); - - if ($plupload && $plupload->is_active()) - { - $plupload->emit_error(104, 'ATTACHED_IMAGE_NOT_IMAGE'); - } - - // If this error occurs a user tried to exploit an IE Bug by renaming extensions - // Since the image category is displaying content inline we need to catch this. - trigger_error($user->lang['ATTACHED_IMAGE_NOT_IMAGE']); - } - - $filedata['filesize'] = $file->get('filesize'); - $filedata['mimetype'] = $file->get('mimetype'); - $filedata['extension'] = $file->get('extension'); - $filedata['physical_filename'] = $file->get('realname'); - $filedata['real_filename'] = $file->get('uploadname'); - $filedata['filetime'] = time(); - - // Check our complete quota - if ($config['attachment_quota']) - { - if ($config['upload_dir_size'] + $file->get('filesize') > $config['attachment_quota']) - { - $filedata['error'][] = $user->lang['ATTACH_QUOTA_REACHED']; - $filedata['post_attach'] = false; + global $phpbb_container; - $file->remove(); + /** @var \phpbb\attachment\manager $attachment_manager */ + $attachment_manager = $phpbb_container->get('attachment.manager'); + $file = $attachment_manager->upload($form_name, $forum_id, $local, $local_storage, $is_message, $local_filedata); + unset($attachment_manager); - return $filedata; - } - } - - // Check free disk space - if ($free_space = @disk_free_space($phpbb_root_path . $config['upload_path'])) - { - if ($free_space <= $file->get('filesize')) - { - if ($auth->acl_get('a_')) - { - $filedata['error'][] = $user->lang['ATTACH_DISK_FULL']; - } - else - { - $filedata['error'][] = $user->lang['ATTACH_QUOTA_REACHED']; - } - $filedata['post_attach'] = false; - - $file->remove(); - - return $filedata; - } - } - - // Create Thumbnail - if ($filedata['thumbnail']) - { - $source = $file->get('destination_file'); - $destination = $file->get('destination_path') . '/thumb_' . $file->get('realname'); - - if (!create_thumbnail($source, $destination, $file->get('mimetype'))) - { - $filedata['thumbnail'] = 0; - } - } - - return $filedata; + return $file; } /** @@ -645,7 +510,7 @@ function get_supported_image_types($type = false) */ function create_thumbnail($source, $destination, $mimetype) { - global $config; + global $config, $phpbb_filesystem; $min_filesize = (int) $config['img_min_thumb_filesize']; $img_filesize = (file_exists($source)) ? @filesize($source) : false; @@ -797,7 +662,14 @@ function create_thumbnail($source, $destination, $mimetype) return false; } - phpbb_chmod($destination, CHMOD_READ | CHMOD_WRITE); + try + { + $phpbb_filesystem->phpbb_chmod($destination, CHMOD_READ | CHMOD_WRITE); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } return true; } @@ -886,7 +758,7 @@ function posting_gen_attachment_entry($attachment_data, &$filename_data, $show_a function load_drafts($topic_id = 0, $forum_id = 0, $id = 0, $pm_action = '', $msg_id = 0) { global $user, $db, $template, $auth; - global $phpbb_root_path, $phpEx; + global $phpbb_root_path, $phpbb_dispatcher, $phpEx; $topic_ids = $forum_ids = $draft_rows = array(); @@ -929,7 +801,7 @@ function load_drafts($topic_id = 0, $forum_id = 0, $id = 0, $pm_action = '', $ms $topic_rows = array(); if (sizeof($topic_ids)) { - $sql = 'SELECT topic_id, forum_id, topic_title + $sql = 'SELECT topic_id, forum_id, topic_title, topic_poster FROM ' . TOPICS_TABLE . ' WHERE ' . $db->sql_in_set('topic_id', array_unique($topic_ids)); $result = $db->sql_query($sql); @@ -940,6 +812,20 @@ function load_drafts($topic_id = 0, $forum_id = 0, $id = 0, $pm_action = '', $ms } $db->sql_freeresult($result); } + + /** + * Drafts found and their topics + * Edit $draft_rows in order to add or remove drafts loaded + * + * @event core.load_drafts_draft_list_result + * @var array draft_rows The drafts query result. Includes its forum id and everything about the draft + * @var array topic_ids The list of topics got from the topics table + * @var array topic_rows The topics that draft_rows references + * @since 3.1.0-RC3 + */ + $vars = array('draft_rows', 'topic_ids', 'topic_rows'); + extract($phpbb_dispatcher->trigger_event('core.load_drafts_draft_list_result', compact($vars))); + unset($topic_ids); $template->assign_var('S_SHOW_DRAFTS', true); @@ -947,7 +833,7 @@ function load_drafts($topic_id = 0, $forum_id = 0, $id = 0, $pm_action = '', $ms foreach ($draft_rows as $draft) { $link_topic = $link_forum = $link_pm = false; - $insert_url = $view_url = $title = ''; + $view_url = $title = ''; if (isset($topic_rows[$draft['topic_id']]) && ( @@ -1000,10 +886,12 @@ function load_drafts($topic_id = 0, $forum_id = 0, $id = 0, $pm_action = '', $ms */ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id = 0, $show_quote_button = true) { - global $user, $auth, $db, $template, $bbcode, $cache; - global $config, $phpbb_root_path, $phpEx, $phpbb_container; + global $user, $auth, $db, $template; + global $config, $phpbb_root_path, $phpEx, $phpbb_container, $phpbb_dispatcher; + /* @var $phpbb_content_visibility \phpbb\content_visibility */ $phpbb_content_visibility = $phpbb_container->get('content.visibility'); + $sql_sort = ($mode == 'post_review') ? 'ASC' : 'DESC'; // Go ahead and pull all data for this topic $sql = 'SELECT p.post_id @@ -1012,8 +900,7 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id AND " . $phpbb_content_visibility->get_visibility_sql('post', $forum_id, 'p.') . ' ' . (($mode == 'post_review') ? " AND p.post_id > $cur_post_id" : '') . ' ' . (($mode == 'post_review_edit') ? " AND p.post_id = $cur_post_id" : '') . ' - ORDER BY p.post_time '; - $sql .= ($mode == 'post_review') ? 'ASC' : 'DESC'; + ORDER BY p.post_time ' . $sql_sort . ', p.post_id ' . $sql_sort; $result = $db->sql_query_limit($sql, $config['posts_per_page']); $post_list = array(); @@ -1058,13 +945,11 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id $sql = $db->sql_build_query('SELECT', $sql_ary); $result = $db->sql_query($sql); - $bbcode_bitfield = ''; $rowset = array(); $has_attachments = false; while ($row = $db->sql_fetchrow($result)) { $rowset[$row['post_id']] = $row; - $bbcode_bitfield = $bbcode_bitfield | base64_decode($row['bbcode_bitfield']); if ($row['post_attachment']) { @@ -1073,19 +958,10 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id } $db->sql_freeresult($result); - // Instantiate BBCode class - if (!isset($bbcode) && $bbcode_bitfield !== '') - { - include_once($phpbb_root_path . 'includes/bbcode.' . $phpEx); - $bbcode = new bbcode(base64_encode($bbcode_bitfield)); - } - // Grab extensions - $extensions = $attachments = array(); + $attachments = array(); if ($has_attachments && $auth->acl_get('u_download') && $auth->acl_get('f_download', $forum_id)) { - $extensions = $cache->obtain_attach_extensions($forum_id); - // Get attachments... $sql = 'SELECT * FROM ' . ATTACHMENTS_TABLE . ' @@ -1140,7 +1016,7 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id $post_anchor = ($mode == 'post_review') ? 'ppr' . $row['post_id'] : 'pr' . $row['post_id']; $u_show_post = append_sid($phpbb_root_path . 'viewtopic.' . $phpEx, "f=$forum_id&t=$topic_id&p={$row['post_id']}&view=show#p{$row['post_id']}"); - $template->assign_block_vars($mode . '_row', array( + $post_row = array( 'POST_AUTHOR_FULL' => get_username_string('full', $poster_id, $row['username'], $row['user_colour'], $row['post_username']), 'POST_AUTHOR_COLOUR' => get_username_string('colour', $poster_id, $row['username'], $row['user_colour'], $row['post_username']), 'POST_AUTHOR' => get_username_string('username', $poster_id, $row['username'], $row['user_colour'], $row['post_username']), @@ -1149,7 +1025,7 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id 'S_HAS_ATTACHMENTS' => (!empty($attachments[$row['post_id']])) ? true : false, 'S_FRIEND' => ($row['friend']) ? true : false, 'S_IGNORE_POST' => ($row['foe']) ? true : false, - 'L_IGNORE_POST' => ($row['foe']) ? sprintf($user->lang['POST_BY_FOE'], get_username_string('full', $poster_id, $row['username'], $row['user_colour'], $row['post_username']), "<a href=\"{$u_show_post}\" onclick=\"dE('{$post_anchor}', 1); return false;\">", '</a>') : '', + 'L_IGNORE_POST' => ($row['foe']) ? sprintf($user->lang['POST_BY_FOE'], get_username_string('full', $poster_id, $row['username'], $row['user_colour'], $row['post_username']), "<a href=\"{$u_show_post}\" onclick=\"phpbb.toggleDisplay('{$post_anchor}', 1); return false;\">", '</a>') : '', 'POST_SUBJECT' => $post_subject, 'MINI_POST_IMG' => $user->img('icon_post_target', $user->lang['POST']), @@ -1157,11 +1033,41 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id 'MESSAGE' => $message, 'DECODED_MESSAGE' => $decoded_message, 'POST_ID' => $row['post_id'], + 'POST_TIME' => $row['post_time'], + 'USER_ID' => $row['user_id'], 'U_MINI_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'p=' . $row['post_id']) . '#p' . $row['post_id'], 'U_MCP_DETAILS' => ($auth->acl_get('m_info', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=main&mode=post_details&f=' . $forum_id . '&p=' . $row['post_id'], true, $user->session_id) : '', - 'POSTER_QUOTE' => ($show_quote_button && $auth->acl_get('f_reply', $forum_id)) ? addslashes(get_username_string('username', $poster_id, $row['username'], $row['user_colour'], $row['post_username'])) : '') + 'POSTER_QUOTE' => ($show_quote_button && $auth->acl_get('f_reply', $forum_id)) ? addslashes(get_username_string('username', $poster_id, $row['username'], $row['user_colour'], $row['post_username'])) : '', ); + $current_row_number = $i; + + /** + * Event to modify the template data block for topic reviews + * + * @event core.topic_review_modify_row + * @var string mode The review mode + * @var int topic_id The topic that is being reviewed + * @var int forum_id The topic's forum + * @var int cur_post_id Post offset id + * @var int current_row_number Number of the current row being iterated + * @var array post_row Template block array of the current post + * @var array row Array with original post and user data + * @since 3.1.4-RC1 + */ + $vars = array( + 'mode', + 'topic_id', + 'forum_id', + 'cur_post_id', + 'current_row_number', + 'post_row', + 'row', + ); + extract($phpbb_dispatcher->trigger_event('core.topic_review_modify_row', compact($vars))); + + $template->assign_block_vars($mode . '_row', $post_row); + // Display not already displayed Attachments for this post, we already parsed them. ;) if (!empty($attachments[$row['post_id']])) { @@ -1193,7 +1099,7 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id */ function delete_post($forum_id, $topic_id, $post_id, &$data, $is_soft = false, $softdelete_reason = '') { - global $db, $user, $auth, $phpbb_container; + global $db, $user, $phpbb_container; global $config, $phpEx, $phpbb_root_path; // Specify our post mode @@ -1240,6 +1146,7 @@ function delete_post($forum_id, $topic_id, $post_id, &$data, $is_soft = false, $ $db->sql_freeresult($result); } + /* @var $phpbb_content_visibility \phpbb\content_visibility */ $phpbb_content_visibility = $phpbb_container->get('content.visibility'); // (Soft) delete the post @@ -1281,25 +1188,13 @@ function delete_post($forum_id, $topic_id, $post_id, &$data, $is_soft = false, $ if ($is_soft) { - $topic_row = array(); $phpbb_content_visibility->set_topic_visibility(ITEM_DELETED, $topic_id, $forum_id, $user->data['user_id'], time(), $softdelete_reason); } else { delete_topics('topic_id', array($topic_id), false); - if ($data['topic_visibility'] == ITEM_APPROVED) - { - $sql_data[FORUMS_TABLE] .= 'forum_posts_approved = forum_posts_approved - 1, forum_topics_approved = forum_topics_approved - 1'; - } - else if ($data['topic_visibility'] == ITEM_UNAPPROVED) - { - $sql_data[FORUMS_TABLE] .= 'forum_posts_unapproved = forum_posts_unapproved - 1, forum_topics_unapproved = forum_topics_unapproved - 1'; - } - else if ($data['topic_visibility'] == ITEM_DELETED) - { - $sql_data[FORUMS_TABLE] .= 'forum_posts_softdeleted = forum_posts_softdeleted - 1, forum_topics_softdeleted = forum_topics_softdeleted - 1'; - } + $phpbb_content_visibility->remove_topic_from_statistic($data, $sql_data); $update_sql = update_post_information('forum', $forum_id, true); if (sizeof($update_sql)) @@ -1317,7 +1212,7 @@ function delete_post($forum_id, $topic_id, $post_id, &$data, $is_soft = false, $ WHERE p.topic_id = $topic_id AND p.poster_id = u.user_id AND p.post_visibility = " . ITEM_APPROVED . ' - ORDER BY p.post_time ASC'; + ORDER BY p.post_time ASC, p.post_id ASC'; $result = $db->sql_query_limit($sql, 1); $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); @@ -1329,7 +1224,7 @@ function delete_post($forum_id, $topic_id, $post_id, &$data, $is_soft = false, $ FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . " u WHERE p.topic_id = $topic_id AND p.poster_id = u.user_id - ORDER BY p.post_time ASC"; + ORDER BY p.post_time ASC, p.post_id ASC"; $result = $db->sql_query_limit($sql, 1); $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); @@ -1384,7 +1279,7 @@ function delete_post($forum_id, $topic_id, $post_id, &$data, $is_soft = false, $ WHERE topic_id = $topic_id AND " . $phpbb_content_visibility->get_visibility_sql('post', $forum_id) . ' AND post_time > ' . $data['post_time'] . ' - ORDER BY post_time ASC'; + ORDER BY post_time ASC, post_id ASC'; $result = $db->sql_query_limit($sql, 1); $next_post_id = (int) $db->sql_fetchfield('post_id'); $db->sql_freeresult($result); @@ -1395,20 +1290,7 @@ function delete_post($forum_id, $topic_id, $post_id, &$data, $is_soft = false, $ { if (!$is_soft) { - if ($data['post_visibility'] == ITEM_APPROVED) - { - $phpbb_content_visibility->remove_post_from_statistic($data, $sql_data); - } - else if ($data['post_visibility'] == ITEM_UNAPPROVED) - { - $sql_data[FORUMS_TABLE] = (($sql_data[FORUMS_TABLE]) ? $sql_data[FORUMS_TABLE] . ', ' : '') . 'forum_posts_unapproved = forum_posts_unapproved - 1'; - $sql_data[TOPICS_TABLE] = (($sql_data[TOPICS_TABLE]) ? $sql_data[TOPICS_TABLE] . ', ' : '') . 'topic_posts_unapproved = topic_posts_unapproved - 1'; - } - else if ($data['post_visibility'] == ITEM_DELETED) - { - $sql_data[FORUMS_TABLE] = (($sql_data[FORUMS_TABLE]) ? $sql_data[FORUMS_TABLE] . ', ' : '') . 'forum_posts_softdeleted = forum_posts_softdeleted - 1'; - $sql_data[TOPICS_TABLE] = (($sql_data[TOPICS_TABLE]) ? $sql_data[TOPICS_TABLE] . ', ' : '') . 'topic_posts_softdeleted = topic_posts_softdeleted - 1'; - } + $phpbb_content_visibility->remove_post_from_statistic($data, $sql_data); } $sql = 'SELECT 1 AS has_attachments @@ -1475,10 +1357,12 @@ function delete_post($forum_id, $topic_id, $post_id, &$data, $is_soft = false, $ * Submit Post * @todo Split up and create lightweight, simple API for this. */ -function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $update_message = true, $update_search_index = true) +function submit_post($mode, $subject, $username, $topic_type, &$poll_ary, &$data_ary, $update_message = true, $update_search_index = true) { - global $db, $auth, $user, $config, $phpEx, $template, $phpbb_root_path, $phpbb_container, $phpbb_dispatcher; + global $db, $auth, $user, $config, $phpEx, $phpbb_root_path, $phpbb_container, $phpbb_dispatcher, $phpbb_log, $request; + $poll = $poll_ary; + $data = $data_ary; /** * Modify the data for post submitting * @@ -1493,7 +1377,21 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u * @var bool update_search_index Flag indicating if the search index will be updated * @since 3.1.0-a4 */ - extract($phpbb_dispatcher->trigger_event('core.modify_submit_post_data', compact(array('mode', 'subject', 'username', 'topic_type', 'poll', 'data', 'update_message', 'update_search_index')))); + $vars = array( + 'mode', + 'subject', + 'username', + 'topic_type', + 'poll', + 'data', + 'update_message', + 'update_search_index', + ); + extract($phpbb_dispatcher->trigger_event('core.modify_submit_post_data', compact($vars))); + $poll_ary = $poll; + $data_ary = $data; + unset($poll); + unset($data); // We do not handle erasing posts here if ($mode == 'delete') @@ -1501,7 +1399,14 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u return false; } - $current_time = time(); + if (!empty($data_ary['post_time'])) + { + $current_time = $data_ary['post_time']; + } + else + { + $current_time = time(); + } if ($mode == 'post') { @@ -1515,31 +1420,31 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u } else if ($mode == 'edit') { - $post_mode = ($data['topic_posts_approved'] + $data['topic_posts_unapproved'] + $data['topic_posts_softdeleted'] == 1) ? 'edit_topic' : (($data['topic_first_post_id'] == $data['post_id']) ? 'edit_first_post' : (($data['topic_last_post_id'] == $data['post_id']) ? 'edit_last_post' : 'edit')); + $post_mode = ($data_ary['topic_posts_approved'] + $data_ary['topic_posts_unapproved'] + $data_ary['topic_posts_softdeleted'] == 1) ? 'edit_topic' : (($data_ary['topic_first_post_id'] == $data_ary['post_id']) ? 'edit_first_post' : (($data_ary['topic_last_post_id'] == $data_ary['post_id']) ? 'edit_last_post' : 'edit')); } // First of all make sure the subject and topic title are having the correct length. // To achieve this without cutting off between special chars we convert to an array and then count the elements. $subject = truncate_string($subject, 120); - $data['topic_title'] = truncate_string($data['topic_title'], 120); + $data_ary['topic_title'] = truncate_string($data_ary['topic_title'], 120); // Collect some basic information about which tables and which rows to update/insert $sql_data = $topic_row = array(); - $poster_id = ($mode == 'edit') ? $data['poster_id'] : (int) $user->data['user_id']; + $poster_id = ($mode == 'edit') ? $data_ary['poster_id'] : (int) $user->data['user_id']; // Retrieve some additional information if not present - if ($mode == 'edit' && (!isset($data['post_visibility']) || !isset($data['topic_visibility']) || $data['post_visibility'] === false || $data['topic_visibility'] === false)) + if ($mode == 'edit' && (!isset($data_ary['post_visibility']) || !isset($data_ary['topic_visibility']) || $data_ary['post_visibility'] === false || $data_ary['topic_visibility'] === false)) { $sql = 'SELECT p.post_visibility, t.topic_type, t.topic_posts_approved, t.topic_posts_unapproved, t.topic_posts_softdeleted, t.topic_visibility FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . ' p WHERE t.topic_id = p.topic_id - AND p.post_id = ' . $data['post_id']; + AND p.post_id = ' . $data_ary['post_id']; $result = $db->sql_query($sql); $topic_row = $db->sql_fetchrow($result); $db->sql_freeresult($result); - $data['topic_visibility'] = $topic_row['topic_visibility']; - $data['post_visibility'] = $topic_row['post_visibility']; + $data_ary['topic_visibility'] = $topic_row['topic_visibility']; + $data_ary['post_visibility'] = $topic_row['post_visibility']; } // This variable indicates if the user is able to post or put into the queue @@ -1547,20 +1452,29 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u // Check the permissions for post approval. // Moderators must go through post approval like ordinary users. - if (!$auth->acl_get('f_noapprove', $data['forum_id'])) + if (!$auth->acl_get('f_noapprove', $data_ary['forum_id'])) { // Post not approved, but in queue $post_visibility = ITEM_UNAPPROVED; + switch ($post_mode) + { + case 'edit_first_post': + case 'edit': + case 'edit_last_post': + case 'edit_topic': + $post_visibility = ITEM_REAPPROVE; + break; + } } // MODs/Extensions are able to force any visibility on posts - if (isset($data['force_approved_state'])) + if (isset($data_ary['force_approved_state'])) { - $post_visibility = (in_array((int) $data['force_approved_state'], array(ITEM_APPROVED, ITEM_UNAPPROVED, ITEM_DELETED))) ? (int) $data['force_approved_state'] : $post_visibility; + $post_visibility = (in_array((int) $data_ary['force_approved_state'], array(ITEM_APPROVED, ITEM_UNAPPROVED, ITEM_DELETED, ITEM_REAPPROVE))) ? (int) $data_ary['force_approved_state'] : $post_visibility; } - if (isset($data['force_visibility'])) + if (isset($data_ary['force_visibility'])) { - $post_visibility = (in_array((int) $data['force_visibility'], array(ITEM_APPROVED, ITEM_UNAPPROVED, ITEM_DELETED))) ? (int) $data['force_visibility'] : $post_visibility; + $post_visibility = (in_array((int) $data_ary['force_visibility'], array(ITEM_APPROVED, ITEM_UNAPPROVED, ITEM_DELETED, ITEM_REAPPROVE))) ? (int) $data_ary['force_visibility'] : $post_visibility; } // Start the transaction here @@ -1572,25 +1486,25 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u case 'post': case 'reply': $sql_data[POSTS_TABLE]['sql'] = array( - 'forum_id' => $data['forum_id'], + 'forum_id' => $data_ary['forum_id'], 'poster_id' => (int) $user->data['user_id'], - 'icon_id' => $data['icon_id'], + 'icon_id' => $data_ary['icon_id'], 'poster_ip' => $user->ip, 'post_time' => $current_time, 'post_visibility' => $post_visibility, - 'enable_bbcode' => $data['enable_bbcode'], - 'enable_smilies' => $data['enable_smilies'], - 'enable_magic_url' => $data['enable_urls'], - 'enable_sig' => $data['enable_sig'], + 'enable_bbcode' => $data_ary['enable_bbcode'], + 'enable_smilies' => $data_ary['enable_smilies'], + 'enable_magic_url' => $data_ary['enable_urls'], + 'enable_sig' => $data_ary['enable_sig'], 'post_username' => (!$user->data['is_registered']) ? $username : '', 'post_subject' => $subject, - 'post_text' => $data['message'], - 'post_checksum' => $data['message_md5'], - 'post_attachment' => (!empty($data['attachment_data'])) ? 1 : 0, - 'bbcode_bitfield' => $data['bbcode_bitfield'], - 'bbcode_uid' => $data['bbcode_uid'], - 'post_postcount' => ($auth->acl_get('f_postcount', $data['forum_id'])) ? 1 : 0, - 'post_edit_locked' => $data['post_edit_locked'] + 'post_text' => $data_ary['message'], + 'post_checksum' => $data_ary['message_md5'], + 'post_attachment' => (!empty($data_ary['attachment_data'])) ? 1 : 0, + 'bbcode_bitfield' => $data_ary['bbcode_bitfield'], + 'bbcode_uid' => $data_ary['bbcode_uid'], + 'post_postcount' => ($auth->acl_get('f_postcount', $data_ary['forum_id'])) ? 1 : 0, + 'post_edit_locked' => $data_ary['post_edit_locked'] ); break; @@ -1607,19 +1521,19 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u // If normal edit display edit info // Display edit info if edit reason given or user is editing his post, which is not the last within the topic. - if ($data['post_edit_reason'] || (!$auth->acl_get('m_edit', $data['forum_id']) && ($post_mode == 'edit' || $post_mode == 'edit_first_post'))) + if ($data_ary['post_edit_reason'] || (!$auth->acl_get('m_edit', $data_ary['forum_id']) && ($post_mode == 'edit' || $post_mode == 'edit_first_post'))) { - $data['post_edit_reason'] = truncate_string($data['post_edit_reason'], 255, 255, false); + $data_ary['post_edit_reason'] = truncate_string($data_ary['post_edit_reason'], 255, 255, false); $sql_data[POSTS_TABLE]['sql'] = array( 'post_edit_time' => $current_time, - 'post_edit_reason' => $data['post_edit_reason'], - 'post_edit_user' => (int) $data['post_edit_user'], + 'post_edit_reason' => $data_ary['post_edit_reason'], + 'post_edit_user' => (int) $data_ary['post_edit_user'], ); $sql_data[POSTS_TABLE]['stat'][] = 'post_edit_count = post_edit_count + 1'; } - else if (!$data['post_edit_reason'] && $mode == 'edit' && $auth->acl_get('m_edit', $data['forum_id'])) + else if (!$data_ary['post_edit_reason'] && $mode == 'edit' && $auth->acl_get('m_edit', $data_ary['forum_id'])) { $sql_data[POSTS_TABLE]['sql'] = array( 'post_edit_reason' => '', @@ -1630,8 +1544,15 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u // Could be simplified by only adding to the log if the edit is not tracked - but this may confuse admins/mods if ($user->data['user_id'] != $poster_id) { - $log_subject = ($subject) ? $subject : $data['topic_title']; - add_log('mod', $data['forum_id'], $data['topic_id'], 'LOG_POST_EDITED', $log_subject, (!empty($username)) ? $username : $user->lang['GUEST']); + $log_subject = ($subject) ? $subject : $data_ary['topic_title']; + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_POST_EDITED', false, array( + 'forum_id' => $data_ary['forum_id'], + 'topic_id' => $data_ary['topic_id'], + 'post_id' => $data_ary['post_id'], + $log_subject, + (!empty($username)) ? $username : $user->lang['GUEST'], + $data_ary['post_edit_reason'] + )); } if (!isset($sql_data[POSTS_TABLE]['sql'])) @@ -1640,32 +1561,31 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u } $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array( - 'forum_id' => $data['forum_id'], - 'poster_id' => $data['poster_id'], - 'icon_id' => $data['icon_id'], + 'forum_id' => $data_ary['forum_id'], + 'poster_id' => $data_ary['poster_id'], + 'icon_id' => $data_ary['icon_id'], // We will change the visibility later //'post_visibility' => $post_visibility, - 'enable_bbcode' => $data['enable_bbcode'], - 'enable_smilies' => $data['enable_smilies'], - 'enable_magic_url' => $data['enable_urls'], - 'enable_sig' => $data['enable_sig'], - 'post_username' => ($username && $data['poster_id'] == ANONYMOUS) ? $username : '', + 'enable_bbcode' => $data_ary['enable_bbcode'], + 'enable_smilies' => $data_ary['enable_smilies'], + 'enable_magic_url' => $data_ary['enable_urls'], + 'enable_sig' => $data_ary['enable_sig'], + 'post_username' => ($username && $data_ary['poster_id'] == ANONYMOUS) ? $username : '', 'post_subject' => $subject, - 'post_checksum' => $data['message_md5'], - 'post_attachment' => (!empty($data['attachment_data'])) ? 1 : 0, - 'bbcode_bitfield' => $data['bbcode_bitfield'], - 'bbcode_uid' => $data['bbcode_uid'], - 'post_edit_locked' => $data['post_edit_locked']) + 'post_checksum' => $data_ary['message_md5'], + 'post_attachment' => (!empty($data_ary['attachment_data'])) ? 1 : 0, + 'bbcode_bitfield' => $data_ary['bbcode_bitfield'], + 'bbcode_uid' => $data_ary['bbcode_uid'], + 'post_edit_locked' => $data_ary['post_edit_locked']) ); if ($update_message) { - $sql_data[POSTS_TABLE]['sql']['post_text'] = $data['message']; + $sql_data[POSTS_TABLE]['sql']['post_text'] = $data_ary['message']; } break; } - $topic_row = array(); // And the topic ladies and gentlemen switch ($post_mode) @@ -1675,8 +1595,8 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u 'topic_poster' => (int) $user->data['user_id'], 'topic_time' => $current_time, 'topic_last_view_time' => $current_time, - 'forum_id' => $data['forum_id'], - 'icon_id' => $data['icon_id'], + 'forum_id' => $data_ary['forum_id'], + 'icon_id' => $data_ary['icon_id'], 'topic_posts_approved' => ($post_visibility == ITEM_APPROVED) ? 1 : 0, 'topic_posts_softdeleted' => ($post_visibility == ITEM_DELETED) ? 1 : 0, 'topic_posts_unapproved' => ($post_visibility == ITEM_UNAPPROVED) ? 1 : 0, @@ -1686,14 +1606,15 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u 'topic_first_poster_name' => (!$user->data['is_registered'] && $username) ? $username : (($user->data['user_id'] != ANONYMOUS) ? $user->data['username'] : ''), 'topic_first_poster_colour' => $user->data['user_colour'], 'topic_type' => $topic_type, - 'topic_time_limit' => ($topic_type == POST_STICKY || $topic_type == POST_ANNOUNCE) ? ($data['topic_time_limit'] * 86400) : 0, - 'topic_attachment' => (!empty($data['attachment_data'])) ? 1 : 0, + 'topic_time_limit' => ($topic_type == POST_STICKY || $topic_type == POST_ANNOUNCE) ? ($data_ary['topic_time_limit'] * 86400) : 0, + 'topic_attachment' => (!empty($data_ary['attachment_data'])) ? 1 : 0, + 'topic_status' => (isset($data_ary['topic_status'])) ? $data_ary['topic_status'] : ITEM_UNLOCKED, ); - if (isset($poll['poll_options']) && !empty($poll['poll_options'])) + if (isset($poll_ary['poll_options']) && !empty($poll_ary['poll_options'])) { - $poll_start = ($poll['poll_start']) ? $poll['poll_start'] : $current_time; - $poll_length = $poll['poll_length'] * 86400; + $poll_start = ($poll_ary['poll_start']) ? $poll_ary['poll_start'] : $current_time; + $poll_length = $poll_ary['poll_length'] * 86400; if ($poll_length < 0) { $poll_start = $poll_start + $poll_length; @@ -1705,15 +1626,15 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u } $sql_data[TOPICS_TABLE]['sql'] = array_merge($sql_data[TOPICS_TABLE]['sql'], array( - 'poll_title' => $poll['poll_title'], + 'poll_title' => $poll_ary['poll_title'], 'poll_start' => $poll_start, - 'poll_max_options' => $poll['poll_max_options'], + 'poll_max_options' => $poll_ary['poll_max_options'], 'poll_length' => $poll_length, - 'poll_vote_change' => $poll['poll_vote_change']) + 'poll_vote_change' => $poll_ary['poll_vote_change']) ); } - $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = $current_time" . (($auth->acl_get('f_postcount', $data['forum_id']) && $post_visibility == ITEM_APPROVED) ? ', user_posts = user_posts + 1' : ''); + $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = $current_time" . (($auth->acl_get('f_postcount', $data_ary['forum_id']) && $post_visibility == ITEM_APPROVED) ? ', user_posts = user_posts + 1' : ''); if ($post_visibility == ITEM_APPROVED) { @@ -1739,9 +1660,9 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u (($post_visibility == ITEM_APPROVED) ? ', topic_posts_approved = topic_posts_approved + 1' : '') . (($post_visibility == ITEM_UNAPPROVED) ? ', topic_posts_unapproved = topic_posts_unapproved + 1' : '') . (($post_visibility == ITEM_DELETED) ? ', topic_posts_softdeleted = topic_posts_softdeleted + 1' : '') . - ((!empty($data['attachment_data']) || (isset($data['topic_attachment']) && $data['topic_attachment'])) ? ', topic_attachment = 1' : ''); + ((!empty($data_ary['attachment_data']) || (isset($data_ary['topic_attachment']) && $data_ary['topic_attachment'])) ? ', topic_attachment = 1' : ''); - $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = $current_time" . (($auth->acl_get('f_postcount', $data['forum_id']) && $post_visibility == ITEM_APPROVED) ? ', user_posts = user_posts + 1' : ''); + $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = $current_time" . (($auth->acl_get('f_postcount', $data_ary['forum_id']) && $post_visibility == ITEM_APPROVED) ? ', user_posts = user_posts + 1' : ''); if ($post_visibility == ITEM_APPROVED) { @@ -1759,10 +1680,10 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u case 'edit_topic': case 'edit_first_post': - if (isset($poll['poll_options'])) + if (isset($poll_ary['poll_options'])) { - $poll_start = ($poll['poll_start'] || empty($poll['poll_options'])) ? $poll['poll_start'] : $current_time; - $poll_length = $poll['poll_length'] * 86400; + $poll_start = ($poll_ary['poll_start'] || empty($poll_ary['poll_options'])) ? $poll_ary['poll_start'] : $current_time; + $poll_length = $poll_ary['poll_length'] * 86400; if ($poll_length < 0) { $poll_start = $poll_start + $poll_length; @@ -1775,25 +1696,55 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u } $sql_data[TOPICS_TABLE]['sql'] = array( - 'forum_id' => $data['forum_id'], - 'icon_id' => $data['icon_id'], + 'forum_id' => $data_ary['forum_id'], + 'icon_id' => $data_ary['icon_id'], 'topic_title' => $subject, 'topic_first_poster_name' => $username, 'topic_type' => $topic_type, - 'topic_time_limit' => ($topic_type == POST_STICKY || $topic_type == POST_ANNOUNCE) ? ($data['topic_time_limit'] * 86400) : 0, - 'poll_title' => (isset($poll['poll_options'])) ? $poll['poll_title'] : '', - 'poll_start' => (isset($poll['poll_options'])) ? $poll_start : 0, - 'poll_max_options' => (isset($poll['poll_options'])) ? $poll['poll_max_options'] : 1, - 'poll_length' => (isset($poll['poll_options'])) ? $poll_length : 0, - 'poll_vote_change' => (isset($poll['poll_vote_change'])) ? $poll['poll_vote_change'] : 0, + 'topic_time_limit' => ($topic_type == POST_STICKY || $topic_type == POST_ANNOUNCE) ? ($data_ary['topic_time_limit'] * 86400) : 0, + 'poll_title' => (isset($poll_ary['poll_options'])) ? $poll_ary['poll_title'] : '', + 'poll_start' => (isset($poll_ary['poll_options'])) ? $poll_start : 0, + 'poll_max_options' => (isset($poll_ary['poll_options'])) ? $poll_ary['poll_max_options'] : 1, + 'poll_length' => (isset($poll_ary['poll_options'])) ? $poll_length : 0, + 'poll_vote_change' => (isset($poll_ary['poll_vote_change'])) ? $poll_ary['poll_vote_change'] : 0, 'topic_last_view_time' => $current_time, - 'topic_attachment' => (!empty($data['attachment_data'])) ? 1 : (isset($data['topic_attachment']) ? $data['topic_attachment'] : 0), + 'topic_attachment' => (!empty($data_ary['attachment_data'])) ? 1 : (isset($data_ary['topic_attachment']) ? $data_ary['topic_attachment'] : 0), ); break; } + $poll = $poll_ary; + $data = $data_ary; + /** + * Modify sql query data for post submitting + * + * @event core.submit_post_modify_sql_data + * @var array data Array with the data for the post + * @var array poll Array with the poll data for the post + * @var string post_mode Variable containing posting mode value + * @var bool sql_data Array with the data for the posting SQL query + * @var string subject Variable containing post subject value + * @var int topic_type Variable containing topic type value + * @var string username Variable containing post author name + * @since 3.1.3-RC1 + */ + $vars = array( + 'data', + 'poll', + 'post_mode', + 'sql_data', + 'subject', + 'topic_type', + 'username', + ); + extract($phpbb_dispatcher->trigger_event('core.submit_post_modify_sql_data', compact($vars))); + $poll_ary = $poll; + $data_ary = $data; + unset($poll); + unset($data); + // Submit new topic if ($post_mode == 'post') { @@ -1801,10 +1752,10 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u $db->sql_build_array('INSERT', $sql_data[TOPICS_TABLE]['sql']); $db->sql_query($sql); - $data['topic_id'] = $db->sql_nextid(); + $data_ary['topic_id'] = $db->sql_nextid(); $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array( - 'topic_id' => $data['topic_id']) + 'topic_id' => $data_ary['topic_id']) ); unset($sql_data[TOPICS_TABLE]['sql']); } @@ -1815,18 +1766,18 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u if ($post_mode == 'reply') { $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array( - 'topic_id' => $data['topic_id'], + 'topic_id' => $data_ary['topic_id'], )); } $sql = 'INSERT INTO ' . POSTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_data[POSTS_TABLE]['sql']); $db->sql_query($sql); - $data['post_id'] = $db->sql_nextid(); + $data_ary['post_id'] = $db->sql_nextid(); if ($post_mode == 'post' || $post_visibility == ITEM_APPROVED) { $sql_data[TOPICS_TABLE]['sql'] = array( - 'topic_last_post_id' => $data['post_id'], + 'topic_last_post_id' => $data_ary['post_id'], 'topic_last_post_time' => $current_time, 'topic_last_poster_id' => $sql_data[POSTS_TABLE]['sql']['poster_id'], 'topic_last_poster_name' => ($user->data['user_id'] == ANONYMOUS) ? $sql_data[POSTS_TABLE]['sql']['post_username'] : $user->data['username'], @@ -1837,7 +1788,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u if ($post_mode == 'post') { - $sql_data[TOPICS_TABLE]['sql']['topic_first_post_id'] = $data['post_id']; + $sql_data[TOPICS_TABLE]['sql']['topic_first_post_id'] = $data_ary['post_id']; } // Update total post count and forum information @@ -1845,11 +1796,11 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u { if ($post_mode == 'post') { - set_config_count('num_topics', 1, true); + $config->increment('num_topics', 1, false); } - set_config_count('num_posts', 1, true); + $config->increment('num_posts', 1, false); - $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = ' . $data['post_id']; + $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = ' . $data_ary['post_id']; $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . $db->sql_escape($subject) . "'"; $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = ' . $current_time; $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = ' . (int) $user->data['user_id']; @@ -1865,7 +1816,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u { $sql = 'UPDATE ' . TOPICS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_data[TOPICS_TABLE]['sql']) . ' - WHERE topic_id = ' . $data['topic_id']; + WHERE topic_id = ' . $data_ary['topic_id']; $db->sql_query($sql); unset($sql_data[TOPICS_TABLE]['sql']); @@ -1876,14 +1827,14 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u { $sql = 'UPDATE ' . POSTS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_data[POSTS_TABLE]['sql']) . ' - WHERE post_id = ' . $data['post_id']; + WHERE post_id = ' . $data_ary['post_id']; $db->sql_query($sql); unset($sql_data[POSTS_TABLE]['sql']); } // Update Poll Tables - if (isset($poll['poll_options'])) + if (isset($poll_ary['poll_options'])) { $cur_poll_options = array(); @@ -1891,7 +1842,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u { $sql = 'SELECT * FROM ' . POLL_OPTIONS_TABLE . ' - WHERE topic_id = ' . $data['topic_id'] . ' + WHERE topic_id = ' . $data_ary['topic_id'] . ' ORDER BY poll_option_id'; $result = $db->sql_query($sql); @@ -1905,25 +1856,25 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u $sql_insert_ary = array(); - for ($i = 0, $size = sizeof($poll['poll_options']); $i < $size; $i++) + for ($i = 0, $size = sizeof($poll_ary['poll_options']); $i < $size; $i++) { - if (strlen(trim($poll['poll_options'][$i]))) + if (strlen(trim($poll_ary['poll_options'][$i]))) { if (empty($cur_poll_options[$i])) { // If we add options we need to put them to the end to be able to preserve votes... $sql_insert_ary[] = array( 'poll_option_id' => (int) sizeof($cur_poll_options) + 1 + sizeof($sql_insert_ary), - 'topic_id' => (int) $data['topic_id'], - 'poll_option_text' => (string) $poll['poll_options'][$i] + 'topic_id' => (int) $data_ary['topic_id'], + 'poll_option_text' => (string) $poll_ary['poll_options'][$i] ); } - else if ($poll['poll_options'][$i] != $cur_poll_options[$i]) + else if ($poll_ary['poll_options'][$i] != $cur_poll_options[$i]) { $sql = 'UPDATE ' . POLL_OPTIONS_TABLE . " - SET poll_option_text = '" . $db->sql_escape($poll['poll_options'][$i]) . "' + SET poll_option_text = '" . $db->sql_escape($poll_ary['poll_options'][$i]) . "' WHERE poll_option_id = " . $cur_poll_options[$i]['poll_option_id'] . ' - AND topic_id = ' . $data['topic_id']; + AND topic_id = ' . $data_ary['topic_id']; $db->sql_query($sql); } } @@ -1931,29 +1882,29 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u $db->sql_multi_insert(POLL_OPTIONS_TABLE, $sql_insert_ary); - if (sizeof($poll['poll_options']) < sizeof($cur_poll_options)) + if (sizeof($poll_ary['poll_options']) < sizeof($cur_poll_options)) { $sql = 'DELETE FROM ' . POLL_OPTIONS_TABLE . ' - WHERE poll_option_id > ' . sizeof($poll['poll_options']) . ' - AND topic_id = ' . $data['topic_id']; + WHERE poll_option_id > ' . sizeof($poll_ary['poll_options']) . ' + AND topic_id = ' . $data_ary['topic_id']; $db->sql_query($sql); } // If edited, we would need to reset votes (since options can be re-ordered above, you can't be sure if the change is for changing the text or adding an option - if ($mode == 'edit' && sizeof($poll['poll_options']) != sizeof($cur_poll_options)) + if ($mode == 'edit' && sizeof($poll_ary['poll_options']) != sizeof($cur_poll_options)) { - $db->sql_query('DELETE FROM ' . POLL_VOTES_TABLE . ' WHERE topic_id = ' . $data['topic_id']); - $db->sql_query('UPDATE ' . POLL_OPTIONS_TABLE . ' SET poll_option_total = 0 WHERE topic_id = ' . $data['topic_id']); + $db->sql_query('DELETE FROM ' . POLL_VOTES_TABLE . ' WHERE topic_id = ' . $data_ary['topic_id']); + $db->sql_query('UPDATE ' . POLL_OPTIONS_TABLE . ' SET poll_option_total = 0 WHERE topic_id = ' . $data_ary['topic_id']); } } // Submit Attachments - if (!empty($data['attachment_data']) && $data['post_id'] && in_array($mode, array('post', 'reply', 'quote', 'edit'))) + if (!empty($data_ary['attachment_data']) && $data_ary['post_id'] && in_array($mode, array('post', 'reply', 'quote', 'edit'))) { $space_taken = $files_added = 0; $orphan_rows = array(); - foreach ($data['attachment_data'] as $pos => $attach_row) + foreach ($data_ary['attachment_data'] as $pos => $attach_row) { $orphan_rows[(int) $attach_row['attach_id']] = array(); } @@ -1975,7 +1926,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u $db->sql_freeresult($result); } - foreach ($data['attachment_data'] as $pos => $attach_row) + foreach ($data_ary['attachment_data'] as $pos => $attach_row) { if ($attach_row['is_orphan'] && !isset($orphan_rows[$attach_row['attach_id']])) { @@ -2003,8 +1954,8 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u $files_added++; $attach_sql = array( - 'post_msg_id' => $data['post_id'], - 'topic_id' => $data['topic_id'], + 'post_msg_id' => $data_ary['post_id'], + 'topic_id' => $data_ary['topic_id'], 'is_orphan' => 0, 'poster_id' => $poster_id, 'attach_comment' => $attach_row['attach_comment'], @@ -2020,36 +1971,38 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u if ($space_taken && $files_added) { - set_config_count('upload_dir_size', $space_taken, true); - set_config_count('num_files', $files_added, true); + $config->increment('upload_dir_size', $space_taken, false); + $config->increment('num_files', $files_added, false); } } $first_post_has_topic_info = ($post_mode == 'edit_first_post' && - (($post_visibility == ITEM_DELETED && $data['topic_posts_softdeleted'] == 1) || - ($post_visibility == ITEM_UNAPPROVED && $data['topic_posts_unapproved'] == 1) || - ($post_visibility == ITEM_APPROVED && $data['topic_posts_approved'] == 1))); + (($post_visibility == ITEM_DELETED && $data_ary['topic_posts_softdeleted'] == 1) || + ($post_visibility == ITEM_UNAPPROVED && $data_ary['topic_posts_unapproved'] == 1) || + ($post_visibility == ITEM_REAPPROVE && $data_ary['topic_posts_unapproved'] == 1) || + ($post_visibility == ITEM_APPROVED && $data_ary['topic_posts_approved'] == 1))); // Fix the post's and topic's visibility and first/last post information, when the post is edited - if (($post_mode != 'post' && $post_mode != 'reply') && $data['post_visibility'] != $post_visibility) + if (($post_mode != 'post' && $post_mode != 'reply') && $data_ary['post_visibility'] != $post_visibility) { // If the post was not approved, it could also be the starter, // so we sync the starter after approving/restoring, to ensure that the stats are correct // Same applies for the last post - $is_starter = ($post_mode == 'edit_first_post' || $data['post_visibility'] != ITEM_APPROVED); - $is_latest = ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || $data['post_visibility'] != ITEM_APPROVED); + $is_starter = ($post_mode == 'edit_first_post' || $post_mode == 'edit_topic' || $data_ary['post_visibility'] != ITEM_APPROVED); + $is_latest = ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || $data_ary['post_visibility'] != ITEM_APPROVED); + /* @var $phpbb_content_visibility \phpbb\content_visibility */ $phpbb_content_visibility = $phpbb_container->get('content.visibility'); - $phpbb_content_visibility->set_post_visibility($post_visibility, $data['post_id'], $data['topic_id'], $data['forum_id'], $user->data['user_id'], time(), '', $is_starter, $is_latest); + $phpbb_content_visibility->set_post_visibility($post_visibility, $data_ary['post_id'], $data_ary['topic_id'], $data_ary['forum_id'], $user->data['user_id'], time(), '', $is_starter, $is_latest); } else if ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || $first_post_has_topic_info) { - if ($post_visibility == ITEM_APPROVED || $data['topic_visibility'] == $post_visibility) + if ($post_visibility == ITEM_APPROVED || $data_ary['topic_visibility'] == $post_visibility) { // only the subject can be changed from edit $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_post_subject = '" . $db->sql_escape($subject) . "'"; // Maybe not only the subject, but also changing anonymous usernames. ;) - if ($data['poster_id'] == ANONYMOUS) + if ($data_ary['poster_id'] == ANONYMOUS) { $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_name = '" . $db->sql_escape($username) . "'"; } @@ -2060,13 +2013,13 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u // it just means that we might have to $sql = 'SELECT forum_last_post_id, forum_last_post_subject FROM ' . FORUMS_TABLE . ' - WHERE forum_id = ' . (int) $data['forum_id']; + WHERE forum_id = ' . (int) $data_ary['forum_id']; $result = $db->sql_query($sql); $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); // this post is the latest post in the forum, better update - if ($row['forum_last_post_id'] == $data['post_id'] && ($row['forum_last_post_subject'] !== $subject || $data['poster_id'] == ANONYMOUS)) + if ($row['forum_last_post_id'] == $data_ary['post_id'] && ($row['forum_last_post_subject'] !== $subject || $data_ary['poster_id'] == ANONYMOUS)) { // the post's subject changed if ($row['forum_last_post_subject'] !== $subject) @@ -2075,7 +2028,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u } // Update the user name if poster is anonymous... just in case a moderator changed it - if ($data['poster_id'] == ANONYMOUS) + if ($data_ary['poster_id'] == ANONYMOUS) { $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape($username) . "'"; } @@ -2086,9 +2039,9 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u // Update forum stats $where_sql = array( - POSTS_TABLE => 'post_id = ' . $data['post_id'], - TOPICS_TABLE => 'topic_id = ' . $data['topic_id'], - FORUMS_TABLE => 'forum_id = ' . $data['forum_id'], + POSTS_TABLE => 'post_id = ' . $data_ary['post_id'], + TOPICS_TABLE => 'topic_id = ' . $data_ary['topic_id'], + FORUMS_TABLE => 'forum_id = ' . $data_ary['forum_id'], USERS_TABLE => 'user_id = ' . $poster_id ); @@ -2105,7 +2058,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u if ($topic_type == POST_GLOBAL) { $sql = 'DELETE FROM ' . TOPICS_TABLE . ' - WHERE topic_moved_id = ' . $data['topic_id']; + WHERE topic_moved_id = ' . $data_ary['topic_id']; $db->sql_query($sql); } @@ -2113,7 +2066,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u $db->sql_transaction('commit'); // Delete draft if post was loaded... - $draft_id = request_var('draft_loaded', 0); + $draft_id = $request->variable('draft_loaded', 0); if ($draft_id) { $sql = 'DELETE FROM ' . DRAFTS_TABLE . " @@ -2123,7 +2076,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u } // Index message contents - if ($update_search_index && $data['enable_indexing']) + if ($update_search_index && $data_ary['enable_indexing']) { // Select the search method and do some additional checks to ensure it can actually be utilised $search_type = $config['search_type']; @@ -2134,30 +2087,30 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u } $error = false; - $search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user); + $search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher); if ($error) { trigger_error($error); } - $search->index($mode, $data['post_id'], $data['message'], $subject, $poster_id, $data['forum_id']); + $search->index($mode, $data_ary['post_id'], $data_ary['message'], $subject, $poster_id, $data_ary['forum_id']); } // Topic Notification, do not change if moderator is changing other users posts... if ($user->data['user_id'] == $poster_id) { - if (!$data['notify_set'] && $data['notify']) + if (!$data_ary['notify_set'] && $data_ary['notify']) { $sql = 'INSERT INTO ' . TOPICS_WATCH_TABLE . ' (user_id, topic_id) - VALUES (' . $user->data['user_id'] . ', ' . $data['topic_id'] . ')'; + VALUES (' . $user->data['user_id'] . ', ' . $data_ary['topic_id'] . ')'; $db->sql_query($sql); } - else if (($config['email_enable'] || $config['jab_enable']) && $data['notify_set'] && !$data['notify']) + else if (($config['email_enable'] || $config['jab_enable']) && $data_ary['notify_set'] && !$data_ary['notify']) { $sql = 'DELETE FROM ' . TOPICS_WATCH_TABLE . ' WHERE user_id = ' . $user->data['user_id'] . ' - AND topic_id = ' . $data['topic_id']; + AND topic_id = ' . $data_ary['topic_id']; $db->sql_query($sql); } } @@ -2165,12 +2118,12 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u if ($mode == 'post' || $mode == 'reply' || $mode == 'quote') { // Mark this topic as posted to - markread('post', $data['forum_id'], $data['topic_id']); + markread('post', $data_ary['forum_id'], $data_ary['topic_id']); } // Mark this topic as read // We do not use post_time here, this is intended (post_time can have a date in the past if editing a message) - markread('topic', $data['forum_id'], $data['topic_id'], time()); + markread('topic', $data_ary['forum_id'], $data_ary['topic_id'], time()); // if ($config['load_db_lastread'] && $user->data['is_registered']) @@ -2178,7 +2131,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u $sql = 'SELECT mark_time FROM ' . FORUMS_TRACK_TABLE . ' WHERE user_id = ' . $user->data['user_id'] . ' - AND forum_id = ' . $data['forum_id']; + AND forum_id = ' . $data_ary['forum_id']; $result = $db->sql_query($sql); $f_mark_time = (int) $db->sql_fetchfield('mark_time'); $db->sql_freeresult($result); @@ -2193,12 +2146,12 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u // Update forum info $sql = 'SELECT forum_last_post_time FROM ' . FORUMS_TABLE . ' - WHERE forum_id = ' . $data['forum_id']; + WHERE forum_id = ' . $data_ary['forum_id']; $result = $db->sql_query($sql); $forum_last_post_time = (int) $db->sql_fetchfield('forum_last_post_time'); $db->sql_freeresult($result); - update_forum_tracking_info($data['forum_id'], $forum_last_post_time, $f_mark_time, false); + update_forum_tracking_info($data_ary['forum_id'], $forum_last_post_time, $f_mark_time, false); } // If a username was supplied or the poster is a guest, we will use the supplied username. @@ -2207,15 +2160,16 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u $username = ($username !== '' || !$user->data['is_registered']) ? $username : $user->data['username']; // Send Notifications - $notification_data = array_merge($data, array( - 'topic_title' => (isset($data['topic_title'])) ? $data['topic_title'] : $subject, + $notification_data = array_merge($data_ary, array( + 'topic_title' => (isset($data_ary['topic_title'])) ? $data_ary['topic_title'] : $subject, 'post_username' => $username, 'poster_id' => $poster_id, - 'post_text' => $data['message'], + 'post_text' => $data_ary['message'], 'post_time' => $current_time, 'post_subject' => $subject, )); + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); if ($post_visibility == ITEM_APPROVED) @@ -2224,17 +2178,17 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u { case 'post': $phpbb_notifications->add_notifications(array( - 'quote', - 'topic', + 'notification.type.quote', + 'notification.type.topic', ), $notification_data); break; case 'reply': case 'quote': $phpbb_notifications->add_notifications(array( - 'quote', - 'bookmark', - 'post', + 'notification.type.quote', + 'notification.type.bookmark', + 'notification.type.post', ), $notification_data); break; @@ -2243,10 +2197,10 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u case 'edit': case 'edit_last_post': $phpbb_notifications->update_notifications(array( - 'quote', - 'bookmark', - 'topic', - 'post', + 'notification.type.quote', + 'notification.type.bookmark', + 'notification.type.topic', + 'notification.type.post', ), $notification_data); break; } @@ -2256,51 +2210,63 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u switch ($mode) { case 'post': - $phpbb_notifications->add_notifications('topic_in_queue', $notification_data); + $phpbb_notifications->add_notifications('notification.type.topic_in_queue', $notification_data); break; case 'reply': case 'quote': - $phpbb_notifications->add_notifications('post_in_queue', $notification_data); + $phpbb_notifications->add_notifications('notification.type.post_in_queue', $notification_data); break; case 'edit_topic': case 'edit_first_post': case 'edit': case 'edit_last_post': - // @todo: Check whether these notification deletions are correct - $phpbb_notifications->delete_notifications('topic', $data['topic_id']); - - $phpbb_notifications->delete_notifications(array( - 'quote', - 'bookmark', - 'post', - ), $data['post_id']); + // Nothing to do here break; } } - else if ($post_visibility == ITEM_DELETED) + else if ($post_visibility == ITEM_REAPPROVE) { switch ($mode) { + case 'edit_topic': + case 'edit_first_post': + $phpbb_notifications->add_notifications('notification.type.topic_in_queue', $notification_data); + + // Delete the approve_post notification so we can notify the user again, + // when his post got reapproved + $phpbb_notifications->delete_notifications('notification.type.approve_post', $notification_data['post_id']); + break; + + case 'edit': + case 'edit_last_post': + $phpbb_notifications->add_notifications('notification.type.post_in_queue', $notification_data); + + // Delete the approve_post notification so we can notify the user again, + // when his post got reapproved + $phpbb_notifications->delete_notifications('notification.type.approve_post', $notification_data['post_id']); + break; + case 'post': case 'reply': case 'quote': // Nothing to do here break; - + } + } + else if ($post_visibility == ITEM_DELETED) + { + switch ($mode) + { + case 'post': + case 'reply': + case 'quote': case 'edit_topic': case 'edit_first_post': case 'edit': case 'edit_last_post': - // @todo: Check whether these notification deletions are correct - $phpbb_notifications->delete_notifications('topic', $data['topic_id']); - - $phpbb_notifications->delete_notifications(array( - 'quote', - 'bookmark', - 'post', - ), $data['post_id']); + // Nothing to do here break; } } @@ -2309,22 +2275,24 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u if ($post_visibility == ITEM_APPROVED) { - $params .= '&t=' . $data['topic_id']; + $params .= '&t=' . $data_ary['topic_id']; if ($mode != 'post') { - $params .= '&p=' . $data['post_id']; - $add_anchor = '#p' . $data['post_id']; + $params .= '&p=' . $data_ary['post_id']; + $add_anchor = '#p' . $data_ary['post_id']; } } else if ($mode != 'post' && $post_mode != 'edit_first_post' && $post_mode != 'edit_topic') { - $params .= '&t=' . $data['topic_id']; + $params .= '&t=' . $data_ary['topic_id']; } $url = (!$params) ? "{$phpbb_root_path}viewforum.$phpEx" : "{$phpbb_root_path}viewtopic.$phpEx"; - $url = append_sid($url, 'f=' . $data['forum_id'] . $params) . $add_anchor; + $url = append_sid($url, 'f=' . $data_ary['forum_id'] . $params) . $add_anchor; + $poll = $poll_ary; + $data = $data_ary; /** * This event is used for performing actions directly after a post or topic * has been submitted. When a new topic is posted, the topic ID is @@ -2334,13 +2302,38 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u * event is to modify the return URL ($url). * * @event core.submit_post_end - * @var string url The "Return to topic" URL - * @var array data Array of post data about the - * submitted post - * @since 3.1-A3 + * @var string mode Variable containing posting mode value + * @var string subject Variable containing post subject value + * @var string username Variable containing post author name + * @var int topic_type Variable containing topic type value + * @var array poll Array with the poll data for the post + * @var array data Array with the data for the post + * @var int post_visibility Variable containing up to date post visibility + * @var bool update_message Flag indicating if the post will be updated + * @var bool update_search_index Flag indicating if the search index will be updated + * @var string url The "Return to topic" URL + * + * @since 3.1.0-a3 + * @change 3.1.0-RC3 Added vars mode, subject, username, topic_type, + * poll, update_message, update_search_index */ - $vars = array('url', 'data'); + $vars = array( + 'mode', + 'subject', + 'username', + 'topic_type', + 'poll', + 'data', + 'post_visibility', + 'update_message', + 'update_search_index', + 'url', + ); extract($phpbb_dispatcher->trigger_event('core.submit_post_end', compact($vars))); + $data_ary = $data; + $poll_ary = $poll; + unset($data); + unset($poll); return $url; } @@ -2361,7 +2354,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u */ function phpbb_bump_topic($forum_id, $topic_id, $post_data, $bump_time = false) { - global $config, $db, $user, $phpEx, $phpbb_root_path; + global $config, $db, $user, $phpEx, $phpbb_root_path, $phpbb_log; if ($bump_time === false) { @@ -2440,9 +2433,160 @@ function phpbb_bump_topic($forum_id, $topic_id, $post_data, $bump_time = false) update_forum_tracking_info($forum_id, $forum_last_post_time, $f_mark_time, false); } - add_log('mod', $forum_id, $topic_id, 'LOG_BUMP_TOPIC', $post_data['topic_title']); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_BUMP_TOPIC', false, array( + 'forum_id' => $forum_id, + 'topic_id' => $topic_id, + $post_data['topic_title'] + )); $url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&t=$topic_id&p={$post_data['topic_last_post_id']}") . "#p{$post_data['topic_last_post_id']}"; return $url; } + +/** +* Show upload popup (progress bar) +*/ +function phpbb_upload_popup($forum_style = 0) +{ + global $template, $user; + + ($forum_style) ? $user->setup('posting', $forum_style) : $user->setup('posting'); + + page_header($user->lang['PROGRESS_BAR']); + + $template->set_filenames(array( + 'popup' => 'posting_progress_bar.html') + ); + + $template->assign_vars(array( + 'PROGRESS_BAR' => $user->img('upload_bar', $user->lang['UPLOAD_IN_PROGRESS'])) + ); + + $template->display('popup'); + + garbage_collection(); + exit_handler(); +} + +/** +* Do the various checks required for removing posts as well as removing it +*/ +function phpbb_handle_post_delete($forum_id, $topic_id, $post_id, &$post_data, $is_soft = false, $delete_reason = '') +{ + global $user, $auth, $config, $request; + global $phpbb_root_path, $phpEx, $phpbb_log; + + $perm_check = ($is_soft) ? 'softdelete' : 'delete'; + + // If moderator removing post or user itself removing post, present a confirmation screen + if ($auth->acl_get("m_$perm_check", $forum_id) || ($post_data['poster_id'] == $user->data['user_id'] && $user->data['is_registered'] && $auth->acl_get("f_$perm_check", $forum_id) && $post_id == $post_data['topic_last_post_id'] && !$post_data['post_edit_locked'] && ($post_data['post_time'] > time() - ($config['delete_time'] * 60) || !$config['delete_time']))) + { + $s_hidden_fields = array( + 'p' => $post_id, + 'f' => $forum_id, + 'mode' => ($is_soft) ? 'soft_delete' : 'delete', + ); + + if (confirm_box(true)) + { + $data = array( + 'topic_first_post_id' => $post_data['topic_first_post_id'], + 'topic_last_post_id' => $post_data['topic_last_post_id'], + 'topic_posts_approved' => $post_data['topic_posts_approved'], + 'topic_posts_unapproved' => $post_data['topic_posts_unapproved'], + 'topic_posts_softdeleted' => $post_data['topic_posts_softdeleted'], + 'topic_visibility' => $post_data['topic_visibility'], + 'topic_type' => $post_data['topic_type'], + 'post_visibility' => $post_data['post_visibility'], + 'post_reported' => $post_data['post_reported'], + 'post_time' => $post_data['post_time'], + 'poster_id' => $post_data['poster_id'], + 'post_postcount' => $post_data['post_postcount'], + ); + + $next_post_id = delete_post($forum_id, $topic_id, $post_id, $data, $is_soft, $delete_reason); + $post_username = ($post_data['poster_id'] == ANONYMOUS && !empty($post_data['post_username'])) ? $post_data['post_username'] : $post_data['username']; + + if ($next_post_id === false) + { + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, (($is_soft) ? 'LOG_SOFTDELETE_TOPIC' : 'LOG_DELETE_TOPIC'), false, array( + 'forum_id' => $forum_id, + 'topic_id' => $topic_id, + $post_data['topic_title'], + $post_username, + $delete_reason + )); + + $meta_info = append_sid("{$phpbb_root_path}viewforum.$phpEx", "f=$forum_id"); + $message = $user->lang['POST_DELETED']; + } + else + { + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, (($is_soft) ? 'LOG_SOFTDELETE_POST' : 'LOG_DELETE_POST'), false, array( + 'forum_id' => $forum_id, + 'topic_id' => $topic_id, + 'post_id' => $post_id, + $post_data['post_subject'], + $post_username, + $delete_reason + )); + + $meta_info = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&t=$topic_id&p=$next_post_id") . "#p$next_post_id"; + $message = $user->lang['POST_DELETED']; + + if (!$request->is_ajax()) + { + $message .= '<br /><br />' . $user->lang('RETURN_TOPIC', '<a href="' . $meta_info . '">', '</a>'); + } + } + + meta_refresh(3, $meta_info); + if (!$request->is_ajax()) + { + $message .= '<br /><br />' . $user->lang('RETURN_FORUM', '<a href="' . append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id) . '">', '</a>'); + } + trigger_error($message); + } + else + { + global $user, $template, $request; + + $can_delete = $auth->acl_get('m_delete', $forum_id) || ($post_data['poster_id'] == $user->data['user_id'] && $user->data['is_registered'] && $auth->acl_get('f_delete', $forum_id)); + $can_softdelete = $auth->acl_get('m_softdelete', $forum_id) || ($post_data['poster_id'] == $user->data['user_id'] && $user->data['is_registered'] && $auth->acl_get('f_softdelete', $forum_id)); + + $template->assign_vars(array( + 'S_SOFTDELETED' => $post_data['post_visibility'] == ITEM_DELETED, + 'S_CHECKED_PERMANENT' => $request->is_set_post('delete_permanent') ? ' checked="checked"' : '', + 'S_ALLOWED_DELETE' => $can_delete, + 'S_ALLOWED_SOFTDELETE' => $can_softdelete, + )); + + $l_confirm = 'DELETE_POST'; + if ($post_data['post_visibility'] == ITEM_DELETED) + { + $l_confirm .= '_PERMANENTLY'; + $s_hidden_fields['delete_permanent'] = '1'; + } + else if (!$can_softdelete) + { + $s_hidden_fields['delete_permanent'] = '1'; + } + + confirm_box(false, $l_confirm, build_hidden_fields($s_hidden_fields), 'confirm_delete_body.html'); + } + } + + // If we are here the user is not able to delete - present the correct error message + if ($post_data['poster_id'] != $user->data['user_id'] && $auth->acl_get('f_delete', $forum_id)) + { + trigger_error('DELETE_OWN_POSTS'); + } + + if ($post_data['poster_id'] == $user->data['user_id'] && $auth->acl_get('f_delete', $forum_id) && $post_id != $post_data['topic_last_post_id']) + { + trigger_error('CANNOT_DELETE_REPLIED'); + } + + trigger_error('USER_CANNOT_DELETE'); +} diff --git a/phpBB/includes/functions_privmsgs.php b/phpBB/includes/functions_privmsgs.php index a2a79e032f..d92934e59e 100644 --- a/phpBB/includes/functions_privmsgs.php +++ b/phpBB/includes/functions_privmsgs.php @@ -1,9 +1,13 @@ <?php /** * -* @package phpBB3 -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -208,7 +212,7 @@ function get_folder($user_id, $folder_id = false) ); } - if ($folder_id !== false && !isset($folder[$folder_id])) + if ($folder_id !== false && $folder_id !== PRIVMSGS_HOLD_BOX && !isset($folder[$folder_id])) { trigger_error('UNKNOWN_FOLDER'); } @@ -222,7 +226,7 @@ function get_folder($user_id, $folder_id = false) */ function clean_sentbox($num_sentbox_messages) { - global $db, $user, $config; + global $db, $user; // Check Message Limit if ($user->data['message_limit'] && $num_sentbox_messages > $user->data['message_limit']) @@ -251,8 +255,6 @@ function clean_sentbox($num_sentbox_messages) */ function check_rule(&$rules, &$rule_row, &$message_row, $user_id) { - global $user, $config; - if (!isset($rules[$rule_row['rule_check']][$rule_row['rule_connection']])) { return false; @@ -314,7 +316,6 @@ function check_rule(&$rules, &$rule_row, &$message_row, $user_id) break; } - if (!$result) { return false; @@ -332,7 +333,7 @@ function check_rule(&$rules, &$rule_row, &$message_row, $user_id) break; case ACTION_DELETE_MESSAGE: - global $db, $auth; + global $db; // Check for admins/mods - users are not allowed to remove those messages... // We do the check here to make sure the data we use is consistent @@ -543,7 +544,7 @@ function place_pm_into_folder(&$global_privmsgs_rules, $release = false) } // We place actions into arrays, to save queries. - $sql = $unread_ids = $delete_ids = $important_ids = array(); + $unread_ids = $delete_ids = $important_ids = array(); foreach ($action_ary as $msg_id => $msg_ary) { @@ -878,9 +879,10 @@ function update_unread_status($unread, $msg_id, $user_id, $folder_id) global $db, $user, $phpbb_container; + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); - $phpbb_notifications->mark_notifications_read('pm', $msg_id, $user_id); + $phpbb_notifications->mark_notifications('notification.type.pm', $msg_id, $user_id); $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . " SET pm_unread = 0 @@ -911,16 +913,33 @@ function update_unread_status($unread, $msg_id, $user_id, $folder_id) } } +function mark_folder_read($user_id, $folder_id) +{ + global $db; + + $sql = 'SELECT msg_id + FROM ' . PRIVMSGS_TO_TABLE . ' + WHERE folder_id = ' . ((int) $folder_id) . ' + AND user_id = ' . ((int) $user_id) . ' + AND pm_unread = 1'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + update_unread_status(true, $row['msg_id'], $user_id, $folder_id); + } + $db->sql_freeresult($result); +} + /** * Handle all actions possible with marked messages */ function handle_mark_actions($user_id, $mark_action) { - global $db, $user, $phpbb_root_path, $phpEx; + global $db, $user, $phpbb_root_path, $phpEx, $request; - $msg_ids = request_var('marked_msg_id', array(0)); - $cur_folder_id = request_var('cur_folder_id', PRIVMSGS_NO_BOX); - $confirm = (isset($_POST['confirm'])) ? true : false; + $msg_ids = $request->variable('marked_msg_id', array(0)); + $cur_folder_id = $request->variable('cur_folder_id', PRIVMSGS_NO_BOX); if (!sizeof($msg_ids)) { @@ -985,7 +1004,7 @@ function handle_mark_actions($user_id, $mark_action) */ function delete_pm($user_id, $msg_ids, $folder_id) { - global $db, $user, $phpbb_root_path, $phpEx, $phpbb_container; + global $db, $user, $phpbb_container, $phpbb_dispatcher; $user_id = (int) $user_id; $folder_id = (int) $folder_id; @@ -1009,6 +1028,18 @@ function delete_pm($user_id, $msg_ids, $folder_id) return false; } + /** + * Get all info for PM(s) before they are deleted + * + * @event core.delete_pm_before + * @var int user_id ID of the user requested the message delete + * @var array msg_ids array of all messages to be deleted + * @var int folder_id ID of the user folder where the messages are stored + * @since 3.1.0-b5 + */ + $vars = array('user_id', 'msg_ids', 'folder_id'); + extract($phpbb_dispatcher->trigger_event('core.delete_pm_before', compact($vars))); + // Get PM Information for later deleting $sql = 'SELECT msg_id, pm_unread, pm_new FROM ' . PRIVMSGS_TO_TABLE . ' @@ -1097,9 +1128,10 @@ function delete_pm($user_id, $msg_ids, $folder_id) $user->data['user_unread_privmsg'] -= $num_unread; } + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); - $phpbb_notifications->delete_notifications('pm', array_keys($delete_rows)); + $phpbb_notifications->delete_notifications('notification.type.pm', array_keys($delete_rows)); // Now we have to check which messages we can delete completely $sql = 'SELECT msg_id @@ -1118,12 +1150,10 @@ function delete_pm($user_id, $msg_ids, $folder_id) if (sizeof($delete_ids)) { // Check if there are any attachments we need to remove - if (!function_exists('delete_attachments')) - { - include($phpbb_root_path . 'includes/functions_admin.' . $phpEx); - } - - delete_attachments('message', $delete_ids, false); + /** @var \phpbb\attachment\manager $attachment_manager */ + $attachment_manager = $phpbb_container->get('attachment.manager'); + $attachment_manager->delete('message', $delete_ids, false); + unset($attachment_manager); $sql = 'DELETE FROM ' . PRIVMSGS_TABLE . ' WHERE ' . $db->sql_in_set('msg_id', $delete_ids); @@ -1144,8 +1174,6 @@ function delete_pm($user_id, $msg_ids, $folder_id) */ function phpbb_delete_user_pms($user_id) { - global $db, $user, $phpbb_root_path, $phpEx; - $user_id = (int) $user_id; if (!$user_id) @@ -1165,7 +1193,7 @@ function phpbb_delete_user_pms($user_id) */ function phpbb_delete_users_pms($user_ids) { - global $db, $user, $phpbb_root_path, $phpEx, $phpbb_container; + global $db, $phpbb_container; $user_id_sql = $db->sql_in_set('user_id', $user_ids); $author_id_sql = $db->sql_in_set('author_id', $user_ids); @@ -1210,6 +1238,7 @@ function phpbb_delete_users_pms($user_ids) $db->sql_transaction('begin'); + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); if (!empty($undelivered_msg)) @@ -1281,7 +1310,7 @@ function phpbb_delete_users_pms($user_ids) AND ' . $db->sql_in_set('msg_id', $delivered_msg); $db->sql_query($sql); - $phpbb_notifications->delete_notifications('pm', $delivered_msg); + $phpbb_notifications->delete_notifications('notification.type.pm', $delivered_msg); } if (!empty($undelivered_msg)) @@ -1294,7 +1323,7 @@ function phpbb_delete_users_pms($user_ids) WHERE ' . $db->sql_in_set('msg_id', $undelivered_msg); $db->sql_query($sql); - $phpbb_notifications->delete_notifications('pm', $undelivered_msg); + $phpbb_notifications->delete_notifications('notification.type.pm', $undelivered_msg); } } @@ -1327,18 +1356,16 @@ function phpbb_delete_users_pms($user_ids) if (!empty($delete_ids)) { // Check if there are any attachments we need to remove - if (!function_exists('delete_attachments')) - { - include($phpbb_root_path . 'includes/functions_admin.' . $phpEx); - } - - delete_attachments('message', $delete_ids, false); + /** @var \phpbb\attachment\manager $attachment_manager */ + $attachment_manager = $phpbb_container->get('attachment.manager'); + $attachment_manager->delete('message', $delete_ids, false); + unset($attachment_manager); $sql = 'DELETE FROM ' . PRIVMSGS_TABLE . ' WHERE ' . $db->sql_in_set('msg_id', $delete_ids); $db->sql_query($sql); - $phpbb_notifications->delete_notifications('pm', $delete_ids); + $phpbb_notifications->delete_notifications('notification.type.pm', $delete_ids); } } @@ -1364,8 +1391,6 @@ function phpbb_delete_users_pms($user_ids) */ function rebuild_header($check_ary) { - global $db; - $address = array(); foreach ($check_ary as $check_type => $address_field) @@ -1382,9 +1407,9 @@ function rebuild_header($check_ary) $_types = array('u', 'g'); foreach ($_types as $type) { - if (sizeof($$type)) + if (sizeof(${$type})) { - foreach ($$type as $id) + foreach (${$type} as $id) { $address[$type][$id] = $check_type; } @@ -1400,7 +1425,10 @@ function rebuild_header($check_ary) */ function write_pm_addresses($check_ary, $author_id, $plaintext = false) { - global $db, $user, $template, $phpbb_root_path, $phpEx; + global $db, $user, $template, $phpbb_root_path, $phpEx, $phpbb_container; + + /** @var \phpbb\group\helper $group_helper */ + $group_helper = $phpbb_container->get('group_helper'); $addresses = array(); @@ -1461,7 +1489,7 @@ function write_pm_addresses($check_ary, $author_id, $plaintext = false) { if ($check_type == 'to' || $author_id == $user->data['user_id'] || $row['user_id'] == $user->data['user_id']) { - $address[] = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']; + $address[] = $group_helper->get_name($row['group_name']); } } $db->sql_freeresult($result); @@ -1481,7 +1509,7 @@ function write_pm_addresses($check_ary, $author_id, $plaintext = false) { if ($check_type == 'to' || $author_id == $user->data['user_id'] || $row['user_id'] == $user->data['user_id']) { - $row['group_name'] = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']; + $row['group_name'] = $group_helper->get_name($row['group_name']); $address['group'][$row['group_id']] = array('name' => $row['group_name'], 'colour' => $row['group_colour']); } } @@ -1542,7 +1570,7 @@ function write_pm_addresses($check_ary, $author_id, $plaintext = false) */ function get_folder_status($folder_id, $folder) { - global $db, $user, $config; + global $user; if (isset($folder[$folder_id])) { @@ -1558,10 +1586,10 @@ function get_folder_status($folder_id, $folder) 'cur' => $folder['num_messages'], 'remaining' => ($user->data['message_limit']) ? $user->data['message_limit'] - $folder['num_messages'] : 0, 'max' => $user->data['message_limit'], - 'percent' => ($user->data['message_limit']) ? (($user->data['message_limit'] > 0) ? round(($folder['num_messages'] / $user->data['message_limit']) * 100) : 100) : 0, + 'percent' => ($user->data['message_limit']) ? (($user->data['message_limit'] > 0) ? floor(($folder['num_messages'] / $user->data['message_limit']) * 100) : 100) : 0, ); - $return['message'] = $user->lang('FOLDER_STATUS_MSG', (int) $return['max'], $return['cur'], $return['percent']); + $return['message'] = $user->lang('FOLDER_STATUS_MSG', $user->lang('MESSAGES_COUNT', (int) $return['max']), (int) $return['cur'], $return['percent']); return $return; } @@ -1573,9 +1601,9 @@ function get_folder_status($folder_id, $folder) /** * Submit PM */ -function submit_pm($mode, $subject, &$data, $put_in_outbox = true) +function submit_pm($mode, $subject, &$data_ary, $put_in_outbox = true) { - global $db, $auth, $config, $phpEx, $template, $user, $phpbb_root_path, $phpbb_container; + global $db, $auth, $config, $user, $phpbb_root_path, $phpbb_container, $phpbb_dispatcher, $request; // We do not handle erasing pms here if ($mode == 'delete') @@ -1585,6 +1613,21 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true) $current_time = time(); + $data = $data_ary; + /** + * Get all parts of the PM that are to be submited to the DB. + * + * @event core.submit_pm_before + * @var string mode PM Post mode - post|reply|quote|quotepost|forward|edit + * @var string subject Subject of the private message + * @var array data The whole row data of the PM. + * @since 3.1.0-b3 + */ + $vars = array('mode', 'subject', 'data'); + extract($phpbb_dispatcher->trigger_event('core.submit_pm_before', compact($vars))); + $data_ary = $data; + unset($data); + // Collect some basic information about which tables and which rows to update/insert $sql_data = array(); $root_level = 0; @@ -1599,9 +1642,9 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true) $_types = array('u', 'g'); foreach ($_types as $ug_type) { - if (isset($data['address_list'][$ug_type]) && sizeof($data['address_list'][$ug_type])) + if (isset($data_ary['address_list'][$ug_type]) && sizeof($data_ary['address_list'][$ug_type])) { - foreach ($data['address_list'][$ug_type] as $id => $field) + foreach ($data_ary['address_list'][$ug_type] as $id => $field) { $id = (int) $id; @@ -1621,7 +1664,7 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true) } } - if (isset($data['address_list']['g']) && sizeof($data['address_list']['g'])) + if (isset($data_ary['address_list']['g']) && sizeof($data_ary['address_list']['g'])) { // We need to check the PM status of group members (do they want to receive PM's?) // Only check if not a moderator or admin, since they are allowed to override this user setting @@ -1629,7 +1672,7 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true) $sql = 'SELECT u.user_type, ug.group_id, ug.user_id FROM ' . USERS_TABLE . ' u, ' . USER_GROUP_TABLE . ' ug - WHERE ' . $db->sql_in_set('ug.group_id', array_keys($data['address_list']['g'])) . ' + WHERE ' . $db->sql_in_set('ug.group_id', array_keys($data_ary['address_list']['g'])) . ' AND ug.user_pending = 0 AND u.user_id = ug.user_id AND u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')' . @@ -1638,7 +1681,7 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true) while ($row = $db->sql_fetchrow($result)) { - $field = ($data['address_list']['g'][$row['group_id']] == 'to') ? 'to' : 'bcc'; + $field = ($data_ary['address_list']['g'][$row['group_id']] == 'to') ? 'to' : 'bcc'; $recipients[$row['user_id']] = $field; } $db->sql_freeresult($result); @@ -1661,13 +1704,13 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true) { case 'reply': case 'quote': - $root_level = ($data['reply_from_root_level']) ? $data['reply_from_root_level'] : $data['reply_from_msg_id']; + $root_level = ($data_ary['reply_from_root_level']) ? $data_ary['reply_from_root_level'] : $data_ary['reply_from_msg_id']; // Set message_replied switch for this user $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' SET pm_replied = 1 - WHERE user_id = ' . $data['from_user_id'] . ' - AND msg_id = ' . $data['reply_from_msg_id']; + WHERE user_id = ' . $data_ary['from_user_id'] . ' + AND msg_id = ' . $data_ary['reply_from_msg_id']; // no break @@ -1676,19 +1719,19 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true) case 'quotepost': $sql_data = array( 'root_level' => $root_level, - 'author_id' => $data['from_user_id'], - 'icon_id' => $data['icon_id'], - 'author_ip' => $data['from_user_ip'], + 'author_id' => $data_ary['from_user_id'], + 'icon_id' => $data_ary['icon_id'], + 'author_ip' => $data_ary['from_user_ip'], 'message_time' => $current_time, - 'enable_bbcode' => $data['enable_bbcode'], - 'enable_smilies' => $data['enable_smilies'], - 'enable_magic_url' => $data['enable_urls'], - 'enable_sig' => $data['enable_sig'], + 'enable_bbcode' => $data_ary['enable_bbcode'], + 'enable_smilies' => $data_ary['enable_smilies'], + 'enable_magic_url' => $data_ary['enable_urls'], + 'enable_sig' => $data_ary['enable_sig'], 'message_subject' => $subject, - 'message_text' => $data['message'], - 'message_attachment'=> (!empty($data['attachment_data'])) ? 1 : 0, - 'bbcode_bitfield' => $data['bbcode_bitfield'], - 'bbcode_uid' => $data['bbcode_uid'], + 'message_text' => $data_ary['message'], + 'message_attachment'=> (!empty($data_ary['attachment_data'])) ? 1 : 0, + 'bbcode_bitfield' => $data_ary['bbcode_bitfield'], + 'bbcode_uid' => $data_ary['bbcode_uid'], 'to_address' => implode(':', $to), 'bcc_address' => implode(':', $bcc), 'message_reported' => 0, @@ -1697,35 +1740,33 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true) case 'edit': $sql_data = array( - 'icon_id' => $data['icon_id'], + 'icon_id' => $data_ary['icon_id'], 'message_edit_time' => $current_time, - 'enable_bbcode' => $data['enable_bbcode'], - 'enable_smilies' => $data['enable_smilies'], - 'enable_magic_url' => $data['enable_urls'], - 'enable_sig' => $data['enable_sig'], + 'enable_bbcode' => $data_ary['enable_bbcode'], + 'enable_smilies' => $data_ary['enable_smilies'], + 'enable_magic_url' => $data_ary['enable_urls'], + 'enable_sig' => $data_ary['enable_sig'], 'message_subject' => $subject, - 'message_text' => $data['message'], - 'message_attachment'=> (!empty($data['attachment_data'])) ? 1 : 0, - 'bbcode_bitfield' => $data['bbcode_bitfield'], - 'bbcode_uid' => $data['bbcode_uid'] + 'message_text' => $data_ary['message'], + 'message_attachment'=> (!empty($data_ary['attachment_data'])) ? 1 : 0, + 'bbcode_bitfield' => $data_ary['bbcode_bitfield'], + 'bbcode_uid' => $data_ary['bbcode_uid'] ); break; } if (sizeof($sql_data)) { - $query = ''; - if ($mode == 'post' || $mode == 'reply' || $mode == 'quote' || $mode == 'quotepost' || $mode == 'forward') { $db->sql_query('INSERT INTO ' . PRIVMSGS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_data)); - $data['msg_id'] = $db->sql_nextid(); + $data_ary['msg_id'] = $db->sql_nextid(); } else if ($mode == 'edit') { $sql = 'UPDATE ' . PRIVMSGS_TABLE . ' SET message_edit_count = message_edit_count + 1, ' . $db->sql_build_array('UPDATE', $sql_data) . ' - WHERE msg_id = ' . $data['msg_id']; + WHERE msg_id = ' . $data_ary['msg_id']; $db->sql_query($sql); } } @@ -1742,9 +1783,9 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true) foreach ($recipients as $user_id => $type) { $sql_ary[] = array( - 'msg_id' => (int) $data['msg_id'], + 'msg_id' => (int) $data_ary['msg_id'], 'user_id' => (int) $user_id, - 'author_id' => (int) $data['from_user_id'], + 'author_id' => (int) $data_ary['from_user_id'], 'folder_id' => PRIVMSGS_NO_BOX, 'pm_new' => 1, 'pm_unread' => 1, @@ -1763,9 +1804,9 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true) if ($put_in_outbox) { $db->sql_query('INSERT INTO ' . PRIVMSGS_TO_TABLE . ' ' . $db->sql_build_array('INSERT', array( - 'msg_id' => (int) $data['msg_id'], - 'user_id' => (int) $data['from_user_id'], - 'author_id' => (int) $data['from_user_id'], + 'msg_id' => (int) $data_ary['msg_id'], + 'user_id' => (int) $data_ary['from_user_id'], + 'author_id' => (int) $data_ary['from_user_id'], 'folder_id' => PRIVMSGS_OUTBOX, 'pm_new' => 0, 'pm_unread' => 0, @@ -1779,17 +1820,17 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true) { $sql = 'UPDATE ' . USERS_TABLE . " SET user_lastpost_time = $current_time - WHERE user_id = " . $data['from_user_id']; + WHERE user_id = " . $data_ary['from_user_id']; $db->sql_query($sql); } // Submit Attachments - if (!empty($data['attachment_data']) && $data['msg_id'] && in_array($mode, array('post', 'reply', 'quote', 'quotepost', 'edit', 'forward'))) + if (!empty($data_ary['attachment_data']) && $data_ary['msg_id'] && in_array($mode, array('post', 'reply', 'quote', 'quotepost', 'edit', 'forward'))) { $space_taken = $files_added = 0; $orphan_rows = array(); - foreach ($data['attachment_data'] as $pos => $attach_row) + foreach ($data_ary['attachment_data'] as $pos => $attach_row) { $orphan_rows[(int) $attach_row['attach_id']] = array(); } @@ -1812,7 +1853,7 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true) $db->sql_freeresult($result); } - foreach ($data['attachment_data'] as $pos => $attach_row) + foreach ($data_ary['attachment_data'] as $pos => $attach_row) { if ($attach_row['is_orphan'] && !isset($orphan_rows[$attach_row['attach_id']])) { @@ -1840,10 +1881,10 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true) $files_added++; $attach_sql = array( - 'post_msg_id' => $data['msg_id'], + 'post_msg_id' => $data_ary['msg_id'], 'topic_id' => 0, 'is_orphan' => 0, - 'poster_id' => $data['from_user_id'], + 'poster_id' => $data_ary['from_user_id'], 'attach_comment' => $attach_row['attach_comment'], ); @@ -1857,41 +1898,58 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true) if ($space_taken && $files_added) { - set_config_count('upload_dir_size', $space_taken, true); - set_config_count('num_files', $files_added, true); + $config->increment('upload_dir_size', $space_taken, false); + $config->increment('num_files', $files_added, false); } } // Delete draft if post was loaded... - $draft_id = request_var('draft_loaded', 0); + $draft_id = $request->variable('draft_loaded', 0); if ($draft_id) { $sql = 'DELETE FROM ' . DRAFTS_TABLE . " WHERE draft_id = $draft_id - AND user_id = " . $data['from_user_id']; + AND user_id = " . $data_ary['from_user_id']; $db->sql_query($sql); } $db->sql_transaction('commit'); // Send Notifications - $pm_data = array_merge($data, array( + $pm_data = array_merge($data_ary, array( 'message_subject' => $subject, 'recipients' => $recipients, )); + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); if ($mode == 'edit') { - $phpbb_notifications->update_notifications('pm', $pm_data); + $phpbb_notifications->update_notifications('notification.type.pm', $pm_data); } else { - $phpbb_notifications->add_notifications('pm', $pm_data); - } - - return $data['msg_id']; + $phpbb_notifications->add_notifications('notification.type.pm', $pm_data); + } + + $data = $data_ary; + /** + * Get PM message ID after submission to DB + * + * @event core.submit_pm_after + * @var string mode PM Post mode - post|reply|quote|quotepost|forward|edit + * @var string subject Subject of the private message + * @var array data The whole row data of the PM. + * @var array pm_data The data sent to notification class + * @since 3.1.0-b5 + */ + $vars = array('mode', 'subject', 'data', 'pm_data'); + extract($phpbb_dispatcher->trigger_event('core.submit_pm_after', compact($vars))); + $data_ary = $data; + unset($data); + + return $data_ary['msg_id']; } /** @@ -1899,7 +1957,7 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true) */ function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode = false) { - global $db, $user, $config, $template, $phpbb_root_path, $phpEx, $auth, $bbcode; + global $db, $user, $template, $phpbb_root_path, $phpEx, $auth; // Select all receipts and the author from the pm we currently view, to only display their pm-history $sql = 'SELECT author_id, user_id @@ -1951,7 +2009,6 @@ function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode $title = $row['message_subject']; $rowset = array(); - $bbcode_bitfield = ''; $folder_url = append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm') . '&folder='; do @@ -1967,7 +2024,6 @@ function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode else { $rowset[$row['msg_id']] = $row; - $bbcode_bitfield = $bbcode_bitfield | base64_decode($row['bbcode_bitfield']); } } while ($row = $db->sql_fetchrow($result)); @@ -1978,16 +2034,6 @@ function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode return false; } - // Instantiate BBCode class - if ((empty($bbcode) || $bbcode === false) && $bbcode_bitfield !== '') - { - if (!class_exists('bbcode')) - { - include($phpbb_root_path . 'includes/bbcode.' . $phpEx); - } - $bbcode = new bbcode(base64_encode($bbcode_bitfield)); - } - $title = censor_text($title); $url = append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm'); @@ -2018,10 +2064,10 @@ function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode $decoded_message = bbcode_nl2br($decoded_message); } - + $parse_flags = ($row['bbcode_bitfield'] ? OPTION_FLAG_BBCODE : 0); $parse_flags |= ($row['enable_smilies'] ? OPTION_FLAG_SMILIES : 0); - + $message = generate_text_for_display($message, $row['bbcode_uid'], $row['bbcode_bitfield'], $parse_flags, false); $subject = censor_text($subject); @@ -2050,6 +2096,8 @@ function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode 'S_IN_POST_MODE' => $in_post_mode, 'MSG_ID' => $row['msg_id'], + 'MESSAGE_TIME' => $row['message_time'], + 'USER_ID' => $row['user_id'], 'U_VIEW_MESSAGE' => "$url&f=$folder_id&p=" . $row['msg_id'], 'U_QUOTE' => (!$in_post_mode && $auth->acl_get('u_sendpm') && $author_id != ANONYMOUS) ? "$url&mode=compose&action=quote&f=" . $folder_id . "&p=" . $row['msg_id'] : '', 'U_POST_REPLY_PM' => ($author_id != $user->data['user_id'] && $author_id != ANONYMOUS && $auth->acl_get('u_sendpm')) ? "$url&mode=compose&action=reply&f=$folder_id&p=" . $row['msg_id'] : '') @@ -2077,17 +2125,42 @@ function set_user_message_limit() { global $user, $db, $config; - // Get maximum about from user memberships - if it is 0, there is no limit set and we use the maximum value within the config. - $sql = 'SELECT MAX(g.group_message_limit) as max_message_limit + // Get maximum about from user memberships + $message_limit = phpbb_get_max_setting_from_group($db, $user->data['user_id'], 'message_limit'); + + // If it is 0, there is no limit set and we use the maximum value within the config. + $user->data['message_limit'] = (!$message_limit) ? $config['pm_max_msgs'] : $message_limit; +} + +/** + * Get the maximum PM setting for the groups of the user + * + * @param \phpbb\db\driver\driver_interface $db + * @param int $user_id + * @param string $setting Only 'max_recipients' and 'message_limit' are supported + * @return int The maximum setting for all groups of the user, unless one group has '0' + * @throws \InvalidArgumentException If selected group setting is not supported + */ +function phpbb_get_max_setting_from_group(\phpbb\db\driver\driver_interface $db, $user_id, $setting) +{ + if ($setting !== 'max_recipients' && $setting !== 'message_limit') + { + throw new InvalidArgumentException('Setting "' . $setting . '" is not supported'); + } + + // Get maximum number of allowed recipients + $sql = 'SELECT MIN(g.group_' . $setting . ') as min_setting, MAX(g.group_' . $setting . ') as max_setting FROM ' . GROUPS_TABLE . ' g, ' . USER_GROUP_TABLE . ' ug - WHERE ug.user_id = ' . $user->data['user_id'] . ' + WHERE ug.user_id = ' . (int) $user_id . ' AND ug.user_pending = 0 AND ug.group_id = g.group_id'; $result = $db->sql_query($sql); - $message_limit = (int) $db->sql_fetchfield('max_message_limit'); + $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); + $max_setting = (int) $row['max_setting']; + $min_setting = (int) $row['min_setting']; - $user->data['message_limit'] = (!$message_limit) ? $config['pm_max_msgs'] : $message_limit; + return ($min_setting > 0) ? $max_setting : 0; } /** @@ -2101,7 +2174,10 @@ function set_user_message_limit() */ function get_recipient_strings($pm_by_id) { - global $db, $phpbb_root_path, $phpEx, $user; + global $db, $phpbb_root_path, $phpEx, $user, $phpbb_container; + + /** @var \phpbb\group\helper $group_helper */ + $group_helper = $phpbb_container->get('group_helper'); $address_list = $recipient_list = $address = array(); @@ -2147,7 +2223,7 @@ function get_recipient_strings($pm_by_id) { if ($ug_type == 'g') { - $row['name'] = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['name']] : $row['name']; + $row['name'] = $group_helper->get_name($row['name']); } $recipient_list[$ug_type][$row['id']] = array('name' => $row['name'], 'colour' => $row['colour']); diff --git a/phpBB/includes/functions_transfer.php b/phpBB/includes/functions_transfer.php index 9bec17ca8f..0fc8a7eea5 100644 --- a/phpBB/includes/functions_transfer.php +++ b/phpBB/includes/functions_transfer.php @@ -1,9 +1,13 @@ <?php /** * -* @package phpBB3 -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -17,7 +21,6 @@ if (!defined('IN_PHPBB')) /** * Transfer class, wrapper for ftp/sftp/ssh -* @package phpBB3 */ class transfer { @@ -255,7 +258,6 @@ class transfer /** * FTP transfer class -* @package phpBB3 */ class ftp extends transfer { @@ -279,7 +281,7 @@ class ftp extends transfer } // Init some needed values - transfer::transfer(); + $this->transfer(); return; } @@ -404,9 +406,6 @@ class ftp extends transfer */ function _put($from_file, $to_file) { - // get the file extension - $file_extension = strtolower(substr(strrchr($to_file, '.'), 1)); - // We only use the BINARY file mode to cicumvent rewrite actions from ftp server (mostly linefeeds being replaced) $mode = FTP_BINARY; @@ -505,9 +504,6 @@ class ftp extends transfer /** * FTP fsock transfer class -* -* @author wGEric -* @package phpBB3 */ class ftp_fsock extends transfer { @@ -533,7 +529,7 @@ class ftp_fsock extends transfer } // Init some needed values - transfer::transfer(); + $this->transfer(); return; } diff --git a/phpBB/includes/functions_upload.php b/phpBB/includes/functions_upload.php deleted file mode 100644 index 04d483e14c..0000000000 --- a/phpBB/includes/functions_upload.php +++ /dev/null @@ -1,1071 +0,0 @@ -<?php -/** -* -* @package phpBB3 -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Responsible for holding all file relevant information, as well as doing file-specific operations. -* The {@link fileupload fileupload class} can be used to upload several files, each of them being this object to operate further on. -* @package phpBB3 -*/ -class filespec -{ - var $filename = ''; - var $realname = ''; - var $uploadname = ''; - var $mimetype = ''; - var $extension = ''; - var $filesize = 0; - var $width = 0; - var $height = 0; - var $image_info = array(); - - var $destination_file = ''; - var $destination_path = ''; - - var $file_moved = false; - var $init_error = false; - var $local = false; - - var $error = array(); - - var $upload = ''; - - /** - * The plupload object - * @var \phpbb\plupload\plupload - */ - protected $plupload; - - /** - * File Class - * @access private - */ - function filespec($upload_ary, $upload_namespace, \phpbb\plupload\plupload $plupload = null) - { - if (!isset($upload_ary)) - { - $this->init_error = true; - return; - } - - $this->filename = $upload_ary['tmp_name']; - $this->filesize = $upload_ary['size']; - $name = (STRIP) ? stripslashes($upload_ary['name']) : $upload_ary['name']; - $name = trim(utf8_htmlspecialchars(utf8_basename($name))); - $this->realname = $this->uploadname = $name; - $this->mimetype = $upload_ary['type']; - - // Opera adds the name to the mime type - $this->mimetype = (strpos($this->mimetype, '; name') !== false) ? str_replace(strstr($this->mimetype, '; name'), '', $this->mimetype) : $this->mimetype; - - if (!$this->mimetype) - { - $this->mimetype = 'application/octetstream'; - } - - $this->extension = strtolower(self::get_extension($this->realname)); - - // Try to get real filesize from temporary folder (not always working) ;) - $this->filesize = (@filesize($this->filename)) ? @filesize($this->filename) : $this->filesize; - - $this->width = $this->height = 0; - $this->file_moved = false; - - $this->local = (isset($upload_ary['local_mode'])) ? true : false; - $this->upload = $upload_namespace; - $this->plupload = $plupload; - } - - /** - * Cleans destination filename - * - * @param real|unique|unique_ext $mode real creates a realname, filtering some characters, lowering every character. Unique creates an unique filename - * @param string $prefix Prefix applied to filename - * @access public - */ - function clean_filename($mode = 'unique', $prefix = '', $user_id = '') - { - if ($this->init_error) - { - return; - } - - switch ($mode) - { - case 'real': - // Remove every extension from filename (to not let the mime bug being exposed) - if (strpos($this->realname, '.') !== false) - { - $this->realname = substr($this->realname, 0, strpos($this->realname, '.')); - } - - // Replace any chars which may cause us problems with _ - $bad_chars = array("'", "\\", ' ', '/', ':', '*', '?', '"', '<', '>', '|'); - - $this->realname = rawurlencode(str_replace($bad_chars, '_', strtolower($this->realname))); - $this->realname = preg_replace("/%(\w{2})/", '_', $this->realname); - - $this->realname = $prefix . $this->realname . '.' . $this->extension; - break; - - case 'unique': - $this->realname = $prefix . md5(unique_id()); - break; - - case 'avatar': - $this->extension = strtolower($this->extension); - $this->realname = $prefix . $user_id . '.' . $this->extension; - - break; - - case 'unique_ext': - default: - $this->realname = $prefix . md5(unique_id()) . '.' . $this->extension; - break; - } - } - - /** - * Get property from file object - */ - function get($property) - { - if ($this->init_error || !isset($this->$property)) - { - return false; - } - - return $this->$property; - } - - /** - * Check if file is an image (mimetype) - * - * @return true if it is an image, false if not - */ - function is_image() - { - return (strpos($this->mimetype, 'image/') === 0); - } - - /** - * Check if the file got correctly uploaded - * - * @return true if it is a valid upload, false if not - */ - function is_uploaded() - { - $is_plupload = $this->plupload && $this->plupload->is_active(); - - if (!$this->local && !$is_plupload && !is_uploaded_file($this->filename)) - { - return false; - } - - if (($this->local || $is_plupload) && !file_exists($this->filename)) - { - return false; - } - - return true; - } - - /** - * Remove file - */ - function remove() - { - if ($this->file_moved) - { - @unlink($this->destination_file); - } - } - - /** - * Get file extension - * - * @param string Filename that needs to be checked - * @return string Extension of the supplied filename - */ - static public function get_extension($filename) - { - if (strpos($filename, '.') === false) - { - return ''; - } - - $filename = explode('.', $filename); - return array_pop($filename); - } - - /** - * Get mimetype. Utilize mime_content_type if the function exist. - * Not used at the moment... - */ - function get_mimetype($filename) - { - $mimetype = ''; - - if (function_exists('mime_content_type')) - { - $mimetype = mime_content_type($filename); - } - - // Some browsers choke on a mimetype of application/octet-stream - if (!$mimetype || $mimetype == 'application/octet-stream') - { - $mimetype = 'application/octetstream'; - } - - return $mimetype; - } - - /** - * Get filesize - */ - function get_filesize($filename) - { - return @filesize($filename); - } - - - /** - * Check the first 256 bytes for forbidden content - */ - function check_content($disallowed_content) - { - if (empty($disallowed_content)) - { - return true; - } - - $fp = @fopen($this->filename, 'rb'); - - if ($fp !== false) - { - $ie_mime_relevant = fread($fp, 256); - fclose($fp); - foreach ($disallowed_content as $forbidden) - { - if (stripos($ie_mime_relevant, '<' . $forbidden) !== false) - { - return false; - } - } - } - return true; - } - - /** - * Move file to destination folder - * The phpbb_root_path variable will be applied to the destination path - * - * @param string $destination_path Destination path, for example $config['avatar_path'] - * @param bool $overwrite If set to true, an already existing file will be overwritten - * @param string $chmod Permission mask for chmodding the file after a successful move. The mode entered here reflects the mode defined by {@link phpbb_chmod()} - * - * @access public - */ - function move_file($destination, $overwrite = false, $skip_image_check = false, $chmod = false) - { - global $user, $phpbb_root_path; - - if (sizeof($this->error)) - { - return false; - } - - $chmod = ($chmod === false) ? CHMOD_READ | CHMOD_WRITE : $chmod; - - // We need to trust the admin in specifying valid upload directories and an attacker not being able to overwrite it... - $this->destination_path = $phpbb_root_path . $destination; - - // Check if the destination path exist... - if (!file_exists($this->destination_path)) - { - @unlink($this->filename); - return false; - } - - $upload_mode = (@ini_get('open_basedir') || @ini_get('safe_mode') || strtolower(@ini_get('safe_mode')) == 'on') ? 'move' : 'copy'; - $upload_mode = ($this->local) ? 'local' : $upload_mode; - $this->destination_file = $this->destination_path . '/' . utf8_basename($this->realname); - - // Check if the file already exist, else there is something wrong... - if (file_exists($this->destination_file) && !$overwrite) - { - @unlink($this->filename); - } - else - { - if (file_exists($this->destination_file)) - { - @unlink($this->destination_file); - } - - switch ($upload_mode) - { - case 'copy': - - if (!@copy($this->filename, $this->destination_file)) - { - if (!@move_uploaded_file($this->filename, $this->destination_file)) - { - $this->error[] = sprintf($user->lang[$this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR'], $this->destination_file); - } - } - - break; - - case 'move': - - if (!@move_uploaded_file($this->filename, $this->destination_file)) - { - if (!@copy($this->filename, $this->destination_file)) - { - $this->error[] = sprintf($user->lang[$this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR'], $this->destination_file); - } - } - - break; - - case 'local': - - if (!@copy($this->filename, $this->destination_file)) - { - $this->error[] = sprintf($user->lang[$this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR'], $this->destination_file); - } - - break; - } - - // Remove temporary filename - @unlink($this->filename); - - if (sizeof($this->error)) - { - return false; - } - - phpbb_chmod($this->destination_file, $chmod); - } - - // Try to get real filesize from destination folder - $this->filesize = (@filesize($this->destination_file)) ? @filesize($this->destination_file) : $this->filesize; - - if ($this->is_image() && !$skip_image_check) - { - $this->width = $this->height = 0; - - if (($this->image_info = @getimagesize($this->destination_file)) !== false) - { - $this->width = $this->image_info[0]; - $this->height = $this->image_info[1]; - - if (!empty($this->image_info['mime'])) - { - $this->mimetype = $this->image_info['mime']; - } - - // Check image type - $types = fileupload::image_types(); - - if (!isset($types[$this->image_info[2]]) || !in_array($this->extension, $types[$this->image_info[2]])) - { - if (!isset($types[$this->image_info[2]])) - { - $this->error[] = sprintf($user->lang['IMAGE_FILETYPE_INVALID'], $this->image_info[2], $this->mimetype); - } - else - { - $this->error[] = sprintf($user->lang['IMAGE_FILETYPE_MISMATCH'], $types[$this->image_info[2]][0], $this->extension); - } - } - - // Make sure the dimensions match a valid image - if (empty($this->width) || empty($this->height)) - { - $this->error[] = $user->lang['ATTACHED_IMAGE_NOT_IMAGE']; - } - } - else - { - $this->error[] = $user->lang['UNABLE_GET_IMAGE_SIZE']; - } - } - - $this->file_moved = true; - $this->additional_checks(); - unset($this->upload); - - return true; - } - - /** - * Performing additional checks - */ - function additional_checks() - { - global $user; - - if (!$this->file_moved) - { - return false; - } - - // Filesize is too big or it's 0 if it was larger than the maxsize in the upload form - if ($this->upload->max_filesize && ($this->get('filesize') > $this->upload->max_filesize || $this->filesize == 0)) - { - $max_filesize = get_formatted_filesize($this->upload->max_filesize, false); - - $this->error[] = sprintf($user->lang[$this->upload->error_prefix . 'WRONG_FILESIZE'], $max_filesize['value'], $max_filesize['unit']); - - return false; - } - - if (!$this->upload->valid_dimensions($this)) - { - $this->error[] = $user->lang($this->upload->error_prefix . 'WRONG_SIZE', - $user->lang('PIXELS', (int) $this->upload->min_width), - $user->lang('PIXELS', (int) $this->upload->min_height), - $user->lang('PIXELS', (int) $this->upload->max_width), - $user->lang('PIXELS', (int) $this->upload->max_height), - $user->lang('PIXELS', (int) $this->width), - $user->lang('PIXELS', (int) $this->height)); - - return false; - } - - return true; - } -} - -/** -* Class for assigning error messages before a real filespec class can be assigned -* -* @package phpBB3 -*/ -class fileerror extends filespec -{ - function fileerror($error_msg) - { - $this->error[] = $error_msg; - } -} - -/** -* File upload class -* Init class (all parameters optional and able to be set/overwritten separately) - scope is global and valid for all uploads -* -* @package phpBB3 -*/ -class fileupload -{ - var $allowed_extensions = array(); - var $disallowed_content = array('body', 'head', 'html', 'img', 'plaintext', 'a href', 'pre', 'script', 'table', 'title'); - var $max_filesize = 0; - var $min_width = 0; - var $min_height = 0; - var $max_width = 0; - var $max_height = 0; - var $error_prefix = ''; - - /** - * Init file upload class. - * - * @param string $error_prefix Used error messages will get prefixed by this string - * @param array $allowed_extensions Array of allowed extensions, for example array('jpg', 'jpeg', 'gif', 'png') - * @param int $max_filesize Maximum filesize - * @param int $min_width Minimum image width (only checked for images) - * @param int $min_height Minimum image height (only checked for images) - * @param int $max_width Maximum image width (only checked for images) - * @param int $max_height Maximum image height (only checked for images) - * - */ - function fileupload($error_prefix = '', $allowed_extensions = false, $max_filesize = false, $min_width = false, $min_height = false, $max_width = false, $max_height = false, $disallowed_content = false) - { - $this->set_allowed_extensions($allowed_extensions); - $this->set_max_filesize($max_filesize); - $this->set_allowed_dimensions($min_width, $min_height, $max_width, $max_height); - $this->set_error_prefix($error_prefix); - $this->set_disallowed_content($disallowed_content); - } - - /** - * Reset vars - */ - function reset_vars() - { - $this->max_filesize = 0; - $this->min_width = $this->min_height = $this->max_width = $this->max_height = 0; - $this->error_prefix = ''; - $this->allowed_extensions = array(); - $this->disallowed_content = array(); - } - - /** - * Set allowed extensions - */ - function set_allowed_extensions($allowed_extensions) - { - if ($allowed_extensions !== false && is_array($allowed_extensions)) - { - $this->allowed_extensions = $allowed_extensions; - } - } - - /** - * Set allowed dimensions - */ - function set_allowed_dimensions($min_width, $min_height, $max_width, $max_height) - { - $this->min_width = (int) $min_width; - $this->min_height = (int) $min_height; - $this->max_width = (int) $max_width; - $this->max_height = (int) $max_height; - } - - /** - * Set maximum allowed filesize - */ - function set_max_filesize($max_filesize) - { - if ($max_filesize !== false && (int) $max_filesize) - { - $this->max_filesize = (int) $max_filesize; - } - } - - /** - * Set disallowed strings - */ - function set_disallowed_content($disallowed_content) - { - if ($disallowed_content !== false && is_array($disallowed_content)) - { - $this->disallowed_content = array_diff($disallowed_content, array('')); - } - } - - /** - * Set error prefix - */ - function set_error_prefix($error_prefix) - { - $this->error_prefix = $error_prefix; - } - - /** - * Form upload method - * Upload file from users harddisk - * - * @param string $form_name Form name assigned to the file input field (if it is an array, the key has to be specified) - * @param \phpbb\plupload\plupload $plupload The plupload object - * - * @return object $file Object "filespec" is returned, all further operations can be done with this object - * @access public - */ - function form_upload($form_name, \phpbb\plupload\plupload $plupload = null) - { - global $user, $request; - - $upload = $request->file($form_name); - unset($upload['local_mode']); - - if ($plupload) - { - $result = $plupload->handle_upload($form_name); - if (is_array($result)) - { - $upload = array_merge($upload, $result); - } - } - - $file = new filespec($upload, $this, $plupload); - - if ($file->init_error) - { - $file->error[] = ''; - return $file; - } - - // Error array filled? - if (isset($upload['error'])) - { - $error = $this->assign_internal_error($upload['error']); - - if ($error !== false) - { - $file->error[] = $error; - return $file; - } - } - - // Check if empty file got uploaded (not catched by is_uploaded_file) - if (isset($upload['size']) && $upload['size'] == 0) - { - $file->error[] = $user->lang[$this->error_prefix . 'EMPTY_FILEUPLOAD']; - return $file; - } - - // PHP Upload filesize exceeded - if ($file->get('filename') == 'none') - { - $max_filesize = @ini_get('upload_max_filesize'); - $unit = 'MB'; - - if (!empty($max_filesize)) - { - $unit = strtolower(substr($max_filesize, -1, 1)); - $max_filesize = (int) $max_filesize; - - $unit = ($unit == 'k') ? 'KB' : (($unit == 'g') ? 'GB' : 'MB'); - } - - $file->error[] = (empty($max_filesize)) ? $user->lang[$this->error_prefix . 'PHP_SIZE_NA'] : sprintf($user->lang[$this->error_prefix . 'PHP_SIZE_OVERRUN'], $max_filesize, $user->lang[$unit]); - return $file; - } - - // Not correctly uploaded - if (!$file->is_uploaded()) - { - $file->error[] = $user->lang[$this->error_prefix . 'NOT_UPLOADED']; - return $file; - } - - $this->common_checks($file); - - return $file; - } - - /** - * Move file from another location to phpBB - */ - function local_upload($source_file, $filedata = false) - { - global $user, $request; - - $upload = array(); - - $upload['local_mode'] = true; - $upload['tmp_name'] = $source_file; - - if ($filedata === false) - { - $upload['name'] = utf8_basename($source_file); - $upload['size'] = 0; - $mimetype = ''; - - if (function_exists('mime_content_type')) - { - $mimetype = mime_content_type($source_file); - } - - // Some browsers choke on a mimetype of application/octet-stream - if (!$mimetype || $mimetype == 'application/octet-stream') - { - $mimetype = 'application/octetstream'; - } - - $upload['type'] = $mimetype; - } - else - { - $upload['name'] = $filedata['realname']; - $upload['size'] = $filedata['size']; - $upload['type'] = $filedata['type']; - } - - $file = new filespec($upload, $this); - - if ($file->init_error) - { - $file->error[] = ''; - return $file; - } - - if (isset($upload['error'])) - { - $error = $this->assign_internal_error($upload['error']); - - if ($error !== false) - { - $file->error[] = $error; - return $file; - } - } - - // PHP Upload filesize exceeded - if ($file->get('filename') == 'none') - { - $max_filesize = @ini_get('upload_max_filesize'); - $unit = 'MB'; - - if (!empty($max_filesize)) - { - $unit = strtolower(substr($max_filesize, -1, 1)); - $max_filesize = (int) $max_filesize; - - $unit = ($unit == 'k') ? 'KB' : (($unit == 'g') ? 'GB' : 'MB'); - } - - $file->error[] = (empty($max_filesize)) ? $user->lang[$this->error_prefix . 'PHP_SIZE_NA'] : sprintf($user->lang[$this->error_prefix . 'PHP_SIZE_OVERRUN'], $max_filesize, $user->lang[$unit]); - return $file; - } - - // Not correctly uploaded - if (!$file->is_uploaded()) - { - $file->error[] = $user->lang[$this->error_prefix . 'NOT_UPLOADED']; - return $file; - } - - $this->common_checks($file); - $request->overwrite('local', $upload, \phpbb\request\request_interface::FILES); - - return $file; - } - - /** - * Remote upload method - * Uploads file from given url - * - * @param string $upload_url URL pointing to file to upload, for example http://www.foobar.com/example.gif - * @return object $file Object "filespec" is returned, all further operations can be done with this object - * @access public - */ - function remote_upload($upload_url) - { - global $user, $phpbb_root_path; - - $upload_ary = array(); - $upload_ary['local_mode'] = true; - - if (!preg_match('#^(https?://).*?\.(' . implode('|', $this->allowed_extensions) . ')$#i', $upload_url, $match)) - { - $file = new fileerror($user->lang[$this->error_prefix . 'URL_INVALID']); - return $file; - } - - if (empty($match[2])) - { - $file = new fileerror($user->lang[$this->error_prefix . 'URL_INVALID']); - return $file; - } - - $url = parse_url($upload_url); - - $host = $url['host']; - $path = $url['path']; - $port = (!empty($url['port'])) ? (int) $url['port'] : 80; - - $upload_ary['type'] = 'application/octet-stream'; - - $url['path'] = explode('.', $url['path']); - $ext = array_pop($url['path']); - - $url['path'] = implode('', $url['path']); - $upload_ary['name'] = utf8_basename($url['path']) . (($ext) ? '.' . $ext : ''); - $filename = $url['path']; - $filesize = 0; - - $remote_max_filesize = $this->max_filesize; - if (!$remote_max_filesize) - { - $max_filesize = @ini_get('upload_max_filesize'); - - if (!empty($max_filesize)) - { - $unit = strtolower(substr($max_filesize, -1, 1)); - $remote_max_filesize = (int) $max_filesize; - - switch ($unit) - { - case 'g': - $remote_max_filesize *= 1024; - // no break - case 'm': - $remote_max_filesize *= 1024; - // no break - case 'k': - $remote_max_filesize *= 1024; - // no break - } - } - } - - $errno = 0; - $errstr = ''; - - if (!($fsock = @fsockopen($host, $port, $errno, $errstr))) - { - $file = new fileerror($user->lang[$this->error_prefix . 'NOT_UPLOADED']); - return $file; - } - - // Make sure $path not beginning with / - if (strpos($path, '/') === 0) - { - $path = substr($path, 1); - } - - fputs($fsock, 'GET /' . $path . " HTTP/1.1\r\n"); - fputs($fsock, "HOST: " . $host . "\r\n"); - fputs($fsock, "Connection: close\r\n\r\n"); - - $get_info = false; - $data = ''; - while (!@feof($fsock)) - { - if ($get_info) - { - $block = @fread($fsock, 1024); - $filesize += strlen($block); - - if ($remote_max_filesize && $filesize > $remote_max_filesize) - { - $max_filesize = get_formatted_filesize($remote_max_filesize, false); - - $file = new fileerror(sprintf($user->lang[$this->error_prefix . 'WRONG_FILESIZE'], $max_filesize['value'], $max_filesize['unit'])); - return $file; - } - - $data .= $block; - } - else - { - $line = @fgets($fsock, 1024); - - if ($line == "\r\n") - { - $get_info = true; - } - else - { - if (stripos($line, 'content-type: ') !== false) - { - $upload_ary['type'] = rtrim(str_replace('content-type: ', '', strtolower($line))); - } - else if ($this->max_filesize && stripos($line, 'content-length: ') !== false) - { - $length = (int) str_replace('content-length: ', '', strtolower($line)); - - if ($remote_max_filesize && $length && $length > $remote_max_filesize) - { - $max_filesize = get_formatted_filesize($remote_max_filesize, false); - - $file = new fileerror(sprintf($user->lang[$this->error_prefix . 'WRONG_FILESIZE'], $max_filesize['value'], $max_filesize['unit'])); - return $file; - } - } - else if (stripos($line, '404 not found') !== false) - { - $file = new fileerror($user->lang[$this->error_prefix . 'URL_NOT_FOUND']); - return $file; - } - } - } - } - @fclose($fsock); - - if (empty($data)) - { - $file = new fileerror($user->lang[$this->error_prefix . 'EMPTY_REMOTE_DATA']); - return $file; - } - - $tmp_path = (!@ini_get('safe_mode') || strtolower(@ini_get('safe_mode')) == 'off') ? false : $phpbb_root_path . 'cache'; - $filename = tempnam($tmp_path, unique_id() . '-'); - - if (!($fp = @fopen($filename, 'wb'))) - { - $file = new fileerror($user->lang[$this->error_prefix . 'NOT_UPLOADED']); - return $file; - } - - $upload_ary['size'] = fwrite($fp, $data); - fclose($fp); - unset($data); - - $upload_ary['tmp_name'] = $filename; - - $file = new filespec($upload_ary, $this); - $this->common_checks($file); - - return $file; - } - - /** - * Assign internal error - * @access private - */ - function assign_internal_error($errorcode) - { - global $user; - - switch ($errorcode) - { - case 1: - $max_filesize = @ini_get('upload_max_filesize'); - $unit = 'MB'; - - if (!empty($max_filesize)) - { - $unit = strtolower(substr($max_filesize, -1, 1)); - $max_filesize = (int) $max_filesize; - - $unit = ($unit == 'k') ? 'KB' : (($unit == 'g') ? 'GB' : 'MB'); - } - - $error = (empty($max_filesize)) ? $user->lang[$this->error_prefix . 'PHP_SIZE_NA'] : sprintf($user->lang[$this->error_prefix . 'PHP_SIZE_OVERRUN'], $max_filesize, $user->lang[$unit]); - break; - - case 2: - $max_filesize = get_formatted_filesize($this->max_filesize, false); - - $error = sprintf($user->lang[$this->error_prefix . 'WRONG_FILESIZE'], $max_filesize['value'], $max_filesize['unit']); - break; - - case 3: - $error = $user->lang[$this->error_prefix . 'PARTIAL_UPLOAD']; - break; - - case 4: - $error = $user->lang[$this->error_prefix . 'NOT_UPLOADED']; - break; - - case 6: - $error = 'Temporary folder could not be found. Please check your PHP installation.'; - break; - - default: - $error = false; - break; - } - - return $error; - } - - /** - * Perform common checks - */ - function common_checks(&$file) - { - global $user; - - // Filesize is too big or it's 0 if it was larger than the maxsize in the upload form - if ($this->max_filesize && ($file->get('filesize') > $this->max_filesize || $file->get('filesize') == 0)) - { - $max_filesize = get_formatted_filesize($this->max_filesize, false); - - $file->error[] = sprintf($user->lang[$this->error_prefix . 'WRONG_FILESIZE'], $max_filesize['value'], $max_filesize['unit']); - } - - // check Filename - if (preg_match("#[\\/:*?\"<>|]#i", $file->get('realname'))) - { - $file->error[] = sprintf($user->lang[$this->error_prefix . 'INVALID_FILENAME'], $file->get('realname')); - } - - // Invalid Extension - if (!$this->valid_extension($file)) - { - $file->error[] = sprintf($user->lang[$this->error_prefix . 'DISALLOWED_EXTENSION'], $file->get('extension')); - } - - // MIME Sniffing - if (!$this->valid_content($file)) - { - $file->error[] = sprintf($user->lang[$this->error_prefix . 'DISALLOWED_CONTENT']); - } - } - - /** - * Check for allowed extension - */ - function valid_extension(&$file) - { - return (in_array($file->get('extension'), $this->allowed_extensions)) ? true : false; - } - - /** - * Check for allowed dimension - */ - function valid_dimensions(&$file) - { - if (!$this->max_width && !$this->max_height && !$this->min_width && !$this->min_height) - { - return true; - } - - if (($file->get('width') > $this->max_width && $this->max_width) || - ($file->get('height') > $this->max_height && $this->max_height) || - ($file->get('width') < $this->min_width && $this->min_width) || - ($file->get('height') < $this->min_height && $this->min_height)) - { - return false; - } - - return true; - } - - /** - * Check if form upload is valid - */ - function is_valid($form_name) - { - global $request; - $upload = $request->file($form_name); - - return (!empty($upload) && $upload['name'] !== 'none'); - } - - - /** - * Check for bad content (IE mime-sniffing) - */ - function valid_content(&$file) - { - return ($file->check_content($this->disallowed_content)); - } - - /** - * Get image type/extension mapping - * - * @return array Array containing the image types and their extensions - */ - static public function image_types() - { - return array( - IMAGETYPE_GIF => array('gif'), - IMAGETYPE_JPEG => array('jpg', 'jpeg'), - IMAGETYPE_PNG => array('png'), - IMAGETYPE_SWF => array('swf'), - IMAGETYPE_PSD => array('psd'), - IMAGETYPE_BMP => array('bmp'), - IMAGETYPE_TIFF_II => array('tif', 'tiff'), - IMAGETYPE_TIFF_MM => array('tif', 'tiff'), - IMAGETYPE_JPC => array('jpg', 'jpeg'), - IMAGETYPE_JP2 => array('jpg', 'jpeg'), - IMAGETYPE_JPX => array('jpg', 'jpeg'), - IMAGETYPE_JB2 => array('jpg', 'jpeg'), - IMAGETYPE_SWC => array('swc'), - IMAGETYPE_IFF => array('iff'), - IMAGETYPE_WBMP => array('wbmp'), - IMAGETYPE_XBM => array('xbm'), - ); - } -} diff --git a/phpBB/includes/functions_url_matcher.php b/phpBB/includes/functions_url_matcher.php deleted file mode 100644 index c5d6815119..0000000000 --- a/phpBB/includes/functions_url_matcher.php +++ /dev/null @@ -1,106 +0,0 @@ -<?php -/** -* -* @package phpBB3 -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 -* -*/ - -use Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper; -use Symfony\Component\Routing\Matcher\UrlMatcher; -use Symfony\Component\Routing\RequestContext; - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Create a new UrlMatcher class and dump it into the cache file -* -* @param \phpbb\extension\finder $finder Extension finder -* @param RequestContext $context Symfony RequestContext object -* @param string $root_path Root path -* @param string $php_ext PHP extension -* @return null -*/ -function phpbb_get_url_matcher(\phpbb\extension\finder $finder, RequestContext $context, $root_path, $php_ext) -{ - if (defined('DEBUG')) - { - return phpbb_create_url_matcher($finder, $context, $root_path); - } - - if (!phpbb_url_matcher_dumped($root_path, $php_ext)) - { - phpbb_create_dumped_url_matcher($finder, $root_path, $php_ext); - } - - return phpbb_load_url_matcher($context, $root_path, $php_ext); -} - -/** -* Create a new UrlMatcher class and dump it into the cache file -* -* @param \phpbb\extension\finder $finder Extension finder -* @param string $root_path Root path -* @param string $php_ext PHP extension -* @return null -*/ -function phpbb_create_dumped_url_matcher(\phpbb\extension\finder $finder, $root_path, $php_ext) -{ - $provider = new \phpbb\controller\provider(); - $routes = $provider->import_paths_from_finder($finder)->find($root_path); - $dumper = new PhpMatcherDumper($routes); - $cached_url_matcher_dump = $dumper->dump(array( - 'class' => 'phpbb_url_matcher', - )); - - file_put_contents($root_path . 'cache/url_matcher.' . $php_ext, $cached_url_matcher_dump); -} - -/** -* Create a non-cached UrlMatcher -* -* @param \phpbb\extension\finder $finder Extension finder -* @param RequestContext $context Symfony RequestContext object -* @return UrlMatcher -*/ -function phpbb_create_url_matcher(\phpbb\extension\finder $finder, RequestContext $context, $root_path) -{ - $provider = new \phpbb\controller\provider(); - $routes = $provider->import_paths_from_finder($finder)->find($root_path); - return new UrlMatcher($routes, $context); -} - -/** -* Load the cached phpbb_url_matcher class -* -* @param RequestContext $context Symfony RequestContext object -* @param string $root_path Root path -* @param string $php_ext PHP extension -* @return phpbb_url_matcher -*/ -function phpbb_load_url_matcher(RequestContext $context, $root_path, $php_ext) -{ - require($root_path . 'cache/url_matcher.' . $php_ext); - return new phpbb_url_matcher($context); -} - -/** -* Determine whether we have our dumped URL matcher -* -* The class is automatically dumped to the cache directory -* -* @param string $root_path Root path -* @param string $php_ext PHP extension -* @return bool True if it exists, false if not -*/ -function phpbb_url_matcher_dumped($root_path, $php_ext) -{ - return file_exists($root_path . 'cache/url_matcher.' . $php_ext); -} diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php index 6682622d94..e1c687551b 100644 --- a/phpBB/includes/functions_user.php +++ b/phpBB/includes/functions_user.php @@ -1,9 +1,13 @@ <?php /** * -* @package phpBB3 -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -40,13 +44,13 @@ function user_get_id_name(&$user_id_ary, &$username_ary, $user_type = false) $which_ary = ($user_id_ary) ? 'user_id_ary' : 'username_ary'; - if ($$which_ary && !is_array($$which_ary)) + if (${$which_ary} && !is_array(${$which_ary})) { - $$which_ary = array($$which_ary); + ${$which_ary} = array(${$which_ary}); } - $sql_in = ($which_ary == 'user_id_ary') ? array_map('intval', $$which_ary) : array_map('utf8_clean_string', $$which_ary); - unset($$which_ary); + $sql_in = ($which_ary == 'user_id_ary') ? array_map('intval', ${$which_ary}) : array_map('utf8_clean_string', ${$which_ary}); + unset(${$which_ary}); $user_id_ary = $username_ary = array(); @@ -85,7 +89,7 @@ function user_get_id_name(&$user_id_ary, &$username_ary, $user_type = false) */ function update_last_username() { - global $db; + global $config, $db; // Get latest username $sql = 'SELECT user_id, username, user_colour @@ -98,9 +102,9 @@ function update_last_username() if ($row) { - set_config('newest_user_id', $row['user_id'], true); - set_config('newest_username', $row['username'], true); - set_config('newest_user_colour', $row['user_colour'], true); + $config->set('newest_user_id', $row['user_id'], false); + $config->set('newest_username', $row['username'], false); + $config->set('newest_user_colour', $row['user_colour'], false); } } @@ -134,7 +138,7 @@ function user_update_name($old_name, $new_name) if ($config['newest_username'] == $old_name) { - set_config('newest_username', $new_name, true); + $config->set('newest_username', $new_name, false); } /** @@ -143,7 +147,7 @@ function user_update_name($old_name, $new_name) * @event core.update_username * @var string old_name The old username that is replaced * @var string new_name The new username - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('old_name', 'new_name'); extract($phpbb_dispatcher->trigger_event('core.update_username', compact($vars))); @@ -157,11 +161,12 @@ function user_update_name($old_name, $new_name) * * @param mixed $user_row An array containing the following keys (and the appropriate values): username, group_id (the group to place the user in), user_email and the user_type(usually 0). Additional entries not overridden by defaults will be forwarded. * @param string $cp_data custom profile fields, see custom_profile::build_insert_sql_array +* @param array $notifications_data The notifications settings for the new user * @return the new user's ID. */ -function user_add($user_row, $cp_data = false) +function user_add($user_row, $cp_data = false, $notifications_data = null) { - global $db, $user, $auth, $config, $phpbb_root_path, $phpEx; + global $db, $config; global $phpbb_dispatcher, $phpbb_container; if (empty($user_row['username']) || !isset($user_row['group_id']) || !isset($user_row['user_email']) || !isset($user_row['user_type'])) @@ -180,7 +185,6 @@ function user_add($user_row, $cp_data = false) 'username' => $user_row['username'], 'username_clean' => $username_clean, 'user_password' => (isset($user_row['user_password'])) ? $user_row['user_password'] : '', - 'user_pass_convert' => 0, 'user_email' => strtolower($user_row['user_email']), 'user_email_hash' => phpbb_email_hash($user_row['user_email']), 'group_id' => $user_row['group_id'], @@ -258,10 +262,13 @@ function user_add($user_row, $cp_data = false) * Use this event to modify the values to be inserted when a user is added * * @event core.user_add_modify_data + * @var array user_row Array of user details submited to user_add + * @var array cp_data Array of Custom profile fields submited to user_add * @var array sql_ary Array of data to be inserted when a user is added - * @since 3.1-A1 + * @since 3.1.0-a1 + * @change 3.1.0-b5 */ - $vars = array('sql_ary'); + $vars = array('user_row', 'cp_data', 'sql_ary'); extract($phpbb_dispatcher->trigger_event('core.user_add_modify_data', compact($vars))); $sql = 'INSERT INTO ' . USERS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary); @@ -274,6 +281,7 @@ function user_add($user_row, $cp_data = false) { $cp_data['user_id'] = (int) $user_id; + /* @var $cp \phpbb\profilefields\manager */ $cp = $phpbb_container->get('profilefields.manager'); $sql = 'INSERT INTO ' . PROFILE_FIELDS_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $cp->build_insert_sql_array($cp_data)); @@ -306,7 +314,7 @@ function user_add($user_row, $cp_data = false) { global $phpbb_log; - // Because these actions only fill the log unneccessarily we skip the add_log() entry. + // Because these actions only fill the log unnecessarily, we disable it $phpbb_log->disable('admin'); // Add user to "newly registered users" group and set to default group if admin specified so. @@ -327,9 +335,9 @@ function user_add($user_row, $cp_data = false) // set the newest user and adjust the user count if the user is a normal user and no activation mail is sent if ($user_row['user_type'] == USER_NORMAL || $user_row['user_type'] == USER_FOUNDER) { - set_config('newest_user_id', $user_id, true); - set_config('newest_username', $user_row['username'], true); - set_config_count('num_users', 1, true); + $config->set('newest_user_id', $user_id, false); + $config->set('newest_username', $user_row['username'], false); + $config->increment('num_users', 1, false); $sql = 'SELECT group_colour FROM ' . GROUPS_TABLE . ' @@ -338,19 +346,61 @@ function user_add($user_row, $cp_data = false) $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); - set_config('newest_user_colour', $row['group_colour'], true); + $config->set('newest_user_colour', $row['group_colour'], false); + } + + // Use default notifications settings if notifications_data is not set + if ($notifications_data === null) + { + $notifications_data = array( + array( + 'item_type' => 'notification.type.post', + 'method' => 'notification.method.email', + ), + array( + 'item_type' => 'notification.type.topic', + 'method' => 'notification.method.email', + ), + ); + } + + // Subscribe user to notifications if necessary + if (!empty($notifications_data)) + { + /* @var $phpbb_notifications \phpbb\notification\manager */ + $phpbb_notifications = $phpbb_container->get('notification_manager'); + foreach ($notifications_data as $subscription) + { + $phpbb_notifications->add_subscription($subscription['item_type'], 0, $subscription['method'], $user_id); + } } + /** + * Event that returns user id, user detals and user CPF of newly registared user + * + * @event core.user_add_after + * @var int user_id User id of newly registared user + * @var array user_row Array of user details submited to user_add + * @var array cp_data Array of Custom profile fields submited to user_add + * @since 3.1.0-b5 + */ + $vars = array('user_id', 'user_row', 'cp_data'); + extract($phpbb_dispatcher->trigger_event('core.user_add_after', compact($vars))); + return $user_id; } /** -* Remove User -* @param $mode Either 'retain' or 'remove' -*/ + * Remove User + * + * @param string $mode Either 'retain' or 'remove' + * @param mixed $user_ids Either an array of integers or an integer + * @param bool $retain_username + * @return bool + */ function user_delete($mode, $user_ids, $retain_username = true) { - global $cache, $config, $db, $user, $auth, $phpbb_dispatcher; + global $cache, $config, $db, $user, $phpbb_dispatcher, $phpbb_container; global $phpbb_root_path, $phpEx; $db->sql_transaction('begin'); @@ -386,7 +436,7 @@ function user_delete($mode, $user_ids, $retain_username = true) * @var array user_ids IDs of the deleted user * @var mixed retain_username True if username should be retained * or false if not - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('mode', 'user_ids', 'retain_username'); extract($phpbb_dispatcher->trigger_event('core.delete_user_before', compact($vars))); @@ -452,6 +502,9 @@ function user_delete($mode, $user_ids, $retain_username = true) $num_users_delta = 0; + // Get auth provider collection in case accounts might need to be unlinked + $provider_collection = $phpbb_container->get('auth.provider_collection'); + // Some things need to be done in the loop (if the query changes based // on which user is currently being deleted) $added_guest_posts = 0; @@ -462,6 +515,38 @@ function user_delete($mode, $user_ids, $retain_username = true) avatar_delete('user', $user_row); } + // Unlink accounts + foreach ($provider_collection as $provider_name => $auth_provider) + { + $provider_data = $auth_provider->get_auth_link_data($user_id); + + if ($provider_data !== null) + { + $link_data = array( + 'user_id' => $user_id, + 'link_method' => 'user_delete', + ); + + // BLOCK_VARS might contain hidden fields necessary for unlinking accounts + if (isset($provider_data['BLOCK_VARS']) && is_array($provider_data['BLOCK_VARS'])) + { + foreach ($provider_data['BLOCK_VARS'] as $provider_service) + { + if (!array_key_exists('HIDDEN_FIELDS', $provider_service)) + { + $provider_service['HIDDEN_FIELDS'] = array(); + } + + $auth_provider->unlink_account(array_merge($link_data, $provider_service['HIDDEN_FIELDS'])); + } + } + else + { + $auth_provider->unlink_account($link_data); + } + } + } + // Decrement number of users if this user is active if ($user_row['user_type'] != USER_INACTIVE && $user_row['user_type'] != USER_IGNORE) { @@ -523,7 +608,7 @@ function user_delete($mode, $user_ids, $retain_username = true) if ($num_users_delta != 0) { - set_config_count('num_users', $num_users_delta, true); + $config->increment('num_users', $num_users_delta, false); } // Now do the invariant tasks @@ -537,11 +622,6 @@ function user_delete($mode, $user_ids, $retain_username = true) WHERE ' . $db->sql_in_set('poster_id', $user_ids); $db->sql_query($sql); - $sql = 'UPDATE ' . POSTS_TABLE . ' - SET post_edit_user = ' . ANONYMOUS . ' - WHERE ' . $db->sql_in_set('post_edit_user', $user_ids); - $db->sql_query($sql); - $sql = 'UPDATE ' . USERS_TABLE . ' SET user_posts = user_posts + ' . $added_guest_posts . ' WHERE user_id = ' . ANONYMOUS; @@ -571,6 +651,30 @@ function user_delete($mode, $user_ids, $retain_username = true) $cache->destroy('sql', MODERATOR_CACHE_TABLE); + // Change user_id to anonymous for posts edited by this user + $sql = 'UPDATE ' . POSTS_TABLE . ' + SET post_edit_user = ' . ANONYMOUS . ' + WHERE ' . $db->sql_in_set('post_edit_user', $user_ids); + $db->sql_query($sql); + + // Change user_id to anonymous for pms edited by this user + $sql = 'UPDATE ' . PRIVMSGS_TABLE . ' + SET message_edit_user = ' . ANONYMOUS . ' + WHERE ' . $db->sql_in_set('message_edit_user', $user_ids); + $db->sql_query($sql); + + // Change user_id to anonymous for posts deleted by this user + $sql = 'UPDATE ' . POSTS_TABLE . ' + SET post_delete_user = ' . ANONYMOUS . ' + WHERE ' . $db->sql_in_set('post_delete_user', $user_ids); + $db->sql_query($sql); + + // Change user_id to anonymous for topics deleted by this user + $sql = 'UPDATE ' . TOPICS_TABLE . ' + SET topic_delete_user = ' . ANONYMOUS . ' + WHERE ' . $db->sql_in_set('topic_delete_user', $user_ids); + $db->sql_query($sql); + // Delete user log entries about this user $sql = 'DELETE FROM ' . LOG_TABLE . ' WHERE ' . $db->sql_in_set('reportee_id', $user_ids); @@ -605,6 +709,9 @@ function user_delete($mode, $user_ids, $retain_username = true) } phpbb_delete_users_pms($user_ids); + $phpbb_notifications = $phpbb_container->get('notification_manager'); + $phpbb_notifications->delete_notifications('notification.type.admin_activate_user', $user_ids); + $db->sql_transaction('commit'); /** @@ -615,7 +722,7 @@ function user_delete($mode, $user_ids, $retain_username = true) * @var array user_ids IDs of the deleted user * @var mixed retain_username True if username should be retained * or false if not - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('mode', 'user_ids', 'retain_username'); extract($phpbb_dispatcher->trigger_event('core.delete_user_after', compact($vars))); @@ -636,7 +743,7 @@ function user_delete($mode, $user_ids, $retain_username = true) */ function user_active_flip($mode, $user_id_ary, $reason = INACTIVE_MANUAL) { - global $config, $db, $user, $auth; + global $config, $db, $user, $auth, $phpbb_dispatcher; $deactivated = $activated = 0; $sql_statements = array(); @@ -689,6 +796,21 @@ function user_active_flip($mode, $user_id_ary, $reason = INACTIVE_MANUAL) } $db->sql_freeresult($result); + /** + * Check or modify activated/deactivated users data before submitting it to the database + * + * @event core.user_active_flip_before + * @var string mode User type changing mode, can be: flip|activate|deactivate + * @var int reason Reason for changing user type, can be: INACTIVE_REGISTER|INACTIVE_PROFILE|INACTIVE_MANUAL|INACTIVE_REMIND + * @var int activated The number of users to be activated + * @var int deactivated The number of users to be deactivated + * @var array user_id_ary Array with user ids to change user type + * @var array sql_statements Array with users data to submit to the database, keys: user ids, values: arrays with user data + * @since 3.1.4-RC1 + */ + $vars = array('mode', 'reason', 'activated', 'deactivated', 'user_id_ary', 'sql_statements'); + extract($phpbb_dispatcher->trigger_event('core.user_active_flip_before', compact($vars))); + if (sizeof($sql_statements)) { foreach ($sql_statements as $user_id => $sql_ary) @@ -702,14 +824,29 @@ function user_active_flip($mode, $user_id_ary, $reason = INACTIVE_MANUAL) $auth->acl_clear_prefetch(array_keys($sql_statements)); } + /** + * Perform additional actions after the users have been activated/deactivated + * + * @event core.user_active_flip_after + * @var string mode User type changing mode, can be: flip|activate|deactivate + * @var int reason Reason for changing user type, can be: INACTIVE_REGISTER|INACTIVE_PROFILE|INACTIVE_MANUAL|INACTIVE_REMIND + * @var int activated The number of users to be activated + * @var int deactivated The number of users to be deactivated + * @var array user_id_ary Array with user ids to change user type + * @var array sql_statements Array with users data to submit to the database, keys: user ids, values: arrays with user data + * @since 3.1.4-RC1 + */ + $vars = array('mode', 'reason', 'activated', 'deactivated', 'user_id_ary', 'sql_statements'); + extract($phpbb_dispatcher->trigger_event('core.user_active_flip_after', compact($vars))); + if ($deactivated) { - set_config_count('num_users', $deactivated * (-1), true); + $config->increment('num_users', $deactivated * (-1), false); } if ($activated) { - set_config_count('num_users', $activated, true); + $config->increment('num_users', $activated, false); } // Update latest username @@ -729,7 +866,7 @@ function user_active_flip($mode, $user_id_ary, $reason = INACTIVE_MANUAL) */ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reason, $ban_give_reason = '') { - global $db, $user, $auth, $cache; + global $db, $user, $cache, $phpbb_log; // Delete stale bans $sql = 'DELETE FROM ' . BANLIST_TABLE . ' @@ -752,7 +889,7 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas else { $ban_other = explode('-', $ban_len_other); - if (sizeof($ban_other) == 3 && ((int)$ban_other[0] < 9999) && + if (sizeof($ban_other) == 3 && ((int) $ban_other[0] < 9999) && (strlen($ban_other[0]) == 4) && (strlen($ban_other[1]) == 2) && (strlen($ban_other[2]) == 2)) { $ban_end = max($current_time, $user->create_datetime() @@ -878,7 +1015,6 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas if ($ip_2_counter == 0 && $ip_2_end == 254) { $ip_2_counter = 256; - $ip_2_fragment = 256; $banlist_ary[] = "$ip_1_counter.*"; } @@ -891,7 +1027,6 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas if ($ip_3_counter == 0 && $ip_3_end == 254) { $ip_3_counter = 256; - $ip_3_fragment = 256; $banlist_ary[] = "$ip_1_counter.$ip_2_counter.*"; } @@ -904,7 +1039,6 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas if ($ip_4_counter == 0 && $ip_4_end == 254) { $ip_4_counter = 256; - $ip_4_fragment = 256; $banlist_ary[] = "$ip_1_counter.$ip_2_counter.$ip_3_counter.*"; } @@ -1119,14 +1253,23 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas // Update log $log_entry = ($ban_exclude) ? 'LOG_BAN_EXCLUDE_' : 'LOG_BAN_'; - // Add to moderator log, admin log and user notes - add_log('admin', $log_entry . strtoupper($mode), $ban_reason, $ban_list_log); - add_log('mod', 0, 0, $log_entry . strtoupper($mode), $ban_reason, $ban_list_log); + // Add to admin log, moderator log and user notes + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, $log_entry . strtoupper($mode), false, array($ban_reason, $ban_list_log)); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, $log_entry . strtoupper($mode), false, array( + 'forum_id' => 0, + 'topic_id' => 0, + $ban_reason, + $ban_list_log + )); if ($mode == 'user') { foreach ($banlist_ary as $user_id) { - add_log('user', $user_id, $log_entry . strtoupper($mode), $ban_reason, $ban_list_log); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, $log_entry . strtoupper($mode), false, array( + 'reportee_id' => $user_id, + $ban_reason, + $ban_list_log + )); } } @@ -1146,7 +1289,7 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas */ function user_unban($mode, $ban) { - global $db, $user, $auth, $cache; + global $db, $user, $cache, $phpbb_log; // Delete stale bans $sql = 'DELETE FROM ' . BANLIST_TABLE . ' @@ -1204,13 +1347,20 @@ function user_unban($mode, $ban) $db->sql_query($sql); // Add to moderator log, admin log and user notes - add_log('admin', 'LOG_UNBAN_' . strtoupper($mode), $l_unban_list); - add_log('mod', 0, 0, 'LOG_UNBAN_' . strtoupper($mode), $l_unban_list); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_UNBAN_' . strtoupper($mode), false, array($l_unban_list)); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_UNBAN_' . strtoupper($mode), false, array( + 'forum_id' => 0, + 'topic_id' => 0, + $l_unban_list + )); if ($mode == 'user') { foreach ($user_ids_ary as $user_id) { - add_log('user', $user_id, 'LOG_UNBAN_' . strtoupper($mode), $l_unban_list); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_UNBAN_' . strtoupper($mode), false, array( + 'reportee_id' => $user_id, + $l_unban_list + )); } } } @@ -1267,7 +1417,7 @@ function user_ipwhois($ip) $match = array(); // Test for referrals from $whois_host to other whois databases, roll on rwhois - if (preg_match('#ReferralServer: whois://(.+)#im', $ipwhois, $match)) + if (preg_match('#ReferralServer:[\x20]*whois://(.+)#im', $ipwhois, $match)) { if (strpos($match[1], ':') !== false) { @@ -1326,9 +1476,18 @@ function validate_data($data, $val_ary) { $function = array_shift($validate); array_unshift($validate, $data[$var]); - $function_prefix = (function_exists('phpbb_validate_' . $function)) ? 'phpbb_validate_' : 'validate_'; - if ($result = call_user_func_array($function_prefix . $function, $validate)) + if (is_array($function)) + { + $result = call_user_func_array(array($function[0], 'validate_' . $function[1]), $validate); + } + else + { + $function_prefix = (function_exists('phpbb_validate_' . $function)) ? 'phpbb_validate_' : 'validate_'; + $result = call_user_func_array($function_prefix . $function, $validate); + } + + if ($result) { // Since errors are checked later for their language file existence, we need to make sure custom errors are not adjusted. $error[] = (empty($user->lang[$result . '_' . strtoupper($var)])) ? $result : $result . '_' . strtoupper($var); @@ -1520,89 +1679,37 @@ function validate_username($username, $allowed_username = false) return 'INVALID_CHARS'; } - $mbstring = $pcre = false; - - // generic UTF-8 character types supported? - if (phpbb_pcre_utf8_support()) - { - $pcre = true; - } - else if (function_exists('mb_ereg_match')) - { - mb_regex_encoding('UTF-8'); - $mbstring = true; - } - switch ($config['allow_name_chars']) { case 'USERNAME_CHARS_ANY': - $pcre = true; $regex = '.+'; break; case 'USERNAME_ALPHA_ONLY': - $pcre = true; $regex = '[A-Za-z0-9]+'; break; case 'USERNAME_ALPHA_SPACERS': - $pcre = true; $regex = '[A-Za-z0-9-[\]_+ ]+'; break; case 'USERNAME_LETTER_NUM': - if ($pcre) - { - $regex = '[\p{Lu}\p{Ll}\p{N}]+'; - } - else if ($mbstring) - { - $regex = '[[:upper:][:lower:][:digit:]]+'; - } - else - { - $pcre = true; - $regex = '[a-zA-Z0-9]+'; - } + $regex = '[\p{Lu}\p{Ll}\p{N}]+'; break; case 'USERNAME_LETTER_NUM_SPACERS': - if ($pcre) - { - $regex = '[-\]_+ [\p{Lu}\p{Ll}\p{N}]+'; - } - else if ($mbstring) - { - $regex = '[-\]_+ \[[:upper:][:lower:][:digit:]]+'; - } - else - { - $pcre = true; - $regex = '[-\]_+ [a-zA-Z0-9]+'; - } + $regex = '[-\]_+ [\p{Lu}\p{Ll}\p{N}]+'; break; case 'USERNAME_ASCII': default: - $pcre = true; $regex = '[\x01-\x7F]+'; break; } - if ($pcre) + if (!preg_match('#^' . $regex . '$#u', $username)) { - if (!preg_match('#^' . $regex . '$#u', $username)) - { - return 'INVALID_CHARS'; - } - } - else if ($mbstring) - { - mb_ereg_search_init($username, '^' . $regex . '$'); - if (!mb_ereg_search()) - { - return 'INVALID_CHARS'; - } + return 'INVALID_CHARS'; } $sql = 'SELECT username @@ -1657,35 +1764,10 @@ function validate_password($password) return false; } - $pcre = $mbstring = false; - - // generic UTF-8 character types supported? - if (phpbb_pcre_utf8_support()) - { - $upp = '\p{Lu}'; - $low = '\p{Ll}'; - $num = '\p{N}'; - $sym = '[^\p{Lu}\p{Ll}\p{N}]'; - $pcre = true; - } - else if (function_exists('mb_ereg_match')) - { - mb_regex_encoding('UTF-8'); - $upp = '[[:upper:]]'; - $low = '[[:lower:]]'; - $num = '[[:digit:]]'; - $sym = '[^[:upper:][:lower:][:digit:]]'; - $mbstring = true; - } - else - { - $upp = '[A-Z]'; - $low = '[a-z]'; - $num = '[0-9]'; - $sym = '[^A-Za-z0-9]'; - $pcre = true; - } - + $upp = '\p{Lu}'; + $low = '\p{Ll}'; + $num = '\p{N}'; + $sym = '[^\p{Lu}\p{Ll}\p{N}]'; $chars = array(); switch ($config['pass_complex']) @@ -1708,24 +1790,11 @@ function validate_password($password) $chars[] = $upp; } - if ($pcre) + foreach ($chars as $char) { - foreach ($chars as $char) + if (!preg_match('#' . $char . '#u', $password)) { - if (!preg_match('#' . $char . '#u', $password)) - { - return 'INVALID_CHARS'; - } - } - } - else if ($mbstring) - { - foreach ($chars as $char) - { - if (mb_ereg($char, $password) === false) - { - return 'INVALID_CHARS'; - } + return 'INVALID_CHARS'; } } @@ -1733,25 +1802,21 @@ function validate_password($password) } /** -* Check to see if email address is banned or already present in the DB +* Check to see if email address is a valid address and contains a MX record * * @param string $email The email to check -* @param string $allowed_email An allowed email, default being $user->data['user_email'] * * @return mixed Either false if validation succeeded or a string which will be used as the error message (with the variable name appended) */ -function validate_email($email, $allowed_email = false) +function phpbb_validate_email($email, $config = null) { - global $config, $db, $user; - - $email = strtolower($email); - $allowed_email = ($allowed_email === false) ? strtolower($user->data['user_email']) : strtolower($allowed_email); - - if ($allowed_email == $email) + if ($config === null) { - return false; + global $config; } + $email = strtolower($email); + if (!preg_match('/^' . get_preg_expression('email') . '$/i', $email)) { return 'EMAIL_INVALID'; @@ -1769,6 +1834,35 @@ function validate_email($email, $allowed_email = false) } } + return false; +} + +/** +* Check to see if email address is banned or already present in the DB +* +* @param string $email The email to check +* @param string $allowed_email An allowed email, default being $user->data['user_email'] +* +* @return mixed Either false if validation succeeded or a string which will be used as the error message (with the variable name appended) +*/ +function validate_user_email($email, $allowed_email = false) +{ + global $config, $db, $user; + + $email = strtolower($email); + $allowed_email = ($allowed_email === false) ? strtolower($user->data['user_email']) : strtolower($allowed_email); + + if ($allowed_email == $email) + { + return false; + } + + $validate_email = phpbb_validate_email($email, $config); + if ($validate_email) + { + return $validate_email; + } + if (($ban_reason = $user->check_ban(false, false, $email, true)) !== false) { return ($ban_reason === true) ? 'EMAIL_BANNED' : $ban_reason; @@ -2044,12 +2138,12 @@ function phpbb_style_is_active($style_id) */ function avatar_delete($mode, $row, $clean_db = false) { - global $phpbb_root_path, $config, $db, $user; + global $phpbb_root_path, $config; // Check if the users avatar is actually *not* a group avatar if ($mode == 'user') { - if (strpos($row['user_avatar'], 'g') === 0 || (((int)$row['user_avatar'] !== 0) && ((int)$row['user_avatar'] !== (int)$row['user_id']))) + if (strpos($row['user_avatar'], 'g') === 0 || (((int) $row['user_avatar'] !== 0) && ((int) $row['user_avatar'] !== (int) $row['user_id']))) { return false; } @@ -2077,7 +2171,6 @@ function get_avatar_filename($avatar_entry) { global $config; - if ($avatar_entry[0] === 'g') { $avatar_group = true; @@ -2117,7 +2210,10 @@ function phpbb_avatar_explanation_string() */ function group_create(&$group_id, $type, $name, $desc, $group_attributes, $allow_desc_bbcode = false, $allow_desc_urls = false, $allow_desc_smilies = false) { - global $phpbb_root_path, $config, $db, $user, $file_upload, $phpbb_container; + global $db, $user, $phpbb_container, $phpbb_log; + + /** @var \phpbb\group\helper $group_helper */ + $group_helper = $phpbb_container->get('group_helper'); $error = array(); @@ -2149,8 +2245,12 @@ function group_create(&$group_id, $type, $name, $desc, $group_attributes, $allow $current_legend = \phpbb\groupposition\legend::GROUP_DISABLED; $current_teampage = \phpbb\groupposition\teampage::GROUP_DISABLED; + /* @var $legend \phpbb\groupposition\legend */ $legend = $phpbb_container->get('groupposition.legend'); + + /* @var $teampage \phpbb\groupposition\teampage */ $teampage = $phpbb_container->get('groupposition.teampage'); + if ($group_id) { try @@ -2222,8 +2322,6 @@ function group_create(&$group_id, $type, $name, $desc, $group_attributes, $allow // Setting the log message before we set the group id (if group gets added) $log = ($group_id) ? 'LOG_GROUP_UPDATED' : 'LOG_GROUP_CREATED'; - $query = ''; - if ($group_id) { $sql = 'SELECT user_id @@ -2366,8 +2464,8 @@ function group_create(&$group_id, $type, $name, $desc, $group_attributes, $allow group_set_user_default($group_id, $user_ary, $sql_ary); } - $name = ($type == GROUP_SPECIAL) ? $user->lang['G_' . $name] : $name; - add_log('admin', $log, $name); + $name = $group_helper->get_name($name); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, $log, false, array($name)); group_update_listings($group_id); } @@ -2383,7 +2481,7 @@ function group_correct_avatar($group_id, $old_entry) { global $config, $db, $phpbb_root_path; - $group_id = (int)$group_id; + $group_id = (int) $group_id; $ext = substr(strrchr($old_entry, '.'), 1); $old_filename = get_avatar_filename($old_entry); $new_filename = $config['avatar_salt'] . "_g$group_id.$ext"; @@ -2405,7 +2503,7 @@ function group_correct_avatar($group_id, $old_entry) */ function avatar_remove_db($avatar_name) { - global $config, $db; + global $db; $sql = 'UPDATE ' . USERS_TABLE . " SET user_avatar = '', @@ -2420,7 +2518,7 @@ function avatar_remove_db($avatar_name) */ function group_delete($group_id, $group_name = false) { - global $db, $cache, $auth, $user, $phpbb_root_path, $phpEx, $phpbb_dispatcher, $phpbb_container; + global $db, $cache, $auth, $user, $phpbb_root_path, $phpEx, $phpbb_dispatcher, $phpbb_container, $phpbb_log; if (!$group_name) { @@ -2464,6 +2562,7 @@ function group_delete($group_id, $group_name = false) // Delete group from legend and teampage try { + /* @var $legend \phpbb\groupposition\legend */ $legend = $phpbb_container->get('groupposition.legend'); $legend->delete_group($group_id); unset($legend); @@ -2477,6 +2576,7 @@ function group_delete($group_id, $group_name = false) try { + /* @var $teampage \phpbb\groupposition\teampage */ $teampage = $phpbb_container->get('groupposition.teampage'); $teampage->delete_group($group_id); unset($teampage); @@ -2504,7 +2604,7 @@ function group_delete($group_id, $group_name = false) * @event core.delete_group_after * @var int group_id ID of the deleted group * @var string group_name Name of the deleted group - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('group_id', 'group_name'); extract($phpbb_dispatcher->trigger_event('core.delete_group_after', compact($vars))); @@ -2517,7 +2617,7 @@ function group_delete($group_id, $group_name = false) phpbb_cache_moderators($db, $cache, $auth); - add_log('admin', 'LOG_GROUP_DELETE', $group_name); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_GROUP_DELETE', false, array($group_name)); // Return false - no error return false; @@ -2530,7 +2630,7 @@ function group_delete($group_id, $group_name = false) */ function group_user_add($group_id, $user_id_ary = false, $username_ary = false, $group_name = false, $default = false, $leader = 0, $pending = 0, $group_attributes = false) { - global $db, $auth, $phpbb_container; + global $db, $auth, $user, $phpbb_container, $phpbb_log, $phpbb_dispatcher; // We need both username and user_id info $result = user_get_id_name($user_id_ary, $username_ary); @@ -2607,6 +2707,26 @@ function group_user_add($group_id, $user_id_ary = false, $username_ary = false, // Clear permissions cache of relevant users $auth->acl_clear_prefetch($user_id_ary); + /** + * Event after users are added to a group + * + * @event core.group_add_user_after + * @var int group_id ID of the group to which users are added + * @var string group_name Name of the group + * @var array user_id_ary IDs of the users which are added + * @var array username_ary names of the users which are added + * @var int pending Pending setting, 1 if user(s) added are pending + * @since 3.1.7-RC1 + */ + $vars = array( + 'group_id', + 'group_name', + 'user_id_ary', + 'username_ary', + 'pending', + ); + extract($phpbb_dispatcher->trigger_event('core.group_add_user_after', compact($vars))); + if (!$group_name) { $group_name = get_group_name($group_id); @@ -2614,17 +2734,18 @@ function group_user_add($group_id, $user_id_ary = false, $username_ary = false, $log = ($leader) ? 'LOG_MODS_ADDED' : (($pending) ? 'LOG_USERS_PENDING' : 'LOG_USERS_ADDED'); - add_log('admin', $log, $group_name, implode(', ', $username_ary)); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, $log, false, array($group_name, implode(', ', $username_ary))); group_update_listings($group_id); if ($pending) { + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); foreach ($add_id_ary as $user_id) { - $phpbb_notifications->add_notifications('group_request', array( + $phpbb_notifications->add_notifications('notification.type.group_request', array( 'group_id' => $group_id, 'user_id' => $user_id, 'group_name' => $group_name, @@ -2645,7 +2766,7 @@ function group_user_add($group_id, $user_id_ary = false, $username_ary = false, */ function group_user_del($group_id, $user_id_ary = false, $username_ary = false, $group_name = false) { - global $db, $auth, $config, $phpbb_dispatcher, $phpbb_container; + global $db, $auth, $config, $user, $phpbb_dispatcher, $phpbb_container, $phpbb_log; if ($config['coppa_enable']) { @@ -2752,7 +2873,7 @@ function group_user_del($group_id, $user_id_ary = false, $username_ary = false, * @var string group_name Name of the group * @var array user_id_ary IDs of the users which are removed * @var array username_ary names of the users which are removed - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('group_id', 'group_name', 'user_id_ary', 'username_ary'); extract($phpbb_dispatcher->trigger_event('core.group_delete_user_before', compact($vars))); @@ -2765,6 +2886,19 @@ function group_user_del($group_id, $user_id_ary = false, $username_ary = false, // Clear permissions cache of relevant users $auth->acl_clear_prefetch($user_id_ary); + /** + * Event after users are removed from a group + * + * @event core.group_delete_user_after + * @var int group_id ID of the group from which users are deleted + * @var string group_name Name of the group + * @var array user_id_ary IDs of the users which are removed + * @var array username_ary names of the users which are removed + * @since 3.1.7-RC1 + */ + $vars = array('group_id', 'group_name', 'user_id_ary', 'username_ary'); + extract($phpbb_dispatcher->trigger_event('core.group_delete_user_after', compact($vars))); + if (!$group_name) { $group_name = get_group_name($group_id); @@ -2774,14 +2908,15 @@ function group_user_del($group_id, $user_id_ary = false, $username_ary = false, if ($group_name) { - add_log('admin', $log, $group_name, implode(', ', $username_ary)); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, $log, false, array($group_name, implode(', ', $username_ary))); } group_update_listings($group_id); + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); - $phpbb_notifications->delete_notifications('group_request', $user_id_ary, $group_id); + $phpbb_notifications->delete_notifications('notification.type.group_request', $user_id_ary, $group_id); // Return false - no error return false; @@ -2808,7 +2943,7 @@ function remove_default_avatar($group_id, $user_ids) $sql = 'SELECT * FROM ' . GROUPS_TABLE . ' - WHERE group_id = ' . (int)$group_id; + WHERE group_id = ' . (int) $group_id; $result = $db->sql_query($sql); if (!$row = $db->sql_fetchrow($result)) { @@ -2849,7 +2984,7 @@ function remove_default_rank($group_id, $user_ids) $sql = 'SELECT * FROM ' . GROUPS_TABLE . ' - WHERE group_id = ' . (int)$group_id; + WHERE group_id = ' . (int) $group_id; $result = $db->sql_query($sql); if (!$row = $db->sql_fetchrow($result)) { @@ -2860,9 +2995,9 @@ function remove_default_rank($group_id, $user_ids) $sql = 'UPDATE ' . USERS_TABLE . ' SET user_rank = 0 - WHERE group_id = ' . (int)$group_id . ' + WHERE group_id = ' . (int) $group_id . ' AND user_rank <> 0 - AND user_rank = ' . (int)$row['group_rank'] . ' + AND user_rank = ' . (int) $row['group_rank'] . ' AND ' . $db->sql_in_set('user_id', $user_ids); $db->sql_query($sql); } @@ -2872,7 +3007,7 @@ function remove_default_rank($group_id, $user_ids) */ function group_user_attributes($action, $group_id, $user_id_ary = false, $username_ary = false, $group_name = false, $group_attributes = false) { - global $db, $auth, $phpbb_root_path, $phpEx, $config, $phpbb_container; + global $db, $auth, $user, $phpbb_container, $phpbb_log; // We need both username and user_id info $result = user_get_id_name($user_id_ary, $username_ary); @@ -2943,14 +3078,15 @@ function group_user_attributes($action, $group_id, $user_id_ary = false, $userna AND " . $db->sql_in_set('user_id', $user_id_ary); $db->sql_query($sql); + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); - $phpbb_notifications->add_notifications('group_request_approved', array( + $phpbb_notifications->add_notifications('notification.type.group_request_approved', array( 'user_ids' => $user_id_ary, 'group_id' => $group_id, 'group_name' => $group_name, )); - $phpbb_notifications->delete_notifications('group_request', $user_id_ary, $group_id); + $phpbb_notifications->delete_notifications('notification.type.group_request', $user_id_ary, $group_id); $log = 'LOG_USERS_APPROVED'; break; @@ -3006,7 +3142,7 @@ function group_user_attributes($action, $group_id, $user_id_ary = false, $userna // Clear permissions cache of relevant users $auth->acl_clear_prefetch($user_id_ary); - add_log('admin', $log, $group_name, implode(', ', $username_ary)); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, $log, false, array($group_name, implode(', ', $username_ary))); group_update_listings($group_id); @@ -3018,7 +3154,7 @@ function group_user_attributes($action, $group_id, $user_id_ary = false, $userna */ function group_validate_groupname($group_id, $group_name) { - global $config, $db; + global $db; $group_name = utf8_clean_string($group_name); @@ -3066,7 +3202,7 @@ function group_validate_groupname($group_id, $group_name) */ function group_set_user_default($group_id, $user_id_ary, $group_attributes = false, $update_listing = false) { - global $phpbb_container, $db, $phpbb_dispatcher; + global $config, $phpbb_container, $db, $phpbb_dispatcher; if (empty($user_id_ary)) { @@ -3136,8 +3272,8 @@ function group_set_user_default($group_id, $user_id_ary, $group_attributes = fal if (isset($sql_ary[$avatar_option])) { $avatar_sql_ary[$avatar_option] = $sql_ary[$avatar_option]; - } } + } $sql = 'UPDATE ' . USERS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $avatar_sql_ary) . " @@ -3178,11 +3314,9 @@ function group_set_user_default($group_id, $user_id_ary, $group_attributes = fal WHERE " . $db->sql_in_set('topic_last_poster_id', $user_id_ary); $db->sql_query($sql); - global $config; - if (in_array($config['newest_user_id'], $user_id_ary)) { - set_config('newest_user_colour', $sql_ary['user_colour'], true); + $config->set('newest_user_colour', $sql_ary['user_colour'], false); } } @@ -3198,7 +3332,7 @@ function group_set_user_default($group_id, $user_id_ary, $group_attributes = fal * @var array group_attributes Group attributes which were changed * @var array update_listing Update the list of moderators and foes * @var array sql_ary User attributes which were changed - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('group_id', 'user_id_ary', 'group_attributes', 'update_listing', 'sql_ary'); extract($phpbb_dispatcher->trigger_event('core.user_set_default_group', compact($vars))); @@ -3217,7 +3351,7 @@ function group_set_user_default($group_id, $user_id_ary, $group_attributes = fal */ function get_group_name($group_id) { - global $db, $user; + global $db, $phpbb_container; $sql = 'SELECT group_name, group_type FROM ' . GROUPS_TABLE . ' @@ -3226,12 +3360,15 @@ function get_group_name($group_id) $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); - if (!$row || ($row['group_type'] == GROUP_SPECIAL && empty($user->lang))) + if (!$row) { return ''; } - return ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']; + /** @var \phpbb\group\helper $group_helper */ + $group_helper = $phpbb_container->get('group_helper'); + + return $group_helper->get_name($row['group_name']); } /** @@ -3447,9 +3584,12 @@ function remove_newly_registered($user_id, $user_data = false) * * @param array $user_ids Array of users' ids to check for banning, * leave empty to get complete list of banned ids +* @param bool|int $ban_end Bool True to get users currently banned +* Bool False to only get permanently banned users +* Int Unix timestamp to get users banned until that time * @return array Array of banned users' ids if any, empty array otherwise */ -function phpbb_get_banned_user_ids($user_ids = array()) +function phpbb_get_banned_user_ids($user_ids = array(), $ban_end = true) { global $db; @@ -3461,9 +3601,26 @@ function phpbb_get_banned_user_ids($user_ids = array()) $sql = 'SELECT ban_userid FROM ' . BANLIST_TABLE . " WHERE $sql_user_ids - AND ban_exclude <> 1 - AND (ban_end > " . time() . ' + AND ban_exclude <> 1"; + + if ($ban_end === true) + { + // Banned currently + $sql .= " AND (ban_end > " . time() . ' OR ban_end = 0)'; + } + else if ($ban_end === false) + { + // Permanently banned + $sql .= " AND ban_end = 0"; + } + else + { + // Banned until a specified time + $sql .= " AND (ban_end > " . (int) $ban_end . ' + OR ban_end = 0)'; + } + $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) { @@ -3474,3 +3631,23 @@ function phpbb_get_banned_user_ids($user_ids = array()) return $banned_ids_list; } + +/** +* Function for assigning a template var if the zebra module got included +*/ +function phpbb_module_zebra($mode, &$module_row) +{ + global $template; + + $template->assign_var('S_ZEBRA_ENABLED', true); + + if ($mode == 'friends') + { + $template->assign_var('S_ZEBRA_FRIENDS_ENABLED', true); + } + + if ($mode == 'foes') + { + $template->assign_var('S_ZEBRA_FOES_ENABLED', true); + } +} diff --git a/phpBB/includes/hooks/index.php b/phpBB/includes/hooks/index.php index 11478aee1e..805e0eea1a 100644 --- a/phpBB/includes/hooks/index.php +++ b/phpBB/includes/hooks/index.php @@ -1,9 +1,13 @@ <?php /** * -* @package phpBB3 -* @copyright (c) 2007 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -17,7 +21,6 @@ if (!defined('IN_PHPBB')) /** * phpBB Hook Class -* @package phpBB3 */ class phpbb_hook { diff --git a/phpBB/includes/mcp/info/mcp_ban.php b/phpBB/includes/mcp/info/mcp_ban.php index a3a1e0ef9a..b4fd32792a 100644 --- a/phpBB/includes/mcp/info/mcp_ban.php +++ b/phpBB/includes/mcp/info/mcp_ban.php @@ -1,15 +1,16 @@ <?php /** * -* @package mcp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class mcp_ban_info { function module() @@ -17,7 +18,6 @@ class mcp_ban_info return array( 'filename' => 'mcp_ban', 'title' => 'MCP_BAN', - 'version' => '1.0.0', 'modes' => array( 'user' => array('title' => 'MCP_BAN_USERNAMES', 'auth' => 'acl_m_ban', 'cat' => array('MCP_BAN')), 'ip' => array('title' => 'MCP_BAN_IPS', 'auth' => 'acl_m_ban', 'cat' => array('MCP_BAN')), diff --git a/phpBB/includes/mcp/info/mcp_logs.php b/phpBB/includes/mcp/info/mcp_logs.php index fc30a600c0..7a0205fce9 100644 --- a/phpBB/includes/mcp/info/mcp_logs.php +++ b/phpBB/includes/mcp/info/mcp_logs.php @@ -1,15 +1,16 @@ <?php /** * -* @package mcp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class mcp_logs_info { function module() @@ -17,7 +18,6 @@ class mcp_logs_info return array( 'filename' => 'mcp_logs', 'title' => 'MCP_LOGS', - 'version' => '1.0.0', 'modes' => array( 'front' => array('title' => 'MCP_LOGS_FRONT', 'auth' => 'acl_m_ || aclf_m_', 'cat' => array('MCP_LOGS')), 'forum_logs' => array('title' => 'MCP_LOGS_FORUM_VIEW', 'auth' => 'acl_m_,$id', 'cat' => array('MCP_LOGS')), diff --git a/phpBB/includes/mcp/info/mcp_main.php b/phpBB/includes/mcp/info/mcp_main.php index 705715cbeb..c0f0363255 100644 --- a/phpBB/includes/mcp/info/mcp_main.php +++ b/phpBB/includes/mcp/info/mcp_main.php @@ -1,15 +1,16 @@ <?php /** * -* @package mcp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class mcp_main_info { function module() @@ -17,7 +18,6 @@ class mcp_main_info return array( 'filename' => 'mcp_main', 'title' => 'MCP_MAIN', - 'version' => '1.0.0', 'modes' => array( 'front' => array('title' => 'MCP_MAIN_FRONT', 'auth' => '', 'cat' => array('MCP_MAIN')), 'forum_view' => array('title' => 'MCP_MAIN_FORUM_VIEW', 'auth' => 'acl_m_,$id', 'cat' => array('MCP_MAIN')), diff --git a/phpBB/includes/mcp/info/mcp_notes.php b/phpBB/includes/mcp/info/mcp_notes.php index a77b461bbd..de4a41dd80 100644 --- a/phpBB/includes/mcp/info/mcp_notes.php +++ b/phpBB/includes/mcp/info/mcp_notes.php @@ -1,15 +1,16 @@ <?php /** * -* @package mcp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class mcp_notes_info { function module() @@ -17,7 +18,6 @@ class mcp_notes_info return array( 'filename' => 'mcp_notes', 'title' => 'MCP_NOTES', - 'version' => '1.0.0', 'modes' => array( 'front' => array('title' => 'MCP_NOTES_FRONT', 'auth' => '', 'cat' => array('MCP_NOTES')), 'user_notes' => array('title' => 'MCP_NOTES_USER', 'auth' => '', 'cat' => array('MCP_NOTES')), diff --git a/phpBB/includes/mcp/info/mcp_pm_reports.php b/phpBB/includes/mcp/info/mcp_pm_reports.php index 07dc564b19..2a57c0c49a 100644 --- a/phpBB/includes/mcp/info/mcp_pm_reports.php +++ b/phpBB/includes/mcp/info/mcp_pm_reports.php @@ -1,15 +1,16 @@ <?php /** * -* @package mcp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class mcp_pm_reports_info { function module() @@ -17,11 +18,10 @@ class mcp_pm_reports_info return array( 'filename' => 'mcp_pm_reports', 'title' => 'MCP_PM_REPORTS', - 'version' => '1.0.0', 'modes' => array( - 'pm_reports' => array('title' => 'MCP_PM_REPORTS_OPEN', 'auth' => 'aclf_m_report', 'cat' => array('MCP_REPORTS')), - 'pm_reports_closed' => array('title' => 'MCP_PM_REPORTS_CLOSED', 'auth' => 'aclf_m_report', 'cat' => array('MCP_REPORTS')), - 'pm_report_details' => array('title' => 'MCP_PM_REPORT_DETAILS', 'auth' => 'aclf_m_report', 'cat' => array('MCP_REPORTS')), + 'pm_reports' => array('title' => 'MCP_PM_REPORTS_OPEN', 'auth' => 'acl_m_pm_report', 'cat' => array('MCP_REPORTS')), + 'pm_reports_closed' => array('title' => 'MCP_PM_REPORTS_CLOSED', 'auth' => 'acl_m_pm_report', 'cat' => array('MCP_REPORTS')), + 'pm_report_details' => array('title' => 'MCP_PM_REPORT_DETAILS', 'auth' => 'acl_m_pm_report', 'cat' => array('MCP_REPORTS')), ), ); } diff --git a/phpBB/includes/mcp/info/mcp_queue.php b/phpBB/includes/mcp/info/mcp_queue.php index 68cac5abd2..d5605aa50e 100644 --- a/phpBB/includes/mcp/info/mcp_queue.php +++ b/phpBB/includes/mcp/info/mcp_queue.php @@ -1,15 +1,16 @@ <?php /** * -* @package mcp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class mcp_queue_info { function module() @@ -17,7 +18,6 @@ class mcp_queue_info return array( 'filename' => 'mcp_queue', 'title' => 'MCP_QUEUE', - 'version' => '1.0.0', 'modes' => array( 'unapproved_topics' => array('title' => 'MCP_QUEUE_UNAPPROVED_TOPICS', 'auth' => 'aclf_m_approve', 'cat' => array('MCP_QUEUE')), 'unapproved_posts' => array('title' => 'MCP_QUEUE_UNAPPROVED_POSTS', 'auth' => 'aclf_m_approve', 'cat' => array('MCP_QUEUE')), diff --git a/phpBB/includes/mcp/info/mcp_reports.php b/phpBB/includes/mcp/info/mcp_reports.php index cb6962a1d5..76e62efe9c 100644 --- a/phpBB/includes/mcp/info/mcp_reports.php +++ b/phpBB/includes/mcp/info/mcp_reports.php @@ -1,15 +1,16 @@ <?php /** * -* @package mcp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class mcp_reports_info { function module() @@ -17,7 +18,6 @@ class mcp_reports_info return array( 'filename' => 'mcp_reports', 'title' => 'MCP_REPORTS', - 'version' => '1.0.0', 'modes' => array( 'reports' => array('title' => 'MCP_REPORTS_OPEN', 'auth' => 'aclf_m_report', 'cat' => array('MCP_REPORTS')), 'reports_closed' => array('title' => 'MCP_REPORTS_CLOSED', 'auth' => 'aclf_m_report', 'cat' => array('MCP_REPORTS')), diff --git a/phpBB/includes/mcp/info/mcp_warn.php b/phpBB/includes/mcp/info/mcp_warn.php index d5ac1eedbf..b4f83e77c6 100644 --- a/phpBB/includes/mcp/info/mcp_warn.php +++ b/phpBB/includes/mcp/info/mcp_warn.php @@ -1,15 +1,16 @@ <?php /** * -* @package mcp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class mcp_warn_info { function module() @@ -17,7 +18,6 @@ class mcp_warn_info return array( 'filename' => 'mcp_warn', 'title' => 'MCP_WARN', - 'version' => '1.0.0', 'modes' => array( 'front' => array('title' => 'MCP_WARN_FRONT', 'auth' => 'aclf_m_warn', 'cat' => array('MCP_WARN')), 'list' => array('title' => 'MCP_WARN_LIST', 'auth' => 'aclf_m_warn', 'cat' => array('MCP_WARN')), diff --git a/phpBB/includes/mcp/mcp_ban.php b/phpBB/includes/mcp/mcp_ban.php index d3bc336293..4d2151fded 100644 --- a/phpBB/includes/mcp/mcp_ban.php +++ b/phpBB/includes/mcp/mcp_ban.php @@ -1,9 +1,13 @@ <?php /** * -* @package mcp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -15,16 +19,13 @@ if (!defined('IN_PHPBB')) exit; } -/** -* @package mcp -*/ class mcp_ban { var $u_action; function main($id, $mode) { - global $config, $db, $user, $auth, $template, $cache; + global $db, $user, $auth, $template, $request, $phpbb_dispatcher; global $phpbb_root_path, $phpEx; include($phpbb_root_path . 'includes/functions_user.' . $phpEx); @@ -32,55 +33,133 @@ class mcp_ban // Include the admin banning interface... include($phpbb_root_path . 'includes/acp/acp_ban.' . $phpEx); - $bansubmit = (isset($_POST['bansubmit'])) ? true : false; - $unbansubmit = (isset($_POST['unbansubmit'])) ? true : false; - $current_time = time(); + $bansubmit = $request->is_set_post('bansubmit'); + $unbansubmit = $request->is_set_post('unbansubmit'); $user->add_lang(array('acp/ban', 'acp/users')); $this->tpl_name = 'mcp_ban'; + /** + * Use this event to pass perform actions when a ban is issued or revoked + * + * @event core.mcp_ban_main + * @var bool bansubmit True if a ban is issued + * @var bool unbansubmit True if a ban is removed + * @var string mode Mode of the ban that is being worked on + * @since 3.1.0-RC5 + */ + $vars = array( + 'bansubmit', + 'unbansubmit', + 'mode', + ); + extract($phpbb_dispatcher->trigger_event('core.mcp_ban_main', compact($vars))); + // Ban submitted? if ($bansubmit) { // Grab the list of entries - $ban = request_var('ban', '', ($mode === 'user') ? true : false); - - if ($mode === 'user') - { - $ban = utf8_normalize_nfc($ban); - } - - $ban_len = request_var('banlength', 0); - $ban_len_other = request_var('banlengthother', ''); - $ban_exclude = request_var('banexclude', 0); - $ban_reason = utf8_normalize_nfc(request_var('banreason', '', true)); - $ban_give_reason = utf8_normalize_nfc(request_var('bangivereason', '', true)); + $ban = $request->variable('ban', '', $mode === 'user'); + $ban_length = $request->variable('banlength', 0); + $ban_length_other = $request->variable('banlengthother', ''); + $ban_exclude = $request->variable('banexclude', 0); + $ban_reason = $request->variable('banreason', '', true); + $ban_give_reason = $request->variable('bangivereason', '', true); if ($ban) { if (confirm_box(true)) { - user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reason, $ban_give_reason); + $abort_ban = false; + /** + * Use this event to modify the ban details before the ban is performed + * + * @event core.mcp_ban_before + * @var string mode One of the following: user, ip, email + * @var string ban Either string or array with usernames, ips or email addresses + * @var int ban_length Ban length in minutes + * @var string ban_length_other Ban length as a date (YYYY-MM-DD) + * @var bool ban_exclude Are we banning or excluding from another ban + * @var string ban_reason Ban reason displayed to moderators + * @var string ban_give_reason Ban reason displayed to the banned user + * @var mixed abort_ban Either false, or an error message that is displayed to the user. + * If a string is given the bans are not issued. + * @since 3.1.0-RC5 + */ + $vars = array( + 'mode', + 'ban', + 'ban_length', + 'ban_length_other', + 'ban_exclude', + 'ban_reason', + 'ban_give_reason', + 'abort_ban', + ); + extract($phpbb_dispatcher->trigger_event('core.mcp_ban_before', compact($vars))); + + if ($abort_ban) + { + trigger_error($abort_ban); + } + user_ban($mode, $ban, $ban_length, $ban_length_other, $ban_exclude, $ban_reason, $ban_give_reason); + + /** + * Use this event to perform actions after the ban has been performed + * + * @event core.mcp_ban_after + * @var string mode One of the following: user, ip, email + * @var string ban Either string or array with usernames, ips or email addresses + * @var int ban_length Ban length in minutes + * @var string ban_length_other Ban length as a date (YYYY-MM-DD) + * @var bool ban_exclude Are we banning or excluding from another ban + * @var string ban_reason Ban reason displayed to moderators + * @var string ban_give_reason Ban reason displayed to the banned user + * @since 3.1.0-RC5 + */ + $vars = array( + 'mode', + 'ban', + 'ban_length', + 'ban_length_other', + 'ban_exclude', + 'ban_reason', + 'ban_give_reason', + ); + extract($phpbb_dispatcher->trigger_event('core.mcp_ban_after', compact($vars))); trigger_error($user->lang['BAN_UPDATE_SUCCESSFUL'] . '<br /><br /><a href="' . $this->u_action . '">« ' . $user->lang['BACK_TO_PREV'] . '</a>'); } else { - confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + $hidden_fields = array( 'mode' => $mode, 'ban' => $ban, 'bansubmit' => true, - 'banlength' => $ban_len, - 'banlengthother' => $ban_len_other, + 'banlength' => $ban_length, + 'banlengthother' => $ban_length_other, 'banexclude' => $ban_exclude, 'banreason' => $ban_reason, - 'bangivereason' => $ban_give_reason))); + 'bangivereason' => $ban_give_reason, + ); + + /** + * Use this event to pass data from the ban form to the confirmation screen + * + * @event core.mcp_ban_confirm + * @var array hidden_fields Hidden fields that are passed through the confirm screen + * @since 3.1.0-RC5 + */ + $vars = array('hidden_fields'); + extract($phpbb_dispatcher->trigger_event('core.mcp_ban_confirm', compact($vars))); + + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields($hidden_fields)); } } } else if ($unbansubmit) { - $ban = request_var('unban', array('')); + $ban = $request->variable('unban', array('')); if ($ban) { @@ -156,9 +235,9 @@ class mcp_ban } // As a "service" we will check if any post id is specified and populate the username of the poster id if given - $post_id = request_var('p', 0); - $user_id = request_var('u', 0); - $username = $pre_fill = false; + $post_id = $request->variable('p', 0); + $user_id = $request->variable('u', 0); + $pre_fill = false; if ($user_id && $user_id <> ANONYMOUS) { @@ -171,7 +250,7 @@ class mcp_ban case 'user': $pre_fill = (string) $db->sql_fetchfield('username'); break; - + case 'ip': $pre_fill = (string) $db->sql_fetchfield('user_ip'); break; @@ -184,7 +263,7 @@ class mcp_ban } else if ($post_id) { - $post_info = get_post_data($post_id, 'm_ban'); + $post_info = phpbb_get_post_data($post_id, 'm_ban'); if (sizeof($post_info) && !empty($post_info[$post_id])) { diff --git a/phpBB/includes/mcp/mcp_forum.php b/phpBB/includes/mcp/mcp_forum.php index 7c1c61dae7..dc4d59cc46 100644 --- a/phpBB/includes/mcp/mcp_forum.php +++ b/phpBB/includes/mcp/mcp_forum.php @@ -1,9 +1,13 @@ <?php /** * -* @package mcp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -31,21 +35,12 @@ function mcp_forum_view($id, $mode, $action, $forum_info) // merge_topic is the quickmod action, merge_topics is the mcp_forum action, and merge_select is the mcp_topic action $merge_select = ($action == 'merge_select' || $action == 'merge_topic' || $action == 'merge_topics') ? true : false; - if ($merge_select) - { - // Fixes a "bug" that makes forum_view use the same ordering as topic_view - $request->overwrite('sk', null); - $request->overwrite('sd', null); - $request->overwrite('sk', null, \phpbb\request\request_interface::POST); - $request->overwrite('sd', null, \phpbb\request\request_interface::POST); - } - $forum_id = $forum_info['forum_id']; - $start = request_var('start', 0); - $topic_id_list = request_var('topic_id_list', array(0)); - $post_id_list = request_var('post_id_list', array(0)); - $source_topic_ids = array(request_var('t', 0)); - $to_topic_id = request_var('to_topic_id', 0); + $start = $request->variable('start', 0); + $topic_id_list = $request->variable('topic_id_list', array(0)); + $post_id_list = $request->variable('post_id_list', array(0)); + $source_topic_ids = array($request->variable('t', 0)); + $to_topic_id = $request->variable('to_topic_id', 0); $url_extra = ''; $url_extra .= ($forum_id) ? "&f=$forum_id" : ''; @@ -59,7 +54,7 @@ function mcp_forum_view($id, $mode, $action, $forum_info) switch ($action) { case 'resync': - $topic_ids = request_var('topic_id_list', array(0)); + $topic_ids = $request->variable('topic_id_list', array(0)); mcp_resync_topics($topic_ids); break; @@ -73,6 +68,31 @@ function mcp_forum_view($id, $mode, $action, $forum_info) break; } + /** + * Get some data in order to execute other actions. + * + * @event core.mcp_forum_view_before + * @var string action The action + * @var array forum_info Array with forum infos + * @var int start Start value + * @var array topic_id_list Array of topics ids + * @var array post_id_list Array of posts ids + * @var array source_topic_ids Array of source topics ids + * @var int to_topic_id Array of destination topics ids + * @since 3.1.6-RC1 + */ + $vars = array( + 'action', + 'forum_info', + 'start', + 'topic_id_list', + 'post_id_list', + 'source_topic_ids', + 'to_topic_id', + ); + extract($phpbb_dispatcher->trigger_event('core.mcp_forum_view_before', compact($vars))); + + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); $selected_ids = ''; @@ -98,7 +118,7 @@ function mcp_forum_view($id, $mode, $action, $forum_info) $sort_days = $total = 0; $sort_key = $sort_dir = ''; $sort_by_sql = $sort_order_sql = array(); - mcp_sorting('viewforum', $sort_days, $sort_key, $sort_dir, $sort_by_sql, $sort_order_sql, $total, $forum_id); + phpbb_mcp_sorting('viewforum', $sort_days, $sort_key, $sort_dir, $sort_by_sql, $sort_order_sql, $total, $forum_id); $forum_topics = ($total == -1) ? $forum_info['forum_topics_approved'] : $total; $limit_time_sql = ($sort_days) ? 'AND t.topic_last_post_time >= ' . (time() - ($sort_days * 86400)) : ''; @@ -126,9 +146,10 @@ function mcp_forum_view($id, $mode, $action, $forum_info) 'S_CAN_SYNC' => $auth->acl_get('m_', $forum_id), 'S_CAN_APPROVE' => $auth->acl_get('m_approve', $forum_id), 'S_MERGE_SELECT' => ($merge_select) ? true : false, - 'S_CAN_MAKE_NORMAL' => $auth->acl_gets('f_sticky', 'f_announce', $forum_id), + 'S_CAN_MAKE_NORMAL' => $auth->acl_gets('f_sticky', 'f_announce', 'f_announce_global', $forum_id), 'S_CAN_MAKE_STICKY' => $auth->acl_get('f_sticky', $forum_id), 'S_CAN_MAKE_ANNOUNCE' => $auth->acl_get('f_announce', $forum_id), + 'S_CAN_MAKE_ANNOUNCE_GLOBAL' => $auth->acl_get('f_announce_global', $forum_id), 'U_VIEW_FORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id), 'U_VIEW_FORUM_LOGS' => ($auth->acl_gets('a_', 'm_', $forum_id) && $module->loaded('logs')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=logs&mode=forum_logs&f=' . $forum_id) : '', @@ -153,6 +174,7 @@ function mcp_forum_view($id, $mode, $action, $forum_info) $read_tracking_join = $read_tracking_select = ''; } + /* @var $phpbb_content_visibility \phpbb\content_visibility */ $phpbb_content_visibility = $phpbb_container->get('content.visibility'); $sql = 'SELECT t.topic_id @@ -161,13 +183,29 @@ function mcp_forum_view($id, $mode, $action, $forum_info) AND ' . $phpbb_content_visibility->get_visibility_sql('topic', $forum_id, 't.') . " $limit_time_sql ORDER BY t.topic_type DESC, $sort_order_sql"; + + /** + * Modify SQL query before MCP forum view topic list is queried + * + * @event core.mcp_view_forum_modify_sql + * @var string sql SQL query for forum view topic list + * @var int forum_id ID of the forum + * @var string limit_time_sql SQL query part for limit time + * @var string sort_order_sql SQL query part for sort order + * @var int topics_per_page Number of topics per page + * @var int start Start value + * @since 3.1.2-RC1 + */ + $vars = array('sql', 'forum_id', 'limit_time_sql', 'sort_order_sql', 'topics_per_page', 'start'); + extract($phpbb_dispatcher->trigger_event('core.mcp_view_forum_modify_sql', compact($vars))); + $result = $db->sql_query_limit($sql, $topics_per_page, $start); $topic_list = $topic_tracking_info = array(); - while ($row = $db->sql_fetchrow($result)) + while ($row_ary = $db->sql_fetchrow($result)) { - $topic_list[] = $row['topic_id']; + $topic_list[] = $row_ary['topic_id']; } $db->sql_freeresult($result); @@ -176,9 +214,9 @@ function mcp_forum_view($id, $mode, $action, $forum_info) WHERE " . $db->sql_in_set('t.topic_id', $topic_list, false, true); $result = $db->sql_query($sql); - while ($row = $db->sql_fetchrow($result)) + while ($row_ary = $db->sql_fetchrow($result)) { - $topic_rows[$row['topic_id']] = $row; + $topic_rows[$row_ary['topic_id']] = $row_ary; } $db->sql_freeresult($result); @@ -203,109 +241,110 @@ function mcp_forum_view($id, $mode, $action, $forum_info) foreach ($topic_list as $topic_id) { - $topic_title = ''; - - $row = &$topic_rows[$topic_id]; + $row_ary = &$topic_rows[$topic_id]; - $replies = $phpbb_content_visibility->get_count('topic_posts', $row, $forum_id) - 1; + $replies = $phpbb_content_visibility->get_count('topic_posts', $row_ary, $forum_id) - 1; - if ($row['topic_status'] == ITEM_MOVED) + if ($row_ary['topic_status'] == ITEM_MOVED) { $unread_topic = false; } else { - $unread_topic = (isset($topic_tracking_info[$topic_id]) && $row['topic_last_post_time'] > $topic_tracking_info[$topic_id]) ? true : false; + $unread_topic = (isset($topic_tracking_info[$topic_id]) && $row_ary['topic_last_post_time'] > $topic_tracking_info[$topic_id]) ? true : false; } // Get folder img, topic status/type related information $folder_img = $folder_alt = $topic_type = ''; - topic_status($row, $replies, $unread_topic, $folder_img, $folder_alt, $topic_type); + topic_status($row_ary, $replies, $unread_topic, $folder_img, $folder_alt, $topic_type); - $topic_title = censor_text($row['topic_title']); + $topic_title = censor_text($row_ary['topic_title']); - $topic_unapproved = ($row['topic_visibility'] == ITEM_UNAPPROVED && $auth->acl_get('m_approve', $row['forum_id'])) ? true : false; - $posts_unapproved = ($row['topic_visibility'] == ITEM_APPROVED && $row['topic_posts_unapproved'] && $auth->acl_get('m_approve', $row['forum_id'])) ? true : false; - $topic_deleted = $row['topic_visibility'] == ITEM_DELETED; - $u_mcp_queue = ($topic_unapproved || $posts_unapproved) ? $url . '&i=queue&mode=' . (($topic_unapproved) ? 'approve_details' : 'unapproved_posts') . '&t=' . $row['topic_id'] : ''; + $topic_unapproved = (($row_ary['topic_visibility'] == ITEM_UNAPPROVED || $row_ary['topic_visibility'] == ITEM_REAPPROVE) && $auth->acl_get('m_approve', $row_ary['forum_id'])) ? true : false; + $posts_unapproved = ($row_ary['topic_visibility'] == ITEM_APPROVED && $row_ary['topic_posts_unapproved'] && $auth->acl_get('m_approve', $row_ary['forum_id'])) ? true : false; + $topic_deleted = $row_ary['topic_visibility'] == ITEM_DELETED; + $u_mcp_queue = ($topic_unapproved || $posts_unapproved) ? $url . '&i=queue&mode=' . (($topic_unapproved) ? 'approve_details' : 'unapproved_posts') . '&t=' . $row_ary['topic_id'] : ''; $u_mcp_queue = (!$u_mcp_queue && $topic_deleted) ? $url . '&i=queue&mode=deleted_topics&t=' . $topic_id : $u_mcp_queue; $topic_row = array( - 'ATTACH_ICON_IMG' => ($auth->acl_get('u_download') && $auth->acl_get('f_download', $row['forum_id']) && $row['topic_attachment']) ? $user->img('icon_topic_attach', $user->lang['TOTAL_ATTACHMENTS']) : '', + 'ATTACH_ICON_IMG' => ($auth->acl_get('u_download') && $auth->acl_get('f_download', $row_ary['forum_id']) && $row_ary['topic_attachment']) ? $user->img('icon_topic_attach', $user->lang['TOTAL_ATTACHMENTS']) : '', 'TOPIC_IMG_STYLE' => $folder_img, 'TOPIC_FOLDER_IMG' => $user->img($folder_img, $folder_alt), - 'TOPIC_ICON_IMG' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['img'] : '', - 'TOPIC_ICON_IMG_WIDTH' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['width'] : '', - 'TOPIC_ICON_IMG_HEIGHT' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['height'] : '', + 'TOPIC_ICON_IMG' => (!empty($icons[$row_ary['icon_id']])) ? $icons[$row_ary['icon_id']]['img'] : '', + 'TOPIC_ICON_IMG_WIDTH' => (!empty($icons[$row_ary['icon_id']])) ? $icons[$row_ary['icon_id']]['width'] : '', + 'TOPIC_ICON_IMG_HEIGHT' => (!empty($icons[$row_ary['icon_id']])) ? $icons[$row_ary['icon_id']]['height'] : '', 'UNAPPROVED_IMG' => ($topic_unapproved || $posts_unapproved) ? $user->img('icon_topic_unapproved', ($topic_unapproved) ? 'TOPIC_UNAPPROVED' : 'POSTS_UNAPPROVED') : '', 'DELETED_IMG' => ($topic_deleted) ? $user->img('icon_topic_deleted', 'POSTS_DELETED') : '', - 'TOPIC_AUTHOR' => get_username_string('username', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), - 'TOPIC_AUTHOR_COLOUR' => get_username_string('colour', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), - 'TOPIC_AUTHOR_FULL' => get_username_string('full', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), - 'U_TOPIC_AUTHOR' => get_username_string('profile', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), + 'TOPIC_AUTHOR' => get_username_string('username', $row_ary['topic_poster'], $row_ary['topic_first_poster_name'], $row_ary['topic_first_poster_colour']), + 'TOPIC_AUTHOR_COLOUR' => get_username_string('colour', $row_ary['topic_poster'], $row_ary['topic_first_poster_name'], $row_ary['topic_first_poster_colour']), + 'TOPIC_AUTHOR_FULL' => get_username_string('full', $row_ary['topic_poster'], $row_ary['topic_first_poster_name'], $row_ary['topic_first_poster_colour']), + 'U_TOPIC_AUTHOR' => get_username_string('profile', $row_ary['topic_poster'], $row_ary['topic_first_poster_name'], $row_ary['topic_first_poster_colour']), - 'LAST_POST_AUTHOR' => get_username_string('username', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), - 'LAST_POST_AUTHOR_COLOUR' => get_username_string('colour', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), - 'LAST_POST_AUTHOR_FULL' => get_username_string('full', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), - 'U_LAST_POST_AUTHOR' => get_username_string('profile', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), + 'LAST_POST_AUTHOR' => get_username_string('username', $row_ary['topic_last_poster_id'], $row_ary['topic_last_poster_name'], $row_ary['topic_last_poster_colour']), + 'LAST_POST_AUTHOR_COLOUR' => get_username_string('colour', $row_ary['topic_last_poster_id'], $row_ary['topic_last_poster_name'], $row_ary['topic_last_poster_colour']), + 'LAST_POST_AUTHOR_FULL' => get_username_string('full', $row_ary['topic_last_poster_id'], $row_ary['topic_last_poster_name'], $row_ary['topic_last_poster_colour']), + 'U_LAST_POST_AUTHOR' => get_username_string('profile', $row_ary['topic_last_poster_id'], $row_ary['topic_last_poster_name'], $row_ary['topic_last_poster_colour']), 'TOPIC_TYPE' => $topic_type, 'TOPIC_TITLE' => $topic_title, - 'REPLIES' => $phpbb_content_visibility->get_count('topic_posts', $row, $row['forum_id']) - 1, - 'LAST_POST_TIME' => $user->format_date($row['topic_last_post_time']), - 'FIRST_POST_TIME' => $user->format_date($row['topic_time']), - 'LAST_POST_SUBJECT' => $row['topic_last_post_subject'], - 'LAST_VIEW_TIME' => $user->format_date($row['topic_last_view_time']), + 'REPLIES' => $phpbb_content_visibility->get_count('topic_posts', $row_ary, $row_ary['forum_id']) - 1, + 'LAST_POST_TIME' => $user->format_date($row_ary['topic_last_post_time']), + 'FIRST_POST_TIME' => $user->format_date($row_ary['topic_time']), + 'LAST_POST_SUBJECT' => $row_ary['topic_last_post_subject'], + 'LAST_VIEW_TIME' => $user->format_date($row_ary['topic_last_view_time']), - 'S_TOPIC_REPORTED' => (!empty($row['topic_reported']) && empty($row['topic_moved_id']) && $auth->acl_get('m_report', $row['forum_id'])) ? true : false, + 'S_TOPIC_REPORTED' => (!empty($row_ary['topic_reported']) && empty($row_ary['topic_moved_id']) && $auth->acl_get('m_report', $row_ary['forum_id'])) ? true : false, 'S_TOPIC_UNAPPROVED' => $topic_unapproved, 'S_POSTS_UNAPPROVED' => $posts_unapproved, 'S_TOPIC_DELETED' => $topic_deleted, 'S_UNREAD_TOPIC' => $unread_topic, ); - if ($row['topic_status'] == ITEM_MOVED) + if ($row_ary['topic_status'] == ITEM_MOVED) { $topic_row = array_merge($topic_row, array( - 'U_VIEW_TOPIC' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", "t={$row['topic_moved_id']}"), - 'U_DELETE_TOPIC' => ($auth->acl_get('m_delete', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", "i=$id&f=$forum_id&topic_id_list[]={$row['topic_id']}&mode=forum_view&action=delete_topic") : '', + 'U_VIEW_TOPIC' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", "t={$row_ary['topic_moved_id']}"), + 'U_DELETE_TOPIC' => ($auth->acl_get('m_delete', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", "i=$id&f=$forum_id&topic_id_list[]={$row_ary['topic_id']}&mode=forum_view&action=delete_topic") : '', 'S_MOVED_TOPIC' => true, - 'TOPIC_ID' => $row['topic_moved_id'], + 'TOPIC_ID' => $row_ary['topic_moved_id'], )); } else { if ($action == 'merge_topic' || $action == 'merge_topics') { - $u_select_topic = $url . "&i=$id&mode=forum_view&action=$action&to_topic_id=" . $row['topic_id'] . $selected_ids; + $u_select_topic = $url . "&i=$id&mode=forum_view&action=$action&to_topic_id=" . $row_ary['topic_id'] . $selected_ids; } else { - $u_select_topic = $url . "&i=$id&mode=topic_view&action=merge&to_topic_id=" . $row['topic_id'] . $selected_ids; + $u_select_topic = $url . "&i=$id&mode=topic_view&action=merge&to_topic_id=" . $row_ary['topic_id'] . $selected_ids; } $topic_row = array_merge($topic_row, array( - 'U_VIEW_TOPIC' => append_sid("{$phpbb_root_path}mcp.$phpEx", "i=$id&f=$forum_id&t={$row['topic_id']}&mode=topic_view"), + 'U_VIEW_TOPIC' => append_sid("{$phpbb_root_path}mcp.$phpEx", "i=$id&f=$forum_id&t={$row_ary['topic_id']}&mode=topic_view"), - 'S_SELECT_TOPIC' => ($merge_select && !in_array($row['topic_id'], $source_topic_ids)) ? true : false, + 'S_SELECT_TOPIC' => ($merge_select && !in_array($row_ary['topic_id'], $source_topic_ids)) ? true : false, 'U_SELECT_TOPIC' => $u_select_topic, 'U_MCP_QUEUE' => $u_mcp_queue, - 'U_MCP_REPORT' => ($auth->acl_get('m_report', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=main&mode=topic_view&t=' . $row['topic_id'] . '&action=reports') : '', - 'TOPIC_ID' => $row['topic_id'], - 'S_TOPIC_CHECKED' => ($topic_id_list && in_array($row['topic_id'], $topic_id_list)) ? true : false, + 'U_MCP_REPORT' => ($auth->acl_get('m_report', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=main&mode=topic_view&t=' . $row_ary['topic_id'] . '&action=reports') : '', + 'TOPIC_ID' => $row_ary['topic_id'], + 'S_TOPIC_CHECKED' => ($topic_id_list && in_array($row_ary['topic_id'], $topic_id_list)) ? true : false, )); } + $row = $row_ary; /** * Modify the topic data before it is assigned to the template in MCP * * @event core.mcp_view_forum_modify_topicrow - * @var array row Array with topic data + * @var array row Array with topic data * @var array topic_row Template array with topic data - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('row', 'topic_row'); extract($phpbb_dispatcher->trigger_event('core.mcp_view_forum_modify_topicrow', compact($vars))); + $row_ary = $row; + unset($row); $template->assign_block_vars('topicrow', $topic_row); } @@ -317,14 +356,14 @@ function mcp_forum_view($id, $mode, $action, $forum_info) */ function mcp_resync_topics($topic_ids) { - global $auth, $db, $template, $phpEx, $user, $phpbb_root_path; + global $db, $user, $phpbb_log, $request; if (!sizeof($topic_ids)) { trigger_error('NO_TOPIC_SELECTED'); } - if (!check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('m_'))) + if (!phpbb_check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('m_'))) { return; } @@ -342,13 +381,17 @@ function mcp_resync_topics($topic_ids) // Log this action while ($row = $db->sql_fetchrow($result)) { - add_log('mod', $row['forum_id'], $row['topic_id'], 'LOG_TOPIC_RESYNC', $row['topic_title']); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_TOPIC_RESYNC', false, array( + 'forum_id' => $row['forum_id'], + 'topic_id' => $row['topic_id'], + $row['topic_title'] + )); } $db->sql_freeresult($result); $msg = (sizeof($topic_ids) == 1) ? $user->lang['TOPIC_RESYNC_SUCCESS'] : $user->lang['TOPICS_RESYNC_SUCCESS']; - $redirect = request_var('redirect', $user->data['session_page']); + $redirect = $request->variable('redirect', $user->data['session_page']); meta_refresh(3, $redirect); trigger_error($msg . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $redirect . '">', '</a>')); @@ -361,7 +404,7 @@ function mcp_resync_topics($topic_ids) */ function merge_topics($forum_id, $topic_ids, $to_topic_id) { - global $db, $template, $user, $phpEx, $phpbb_root_path, $auth; + global $db, $template, $user, $phpEx, $phpbb_root_path, $phpbb_log, $request; if (!sizeof($topic_ids)) { @@ -374,18 +417,26 @@ function merge_topics($forum_id, $topic_ids, $to_topic_id) return; } - $topic_data = get_topic_data(array($to_topic_id), 'm_merge'); + $sync_topics = array_merge($topic_ids, array($to_topic_id)); - if (!sizeof($topic_data)) + $topic_data = phpbb_get_topic_data($sync_topics, 'm_merge'); + + if (!sizeof($topic_data) || empty($topic_data[$to_topic_id])) { $template->assign_var('MESSAGE', $user->lang['NO_FINAL_TOPIC_SELECTED']); return; } + $sync_forums = array(); + foreach ($topic_data as $data) + { + $sync_forums[$data['forum_id']] = $data['forum_id']; + } + $topic_data = $topic_data[$to_topic_id]; - $post_id_list = request_var('post_id_list', array(0)); - $start = request_var('start', 0); + $post_id_list = $request->variable('post_id_list', array(0)); + $start = $request->variable('start', 0); if (!sizeof($post_id_list) && sizeof($topic_ids)) { @@ -408,12 +459,12 @@ function merge_topics($forum_id, $topic_ids, $to_topic_id) return; } - if (!check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_merge'))) + if (!phpbb_check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_merge'))) { return; } - $redirect = request_var('redirect', build_url(array('quickmod'))); + $redirect = $request->variable('redirect', build_url(array('quickmod'))); $s_hidden_fields = build_hidden_fields(array( 'i' => 'main', @@ -426,14 +477,19 @@ function merge_topics($forum_id, $topic_ids, $to_topic_id) 'redirect' => $redirect, 'topic_id_list' => $topic_ids) ); - $success_msg = $return_link = ''; + $return_link = ''; if (confirm_box(true)) { $to_forum_id = $topic_data['forum_id']; - move_posts($post_id_list, $to_topic_id); - add_log('mod', $to_forum_id, $to_topic_id, 'LOG_MERGE', $topic_data['topic_title']); + move_posts($post_id_list, $to_topic_id, false); + + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_MERGE', false, array( + 'forum_id' => $to_forum_id, + 'topic_id' => $to_topic_id, + $topic_data['topic_title'] + )); // Message and return links $success_msg = 'POSTS_MERGED_SUCCESS'; @@ -449,9 +505,15 @@ function merge_topics($forum_id, $topic_ids, $to_topic_id) // Update the bookmarks table. phpbb_update_rows_avoiding_duplicates($db, BOOKMARKS_TABLE, 'topic_id', $topic_ids, $to_topic_id); + // Re-sync the topics and forums because the auto-sync was deactivated in the call of move_posts() + sync('topic_reported', 'topic_id', $sync_topics); + sync('topic_attachment', 'topic_id', $sync_topics); + sync('topic', 'topic_id', $sync_topics, true); + sync('forum', 'forum_id', $sync_forums, true, true); + // Link to the new topic $return_link .= (($return_link) ? '<br /><br />' : '') . sprintf($user->lang['RETURN_NEW_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $to_forum_id . '&t=' . $to_topic_id) . '">', '</a>'); - $redirect = request_var('redirect', "{$phpbb_root_path}viewtopic.$phpEx?f=$to_forum_id&t=$to_topic_id"); + $redirect = $request->variable('redirect', "{$phpbb_root_path}viewtopic.$phpEx?f=$to_forum_id&t=$to_topic_id"); $redirect = reapply_sid($redirect); meta_refresh(3, $redirect); diff --git a/phpBB/includes/mcp/mcp_front.php b/phpBB/includes/mcp/mcp_front.php index 44cab5d910..432b26ad11 100644 --- a/phpBB/includes/mcp/mcp_front.php +++ b/phpBB/includes/mcp/mcp_front.php @@ -1,9 +1,13 @@ <?php /** * -* @package mcp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -20,8 +24,9 @@ if (!defined('IN_PHPBB')) */ function mcp_front_view($id, $mode, $action) { - global $phpEx, $phpbb_root_path, $config; + global $phpEx, $phpbb_root_path; global $template, $db, $user, $auth, $module; + global $phpbb_dispatcher, $request; // Latest 5 unapproved if ($module->loaded('queue')) @@ -30,16 +35,33 @@ function mcp_front_view($id, $mode, $action) $post_list = array(); $forum_names = array(); - $forum_id = request_var('f', 0); + $forum_id = $request->variable('f', 0); $template->assign_var('S_SHOW_UNAPPROVED', (!empty($forum_list)) ? true : false); if (!empty($forum_list)) { - $sql = 'SELECT COUNT(post_id) AS total - FROM ' . POSTS_TABLE . ' - WHERE ' . $db->sql_in_set('forum_id', $forum_list) . ' - AND post_visibility = ' . ITEM_UNAPPROVED; + $sql_ary = array( + 'SELECT' => 'COUNT(post_id) AS total', + 'FROM' => array( + POSTS_TABLE => 'p', + ), + 'WHERE' => $db->sql_in_set('p.forum_id', $forum_list) . ' + AND ' . $db->sql_in_set('p.post_visibility', array(ITEM_UNAPPROVED, ITEM_REAPPROVE)) + ); + + /** + * Allow altering the query to get the number of unapproved posts + * + * @event core.mcp_front_queue_unapproved_total_before + * @var int sql_ary Query to get the total number of unapproved posts + * @var array forum_list List of forums to look for unapproved posts + * @since 3.1.5-RC1 + */ + $vars = array('sql_ary', 'forum_list'); + extract($phpbb_dispatcher->trigger_event('core.mcp_front_queue_unapproved_total_before', compact($vars))); + + $sql = $db->sql_build_query('SELECT', $sql_ary); $result = $db->sql_query($sql); $total = (int) $db->sql_fetchfield('total'); $db->sql_freeresult($result); @@ -60,8 +82,8 @@ function mcp_front_view($id, $mode, $action) $sql = 'SELECT post_id FROM ' . POSTS_TABLE . ' WHERE ' . $db->sql_in_set('forum_id', $forum_list) . ' - AND post_visibility = ' . ITEM_UNAPPROVED . ' - ORDER BY post_time DESC'; + AND ' . $db->sql_in_set('post_visibility', array(ITEM_UNAPPROVED, ITEM_REAPPROVE)) . ' + ORDER BY post_time DESC, post_id DESC'; $result = $db->sql_query_limit($sql, 5); while ($row = $db->sql_fetchrow($result)) @@ -76,6 +98,19 @@ function mcp_front_view($id, $mode, $action) } } + /** + * Alter list of posts and total as required + * + * @event core.mcp_front_view_queue_postid_list_after + * @var int total Number of unapproved posts + * @var array post_list List of unapproved posts + * @var array forum_list List of forums that contain the posts + * @var array forum_names Associative array with forum_id as key and it's corresponding forum_name as value + * @since 3.1.0-RC3 + */ + $vars = array('total', 'post_list', 'forum_list', 'forum_names'); + extract($phpbb_dispatcher->trigger_event('core.mcp_front_view_queue_postid_list_after', compact($vars))); + if ($total) { $sql = 'SELECT p.post_id, p.post_subject, p.post_time, p.post_attachment, p.poster_id, p.post_username, u.username, u.username_clean, u.user_colour, t.topic_id, t.topic_title, t.topic_first_post_id, p.forum_id @@ -83,7 +118,7 @@ function mcp_front_view($id, $mode, $action) WHERE ' . $db->sql_in_set('p.post_id', $post_list) . ' AND t.topic_id = p.topic_id AND p.poster_id = u.user_id - ORDER BY p.post_time DESC'; + ORDER BY p.post_time DESC, p.post_id DESC'; $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) @@ -139,6 +174,18 @@ function mcp_front_view($id, $mode, $action) AND r.pm_id = 0 AND r.report_closed = 0 AND ' . $db->sql_in_set('p.forum_id', $forum_list); + + /** + * Alter sql query to count the number of reported posts + * + * @event core.mcp_front_reports_count_query_before + * @var int sql The query string used to get the number of reports that exist + * @var array forum_list List of forums that contain the posts + * @since 3.1.5-RC1 + */ + $vars = array('sql', 'forum_list'); + extract($phpbb_dispatcher->trigger_event('core.mcp_front_reports_count_query_before', compact($vars))); + $result = $db->sql_query($sql); $total = (int) $db->sql_fetchfield('total'); $db->sql_freeresult($result); @@ -172,8 +219,20 @@ function mcp_front_view($id, $mode, $action) AND p.poster_id = u2.user_id AND ' . $db->sql_in_set('p.forum_id', $forum_list), - 'ORDER_BY' => 'p.post_time DESC', + 'ORDER_BY' => 'p.post_time DESC, p.post_id DESC', ); + + /** + * Alter sql query to get latest reported posts + * + * @event core.mcp_front_reports_listing_query_before + * @var int sql_ary Associative array with the query to be executed + * @var array forum_list List of forums that contain the posts + * @since 3.1.0-RC3 + */ + $vars = array('sql_ary', 'forum_list'); + extract($phpbb_dispatcher->trigger_event('core.mcp_front_reports_listing_query_before', compact($vars))); + $sql = $db->sql_build_query('SELECT', $sql_ary); $result = $db->sql_query_limit($sql, 5); @@ -204,6 +263,7 @@ function mcp_front_view($id, $mode, $action) 'ATTACH_ICON_IMG' => ($auth->acl_get('u_download') && $auth->acl_get('f_download', $row['forum_id']) && $row['post_attachment']) ? $user->img('icon_topic_attach', $user->lang['TOTAL_ATTACHMENTS']) : '', )); } + $db->sql_freeresult($result); } $template->assign_vars(array( @@ -214,7 +274,7 @@ function mcp_front_view($id, $mode, $action) } // Latest 5 reported PMs - if ($module->loaded('pm_reports') && $auth->acl_getf_global('m_report')) + if ($module->loaded('pm_reports') && $auth->acl_get('m_pm_report')) { $template->assign_var('S_SHOW_PM_REPORTS', true); $user->add_lang(array('ucp')); @@ -260,6 +320,7 @@ function mcp_front_view($id, $mode, $action) $pm_by_id[(int) $row['msg_id']] = $row; $pm_list[] = (int) $row['msg_id']; } + $db->sql_freeresult($result); $address_list = get_recipient_strings($pm_by_id); diff --git a/phpBB/includes/mcp/mcp_logs.php b/phpBB/includes/mcp/mcp_logs.php index 7bcb0fc477..fca0412321 100644 --- a/phpBB/includes/mcp/mcp_logs.php +++ b/phpBB/includes/mcp/mcp_logs.php @@ -1,9 +1,13 @@ <?php /** * -* @package mcp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -18,7 +22,6 @@ if (!defined('IN_PHPBB')) /** * mcp_logs * Handling warning the users -* @package mcp */ class mcp_logs { @@ -32,12 +35,12 @@ class mcp_logs function main($id, $mode) { - global $auth, $db, $user, $template; - global $config, $phpbb_root_path, $phpEx, $phpbb_container; + global $auth, $db, $user, $template, $request; + global $config, $phpbb_container, $phpbb_log; $user->add_lang('acp/common'); - $action = request_var('action', array('' => '')); + $action = $request->variable('action', array('' => '')); if (is_array($action)) { @@ -45,23 +48,24 @@ class mcp_logs } else { - $action = request_var('action', ''); + $action = $request->variable('action', ''); } // Set up general vars - $start = request_var('start', 0); + $start = $request->variable('start', 0); $deletemark = ($action == 'del_marked') ? true : false; $deleteall = ($action == 'del_all') ? true : false; - $marked = request_var('mark', array(0)); + $marked = $request->variable('mark', array(0)); // Sort keys - $sort_days = request_var('st', 0); - $sort_key = request_var('sk', 't'); - $sort_dir = request_var('sd', 'd'); + $sort_days = $request->variable('st', 0); + $sort_key = $request->variable('sk', 't'); + $sort_dir = $request->variable('sd', 'd'); $this->tpl_name = 'mcp_logs'; $this->page_title = 'MCP_LOGS'; + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); $forum_list = array_values(array_intersect(get_forum_list('f_read'), get_forum_list('m_'))); @@ -75,7 +79,7 @@ class mcp_logs break; case 'forum_logs': - $forum_id = request_var('f', 0); + $forum_id = $request->variable('f', 0); if (!in_array($forum_id, $forum_list)) { @@ -86,7 +90,7 @@ class mcp_logs break; case 'topic_logs': - $topic_id = request_var('t', 0); + $topic_id = $request->variable('t', 0); $sql = 'SELECT forum_id FROM ' . TOPICS_TABLE . ' @@ -111,27 +115,33 @@ class mcp_logs { if ($deletemark && sizeof($marked)) { - $sql = 'DELETE FROM ' . LOG_TABLE . ' - WHERE log_type = ' . LOG_MOD . ' - AND ' . $db->sql_in_set('forum_id', $forum_list) . ' - AND ' . $db->sql_in_set('log_id', $marked); - $db->sql_query($sql); + $conditions = array( + 'forum_id' => array('IN' => $forum_list), + 'log_id' => array('IN' => $marked), + ); - add_log('admin', 'LOG_CLEAR_MOD'); + $phpbb_log->delete('mod', $conditions); } else if ($deleteall) { - $sql = 'DELETE FROM ' . LOG_TABLE . ' - WHERE log_type = ' . LOG_MOD . ' - AND ' . $db->sql_in_set('forum_id', $forum_list); + $keywords = $request->variable('keywords', '', true); + + $conditions = array( + 'forum_id' => array('IN' => $forum_list), + 'keywords' => $keywords, + ); + + if ($sort_days) + { + $conditions['log_time'] = array('>=', time() - ($sort_days * 86400)); + } if ($mode == 'topic_logs') { - $sql .= ' AND topic_id = ' . $topic_id; + $conditions['topic_id'] = $topic_id; } - $db->sql_query($sql); - add_log('admin', 'LOG_CLEAR_MOD'); + $phpbb_log->delete('mod', $conditions); } } else @@ -148,7 +158,7 @@ class mcp_logs 'sd' => $sort_dir, 'i' => $id, 'mode' => $mode, - 'action' => request_var('action', array('' => '')))) + 'action' => $request->variable('action', array('' => '')))) ); } } @@ -165,7 +175,7 @@ class mcp_logs $sql_where = ($sort_days) ? (time() - ($sort_days * 86400)) : 0; $sql_sort = $sort_by_sql[$sort_key] . ' ' . (($sort_dir == 'd') ? 'DESC' : 'ASC'); - $keywords = utf8_normalize_nfc(request_var('keywords', '', true)); + $keywords = $request->variable('keywords', '', true); $keywords_param = !empty($keywords) ? '&keywords=' . urlencode(htmlspecialchars_decode($keywords)) : ''; // Grab log data @@ -195,7 +205,7 @@ class mcp_logs { $data = array(); - $checks = array('viewtopic', 'viewforum'); + $checks = array('viewpost', 'viewtopic', 'viewforum'); foreach ($checks as $check) { if (isset($row[$check]) && $row[$check]) diff --git a/phpBB/includes/mcp/mcp_main.php b/phpBB/includes/mcp/mcp_main.php index 016094c5d4..9702056d7b 100644 --- a/phpBB/includes/mcp/mcp_main.php +++ b/phpBB/includes/mcp/mcp_main.php @@ -1,9 +1,13 @@ <?php /** * -* @package mcp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -18,7 +22,6 @@ if (!defined('IN_PHPBB')) /** * mcp_main * Handling mcp actions -* @package mcp */ class mcp_main { @@ -32,8 +35,8 @@ class mcp_main function main($id, $mode) { - global $auth, $db, $user, $template, $action; - global $config, $phpbb_root_path, $phpEx, $request; + global $auth, $user, $action; + global $phpbb_root_path, $phpEx, $request; global $phpbb_dispatcher; $quickmod = ($mode == 'quickmod') ? true : false; @@ -42,7 +45,7 @@ class mcp_main { case 'lock': case 'unlock': - $topic_ids = (!$quickmod) ? request_var('topic_id_list', array(0)) : array(request_var('t', 0)); + $topic_ids = (!$quickmod) ? $request->variable('topic_id_list', array(0)) : array($request->variable('t', 0)); if (!sizeof($topic_ids)) { @@ -55,7 +58,7 @@ class mcp_main case 'lock_post': case 'unlock_post': - $post_ids = (!$quickmod) ? request_var('post_id_list', array(0)) : array(request_var('p', 0)); + $post_ids = (!$quickmod) ? $request->variable('post_id_list', array(0)) : array($request->variable('p', 0)); if (!sizeof($post_ids)) { @@ -70,7 +73,7 @@ class mcp_main case 'make_global': case 'make_normal': - $topic_ids = (!$quickmod) ? request_var('topic_id_list', array(0)) : array(request_var('t', 0)); + $topic_ids = (!$quickmod) ? $request->variable('topic_id_list', array(0)) : array($request->variable('t', 0)); if (!sizeof($topic_ids)) { @@ -83,7 +86,7 @@ class mcp_main case 'move': $user->add_lang('viewtopic'); - $topic_ids = (!$quickmod) ? request_var('topic_id_list', array(0)) : array(request_var('t', 0)); + $topic_ids = (!$quickmod) ? $request->variable('topic_id_list', array(0)) : array($request->variable('t', 0)); if (!sizeof($topic_ids)) { @@ -96,7 +99,7 @@ class mcp_main case 'fork': $user->add_lang('viewtopic'); - $topic_ids = (!$quickmod) ? request_var('topic_id_list', array(0)) : array(request_var('t', 0)); + $topic_ids = (!$quickmod) ? $request->variable('topic_id_list', array(0)) : array($request->variable('t', 0)); if (!sizeof($topic_ids)) { @@ -120,7 +123,7 @@ class mcp_main trigger_error('NO_TOPIC_SELECTED'); } - mcp_delete_topic($topic_ids, $soft_delete, ($soft_delete) ? $request->variable('delete_reason', '', true) : ''); + mcp_delete_topic($topic_ids, $soft_delete, $request->variable('delete_reason', '', true)); break; case 'delete_post': @@ -137,7 +140,7 @@ class mcp_main trigger_error('NO_POST_SELECTED'); } - mcp_delete_post($post_ids, $soft_delete, ($soft_delete) ? $request->variable('delete_reason', '', true) : ''); + mcp_delete_post($post_ids, $soft_delete, $request->variable('delete_reason', '', true)); break; case 'restore_topic': @@ -158,9 +161,13 @@ class mcp_main * This event allows you to handle custom quickmod options * * @event core.modify_quickmod_actions + * @var string action Topic quick moderation action name + * @var bool quickmod Flag indicating whether MCP is in quick moderation mode * @since 3.1.0-a4 + * @change 3.1.0-RC4 Added variables: action, quickmod */ - $phpbb_dispatcher->dispatch('core.modify_quickmod_actions'); + $vars = array('action', 'quickmod'); + extract($phpbb_dispatcher->trigger_event('core.modify_quickmod_actions', compact($vars))); break; } @@ -182,9 +189,9 @@ class mcp_main $user->add_lang('viewforum'); - $forum_id = request_var('f', 0); + $forum_id = $request->variable('f', 0); - $forum_info = get_forum_data($forum_id, 'm_', true); + $forum_info = phpbb_get_forum_data($forum_id, 'm_', true); if (!sizeof($forum_info)) { @@ -219,6 +226,31 @@ class mcp_main break; default: + if ($quickmod) + { + switch ($action) + { + case 'lock': + case 'unlock': + case 'make_announce': + case 'make_sticky': + case 'make_global': + case 'make_normal': + case 'make_onindex': + case 'move': + case 'fork': + case 'delete_topic': + trigger_error('TOPIC_NOT_EXIST'); + break; + + case 'lock_post': + case 'unlock_post': + case 'delete_post': + trigger_error('POST_NOT_EXIST'); + break; + } + } + trigger_error('NO_MODE', E_USER_ERROR); break; } @@ -230,7 +262,7 @@ class mcp_main */ function lock_unlock($action, $ids) { - global $auth, $user, $db, $phpEx, $phpbb_root_path, $request; + global $user, $db, $request, $phpbb_log, $phpbb_dispatcher; if ($action == 'lock' || $action == 'unlock') { @@ -249,7 +281,7 @@ function lock_unlock($action, $ids) $orig_ids = $ids; - if (!check_ids($ids, $table, $sql_id, array('m_lock'))) + if (!phpbb_check_ids($ids, $table, $sql_id, array('m_lock'))) { // Make sure that for f_user_lock only the lock action is triggered. if ($action != 'lock') @@ -259,14 +291,14 @@ function lock_unlock($action, $ids) $ids = $orig_ids; - if (!check_ids($ids, $table, $sql_id, array('f_user_lock'))) + if (!phpbb_check_ids($ids, $table, $sql_id, array('f_user_lock'))) { return; } } unset($orig_ids); - $redirect = request_var('redirect', build_url(array('action', 'quickmod'))); + $redirect = $request->variable('redirect', build_url(array('action', 'quickmod'))); $redirect = reapply_sid($redirect); $s_hidden_fields = build_hidden_fields(array( @@ -274,7 +306,6 @@ function lock_unlock($action, $ids) 'action' => $action, 'redirect' => $redirect) ); - $success_msg = ''; if (confirm_box(true)) { @@ -283,13 +314,34 @@ function lock_unlock($action, $ids) WHERE ' . $db->sql_in_set($sql_id, $ids); $db->sql_query($sql); - $data = ($action == 'lock' || $action == 'unlock') ? get_topic_data($ids) : get_post_data($ids); + $data = ($action == 'lock' || $action == 'unlock') ? phpbb_get_topic_data($ids) : phpbb_get_post_data($ids); foreach ($data as $id => $row) { - add_log('mod', $row['forum_id'], $row['topic_id'], 'LOG_' . strtoupper($action), $row['topic_title']); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_' . strtoupper($action), false, array( + 'forum_id' => $row['forum_id'], + 'topic_id' => $row['topic_id'], + 'post_id' => isset($row['post_id']) ? $row['post_id'] : 0, + $row['topic_title'] + )); } + /** + * Perform additional actions after locking/unlocking posts/topics + * + * @event core.mcp_lock_unlock_after + * @var string action Variable containing the action we perform on the posts/topics ('lock', 'unlock', 'lock_post' or 'unlock_post') + * @var array ids Array containing the post/topic IDs that have been locked/unlocked + * @var array data Array containing posts/topics data + * @since 3.1.7-RC1 + */ + $vars = array( + 'action', + 'ids', + 'data', + ); + extract($phpbb_dispatcher->trigger_event('core.mcp_lock_unlock_after', compact($vars))); + $success_msg = $l_prefix . ((sizeof($ids) == 1) ? '' : 'S') . '_' . (($action == 'lock' || $action == 'lock_post') ? 'LOCKED' : 'UNLOCKED') . '_SUCCESS'; meta_refresh(2, $redirect); @@ -314,7 +366,7 @@ function lock_unlock($action, $ids) */ function change_topic_type($action, $topic_ids) { - global $auth, $user, $db, $phpEx, $phpbb_root_path, $request; + global $user, $db, $request, $phpbb_log; switch ($action) { @@ -326,7 +378,7 @@ function change_topic_type($action, $topic_ids) case 'make_global': $new_topic_type = POST_GLOBAL; - $check_acl = 'f_announce'; + $check_acl = 'f_announce_global'; $l_new_type = (sizeof($topic_ids) == 1) ? 'MCP_MAKE_GLOBAL' : 'MCP_MAKE_GLOBALS'; break; @@ -343,14 +395,14 @@ function change_topic_type($action, $topic_ids) break; } - $forum_id = check_ids($topic_ids, TOPICS_TABLE, 'topic_id', $check_acl, true); + $forum_id = phpbb_check_ids($topic_ids, TOPICS_TABLE, 'topic_id', $check_acl, true); if ($forum_id === false) { return; } - $redirect = request_var('redirect', build_url(array('action', 'quickmod'))); + $redirect = $request->variable('redirect', build_url(array('action', 'quickmod'))); $redirect = reapply_sid($redirect); $s_hidden_fields = array( @@ -359,7 +411,6 @@ function change_topic_type($action, $topic_ids) 'action' => $action, 'redirect' => $redirect, ); - $success_msg = ''; if (confirm_box(true)) { @@ -385,11 +436,15 @@ function change_topic_type($action, $topic_ids) if (sizeof($topic_ids)) { - $data = get_topic_data($topic_ids); + $data = phpbb_get_topic_data($topic_ids); foreach ($data as $topic_id => $row) { - add_log('mod', $forum_id, $topic_id, 'LOG_TOPIC_TYPE_CHANGED', $row['topic_title']); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_TOPIC_TYPE_CHANGED', false, array( + 'forum_id' => $forum_id, + 'topic_id' => $topic_id, + $row['topic_title'] + )); } } @@ -415,20 +470,19 @@ function change_topic_type($action, $topic_ids) */ function mcp_move_topic($topic_ids) { - global $auth, $user, $db, $template; + global $auth, $user, $db, $template, $phpbb_log, $request; global $phpEx, $phpbb_root_path; - global $request; // Here we limit the operation to one forum only - $forum_id = check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('m_move'), true); + $forum_id = phpbb_check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('m_move'), true); if ($forum_id === false) { return; } - $to_forum_id = request_var('to_forum_id', 0); - $redirect = request_var('redirect', build_url(array('action', 'quickmod'))); + $to_forum_id = $request->variable('to_forum_id', 0); + $redirect = $request->variable('redirect', build_url(array('action', 'quickmod'))); $additional_msg = $success_msg = ''; $s_hidden_fields = build_hidden_fields(array( @@ -440,7 +494,7 @@ function mcp_move_topic($topic_ids) if ($to_forum_id) { - $forum_data = get_forum_data($to_forum_id, 'f_post'); + $forum_data = phpbb_get_forum_data($to_forum_id, 'f_post'); if (!sizeof($forum_data)) { @@ -477,7 +531,7 @@ function mcp_move_topic($topic_ids) if (confirm_box(true)) { - $topic_data = get_topic_data($topic_ids); + $topic_data = phpbb_get_topic_data($topic_ids); $leave_shadow = (isset($_POST['move_leave_shadow'])) ? true : false; $forum_sync_data = array(); @@ -494,11 +548,11 @@ function mcp_move_topic($topic_ids) { $topics_moved++; } - elseif ($topic_info['topic_visibility'] == ITEM_UNAPPROVED) + else if ($topic_info['topic_visibility'] == ITEM_UNAPPROVED || $topic_info['topic_visibility'] == ITEM_REAPPROVE) { $topics_moved_unapproved++; } - elseif ($topic_info['topic_visibility'] == ITEM_DELETED) + else if ($topic_info['topic_visibility'] == ITEM_DELETED) { $topics_moved_softdeleted++; } @@ -525,9 +579,19 @@ function mcp_move_topic($topic_ids) $forum_ids = array($to_forum_id); foreach ($topic_data as $topic_id => $row) { - // Get the list of forums to resync, add a log entry + // Get the list of forums to resync $forum_ids[] = $row['forum_id']; - add_log('mod', $to_forum_id, $topic_id, 'LOG_MOVE', $row['forum_name'], $forum_data['forum_name']); + + // We add the $to_forum_id twice, because 'forum_id' is updated + // when the topic is moved again later. + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_MOVE', false, array( + 'forum_id' => (int) $to_forum_id, + 'topic_id' => (int) $topic_id, + $row['forum_name'], + $forum_data['forum_name'], + (int) $row['forum_id'], + (int) $forum_data['forum_id'], + )); // Leave a redirection if required and only if the topic is visible to users if ($leave_shadow && $row['topic_visibility'] == ITEM_APPROVED && $row['topic_type'] != POST_GLOBAL) @@ -555,7 +619,7 @@ function mcp_move_topic($topic_ids) 'topic_last_poster_id' => (int) $row['topic_last_poster_id'], 'topic_last_poster_colour'=>(string) $row['topic_last_poster_colour'], 'topic_last_poster_name'=> (string) $row['topic_last_poster_name'], - 'topic_last_post_subject'=> (string) $row['topic_last_post_subject'], + 'topic_last_post_subject'=> (string) $row['topic_last_post_subject'], 'topic_last_post_time' => (int) $row['topic_last_post_time'], 'topic_last_view_time' => (int) $row['topic_last_view_time'], 'topic_moved_id' => (int) $row['topic_id'], @@ -638,7 +702,7 @@ function mcp_move_topic($topic_ids) confirm_box(false, 'MOVE_TOPIC' . ((sizeof($topic_ids) == 1) ? '' : 'S'), $s_hidden_fields, 'mcp_move.html'); } - $redirect = request_var('redirect', "index.$phpEx"); + $redirect = $request->variable('redirect', "index.$phpEx"); $redirect = reapply_sid($redirect); if (!$success_msg) @@ -663,9 +727,9 @@ function mcp_move_topic($topic_ids) */ function mcp_restore_topic($topic_ids) { - global $auth, $user, $db, $phpEx, $phpbb_root_path, $request, $phpbb_container; + global $user, $phpEx, $phpbb_root_path, $request, $phpbb_container, $phpbb_log; - if (!check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('m_approve'))) + if (!phpbb_check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('m_approve'))) { return; } @@ -685,15 +749,21 @@ function mcp_restore_topic($topic_ids) { $success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_RESTORED_SUCCESS' : 'TOPICS_RESTORED_SUCCESS'; - $data = get_topic_data($topic_ids); + $data = phpbb_get_topic_data($topic_ids); + /* @var $phpbb_content_visibility \phpbb\content_visibility */ $phpbb_content_visibility = $phpbb_container->get('content.visibility'); foreach ($data as $topic_id => $row) { $return = $phpbb_content_visibility->set_topic_visibility(ITEM_APPROVED, $topic_id, $row['forum_id'], $user->data['user_id'], time(), ''); if (!empty($return)) { - add_log('mod', $row['forum_id'], $topic_id, 'LOG_RESTORE_TOPIC', $row['topic_title'], $row['topic_first_poster_name']); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_RESTORE_TOPIC', false, array( + 'forum_id' => $row['forum_id'], + 'topic_id' => $topic_id, + $row['topic_title'], + $row['topic_first_poster_name'] + )); } } } @@ -736,9 +806,10 @@ function mcp_restore_topic($topic_ids) */ function mcp_delete_topic($topic_ids, $is_soft = false, $soft_delete_reason = '', $action = 'delete_topic') { - global $auth, $user, $db, $phpEx, $phpbb_root_path, $request, $phpbb_container; + global $auth, $user, $db, $phpEx, $phpbb_root_path, $request, $phpbb_container, $phpbb_log; - if (!check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('m_delete'))) + $check_permission = ($is_soft) ? 'm_softdelete' : 'm_delete'; + if (!phpbb_check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array($check_permission))) { return; } @@ -758,36 +829,53 @@ function mcp_delete_topic($topic_ids, $is_soft = false, $soft_delete_reason = '' { $success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_DELETED_SUCCESS' : 'TOPICS_DELETED_SUCCESS'; - $data = get_topic_data($topic_ids); + $data = phpbb_get_topic_data($topic_ids); foreach ($data as $topic_id => $row) { if ($row['topic_moved_id']) { - add_log('mod', $row['forum_id'], $topic_id, 'LOG_DELETE_SHADOW_TOPIC', $row['topic_title']); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_DELETE_SHADOW_TOPIC', false, array( + 'forum_id' => $row['forum_id'], + 'topic_id' => $topic_id, + $row['topic_title'] + )); } else { // Only soft delete non-shadow topics if ($is_soft) { + /* @var $phpbb_content_visibility \phpbb\content_visibility */ $phpbb_content_visibility = $phpbb_container->get('content.visibility'); $return = $phpbb_content_visibility->set_topic_visibility(ITEM_DELETED, $topic_id, $row['forum_id'], $user->data['user_id'], time(), $soft_delete_reason); if (!empty($return)) { - add_log('mod', $row['forum_id'], $topic_id, 'LOG_SOFTDELETE_TOPIC', $row['topic_title'], $row['topic_first_poster_name']); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_SOFTDELETE_TOPIC', false, array( + 'forum_id' => $row['forum_id'], + 'topic_id' => $topic_id, + $row['topic_title'], + $row['topic_first_poster_name'], + $soft_delete_reason + )); } } else { - add_log('mod', $row['forum_id'], $topic_id, 'LOG_DELETE_TOPIC', $row['topic_title'], $row['topic_first_poster_name']); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_DELETE_TOPIC', false, array( + 'forum_id' => $row['forum_id'], + 'topic_id' => $topic_id, + $row['topic_title'], + $row['topic_first_poster_name'], + $soft_delete_reason + )); } } } if (!$is_soft) { - $return = delete_topics('topic_id', $topic_ids); + delete_topics('topic_id', $topic_ids); } } else @@ -796,8 +884,17 @@ function mcp_delete_topic($topic_ids, $is_soft = false, $soft_delete_reason = '' $user->add_lang('posting'); + // If there are only shadow topics, we neither need a reason nor softdelete + $sql = 'SELECT topic_id + FROM ' . TOPICS_TABLE . ' + WHERE ' . $db->sql_in_set('topic_id', $topic_ids) . ' + AND topic_moved_id = 0'; + $result = $db->sql_query_limit($sql, 1); + $only_shadow = !$db->sql_fetchfield('topic_id'); + $db->sql_freeresult($result); + $only_softdeleted = false; - if ($auth->acl_get('m_delete', $forum_id) && $auth->acl_get('m_softdelete', $forum_id)) + if (!$only_shadow && $auth->acl_get('m_delete', $forum_id) && $auth->acl_get('m_softdelete', $forum_id)) { // If there are only soft deleted topics, we display a message why the option is not available $sql = 'SELECT topic_id @@ -810,11 +907,11 @@ function mcp_delete_topic($topic_ids, $is_soft = false, $soft_delete_reason = '' } $template->assign_vars(array( + 'S_SHADOW_TOPICS' => $only_shadow, 'S_SOFTDELETED' => $only_softdeleted, 'S_TOPIC_MODE' => true, 'S_ALLOWED_DELETE' => $auth->acl_get('m_delete', $forum_id), 'S_ALLOWED_SOFTDELETE' => $auth->acl_get('m_softdelete', $forum_id), - 'S_DELETE_REASON' => $auth->acl_get('m_softdelete', $forum_id), )); $l_confirm = (sizeof($topic_ids) == 1) ? 'DELETE_TOPIC' : 'DELETE_TOPICS'; @@ -823,7 +920,7 @@ function mcp_delete_topic($topic_ids, $is_soft = false, $soft_delete_reason = '' $l_confirm .= '_PERMANENTLY'; $s_hidden_fields['delete_permanent'] = '1'; } - else if (!$auth->acl_get('m_softdelete', $forum_id)) + else if ($only_shadow || !$auth->acl_get('m_softdelete', $forum_id)) { $s_hidden_fields['delete_permanent'] = '1'; } @@ -865,9 +962,10 @@ function mcp_delete_topic($topic_ids, $is_soft = false, $soft_delete_reason = '' */ function mcp_delete_post($post_ids, $is_soft = false, $soft_delete_reason = '', $action = 'delete_post') { - global $auth, $user, $db, $phpEx, $phpbb_root_path, $request, $phpbb_container; + global $auth, $user, $db, $phpEx, $phpbb_root_path, $request, $phpbb_container, $phpbb_log; - if (!check_ids($post_ids, POSTS_TABLE, 'post_id', array('m_softdelete'))) + $check_permission = ($is_soft) ? 'm_softdelete' : 'm_delete'; + if (!phpbb_check_ids($post_ids, POSTS_TABLE, 'post_id', array($check_permission))) { return; } @@ -885,7 +983,7 @@ function mcp_delete_post($post_ids, $is_soft = false, $soft_delete_reason = '', if (confirm_box(true) && $is_soft) { - $post_info = get_post_data($post_ids); + $post_info = phpbb_get_post_data($post_ids); $topic_info = $approve_log = array(); @@ -921,6 +1019,7 @@ function mcp_delete_post($post_ids, $is_soft = false, $soft_delete_reason = '', ); } + /* @var $phpbb_content_visibility \phpbb\content_visibility */ $phpbb_content_visibility = $phpbb_container->get('content.visibility'); foreach ($topic_info as $topic_id => $topic_data) { @@ -935,7 +1034,14 @@ function mcp_delete_post($post_ids, $is_soft = false, $soft_delete_reason = '', foreach ($approve_log as $row) { $post_username = ($row['poster_id'] == ANONYMOUS && !empty($row['post_username'])) ? $row['post_username'] : $row['username']; - add_log('mod', $row['forum_id'], $row['topic_id'], 'LOG_SOFTDELETE_POST', $row['post_subject'], $post_username); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_SOFTDELETE_POST', false, array( + 'forum_id' => $row['forum_id'], + 'topic_id' => $row['topic_id'], + 'post_id' => $row['post_id'], + $row['post_subject'], + $post_username, + $soft_delete_reason + )); } $topic_id = $request->variable('t', 0); @@ -973,12 +1079,19 @@ function mcp_delete_post($post_ids, $is_soft = false, $soft_delete_reason = '', $affected_topics = sizeof($topic_id_list); $db->sql_freeresult($result); - $post_data = get_post_data($post_ids); + $post_data = phpbb_get_post_data($post_ids); foreach ($post_data as $id => $row) { $post_username = ($row['poster_id'] == ANONYMOUS && !empty($row['post_username'])) ? $row['post_username'] : $row['username']; - add_log('mod', $row['forum_id'], $row['topic_id'], 'LOG_DELETE_POST', $row['post_subject'], $post_username); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_DELETE_POST', false, array( + 'forum_id' => $row['forum_id'], + 'topic_id' => $row['topic_id'], + 'post_id' => $row['post_id'], + $row['post_subject'], + $post_username, + $soft_delete_reason + )); } // Now delete the posts, topics and forums are automatically resync'ed @@ -1051,7 +1164,6 @@ function mcp_delete_post($post_ids, $is_soft = false, $soft_delete_reason = '', 'S_SOFTDELETED' => $only_softdeleted, 'S_ALLOWED_DELETE' => $auth->acl_get('m_delete', $forum_id), 'S_ALLOWED_SOFTDELETE' => $auth->acl_get('m_softdelete', $forum_id), - 'S_DELETE_REASON' => $auth->acl_get('m_softdelete', $forum_id), )); $l_confirm = (sizeof($post_ids) == 1) ? 'DELETE_POST' : 'DELETE_POSTS'; @@ -1093,17 +1205,18 @@ function mcp_delete_post($post_ids, $is_soft = false, $soft_delete_reason = '', function mcp_fork_topic($topic_ids) { global $auth, $user, $db, $template, $config; - global $phpEx, $phpbb_root_path; + global $phpEx, $phpbb_root_path, $phpbb_log, $request, $phpbb_dispatcher; - if (!check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('m_'))) + if (!phpbb_check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('m_'))) { return; } - $to_forum_id = request_var('to_forum_id', 0); - $forum_id = request_var('f', 0); - $redirect = request_var('redirect', build_url(array('action', 'quickmod'))); + $to_forum_id = $request->variable('to_forum_id', 0); + $forum_id = $request->variable('f', 0); + $redirect = $request->variable('redirect', build_url(array('action', 'quickmod'))); $additional_msg = $success_msg = ''; + $counter = array(); $s_hidden_fields = build_hidden_fields(array( 'topic_id_list' => $topic_ids, @@ -1114,7 +1227,7 @@ function mcp_fork_topic($topic_ids) if ($to_forum_id) { - $forum_data = get_forum_data($to_forum_id, 'f_post'); + $forum_data = phpbb_get_forum_data($to_forum_id, 'f_post'); if (!sizeof($topic_ids)) { @@ -1151,7 +1264,7 @@ function mcp_fork_topic($topic_ids) if (confirm_box(true)) { - $topic_data = get_topic_data($topic_ids, 'f_post'); + $topic_data = phpbb_get_topic_data($topic_ids, 'f_post'); $total_topics = $total_topics_unapproved = $total_topics_softdeleted = 0; $total_posts = $total_posts_unapproved = $total_posts_softdeleted = 0; @@ -1170,7 +1283,7 @@ function mcp_fork_topic($topic_ids) } $error = false; - $search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user); + $search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher); $search_mode = 'post'; if ($error) @@ -1221,6 +1334,7 @@ function mcp_fork_topic($topic_ids) $total_topics++; break; case ITEM_UNAPPROVED: + case ITEM_REAPPROVE: $total_topics_unapproved++; break; case ITEM_DELETED: @@ -1230,8 +1344,6 @@ function mcp_fork_topic($topic_ids) if ($topic_row['poll_start']) { - $poll_rows = array(); - $sql = 'SELECT * FROM ' . POLL_OPTIONS_TABLE . " WHERE topic_id = $topic_id"; @@ -1248,12 +1360,13 @@ function mcp_fork_topic($topic_ids) $db->sql_query('INSERT INTO ' . POLL_OPTIONS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); } + $db->sql_freeresult($result); } $sql = 'SELECT * FROM ' . POSTS_TABLE . " WHERE topic_id = $topic_id - ORDER BY post_time ASC"; + ORDER BY post_time ASC, post_id ASC"; $result = $db->sql_query($sql); $post_rows = array(); @@ -1295,9 +1408,20 @@ function mcp_fork_topic($topic_ids) 'post_edit_time' => (int) $row['post_edit_time'], 'post_edit_count' => (int) $row['post_edit_count'], 'post_edit_locked' => (int) $row['post_edit_locked'], - 'post_postcount' => 0, + 'post_postcount' => $row['post_postcount'], ); - + // Adjust post count only if the post can be incremented to the user counter + if ($row['post_postcount']) + { + if (isset($counter[$row['poster_id']])) + { + ++$counter[$row['poster_id']]; + } + else + { + $counter[$row['poster_id']] = 1; + } + } $db->sql_query('INSERT INTO ' . POSTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); $new_post_id = $db->sql_nextid(); @@ -1307,6 +1431,7 @@ function mcp_fork_topic($topic_ids) $total_posts++; break; case ITEM_UNAPPROVED: + case ITEM_REAPPROVE: $total_posts_unapproved++; break; case ITEM_DELETED: @@ -1416,15 +1541,31 @@ function mcp_fork_topic($topic_ids) WHERE forum_id = ' . $to_forum_id; $db->sql_query($sql); + if (!empty($counter)) + { + // Do only one query per user and not a query per post. + foreach ($counter as $user_id => $count) + { + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_posts = user_posts + ' . (int) $count . ' + WHERE user_id = ' . (int) $user_id; + $db->sql_query($sql); + } + } + sync('topic', 'topic_id', $new_topic_id_list); sync('forum', 'forum_id', $to_forum_id); - set_config_count('num_topics', sizeof($new_topic_id_list), true); - set_config_count('num_posts', $total_posts, true); + $config->increment('num_topics', sizeof($new_topic_id_list), false); + $config->increment('num_posts', $total_posts, false); foreach ($new_topic_id_list as $topic_id => $new_topic_id) { - add_log('mod', $to_forum_id, $new_topic_id, 'LOG_FORK', $topic_row['forum_name']); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_FORK', false, array( + 'forum_id' => $to_forum_id, + 'topic_id' => $new_topic_id, + $topic_row['forum_name'] + )); } $success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_FORKED_SUCCESS' : 'TOPICS_FORKED_SUCCESS'; @@ -1440,7 +1581,7 @@ function mcp_fork_topic($topic_ids) confirm_box(false, 'FORK_TOPIC' . ((sizeof($topic_ids) == 1) ? '' : 'S'), $s_hidden_fields, 'mcp_move.html'); } - $redirect = request_var('redirect', "index.$phpEx"); + $redirect = $request->variable('redirect', "index.$phpEx"); $redirect = reapply_sid($redirect); if (!$success_msg) diff --git a/phpBB/includes/mcp/mcp_notes.php b/phpBB/includes/mcp/mcp_notes.php index 28de8724be..67f59bd618 100644 --- a/phpBB/includes/mcp/mcp_notes.php +++ b/phpBB/includes/mcp/mcp_notes.php @@ -1,9 +1,13 @@ <?php /** * -* @package mcp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -18,7 +22,6 @@ if (!defined('IN_PHPBB')) /** * mcp_notes * Displays notes about a user -* @package mcp */ class mcp_notes { @@ -32,10 +35,10 @@ class mcp_notes function main($id, $mode) { - global $auth, $db, $user, $template; - global $config, $phpbb_root_path, $phpEx; + global $user, $template, $request; + global $phpbb_root_path, $phpEx; - $action = request_var('action', array('' => '')); + $action = $request->variable('action', array('' => '')); if (is_array($action)) { @@ -71,15 +74,17 @@ class mcp_notes */ function mcp_notes_user_view($action) { - global $phpEx, $phpbb_root_path, $config; + global $config, $phpbb_log, $request; global $template, $db, $user, $auth, $phpbb_container; - $user_id = request_var('u', 0); - $username = request_var('username', '', true); - $start = request_var('start', 0); - $st = request_var('st', 0); - $sk = request_var('sk', 'b'); - $sd = request_var('sd', 'd'); + $user_id = $request->variable('u', 0); + $username = $request->variable('username', '', true); + $start = $request->variable('start', 0); + $st = $request->variable('st', 0); + $sk = $request->variable('sk', 'b'); + $sd = $request->variable('sd', 'd'); + + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); add_form_key('mcp_notes'); @@ -111,8 +116,8 @@ class mcp_notes $deletemark = ($action == 'del_marked') ? true : false; $deleteall = ($action == 'del_all') ? true : false; - $marked = request_var('marknote', array(0)); - $usernote = utf8_normalize_nfc(request_var('usernote', '', true)); + $marked = $request->variable('marknote', array(0)); + $usernote = $request->variable('usernote', '', true); // Handle any actions if (($deletemark || $deleteall) && $auth->acl_get('a_clearlogs')) @@ -139,7 +144,7 @@ class mcp_notes $where_sql"; $db->sql_query($sql); - add_log('admin', 'LOG_CLEAR_USER', $userrow['username']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CLEAR_USER', false, array($userrow['username'])); $msg = ($deletemark) ? 'MARKED_NOTES_DELETED' : 'ALL_NOTES_DELETED'; } @@ -157,10 +162,17 @@ class mcp_notes { if (check_form_key('mcp_notes')) { - add_log('admin', 'LOG_USER_FEEDBACK', $userrow['username']); - add_log('mod', 0, 0, 'LOG_USER_FEEDBACK', $userrow['username']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_FEEDBACK', false, array($userrow['username'])); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_USER_FEEDBACK', false, array( + 'forum_id' => 0, + 'topic_id' => 0, + $userrow['username'] + )); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_GENERAL', false, array( + 'reportee_id' => $user_id, + $usernote + )); - add_log('user', $user_id, 'LOG_USER_GENERAL', $usernote); $msg = $user->lang['USER_FEEDBACK_ADDED']; } else @@ -174,10 +186,6 @@ class mcp_notes } // Generate the appropriate user information for the user we are looking at - if (!function_exists('phpbb_get_user_avatar')) - { - include($phpbb_root_path . 'includes/functions_display.' . $phpEx); - } $rank_title = $rank_img = ''; $avatar_img = phpbb_get_user_avatar($userrow); @@ -193,7 +201,7 @@ class mcp_notes $sql_where = ($st) ? (time() - ($st * 86400)) : 0; $sql_sort = $sort_by_sql[$sk] . ' ' . (($sd == 'd') ? 'DESC' : 'ASC'); - $keywords = utf8_normalize_nfc(request_var('keywords', '', true)); + $keywords = $request->variable('keywords', '', true); $keywords_param = !empty($keywords) ? '&keywords=' . urlencode(htmlspecialchars_decode($keywords)) : ''; $log_data = array(); diff --git a/phpBB/includes/mcp/mcp_pm_reports.php b/phpBB/includes/mcp/mcp_pm_reports.php index 008984b1c3..67a1a959e4 100644 --- a/phpBB/includes/mcp/mcp_pm_reports.php +++ b/phpBB/includes/mcp/mcp_pm_reports.php @@ -1,9 +1,13 @@ <?php /** * -* @package mcp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -18,7 +22,6 @@ if (!defined('IN_PHPBB')) /** * mcp_reports * Handling the reports queue -* @package mcp */ class mcp_pm_reports { @@ -32,14 +35,15 @@ class mcp_pm_reports function main($id, $mode) { - global $auth, $db, $user, $template, $cache; + global $auth, $db, $user, $template, $request; global $config, $phpbb_root_path, $phpEx, $action, $phpbb_container; include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx); include_once($phpbb_root_path . 'includes/functions_privmsgs.' . $phpEx); - $start = request_var('start', 0); + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); + $start = $request->variable('start', 0); $this->page_title = 'MCP_PM_REPORTS'; @@ -49,7 +53,7 @@ class mcp_pm_reports case 'delete': include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); - $report_id_list = request_var('report_id_list', array(0)); + $report_id_list = $request->variable('report_id_list', array(0)); if (!sizeof($report_id_list)) { @@ -72,7 +76,7 @@ class mcp_pm_reports $user->add_lang(array('posting', 'viewforum', 'viewtopic', 'ucp')); - $report_id = request_var('r', 0); + $report_id = $request->variable('r', 0); $sql = 'SELECT r.pm_id, r.user_id, r.report_id, r.report_closed, report_time, r.report_text, rr.reason_title, rr.reason_description, u.username, u.username_clean, u.user_colour FROM ' . REPORTS_TABLE . ' r, ' . REPORTS_REASONS_TABLE . ' rr, ' . USERS_TABLE . ' u @@ -90,14 +94,15 @@ class mcp_pm_reports trigger_error('NO_REPORT'); } + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); - $phpbb_notifications->mark_notifications_read_by_parent('report_pm', $report_id, $user->data['user_id']); + $phpbb_notifications->mark_notifications_by_parent('report_pm', $report_id, $user->data['user_id']); $pm_id = $report['pm_id']; $report_id = $report['report_id']; - $pm_info = get_pm_data(array($pm_id)); + $pm_info = phpbb_get_pm_data(array($pm_id)); if (!sizeof($pm_info)) { @@ -170,7 +175,7 @@ class mcp_pm_reports 'U_MCP_USER_NOTES' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=notes&mode=user_notes&u=' . $pm_info['author_id']), 'U_MCP_WARN_REPORTER' => ($auth->acl_get('m_warn')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=warn&mode=warn_user&u=' . $report['user_id']) : '', 'U_MCP_WARN_USER' => ($auth->acl_get('m_warn')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=warn&mode=warn_user&u=' . $pm_info['author_id']) : '', - + 'EDIT_IMG' => $user->img('icon_post_edit', $user->lang['EDIT_POST']), 'MINI_POST_IMG' => $user->img('icon_post_target', 'POST'), @@ -196,7 +201,7 @@ class mcp_pm_reports 'POST_SUBJECT' => ($pm_info['message_subject']) ? $pm_info['message_subject'] : $user->lang['NO_SUBJECT'], 'POST_DATE' => $user->format_date($pm_info['message_time']), 'POST_IP' => $pm_info['author_ip'], - 'POST_IPADDR' => ($auth->acl_getf_global('m_info') && request_var('lookup', '')) ? @gethostbyaddr($pm_info['author_ip']) : '', + 'POST_IPADDR' => ($auth->acl_getf_global('m_info') && $request->variable('lookup', '')) ? @gethostbyaddr($pm_info['author_ip']) : '', 'POST_ID' => $pm_info['msg_id'], 'U_LOOKUP_IP' => ($auth->acl_getf_global('m_info')) ? $this->u_action . '&r=' . $report_id . '&pm=' . $pm_id . '&lookup=' . $pm_info['author_ip'] . '#ip' : '', @@ -213,7 +218,7 @@ class mcp_pm_reports $sort_days = $total = 0; $sort_key = $sort_dir = ''; $sort_by_sql = $sort_order_sql = array(); - mcp_sorting($mode, $sort_days, $sort_key, $sort_dir, $sort_by_sql, $sort_order_sql, $total); + phpbb_mcp_sorting($mode, $sort_days, $sort_key, $sort_dir, $sort_by_sql, $sort_order_sql, $total); $limit_time_sql = ($sort_days) ? 'AND r.report_time >= ' . (time() - ($sort_days * 86400)) : ''; @@ -304,7 +309,7 @@ class mcp_pm_reports $template->assign_vars(array( 'L_EXPLAIN' => ($mode == 'pm_reports') ? $user->lang['MCP_PM_REPORTS_OPEN_EXPLAIN'] : $user->lang['MCP_PM_REPORTS_CLOSED_EXPLAIN'], 'L_TITLE' => ($mode == 'pm_reports') ? $user->lang['MCP_PM_REPORTS_OPEN'] : $user->lang['MCP_PM_REPORTS_CLOSED'], - + 'S_PM' => true, 'S_MCP_ACTION' => $this->u_action, 'S_CLOSED' => ($mode == 'pm_reports_closed') ? true : false, diff --git a/phpBB/includes/mcp/mcp_post.php b/phpBB/includes/mcp/mcp_post.php index 06f27655ae..7fa6ef4fff 100644 --- a/phpBB/includes/mcp/mcp_post.php +++ b/phpBB/includes/mcp/mcp_post.php @@ -1,9 +1,13 @@ <?php /** * -* @package mcp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -20,16 +24,17 @@ if (!defined('IN_PHPBB')) */ function mcp_post_details($id, $mode, $action) { - global $phpEx, $phpbb_root_path, $config; - global $template, $db, $user, $auth, $cache; + global $phpEx, $phpbb_root_path, $config, $request; + global $template, $db, $user, $auth; + global $phpbb_dispatcher; $user->add_lang('posting'); - $post_id = request_var('p', 0); - $start = request_var('start', 0); + $post_id = $request->variable('p', 0); + $start = $request->variable('start', 0); // Get post data - $post_info = get_post_data(array($post_id), false, true); + $post_info = phpbb_get_post_data(array($post_id), false, true); add_form_key('mcp_post_details'); @@ -39,7 +44,7 @@ function mcp_post_details($id, $mode, $action) } $post_info = $post_info[$post_id]; - $url = append_sid("{$phpbb_root_path}mcp.$phpEx?" . extra_url()); + $url = append_sid("{$phpbb_root_path}mcp.$phpEx?" . phpbb_extra_url()); switch ($action) { @@ -47,7 +52,7 @@ function mcp_post_details($id, $mode, $action) if ($auth->acl_get('m_info', $post_info['forum_id'])) { - $ip = request_var('ip', ''); + $ip = $request->variable('ip', ''); include($phpbb_root_path . 'includes/functions_user.' . $phpEx); $template->assign_vars(array( @@ -68,12 +73,12 @@ function mcp_post_details($id, $mode, $action) if ($action == 'chgposter') { - $username = request_var('username', '', true); + $username = $request->variable('username', '', true); $sql_where = "username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'"; } else { - $new_user_id = request_var('u', 0); + $new_user_id = $request->variable('u', 0); $sql_where = 'user_id = ' . $new_user_id; } @@ -102,13 +107,27 @@ function mcp_post_details($id, $mode, $action) } break; + + default: + + /** + * This event allows you to handle custom post moderation options + * + * @event core.mcp_post_additional_options + * @var string action Post moderation action name + * @var array post_info Information on the affected post + * @since 3.1.5-RC1 + */ + $vars = array('action', 'post_info'); + extract($phpbb_dispatcher->trigger_event('core.mcp_post_additional_options', compact($vars))); + + break; } // Set some vars $users_ary = $usernames_ary = array(); $attachments = $extensions = array(); $post_id = $post_info['post_id']; - $topic_tracking_info = array(); // Get topic tracking info if ($config['load_db_lastread']) @@ -130,8 +149,6 @@ function mcp_post_details($id, $mode, $action) if ($post_info['post_attachment'] && $auth->acl_get('u_download') && $auth->acl_get('f_download', $post_info['forum_id'])) { - $extensions = $cache->obtain_attach_extensions($post_info['forum_id']); - $sql = 'SELECT * FROM ' . ATTACHMENTS_TABLE . ' WHERE post_msg_id = ' . $post_id . ' @@ -147,6 +164,7 @@ function mcp_post_details($id, $mode, $action) if (sizeof($attachments)) { + $user->add_lang('viewtopic'); $update_count = array(); parse_attachments($post_info['forum_id'], $message, $attachments, $update_count); } @@ -192,7 +210,7 @@ function mcp_post_details($id, $mode, $action) $l_deleted_by = ''; } - $template->assign_vars(array( + $mcp_post_template_data = array( 'U_MCP_ACTION' => "$url&i=main&quickmod=1&mode=post_details", // Use this for mode paramaters 'U_POST_ACTION' => "$url&i=$id&mode=post_details", // Use this for action parameters 'U_APPROVE_ACTION' => append_sid("{$phpbb_root_path}mcp.$phpEx", "i=queue&p=$post_id&f={$post_info['forum_id']}"), @@ -203,7 +221,7 @@ function mcp_post_details($id, $mode, $action) 'S_CAN_DELETE_POST' => $auth->acl_get('m_delete', $post_info['forum_id']), 'S_POST_REPORTED' => ($post_info['post_reported']) ? true : false, - 'S_POST_UNAPPROVED' => ($post_info['post_visibility'] == ITEM_UNAPPROVED) ? true : false, + 'S_POST_UNAPPROVED' => ($post_info['post_visibility'] == ITEM_UNAPPROVED || $post_info['post_visibility'] == ITEM_REAPPROVE) ? true : false, 'S_POST_DELETED' => ($post_info['post_visibility'] == ITEM_DELETED) ? true : false, 'S_POST_LOCKED' => ($post_info['post_edit_locked']) ? true : false, 'S_USER_NOTES' => true, @@ -239,12 +257,37 @@ function mcp_post_details($id, $mode, $action) 'POST_SUBJECT' => $post_info['post_subject'], 'POST_DATE' => $user->format_date($post_info['post_time']), 'POST_IP' => $post_info['poster_ip'], - 'POST_IPADDR' => ($auth->acl_get('m_info', $post_info['forum_id']) && request_var('lookup', '')) ? @gethostbyaddr($post_info['poster_ip']) : '', + 'POST_IPADDR' => ($auth->acl_get('m_info', $post_info['forum_id']) && $request->variable('lookup', '')) ? @gethostbyaddr($post_info['poster_ip']) : '', 'POST_ID' => $post_info['post_id'], 'U_LOOKUP_IP' => ($auth->acl_get('m_info', $post_info['forum_id'])) ? "$url&i=$id&mode=$mode&lookup={$post_info['poster_ip']}#ip" : '', 'U_WHOIS' => ($auth->acl_get('m_info', $post_info['forum_id'])) ? append_sid("{$phpbb_root_path}mcp.$phpEx", "i=$id&mode=$mode&action=whois&p=$post_id&ip={$post_info['poster_ip']}") : '', - )); + ); + + $s_additional_opts = false; + + /** + * Event to add/modify MCP post template data + * + * @event core.mcp_post_template_data + * @var array post_info Array with the post information + * @var array mcp_post_template_data Array with the MCP post template data + * @var array attachments Array with the post attachments, if any + * @var bool s_additional_opts Must be set to true in extension if additional options are presented in MCP post panel + * @since 3.1.5-RC1 + */ + $vars = array( + 'post_info', + 'mcp_post_template_data', + 'attachments', + 's_additional_opts', + ); + extract($phpbb_dispatcher->trigger_event('core.mcp_post_template_data', compact($vars))); + + $template->assign_vars($mcp_post_template_data); + $template->assign_var('S_MCP_POST_ADDITIONAL_OPTS', $s_additional_opts); + + unset($mcp_post_template_data); // Get User Notes $log_data = array(); @@ -294,8 +337,8 @@ function mcp_post_details($id, $mode, $action) 'REPORT_ID' => $row['report_id'], 'REASON_TITLE' => $row['reason_title'], 'REASON_DESC' => $row['reason_description'], - 'REPORTER' => ($row['user_id'] != ANONYMOUS) ? $row['username'] : $user->lang['GUEST'], - 'U_REPORTER' => ($row['user_id'] != ANONYMOUS) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&u=' . $row['user_id']) : '', + 'REPORTER' => get_username_string('username', $row['user_id'], $row['username']), + 'U_REPORTER' => get_username_string('profile', $row['user_id'], $row['username']), 'USER_NOTIFY' => ($row['user_notify']) ? true : false, 'REPORT_TIME' => $user->format_date($row['report_time']), 'REPORT_TEXT' => bbcode_nl2br(trim($row['report_text'])), @@ -309,7 +352,7 @@ function mcp_post_details($id, $mode, $action) // Get IP if ($auth->acl_get('m_info', $post_info['forum_id'])) { - $rdns_ip_num = request_var('rdns', ''); + $rdns_ip_num = $request->variable('rdns', ''); if ($rdns_ip_num != 'all') { @@ -354,11 +397,11 @@ function mcp_post_details($id, $mode, $action) foreach ($users_ary as $user_id => $user_row) { $template->assign_block_vars('userrow', array( - 'USERNAME' => ($user_id == ANONYMOUS) ? $user->lang['GUEST'] : $user_row['username'], + 'USERNAME' => get_username_string('username', $user_id, $user_row['username']), 'NUM_POSTS' => $user_row['postings'], 'L_POST_S' => ($user_row['postings'] == 1) ? $user->lang['POST'] : $user->lang['POSTS'], - 'U_PROFILE' => ($user_id == ANONYMOUS) ? '' : append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&u=' . $user_id), + 'U_PROFILE' => get_username_string('profile', $user_id, $user_row['username']), 'U_SEARCHPOSTS' => append_sid("{$phpbb_root_path}search.$phpEx", 'author_id=' . $user_id . '&sr=topics')) ); } @@ -415,7 +458,7 @@ function mcp_post_details($id, $mode, $action) */ function change_poster(&$post_info, $userdata) { - global $auth, $db, $config, $phpbb_root_path, $phpEx, $user; + global $auth, $db, $config, $phpbb_root_path, $phpEx, $user, $phpbb_log, $phpbb_dispatcher; if (empty($userdata) || $userdata['user_id'] == $post_info['user_id']) { @@ -492,7 +535,7 @@ function change_poster(&$post_info, $userdata) { // We do some additional checks in the module to ensure it can actually be utilised $error = false; - $search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user); + $search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher); if (!$error && method_exists($search, 'destroy_cache')) { @@ -503,8 +546,20 @@ function change_poster(&$post_info, $userdata) $from_username = $post_info['username']; $to_username = $userdata['username']; + /** + * This event allows you to perform additional tasks after changing a post's poster + * + * @event core.mcp_change_poster_after + * @var array userdata Information on a post's new poster + * @var array post_info Information on the affected post + * @since 3.1.6-RC1 + * @changed 3.1.7-RC1 Change location to prevent post_info from being set to the new post information + */ + $vars = array('userdata', 'post_info'); + extract($phpbb_dispatcher->trigger_event('core.mcp_change_poster_after', compact($vars))); + // Renew post info - $post_info = get_post_data(array($post_id), false, true); + $post_info = phpbb_get_post_data(array($post_id), false, true); if (!sizeof($post_info)) { @@ -514,5 +569,12 @@ function change_poster(&$post_info, $userdata) $post_info = $post_info[$post_id]; // Now add log entry - add_log('mod', $post_info['forum_id'], $post_info['topic_id'], 'LOG_MCP_CHANGE_POSTER', $post_info['topic_title'], $from_username, $to_username); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_MCP_CHANGE_POSTER', false, array( + 'forum_id' => $post_info['forum_id'], + 'topic_id' => $post_info['topic_id'], + 'post_id' => $post_info['post_id'], + $post_info['topic_title'], + $from_username, + $to_username + )); } diff --git a/phpBB/includes/mcp/mcp_queue.php b/phpBB/includes/mcp/mcp_queue.php index a46c4bd499..bf93593c74 100644 --- a/phpBB/includes/mcp/mcp_queue.php +++ b/phpBB/includes/mcp/mcp_queue.php @@ -1,9 +1,13 @@ <?php /** * -* @package mcp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -18,7 +22,6 @@ if (!defined('IN_PHPBB')) /** * mcp_queue * Handling the moderation queue -* @package mcp */ class mcp_queue { @@ -32,13 +35,14 @@ class mcp_queue public function main($id, $mode) { - global $auth, $db, $user, $template, $cache, $request; + global $auth, $db, $user, $template, $request; global $config, $phpbb_root_path, $phpEx, $action, $phpbb_container; + global $phpbb_dispatcher; include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx); - $forum_id = request_var('f', 0); - $start = request_var('start', 0); + $forum_id = $request->variable('f', 0); + $start = $request->variable('start', 0); $this->page_title = 'MCP_QUEUE'; @@ -68,6 +72,7 @@ class mcp_queue case 'delete': $post_id_list = $request->variable('post_id_list', array(0)); $topic_id_list = $request->variable('topic_id_list', array(0)); + $delete_reason = $request->variable('delete_reason', '', true); if (!empty($post_id_list)) { @@ -76,7 +81,7 @@ class mcp_queue global $phpbb_root_path, $phpEx; include($phpbb_root_path . 'includes/mcp/mcp_main.' . $phpEx); } - mcp_delete_post($post_id_list, false, '', $action); + mcp_delete_post($post_id_list, false, $delete_reason, $action); } else if (!empty($topic_id_list)) { @@ -85,7 +90,7 @@ class mcp_queue global $phpbb_root_path, $phpEx; include($phpbb_root_path . 'includes/mcp/mcp_main.' . $phpEx); } - mcp_delete_topic($topic_id_list, false, '', $action); + mcp_delete_topic($topic_id_list, false, $delete_reason, $action); } else { @@ -115,10 +120,10 @@ class mcp_queue if (!empty($topic_id_list)) { - $post_visibility = ($mode == 'deleted_topics') ? ITEM_DELETED : ITEM_UNAPPROVED; + $post_visibility = ($mode == 'deleted_topics') ? ITEM_DELETED : array(ITEM_UNAPPROVED, ITEM_REAPPROVE); $sql = 'SELECT post_id FROM ' . POSTS_TABLE . ' - WHERE post_visibility = ' . $post_visibility . ' + WHERE ' . $db->sql_in_set('post_visibility', $post_visibility) . ' AND ' . $db->sql_in_set('topic_id', $topic_id_list); $result = $db->sql_query($sql); @@ -149,19 +154,20 @@ class mcp_queue $user->add_lang(array('posting', 'viewtopic')); - $post_id = request_var('p', 0); - $topic_id = request_var('t', 0); + $post_id = $request->variable('p', 0); + $topic_id = $request->variable('t', 0); + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); if ($topic_id) { - $topic_info = get_topic_data(array($topic_id), 'm_approve'); + $topic_info = phpbb_get_topic_data(array($topic_id), 'm_approve'); if (isset($topic_info[$topic_id]['topic_first_post_id'])) { $post_id = (int) $topic_info[$topic_id]['topic_first_post_id']; - $phpbb_notifications->mark_notifications_read('topic_in_queue', $topic_id, $user->data['user_id']); + $phpbb_notifications->mark_notifications('topic_in_queue', $topic_id, $user->data['user_id']); } else { @@ -169,9 +175,9 @@ class mcp_queue } } - $phpbb_notifications->mark_notifications_read('post_in_queue', $post_id, $user->data['user_id']); + $phpbb_notifications->mark_notifications('post_in_queue', $post_id, $user->data['user_id']); - $post_info = get_post_data(array($post_id), 'm_approve', true); + $post_info = phpbb_get_post_data(array($post_id), 'm_approve', true); if (!sizeof($post_info)) { @@ -189,7 +195,7 @@ class mcp_queue )); } - $extensions = $attachments = $topic_tracking_info = array(); + $attachments = $topic_tracking_info = array(); // Get topic tracking info if ($config['load_db_lastread']) @@ -211,8 +217,6 @@ class mcp_queue if ($post_info['post_attachment'] && $auth->acl_get('u_download') && $auth->acl_get('f_download', $post_info['forum_id'])) { - $extensions = $cache->obtain_attach_extensions($post_info['forum_id']); - $sql = 'SELECT * FROM ' . ATTACHMENTS_TABLE . ' WHERE post_msg_id = ' . $post_id . ' @@ -279,9 +283,10 @@ class mcp_queue $template->assign_vars(array( 'S_MCP_QUEUE' => true, 'U_APPROVE_ACTION' => append_sid("{$phpbb_root_path}mcp.$phpEx", "i=queue&p=$post_id&f=$forum_id"), + 'S_CAN_DELETE_POST' => $auth->acl_get('m_delete', $post_info['forum_id']), 'S_CAN_VIEWIP' => $auth->acl_get('m_info', $post_info['forum_id']), 'S_POST_REPORTED' => $post_info['post_reported'], - 'S_POST_UNAPPROVED' => ($post_info['post_visibility'] == ITEM_UNAPPROVED), + 'S_POST_UNAPPROVED' => $post_info['post_visibility'] == ITEM_UNAPPROVED || $post_info['post_visibility'] == ITEM_REAPPROVE, 'S_POST_LOCKED' => $post_info['post_edit_locked'], 'S_USER_NOTES' => true, 'S_POST_DELETED' => ($post_info['post_visibility'] == ITEM_DELETED), @@ -298,7 +303,6 @@ class mcp_queue 'MINI_POST_IMG' => ($post_unread) ? $user->img('icon_post_target_unread', 'UNREAD_POST') : $user->img('icon_post_target', 'POST'), - 'RETURN_QUEUE' => sprintf($user->lang['RETURN_QUEUE'], '<a href="' . append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue' . (($topic_id) ? '&mode=unapproved_topics' : '&mode=unapproved_posts')) . '&start=' . $start . '">', '</a>'), 'RETURN_POST' => sprintf($user->lang['RETURN_POST'], '<a href="' . $post_url . '">', '</a>'), 'RETURN_TOPIC_SIMPLE' => sprintf($user->lang['RETURN_TOPIC_SIMPLE'], '<a href="' . $topic_url . '">', '</a>'), @@ -315,7 +319,7 @@ class mcp_queue 'POST_SUBJECT' => $post_info['post_subject'], 'POST_DATE' => $user->format_date($post_info['post_time']), 'POST_IP' => $post_info['poster_ip'], - 'POST_IPADDR' => ($auth->acl_get('m_info', $post_info['forum_id']) && request_var('lookup', '')) ? @gethostbyaddr($post_info['poster_ip']) : '', + 'POST_IPADDR' => ($auth->acl_get('m_info', $post_info['forum_id']) && $request->variable('lookup', '')) ? @gethostbyaddr($post_info['poster_ip']) : '', 'POST_ID' => $post_info['post_id'], 'S_FIRST_POST' => ($post_info['topic_first_post_id'] == $post_id), @@ -331,17 +335,19 @@ class mcp_queue $m_perm = 'm_approve'; $is_topics = ($mode == 'unapproved_topics' || $mode == 'deleted_topics') ? true : false; $is_restore = ($mode == 'deleted_posts' || $mode == 'deleted_topics') ? true : false; - $visibility_const = (!$is_restore) ? ITEM_UNAPPROVED : ITEM_DELETED; + $visibility_const = (!$is_restore) ? array(ITEM_UNAPPROVED, ITEM_REAPPROVE) : ITEM_DELETED; $user->add_lang(array('viewtopic', 'viewforum')); $topic_id = $request->variable('t', 0); $forum_info = array(); + + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); if ($topic_id) { - $topic_info = get_topic_data(array($topic_id)); + $topic_info = phpbb_get_topic_data(array($topic_id)); if (!sizeof($topic_info)) { @@ -387,29 +393,27 @@ class mcp_queue } else { - $forum_info = get_forum_data(array($forum_id), $m_perm); + $forum_info = phpbb_get_forum_data(array($forum_id), $m_perm); if (!sizeof($forum_info)) { trigger_error('NOT_MODERATOR'); } - $forum_info = $forum_info[$forum_id]; $forum_list = $forum_id; } $forum_options = '<option value="0"' . (($forum_id == 0) ? ' selected="selected"' : '') . '>' . $user->lang['ALL_FORUMS'] . '</option>'; foreach ($forum_list_approve as $row) { - $forum_options .= '<option value="' . $row['forum_id'] . '"' . (($forum_id == $row['forum_id']) ? ' selected="selected"' : '') . '>' . str_repeat(' ', $row['padding']) . $row['forum_name'] . '</option>'; + $forum_options .= '<option value="' . $row['forum_id'] . '"' . (($forum_id == $row['forum_id']) ? ' selected="selected"' : '') . '>' . str_repeat(' ', $row['padding']) . truncate_string($row['forum_name'], 30, 255, false, $user->lang['ELLIPSIS']) . '</option>'; } $sort_days = $total = 0; $sort_key = $sort_dir = ''; $sort_by_sql = $sort_order_sql = array(); - mcp_sorting($mode, $sort_days, $sort_key, $sort_dir, $sort_by_sql, $sort_order_sql, $total, $forum_id, $topic_id); + phpbb_mcp_sorting($mode, $sort_days, $sort_key, $sort_dir, $sort_by_sql, $sort_order_sql, $total, $forum_id, $topic_id); - $forum_topics = ($total == -1) ? $forum_info['forum_topics_approved'] : $total; $limit_time_sql = ($sort_days) ? 'AND t.topic_last_post_time >= ' . (time() - ($sort_days * 86400)) : ''; $forum_names = array(); @@ -419,7 +423,7 @@ class mcp_queue $sql = 'SELECT p.post_id FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t' . (($sort_order_sql[0] == 'u') ? ', ' . USERS_TABLE . ' u' : '') . ' WHERE ' . $db->sql_in_set('p.forum_id', $forum_list) . ' - AND p.post_visibility = ' . $visibility_const . ' + AND ' . $db->sql_in_set('p.post_visibility', $visibility_const) . ' ' . (($sort_order_sql[0] == 'u') ? 'AND u.user_id = p.poster_id' : '') . ' ' . (($topic_id) ? 'AND p.topic_id = ' . $topic_id : '') . " AND t.topic_id = p.topic_id @@ -427,6 +431,29 @@ class mcp_queue OR t.topic_delete_user = 0) $limit_time_sql ORDER BY $sort_order_sql"; + + /** + * Alter sql query to get posts in queue to be accepted + * + * @event core.mcp_queue_get_posts_query_before + * @var string sql Associative array with the query to be executed + * @var array forum_list List of forums that contain the posts + * @var int visibility_const Integer with one of the possible ITEM_* constant values + * @var int topic_id If topic_id not equal to 0, the topic id to filter the posts to display + * @var string limit_time_sql String with the SQL code to limit the time interval of the post (Note: May be empty string) + * @var string sort_order_sql String with the ORDER BY SQL code used in this query + * @since 3.1.0-RC3 + */ + $vars = array( + 'sql', + 'forum_list', + 'visibility_const', + 'topic_id', + 'limit_time_sql', + 'sort_order_sql', + ); + extract($phpbb_dispatcher->trigger_event('core.mcp_queue_get_posts_query_before', compact($vars))); + $result = $db->sql_query_limit($sql, $config['topics_per_page'], $start); $i = 0; @@ -472,10 +499,33 @@ class mcp_queue $sql = 'SELECT t.forum_id, t.topic_id, t.topic_title, t.topic_title AS post_subject, t.topic_time AS post_time, t.topic_poster AS poster_id, t.topic_first_post_id AS post_id, t.topic_attachment AS post_attachment, t.topic_first_poster_name AS username, t.topic_first_poster_colour AS user_colour FROM ' . TOPICS_TABLE . ' t WHERE ' . $db->sql_in_set('forum_id', $forum_list) . ' - AND topic_visibility = ' . $visibility_const . " + AND ' . $db->sql_in_set('topic_visibility', $visibility_const) . " AND topic_delete_user <> 0 $limit_time_sql ORDER BY $sort_order_sql"; + + /** + * Alter sql query to get information on all topics in the list of forums provided. + * + * @event core.mcp_queue_get_posts_for_topics_query_before + * @var string sql String with the query to be executed + * @var array forum_list List of forums that contain the posts + * @var int visibility_const Integer with one of the possible ITEM_* constant values + * @var int topic_id topic_id in the page request + * @var string limit_time_sql String with the SQL code to limit the time interval of the post (Note: May be empty string) + * @var string sort_order_sql String with the ORDER BY SQL code used in this query + * @since 3.1.0-RC3 + */ + $vars = array( + 'sql', + 'forum_list', + 'visibility_const', + 'topic_id', + 'limit_time_sql', + 'sort_order_sql', + ); + extract($phpbb_dispatcher->trigger_event('core.mcp_queue_get_posts_for_topics_query_before', compact($vars))); + $result = $db->sql_query_limit($sql, $config['topics_per_page'], $start); $rowset = array(); @@ -567,18 +617,19 @@ class mcp_queue */ static public function approve_posts($action, $post_id_list, $id, $mode) { - global $db, $template, $user, $config, $request, $phpbb_container; - global $phpEx, $phpbb_root_path; + global $template, $user, $request, $phpbb_container, $phpbb_dispatcher; + global $phpEx, $phpbb_root_path, $phpbb_log; - if (!check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_approve'))) + if (!phpbb_check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_approve'))) { trigger_error('NOT_AUTHORISED'); } $redirect = $request->variable('redirect', build_url(array('quickmod'))); $redirect = reapply_sid($redirect); - $success_msg = $post_url = ''; + $post_url = ''; $approve_log = array(); + $num_topics = 0; $s_hidden_fields = build_hidden_fields(array( 'i' => $id, @@ -588,7 +639,7 @@ class mcp_queue 'redirect' => $redirect, )); - $post_info = get_post_data($post_id_list, 'm_approve'); + $post_info = phpbb_get_post_data($post_id_list, 'm_approve'); if (confirm_box(true)) { @@ -625,29 +676,32 @@ class mcp_queue $approve_log[] = array( 'forum_id' => $post_data['forum_id'], 'topic_id' => $post_data['topic_id'], + 'post_id' => $post_id, 'post_subject' => $post_data['post_subject'], ); } + /* @var $phpbb_content_visibility \phpbb\content_visibility */ $phpbb_content_visibility = $phpbb_container->get('content.visibility'); foreach ($topic_info as $topic_id => $topic_data) { $phpbb_content_visibility->set_post_visibility(ITEM_APPROVED, $topic_data['posts'], $topic_id, $topic_data['forum_id'], $user->data['user_id'], time(), '', isset($topic_data['first_post']), isset($topic_data['last_post'])); } - if (sizeof($post_info) >= 1) - { - $success_msg = (sizeof($post_info) == 1) ? 'POST_' . strtoupper($action) . 'D_SUCCESS' : 'POSTS_' . strtoupper($action) . 'D_SUCCESS'; - } - foreach ($approve_log as $log_data) { - add_log('mod', $log_data['forum_id'], $log_data['topic_id'], 'LOG_POST_' . strtoupper($action) . 'D', $log_data['post_subject']); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_POST_' . strtoupper($action) . 'D', false, array( + 'forum_id' => $log_data['forum_id'], + 'topic_id' => $log_data['topic_id'], + 'post_id' => $log_data['post_id'], + $log_data['post_subject'] + )); } // Only send out the mails, when the posts are being approved if ($action == 'approve') { + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); // Handle notifications @@ -656,20 +710,38 @@ class mcp_queue // A single topic approval may also happen here, so handle deleting the respective notification. if (!$post_data['topic_posts_approved']) { - $phpbb_notifications->delete_notifications('topic_in_queue', $post_data['topic_id']); + $phpbb_notifications->delete_notifications('notification.type.topic_in_queue', $post_data['topic_id']); + + if ($post_data['post_visibility'] == ITEM_UNAPPROVED) + { + $phpbb_notifications->add_notifications(array('notification.type.topic'), $post_data); + } + if ($post_data['post_visibility'] != ITEM_APPROVED) + { + $num_topics++; + } + } + else + { + // Only add notifications, if we are not reapproving post + // When the topic was already approved, but was edited and + // now needs re-approval, we don't want to notify the users + // again. + if ($post_data['post_visibility'] == ITEM_UNAPPROVED) + { + $phpbb_notifications->add_notifications(array( + 'notification.type.bookmark', + 'notification.type.post', + ), $post_data); + } } - $phpbb_notifications->delete_notifications('post_in_queue', $post_id); - - $phpbb_notifications->add_notifications(array( - 'quote', - 'bookmark', - 'post', - ), $post_data); - - $phpbb_notifications->mark_notifications_read(array( - 'quote', - 'bookmark', - 'post', + $phpbb_notifications->add_notifications(array('notification.type.quote'), $post_data); + $phpbb_notifications->delete_notifications('notification.type.post_in_queue', $post_id); + + $phpbb_notifications->mark_notifications(array( + 'notification.type.quote', + 'notification.type.bookmark', + 'notification.type.post', ), $post_data['post_id'], $user->data['user_id']); // Notify Poster? @@ -680,11 +752,51 @@ class mcp_queue continue; } - $phpbb_notifications->add_notifications('approve_post', $post_data); + if (!$post_data['topic_posts_approved']) + { + $phpbb_notifications->add_notifications('notification.type.approve_topic', $post_data); + } + else + { + $phpbb_notifications->add_notifications('notification.type.approve_post', $post_data); + } } } } + if ($num_topics >= 1) + { + $success_msg = ($num_topics == 1) ? 'TOPIC_' . strtoupper($action) . 'D_SUCCESS' : 'TOPICS_' . strtoupper($action) . 'D_SUCCESS'; + } + else + { + $success_msg = (sizeof($post_info) == 1) ? 'POST_' . strtoupper($action) . 'D_SUCCESS' : 'POSTS_' . strtoupper($action) . 'D_SUCCESS'; + } + + /** + * Perform additional actions during post(s) approval + * + * @event core.approve_posts_after + * @var string action Variable containing the action we perform on the posts ('approve' or 'restore') + * @var array post_info Array containing info for all posts being approved + * @var array topic_info Array containing info for all parent topics of the posts + * @var int num_topics Variable containing number of topics + * @var bool notify_poster Variable telling if the post should be notified or not + * @var string success_msg Variable containing the language key for the success message + * @var string redirect Variable containing the redirect url + * @since 3.1.4-RC1 + */ + $vars = array( + 'action', + 'post_info', + 'topic_info', + 'num_topics', + 'notify_poster', + 'success_msg', + 'redirect', + ); + extract($phpbb_dispatcher->trigger_event('core.approve_posts_after', compact($vars))); + meta_refresh(3, $redirect); $message = $user->lang[$success_msg]; @@ -715,14 +827,14 @@ class mcp_queue { foreach ($post_info as $post_data) { - if ($post_data['poster_id'] == ANONYMOUS) + if (!$post_data['topic_posts_approved']) { - continue; + $num_topics++; } - else + + if (!$show_notify && $post_data['poster_id'] != ANONYMOUS) { $show_notify = true; - break; } } } @@ -732,7 +844,18 @@ class mcp_queue 'S_' . strtoupper($action) => true, )); - confirm_box(false, strtoupper($action) . '_POST' . ((sizeof($post_id_list) == 1) ? '' : 'S'), $s_hidden_fields, 'mcp_approve.html'); + // Create the confirm box message + $action_msg = strtoupper($action); + $num_posts = sizeof($post_id_list) - $num_topics; + if ($num_topics > 0 && $num_posts <= 0) + { + $action_msg .= '_TOPIC' . (($num_topics == 1) ? '' : 'S'); + } + else + { + $action_msg .= '_POST' . ((sizeof($post_id_list) == 1) ? '' : 'S'); + } + confirm_box(false, $action_msg, $s_hidden_fields, 'mcp_approve.html'); } redirect($redirect); @@ -749,10 +872,10 @@ class mcp_queue */ static public function approve_topics($action, $topic_id_list, $id, $mode) { - global $db, $template, $user, $config; - global $phpEx, $phpbb_root_path, $request, $phpbb_container; + global $db, $template, $user, $phpbb_log; + global $phpEx, $phpbb_root_path, $request, $phpbb_container, $phpbb_dispatcher; - if (!check_ids($topic_id_list, TOPICS_TABLE, 'topic_id', array('m_approve'))) + if (!phpbb_check_ids($topic_id_list, TOPICS_TABLE, 'topic_id', array('m_approve'))) { trigger_error('NOT_AUTHORISED'); } @@ -770,12 +893,13 @@ class mcp_queue 'redirect' => $redirect, )); - $topic_info = get_topic_data($topic_id_list, 'm_approve'); + $topic_info = phpbb_get_topic_data($topic_id_list, 'm_approve'); if (confirm_box(true)) { $notify_poster = ($action == 'approve' && isset($_REQUEST['notify_poster'])) ? true : false; + /* @var $phpbb_content_visibility \phpbb\content_visibility */ $phpbb_content_visibility = $phpbb_container->get('content.visibility'); $first_post_ids = array(); @@ -800,7 +924,11 @@ class mcp_queue foreach ($approve_log as $log_data) { - add_log('mod', $log_data['forum_id'], $log_data['topic_id'], 'LOG_TOPIC_' . strtoupper($action) . 'D', $log_data['topic_title']); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_TOPIC_' . strtoupper($action) . 'D', false, array( + 'forum_id' => $log_data['forum_id'], + 'topic_id' => $log_data['topic_id'], + $log_data['topic_title'] + )); } // Only send out the mails, when the posts are being approved @@ -819,6 +947,7 @@ class mcp_queue $db->sql_freeresult($result); // Handle notifications + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); foreach ($topic_info as $topic_id => $topic_data) @@ -828,25 +957,55 @@ class mcp_queue 'post_subject' => $topic_data['topic_title'], 'post_time' => $topic_data['topic_time'], 'poster_id' => $topic_data['topic_poster'], - 'username' => $topic_data['topic_first_poster_name'], + 'post_username' => $topic_data['topic_first_poster_name'], )); - $phpbb_notifications->delete_notifications('topic_in_queue', $topic_id); - $phpbb_notifications->add_notifications(array( - 'quote', - 'topic', - ), $topic_data); + $phpbb_notifications->delete_notifications('notification.type.topic_in_queue', $topic_id); - $phpbb_notifications->mark_notifications_read('quote', $topic_data['post_id'], $user->data['user_id']); - $phpbb_notifications->mark_notifications_read('topic', $topic_id, $user->data['user_id']); + // Only add notifications, if we are not reapproving post + // When the topic was already approved, but was edited and + // now needs re-approval, we don't want to notify the users + // again. + if ($topic_data['topic_visibility'] == ITEM_UNAPPROVED) + { + $phpbb_notifications->add_notifications(array( + 'notification.type.quote', + 'notification.type.topic', + ), $topic_data); + } + + $phpbb_notifications->mark_notifications('quote', $topic_data['post_id'], $user->data['user_id']); + $phpbb_notifications->mark_notifications('topic', $topic_id, $user->data['user_id']); if ($notify_poster) { - $phpbb_notifications->add_notifications('approve_topic', $topic_data); + $phpbb_notifications->add_notifications('notification.type.approve_topic', $topic_data); } } } + /** + * Perform additional actions during topics(s) approval + * + * @event core.approve_topics_after + * @var string action Variable containing the action we perform on the posts ('approve' or 'restore') + * @var mixed topic_info Array containing info for all topics being approved + * @var array first_post_ids Array containing ids of all first posts + * @var bool notify_poster Variable telling if the poster should be notified or not + * @var string success_msg Variable containing the language key for the success message + * @var string redirect Variable containing the redirect url + * @since 3.1.4-RC1 + */ + $vars = array( + 'action', + 'topic_info', + 'first_post_ids', + 'notify_poster', + 'success_msg', + 'redirect', + ); + extract($phpbb_dispatcher->trigger_event('core.approve_topics_after', compact($vars))); + meta_refresh(3, $redirect); $message = $user->lang[$success_msg]; @@ -910,10 +1069,10 @@ class mcp_queue */ static public function disapprove_posts($post_id_list, $id, $mode) { - global $db, $template, $user, $config, $phpbb_container; - global $phpEx, $phpbb_root_path, $request; + global $db, $template, $user, $phpbb_container, $phpbb_dispatcher; + global $phpEx, $phpbb_root_path, $request, $phpbb_log; - if (!check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_approve'))) + if (!phpbb_check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_approve'))) { trigger_error('NOT_AUTHORISED'); } @@ -922,7 +1081,7 @@ class mcp_queue $redirect = reapply_sid($redirect); $reason = $request->variable('reason', '', true); $reason_id = $request->variable('reason_id', 0); - $success_msg = $additional_msg = ''; + $additional_msg = ''; $s_hidden_fields = build_hidden_fields(array( 'i' => $id, @@ -965,7 +1124,7 @@ class mcp_queue } } - $post_info = get_post_data($post_id_list, 'm_approve'); + $post_info = phpbb_get_post_data($post_id_list, 'm_approve'); $is_disapproving = false; foreach ($post_info as $post_id => $post_data) @@ -980,12 +1139,17 @@ class mcp_queue if (confirm_box(true)) { - $disapprove_log = $disapprove_log_topics = $disapprove_log_posts = array(); + $disapprove_log_topics = $disapprove_log_posts = array(); $topic_posts_unapproved = $post_disapprove_list = $topic_information = array(); // Build a list of posts to be disapproved and get the related topics real replies count foreach ($post_info as $post_id => $post_data) { + if ($mode === 'unapproved_topics' && $post_data['post_visibility'] == ITEM_APPROVED) + { + continue; + } + $post_disapprove_list[$post_id] = $post_data['topic_id']; if (!isset($topic_posts_unapproved[$post_data['topic_id']])) { @@ -995,6 +1159,12 @@ class mcp_queue $topic_posts_unapproved[$post_data['topic_id']]++; } + // Do not try to disapprove if no posts are selected + if (empty($post_disapprove_list)) + { + trigger_error('NO_POST_SELECTED'); + } + // Now we build the log array foreach ($post_disapprove_list as $post_id => $topic_id) { @@ -1060,16 +1230,28 @@ class mcp_queue if ($is_disapproving) { $l_log_message = ($log_data['type'] == 'topic') ? 'LOG_TOPIC_DISAPPROVED' : 'LOG_POST_DISAPPROVED'; - add_log('mod', $log_data['forum_id'], $log_data['topic_id'], $l_log_message, $log_data['post_subject'], $disapprove_reason); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, $l_log_message, false, array( + 'forum_id' => $log_data['forum_id'], + 'topic_id' => $log_data['topic_id'], + $log_data['post_subject'], + $disapprove_reason, + $log_data['post_username'] + )); } else { $l_log_message = ($log_data['type'] == 'topic') ? 'LOG_DELETE_TOPIC' : 'LOG_DELETE_POST'; - add_log('mod', $log_data['forum_id'], $log_data['topic_id'], $l_log_message, $log_data['post_subject'], $log_data['post_username']); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, $l_log_message, false, array( + 'forum_id' => $log_data['forum_id'], + 'topic_id' => $log_data['topic_id'], + $log_data['post_subject'], + $log_data['post_username'] + )); } } } + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); $lang_reasons = array(); @@ -1080,12 +1262,12 @@ class mcp_queue $topic_information[$topic_id]['topic_posts_softdeleted'] == 0 && $topic_information[$topic_id]['topic_posts_unapproved'] == $topic_posts_unapproved[$topic_id]; - $phpbb_notifications->delete_notifications('post_in_queue', $post_id); + $phpbb_notifications->delete_notifications('notification.type.post_in_queue', $post_id); // Do we disapprove the whole topic? Remove potential notifications if ($disapprove_all_posts_in_topic) { - $phpbb_notifications->delete_notifications('topic_in_queue', $post_data['topic_id']); + $phpbb_notifications->delete_notifications('notification.type.topic_in_queue', $post_data['topic_id']); } // Notify Poster? @@ -1096,7 +1278,7 @@ class mcp_queue continue; } - $post_data['disapprove_reason'] = ''; + $post_data['disapprove_reason'] = $disapprove_reason; if (isset($disapprove_reason_lang)) { // Okay we need to get the reason from the posters language @@ -1126,25 +1308,21 @@ class mcp_queue $post_data['disapprove_reason'] .= ($reason) ? "\n\n" . $reason : ''; } - if ($disapprove_all_posts_in_topic && $topic_information[$topic_id]['topic_posts_unapproved'] == 1) { // If there is only 1 post when disapproving the topic, // we send the user a "disapprove topic" notification... - $phpbb_notifications->add_notifications('disapprove_topic', $post_data); + $phpbb_notifications->add_notifications('notification.type.disapprove_topic', $post_data); } else { // ... otherwise there are multiple unapproved posts and // all of them are disapproved as posts. - $phpbb_notifications->add_notifications('disapprove_post', $post_data); + $phpbb_notifications->add_notifications('notification.type.disapprove_post', $post_data); } } } - unset($lang_reasons, $post_info, $disapprove_reason, $disapprove_reason_lang); - - if ($num_disapproved_topics) { $success_msg = ($num_disapproved_topics == 1) ? 'TOPIC' : 'TOPICS'; @@ -1163,6 +1341,60 @@ class mcp_queue $success_msg .= '_DELETED_SUCCESS'; } + // If we came from viewtopic, we try to go back to it. + if (strpos($redirect, $phpbb_root_path . 'viewtopic.' . $phpEx) === 0) + { + if ($num_disapproved_topics == 0) + { + // So we need to remove the post id part from the Url + $redirect = str_replace("&p={$post_id_list[0]}#p{$post_id_list[0]}", '', $redirect); + } + else + { + // However this is only possible if the topic still exists, + // Otherwise we go back to the viewforum page + $redirect = append_sid($phpbb_root_path . 'viewforum.' . $phpEx, 'f=' . $request->variable('f', 0)); + } + } + + /** + * Perform additional actions during post(s) disapproval + * + * @event core.disapprove_posts_after + * @var array post_info Array containing info for all posts being disapproved + * @var array topic_information Array containing information for the topics + * @var array topic_posts_unapproved Array containing list of topic ids and the count of disapproved posts in them + * @var array post_disapprove_list Array containing list of posts and their topic id + * @var int num_disapproved_topics Variable containing the number of disapproved topics + * @var int num_disapproved_posts Variable containing the number of disapproved posts + * @var array lang_reasons Array containing the language keys for reasons + * @var string disapprove_reason Variable containing the language key for the success message + * @var string disapprove_reason_lang Variable containing the language key for the success message + * @var bool is_disapproving Variable telling if anything is going to be disapproved + * @var bool notify_poster Variable telling if the post should be notified or not + * @var string success_msg Variable containing the language key for the success message + * @var string redirect Variable containing the redirect url + * @since 3.1.4-RC1 + */ + $vars = array( + 'post_info', + 'topic_information', + 'topic_posts_unapproved', + 'post_disapprove_list', + 'num_disapproved_topics', + 'num_disapproved_posts', + 'lang_reasons', + 'disapprove_reason', + 'disapprove_reason_lang', + 'is_disapproving', + 'notify_poster', + 'success_msg', + 'redirect', + ); + extract($phpbb_dispatcher->trigger_event('core.disapprove_posts_after', compact($vars))); + + unset($lang_reasons, $post_info, $disapprove_reason, $disapprove_reason_lang); + meta_refresh(3, $redirect); $message = $user->lang[$success_msg]; @@ -1181,11 +1413,6 @@ class mcp_queue } else { - if (!function_exists('display_reasons')) - { - include($phpbb_root_path . 'includes/functions_display.' . $phpEx); - } - $show_notify = false; foreach ($post_info as $post_data) @@ -1205,7 +1432,7 @@ class mcp_queue $confirm_template = 'mcp_approve.html'; if ($is_disapproving) { - display_reasons($reason_id); + $phpbb_container->get('phpbb.report.report_reason_list_provider')->display_reasons($reason_id); } else { diff --git a/phpBB/includes/mcp/mcp_reports.php b/phpBB/includes/mcp/mcp_reports.php index 8026e071cd..48d0e8d890 100644 --- a/phpBB/includes/mcp/mcp_reports.php +++ b/phpBB/includes/mcp/mcp_reports.php @@ -1,9 +1,13 @@ <?php /** * -* @package mcp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -18,7 +22,6 @@ if (!defined('IN_PHPBB')) /** * mcp_reports * Handling the reports queue -* @package mcp */ class mcp_reports { @@ -32,13 +35,13 @@ class mcp_reports function main($id, $mode) { - global $auth, $db, $user, $template, $cache; - global $config, $phpbb_root_path, $phpEx, $action, $phpbb_container; + global $auth, $db, $user, $template, $request; + global $config, $phpbb_root_path, $phpEx, $action, $phpbb_container, $phpbb_dispatcher; include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx); - $forum_id = request_var('f', 0); - $start = request_var('start', 0); + $forum_id = $request->variable('f', 0); + $start = $request->variable('start', 0); $this->page_title = 'MCP_REPORTS'; @@ -48,7 +51,7 @@ class mcp_reports case 'delete': include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); - $report_id_list = request_var('report_id_list', array(0)); + $report_id_list = $request->variable('report_id_list', array(0)); if (!sizeof($report_id_list)) { @@ -66,30 +69,80 @@ class mcp_reports $user->add_lang(array('posting', 'viewforum', 'viewtopic')); - $post_id = request_var('p', 0); + $post_id = $request->variable('p', 0); // closed reports are accessed by report id - $report_id = request_var('r', 0); + $report_id = $request->variable('r', 0); + + $sql_ary = array( + 'SELECT' => 'r.post_id, r.user_id, r.report_id, r.report_closed, report_time, r.report_text, r.reported_post_text, r.reported_post_uid, r.reported_post_bitfield, r.reported_post_enable_magic_url, r.reported_post_enable_smilies, r.reported_post_enable_bbcode, rr.reason_title, rr.reason_description, u.username, u.username_clean, u.user_colour', - $sql = 'SELECT r.post_id, r.user_id, r.report_id, r.report_closed, report_time, r.report_text, r.reported_post_text, r.reported_post_uid, r.reported_post_bitfield, r.reported_post_enable_magic_url, r.reported_post_enable_smilies, r.reported_post_enable_bbcode, rr.reason_title, rr.reason_description, u.username, u.username_clean, u.user_colour - FROM ' . REPORTS_TABLE . ' r, ' . REPORTS_REASONS_TABLE . ' rr, ' . USERS_TABLE . ' u - WHERE ' . (($report_id) ? 'r.report_id = ' . $report_id : "r.post_id = $post_id") . ' + 'FROM' => array( + REPORTS_TABLE => 'r', + REPORTS_REASONS_TABLE => 'rr', + USERS_TABLE => 'u', + ), + + 'WHERE' => (($report_id) ? 'r.report_id = ' . $report_id : "r.post_id = $post_id") . ' AND rr.reason_id = r.reason_id AND r.user_id = u.user_id - AND r.pm_id = 0 - ORDER BY report_closed ASC'; + AND r.pm_id = 0', + + 'ORDER_BY' => 'report_closed ASC', + ); + + /** + * Allow changing the query to obtain the user-submitted report. + * + * @event core.mcp_reports_report_details_query_before + * @var array sql_ary The array in the format of the query builder with the query + * @var mixed forum_id The forum_id, the number in the f GET parameter + * @var int post_id The post_id of the report being viewed (if 0, it is meaningless) + * @var int report_id The report_id of the report being viewed + * @since 3.1.5-RC1 + */ + $vars = array( + 'sql_ary', + 'forum_id', + 'post_id', + 'report_id', + ); + extract($phpbb_dispatcher->trigger_event('core.mcp_reports_report_details_query_before', compact($vars))); + + $sql = $db->sql_build_query('SELECT', $sql_ary); $result = $db->sql_query_limit($sql, 1); $report = $db->sql_fetchrow($result); $db->sql_freeresult($result); + /** + * Allow changing the data obtained from the user-submitted report. + * + * @event core.mcp_reports_report_details_query_after + * @var array sql_ary The array in the format of the query builder with the query that had been executted + * @var mixed forum_id The forum_id, the number in the f GET parameter + * @var int post_id The post_id of the report being viewed (if 0, it is meaningless) + * @var int report_id The report_id of the report being viewed + * @var int report The query's resulting row. + * @since 3.1.5-RC1 + */ + $vars = array( + 'sql_ary', + 'forum_id', + 'post_id', + 'report_id', + 'report', + ); + extract($phpbb_dispatcher->trigger_event('core.mcp_reports_report_details_query_after', compact($vars))); + if (!$report) { trigger_error('NO_REPORT'); } + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); - $phpbb_notifications->mark_notifications_read('report_post', $post_id, $user->data['user_id']); + $phpbb_notifications->mark_notifications('report_post', $post_id, $user->data['user_id']); if (!$report_id && $report['report_closed']) { @@ -98,12 +151,12 @@ class mcp_reports $post_id = $report['post_id']; $report_id = $report['report_id']; - + $parse_post_flags = $report['reported_post_enable_bbcode'] ? OPTION_FLAG_BBCODE : 0; $parse_post_flags += $report['reported_post_enable_smilies'] ? OPTION_FLAG_SMILIES : 0; - $parse_post_flags += $report['reported_post_enable_magic_url'] ? OPTION_FLAG_LINKS : 0; + $parse_post_flags += $report['reported_post_enable_magic_url'] ? OPTION_FLAG_LINKS : 0; - $post_info = get_post_data(array($post_id), 'm_report', true); + $post_info = phpbb_get_post_data(array($post_id), 'm_report', true); if (!sizeof($post_info)) { @@ -129,7 +182,7 @@ class mcp_reports )); } - $topic_tracking_info = $extensions = $attachments = array(); + $attachments = array(); // Get topic tracking info if ($config['load_db_lastread']) { @@ -143,7 +196,13 @@ class mcp_reports } $post_unread = (isset($topic_tracking_info[$post_info['topic_id']]) && $post_info['post_time'] > $topic_tracking_info[$post_info['topic_id']]) ? true : false; - + $message = generate_text_for_display( + $report['reported_post_text'], + $report['reported_post_uid'], + $report['reported_post_bitfield'], + $parse_post_flags, + false + ); $report['report_text'] = make_clickable(bbcode_nl2br($report['report_text'])); @@ -153,6 +212,7 @@ class mcp_reports FROM ' . ATTACHMENTS_TABLE . ' WHERE post_msg_id = ' . $post_id . ' AND in_message = 0 + AND filetime <= ' . (int) $report['report_time'] . ' ORDER BY filetime DESC'; $result = $db->sql_query($sql); @@ -165,7 +225,7 @@ class mcp_reports if (sizeof($attachments)) { $update_count = array(); - parse_attachments($post_info['forum_id'], $report['reported_post_text'], $attachments, $update_count); + parse_attachments($post_info['forum_id'], $message, $attachments, $update_count); } // Display not already displayed Attachments for this post, we already parsed them. ;) @@ -187,7 +247,7 @@ class mcp_reports 'S_CLOSE_ACTION' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=reports&mode=report_details&f=' . $post_info['forum_id'] . '&p=' . $post_id), 'S_CAN_VIEWIP' => $auth->acl_get('m_info', $post_info['forum_id']), 'S_POST_REPORTED' => $post_info['post_reported'], - 'S_POST_UNAPPROVED' => ($post_info['post_visibility'] == ITEM_UNAPPROVED), + 'S_POST_UNAPPROVED' => $post_info['post_visibility'] == ITEM_UNAPPROVED || $post_info['post_visibility'] == ITEM_REAPPROVE, 'S_POST_LOCKED' => $post_info['post_edit_locked'], 'S_REPORT_CLOSED' => $report['report_closed'], 'S_USER_NOTES' => true, @@ -225,11 +285,11 @@ class mcp_reports 'REPORTER_NAME' => get_username_string('username', $report['user_id'], $report['username'], $report['user_colour']), 'U_VIEW_REPORTER_PROFILE' => get_username_string('profile', $report['user_id'], $report['username'], $report['user_colour']), - 'POST_PREVIEW' => generate_text_for_display($report['reported_post_text'], $report['reported_post_uid'], $report['reported_post_bitfield'], $parse_post_flags, false), + 'POST_PREVIEW' => $message, 'POST_SUBJECT' => ($post_info['post_subject']) ? $post_info['post_subject'] : $user->lang['NO_SUBJECT'], 'POST_DATE' => $user->format_date($post_info['post_time']), 'POST_IP' => $post_info['poster_ip'], - 'POST_IPADDR' => ($auth->acl_get('m_info', $post_info['forum_id']) && request_var('lookup', '')) ? @gethostbyaddr($post_info['poster_ip']) : '', + 'POST_IPADDR' => ($auth->acl_get('m_info', $post_info['forum_id']) && $request->variable('lookup', '')) ? @gethostbyaddr($post_info['poster_ip']) : '', 'POST_ID' => $post_info['post_id'], 'U_LOOKUP_IP' => ($auth->acl_get('m_info', $post_info['forum_id'])) ? $this->u_action . '&r=' . $report_id . '&p=' . $post_id . '&f=' . $forum_id . '&lookup=' . $post_info['poster_ip'] . '#ip' : '', @@ -241,7 +301,7 @@ class mcp_reports case 'reports': case 'reports_closed': - $topic_id = request_var('t', 0); + $topic_id = $request->variable('t', 0); $forum_info = array(); $forum_list_reports = get_forum_list('m_report', false, true); @@ -259,7 +319,7 @@ class mcp_reports if ($topic_id) { - $topic_info = get_topic_data(array($topic_id)); + $topic_info = phpbb_get_topic_data(array($topic_id)); if (!sizeof($topic_info)) { @@ -291,8 +351,6 @@ class mcp_reports trigger_error('NOT_MODERATOR'); } - $global_id = $forum_list[0]; - $sql = 'SELECT SUM(forum_topics_approved) as sum_forum_topics FROM ' . FORUMS_TABLE . ' WHERE ' . $db->sql_in_set('forum_id', $forum_list); @@ -302,20 +360,20 @@ class mcp_reports } else { - $forum_info = get_forum_data(array($forum_id), 'm_report'); + $forum_info = phpbb_get_forum_data(array($forum_id), 'm_report'); if (!sizeof($forum_info)) { trigger_error('NOT_MODERATOR'); } - $forum_info = $forum_info[$forum_id]; $forum_list = array($forum_id); } + /* @var $pagination \phpbb\pagination */ + $pagination = $phpbb_container->get('pagination'); $forum_list[] = 0; $forum_data = array(); - $pagination = $phpbb_container->get('pagination'); $forum_options = '<option value="0"' . (($forum_id == 0) ? ' selected="selected"' : '') . '>' . $user->lang['ALL_FORUMS'] . '</option>'; foreach ($forum_list_reports as $row) @@ -328,9 +386,8 @@ class mcp_reports $sort_days = $total = 0; $sort_key = $sort_dir = ''; $sort_by_sql = $sort_order_sql = array(); - mcp_sorting($mode, $sort_days, $sort_key, $sort_dir, $sort_by_sql, $sort_order_sql, $total, $forum_id, $topic_id); + phpbb_mcp_sorting($mode, $sort_days, $sort_key, $sort_dir, $sort_by_sql, $sort_order_sql, $total, $forum_id, $topic_id); - $forum_topics = ($total == -1) ? $forum_info['forum_topics_approved'] : $total; $limit_time_sql = ($sort_days) ? 'AND r.report_time >= ' . (time() - ($sort_days * 86400)) : ''; if ($mode == 'reports') @@ -354,6 +411,27 @@ class mcp_reports AND r.pm_id = 0 $limit_time_sql ORDER BY $sort_order_sql"; + + /** + * Alter sql query to get report id of all reports for requested forum and topic or just forum + * + * @event core.mcp_reports_get_reports_query_before + * @var string sql String with the query to be executed + * @var array forum_list List of forums that contain the posts + * @var int topic_id topic_id in the page request + * @var string limit_time_sql String with the SQL code to limit the time interval of the post (Note: May be empty string) + * @var string sort_order_sql String with the ORDER BY SQL code used in this query + * @since 3.1.0-RC4 + */ + $vars = array( + 'sql', + 'forum_list', + 'topic_id', + 'limit_time_sql', + 'sort_order_sql', + ); + extract($phpbb_dispatcher->trigger_event('core.mcp_reports_get_reports_query_before', compact($vars))); + $result = $db->sql_query_limit($sql, $config['topics_per_page'], $start); $i = 0; @@ -378,7 +456,6 @@ class mcp_reports ORDER BY ' . $sort_order_sql; $result = $db->sql_query($sql); - $report_data = $rowset = array(); while ($row = $db->sql_fetchrow($result)) { $template->assign_block_vars('postrow', array( @@ -440,7 +517,7 @@ class mcp_reports */ function close_report($report_id_list, $mode, $action, $pm = false) { - global $db, $template, $user, $config, $auth; + global $db, $user, $auth, $phpbb_log, $request; global $phpEx, $phpbb_root_path, $phpbb_container; $pm_where = ($pm) ? ' AND r.post_id = 0 ' : ' AND r.pm_id = 0 '; @@ -458,6 +535,7 @@ function close_report($report_id_list, $mode, $action, $pm = false) { $post_id_list[] = $row[$id_column]; } + $db->sql_freeresult($result); $post_id_list = array_unique($post_id_list); if ($pm) @@ -469,7 +547,7 @@ function close_report($report_id_list, $mode, $action, $pm = false) } else { - if (!check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_report'))) + if (!phpbb_check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_report'))) { trigger_error('NOT_AUTHORISED'); } @@ -477,19 +555,19 @@ function close_report($report_id_list, $mode, $action, $pm = false) if ($action == 'delete' && strpos($user->data['session_page'], 'mode=report_details') !== false) { - $redirect = request_var('redirect', build_url(array('mode', 'r', 'quickmod')) . '&mode=reports'); + $redirect = $request->variable('redirect', build_url(array('mode', 'r', 'quickmod')) . '&mode=reports'); } - elseif ($action == 'delete' && strpos($user->data['session_page'], 'mode=pm_report_details') !== false) + else if ($action == 'delete' && strpos($user->data['session_page'], 'mode=pm_report_details') !== false) { - $redirect = request_var('redirect', build_url(array('mode', 'r', 'quickmod')) . '&mode=pm_reports'); + $redirect = $request->variable('redirect', build_url(array('mode', 'r', 'quickmod')) . '&mode=pm_reports'); } - else if ($action == 'close' && !request_var('r', 0)) + else if ($action == 'close' && !$request->variable('r', 0)) { - $redirect = request_var('redirect', build_url(array('mode', 'p', 'quickmod')) . '&mode=' . $module); + $redirect = $request->variable('redirect', build_url(array('mode', 'p', 'quickmod')) . '&mode=' . $module); } else { - $redirect = request_var('redirect', build_url(array('quickmod'))); + $redirect = $request->variable('redirect', build_url(array('quickmod'))); } $success_msg = ''; $forum_ids = array(); @@ -505,7 +583,7 @@ function close_report($report_id_list, $mode, $action, $pm = false) if (confirm_box(true)) { - $post_info = ($pm) ? get_pm_data($post_id_list) : get_post_data($post_id_list, 'm_report'); + $post_info = ($pm) ? phpbb_get_pm_data($post_id_list) : phpbb_get_post_data($post_id_list, 'm_report'); $sql = "SELECT r.report_id, r.$id_column, r.report_closed, r.user_id, r.user_notify, u.username, u.username_clean, u.user_email, u.user_jabber, u.user_lang, u.user_notify_type FROM " . REPORTS_TABLE . ' r, ' . USERS_TABLE . ' u @@ -578,7 +656,6 @@ function close_report($report_id_list, $mode, $action, $pm = false) } $db->sql_query($sql); - if (sizeof($close_report_posts)) { if ($pm) @@ -615,19 +692,29 @@ function close_report($report_id_list, $mode, $action, $pm = false) } unset($close_report_posts, $close_report_topics); + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); foreach ($reports as $report) { if ($pm) { - add_log('mod', 0, 0, 'LOG_PM_REPORT_' . strtoupper($action) . 'D', $post_info[$report['pm_id']]['message_subject']); - $phpbb_notifications->delete_notifications('report_pm', $report['pm_id']); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_PM_REPORT_' . strtoupper($action) . 'D', false, array( + 'forum_id' => 0, + 'topic_id' => 0, + $post_info[$report['pm_id']]['message_subject'] + )); + $phpbb_notifications->delete_notifications('notification.type.report_pm', $report['pm_id']); } else { - add_log('mod', $post_info[$report['post_id']]['forum_id'], $post_info[$report['post_id']]['topic_id'], 'LOG_REPORT_' . strtoupper($action) . 'D', $post_info[$report['post_id']]['post_subject']); - $phpbb_notifications->delete_notifications('report_post', $report['post_id']); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_REPORT_' . strtoupper($action) . 'D', false, array( + 'forum_id' => $post_info[$report['post_id']]['forum_id'], + 'topic_id' => $post_info[$report['post_id']]['topic_id'], + 'post_id' => $report['post_id'], + $post_info[$report['post_id']]['post_subject'] + )); + $phpbb_notifications->delete_notifications('notification.type.report_post', $report['post_id']); } } @@ -645,7 +732,7 @@ function close_report($report_id_list, $mode, $action, $pm = false) if ($pm) { - $phpbb_notifications->add_notifications('report_pm_closed', array_merge($post_info[$post_id], array( + $phpbb_notifications->add_notifications('notification.type.report_pm_closed', array_merge($post_info[$post_id], array( 'reporter' => $reporter['user_id'], 'closer_id' => $user->data['user_id'], 'from_user_id' => $post_info[$post_id]['author_id'], @@ -653,7 +740,7 @@ function close_report($report_id_list, $mode, $action, $pm = false) } else { - $phpbb_notifications->add_notifications('report_post_closed', array_merge($post_info[$post_id], array( + $phpbb_notifications->add_notifications('notification.type.report_post_closed', array_merge($post_info[$post_id], array( 'reporter' => $reporter['user_id'], 'closer_id' => $user->data['user_id'], ))); @@ -679,7 +766,7 @@ function close_report($report_id_list, $mode, $action, $pm = false) confirm_box(false, $user->lang[strtoupper($action) . "_{$pm_prefix}REPORT" . ((sizeof($report_id_list) == 1) ? '' : 'S') . '_CONFIRM'], $s_hidden_fields); } - $redirect = request_var('redirect', "index.$phpEx"); + $redirect = $request->variable('redirect', "index.$phpEx"); $redirect = reapply_sid($redirect); if (!$success_msg) diff --git a/phpBB/includes/mcp/mcp_topic.php b/phpBB/includes/mcp/mcp_topic.php index cdb88bf2bf..ba86484040 100644 --- a/phpBB/includes/mcp/mcp_topic.php +++ b/phpBB/includes/mcp/mcp_topic.php @@ -1,9 +1,13 @@ <?php /** * -* @package mcp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -20,16 +24,17 @@ if (!defined('IN_PHPBB')) */ function mcp_topic_view($id, $mode, $action) { - global $phpEx, $phpbb_root_path, $config; - global $template, $db, $user, $auth, $cache, $phpbb_container; + global $phpEx, $phpbb_root_path, $config, $request; + global $template, $db, $user, $auth, $phpbb_container, $phpbb_dispatcher; - $url = append_sid("{$phpbb_root_path}mcp.$phpEx?" . extra_url()); + $url = append_sid("{$phpbb_root_path}mcp.$phpEx?" . phpbb_extra_url()); - $user->add_lang('viewtopic'); + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); + $user->add_lang('viewtopic'); - $topic_id = request_var('t', 0); - $topic_info = get_topic_data(array($topic_id), false, true); + $topic_id = $request->variable('t', 0); + $topic_info = phpbb_get_topic_data(array($topic_id), false, true); if (!sizeof($topic_info)) { @@ -39,16 +44,16 @@ function mcp_topic_view($id, $mode, $action) $topic_info = $topic_info[$topic_id]; // Set up some vars - $icon_id = request_var('icon', 0); - $subject = utf8_normalize_nfc(request_var('subject', '', true)); - $start = request_var('start', 0); - $sort_days_old = request_var('st_old', 0); - $forum_id = request_var('f', 0); - $to_topic_id = request_var('to_topic_id', 0); - $to_forum_id = request_var('to_forum_id', 0); + $icon_id = $request->variable('icon', 0); + $subject = $request->variable('subject', '', true); + $start = $request->variable('start', 0); + $sort_days_old = $request->variable('st_old', 0); + $forum_id = $request->variable('f', 0); + $to_topic_id = $request->variable('to_topic_id', 0); + $to_forum_id = $request->variable('to_forum_id', 0); $sort = isset($_POST['sort']) ? true : false; - $submitted_id_list = request_var('post_ids', array(0)); - $checked_ids = $post_id_list = request_var('post_id_list', array(0)); + $submitted_id_list = $request->variable('post_ids', array(0)); + $checked_ids = $post_id_list = $request->variable('post_id_list', array(0)); // Resync Topic? if ($action == 'resync') @@ -110,17 +115,18 @@ function mcp_topic_view($id, $mode, $action) $sort_days = $total = 0; $sort_key = $sort_dir = ''; $sort_by_sql = $sort_order_sql = array(); - mcp_sorting('viewtopic', $sort_days, $sort_key, $sort_dir, $sort_by_sql, $sort_order_sql, $total, $topic_info['forum_id'], $topic_id, $where_sql); + phpbb_mcp_sorting('viewtopic', $sort_days, $sort_key, $sort_dir, $sort_by_sql, $sort_order_sql, $total, $topic_info['forum_id'], $topic_id, $where_sql); - $limit_time_sql = ($sort_days) ? 'AND p.post_time >= ' . (time() - ($sort_days * 86400)) : ''; + /* @var $phpbb_content_visibility \phpbb\content_visibility */ $phpbb_content_visibility = $phpbb_container->get('content.visibility'); + $limit_time_sql = ($sort_days) ? 'AND p.post_time >= ' . (time() - ($sort_days * 86400)) : ''; if ($total == -1) { $total = $phpbb_content_visibility->get_count('topic_posts', $topic_info, $topic_info['forum_id']); } - $posts_per_page = max(0, request_var('posts_per_page', intval($config['posts_per_page']))); + $posts_per_page = max(0, $request->variable('posts_per_page', intval($config['posts_per_page']))); if ($posts_per_page == 0) { $posts_per_page = $total; @@ -143,23 +149,13 @@ function mcp_topic_view($id, $mode, $action) $result = $db->sql_query_limit($sql, $posts_per_page, $start); $rowset = $post_id_list = array(); - $bbcode_bitfield = ''; while ($row = $db->sql_fetchrow($result)) { $rowset[] = $row; $post_id_list[] = $row['post_id']; - $bbcode_bitfield = $bbcode_bitfield | base64_decode($row['bbcode_bitfield']); } $db->sql_freeresult($result); - if ($bbcode_bitfield !== '') - { - include_once($phpbb_root_path . 'includes/bbcode.' . $phpEx); - $bbcode = new bbcode(base64_encode($bbcode_bitfield)); - } - - $topic_tracking_info = array(); - // Get topic tracking info if ($config['load_db_lastread']) { @@ -175,11 +171,9 @@ function mcp_topic_view($id, $mode, $action) $has_unapproved_posts = $has_deleted_posts = false; // Grab extensions - $extensions = $attachments = array(); + $attachments = array(); if ($topic_info['topic_attachment'] && sizeof($post_id_list)) { - $extensions = $cache->obtain_attach_extensions($topic_info['forum_id']); - // Get attachments... if ($auth->acl_get('u_download') && $auth->acl_get('f_download', $topic_info['forum_id'])) { @@ -198,6 +192,30 @@ function mcp_topic_view($id, $mode, $action) } } + /** + * Event to modify the post data for the MCP topic review before assigning the posts + * + * @event core.mcp_topic_modify_post_data + * @var array attachments List of attachments post_id => array of attachments + * @var int forum_id The forum ID we are currently in + * @var int id ID of the tab we are displaying + * @var string mode Mode of the MCP page we are displaying + * @var array post_id_list Array with post ids we are going to display + * @var array rowset Array with the posts data + * @var int topic_id The topic ID we are currently reviewing + * @since 3.1.7-RC1 + */ + $vars = array( + 'attachments', + 'forum_id', + 'id', + 'mode', + 'post_id_list', + 'rowset', + 'topic_id', + ); + extract($phpbb_dispatcher->trigger_event('core.mcp_topic_modify_post_data', compact($vars))); + foreach ($rowset as $i => $row) { $message = $row['post_text']; @@ -212,7 +230,7 @@ function mcp_topic_view($id, $mode, $action) parse_attachments($topic_info['forum_id'], $message, $attachments[$row['post_id']], $update_count); } - if ($row['post_visibility'] == ITEM_UNAPPROVED) + if ($row['post_visibility'] == ITEM_UNAPPROVED || $row['post_visibility'] == ITEM_REAPPROVE) { $has_unapproved_posts = true; } @@ -224,7 +242,7 @@ function mcp_topic_view($id, $mode, $action) $post_unread = (isset($topic_tracking_info[$topic_id]) && $row['post_time'] > $topic_tracking_info[$topic_id]) ? true : false; - $template->assign_block_vars('postrow', array( + $post_row = array( 'POST_AUTHOR_FULL' => get_username_string('full', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']), 'POST_AUTHOR_COLOUR' => get_username_string('colour', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']), 'POST_AUTHOR' => get_username_string('username', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']), @@ -239,15 +257,47 @@ function mcp_topic_view($id, $mode, $action) 'MINI_POST_IMG' => ($post_unread) ? $user->img('icon_post_target_unread', 'UNREAD_POST') : $user->img('icon_post_target', 'POST'), 'S_POST_REPORTED' => ($row['post_reported'] && $auth->acl_get('m_report', $topic_info['forum_id'])), - 'S_POST_UNAPPROVED' => ($row['post_visibility'] == ITEM_UNAPPROVED && $auth->acl_get('m_approve', $topic_info['forum_id'])), + 'S_POST_UNAPPROVED' => (($row['post_visibility'] == ITEM_UNAPPROVED || $row['post_visibility'] == ITEM_REAPPROVE) && $auth->acl_get('m_approve', $topic_info['forum_id'])), 'S_POST_DELETED' => ($row['post_visibility'] == ITEM_DELETED && $auth->acl_get('m_approve', $topic_info['forum_id'])), 'S_CHECKED' => (($submitted_id_list && !in_array(intval($row['post_id']), $submitted_id_list)) || in_array(intval($row['post_id']), $checked_ids)) ? true : false, 'S_HAS_ATTACHMENTS' => (!empty($attachments[$row['post_id']])) ? true : false, 'U_POST_DETAILS' => "$url&i=$id&p={$row['post_id']}&mode=post_details" . (($forum_id) ? "&f=$forum_id" : ''), 'U_MCP_APPROVE' => ($auth->acl_get('m_approve', $topic_info['forum_id'])) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue&mode=approve_details&f=' . $topic_info['forum_id'] . '&p=' . $row['post_id']) : '', - 'U_MCP_REPORT' => ($auth->acl_get('m_report', $topic_info['forum_id'])) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=reports&mode=report_details&f=' . $topic_info['forum_id'] . '&p=' . $row['post_id']) : '') + 'U_MCP_REPORT' => ($auth->acl_get('m_report', $topic_info['forum_id'])) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=reports&mode=report_details&f=' . $topic_info['forum_id'] . '&p=' . $row['post_id']) : '', + ); + + /** + * Event to modify the template data block for topic reviews in the MCP + * + * @event core.mcp_topic_review_modify_row + * @var int id ID of the tab we are displaying + * @var string mode Mode of the MCP page we are displaying + * @var int topic_id The topic ID we are currently reviewing + * @var int forum_id The forum ID we are currently in + * @var int start Start item of this page + * @var int current_row_number Number of the post on this page + * @var array post_row Template block array of the current post + * @var array row Array with original post and user data + * @var array topic_info Array with topic data + * @var int total Total posts count + * @since 3.1.4-RC1 + */ + $vars = array( + 'id', + 'mode', + 'topic_id', + 'forum_id', + 'start', + 'current_row_number', + 'post_row', + 'row', + 'topic_info', + 'total', ); + extract($phpbb_dispatcher->trigger_event('core.mcp_topic_review_modify_row', compact($vars))); + + $template->assign_block_vars('postrow', $post_row); // Display not already displayed Attachments for this post, we already parsed them. ;) if (!empty($attachments[$row['post_id']])) @@ -274,7 +324,7 @@ function mcp_topic_view($id, $mode, $action) // Has the user selected a topic for merge? if ($to_topic_id) { - $to_topic_info = get_topic_data(array($to_topic_id), 'm_merge'); + $to_topic_info = phpbb_get_topic_data(array($to_topic_id), 'm_merge'); if (!sizeof($to_topic_info)) { @@ -352,11 +402,11 @@ function mcp_topic_view($id, $mode, $action) */ function split_topic($action, $topic_id, $to_forum_id, $subject) { - global $db, $template, $user, $phpEx, $phpbb_root_path, $auth, $config; + global $db, $template, $user, $phpEx, $phpbb_root_path, $auth, $config, $phpbb_log, $request; - $post_id_list = request_var('post_id_list', array(0)); - $forum_id = request_var('forum_id', 0); - $start = request_var('start', 0); + $post_id_list = $request->variable('post_id_list', array(0)); + $forum_id = $request->variable('forum_id', 0); + $start = $request->variable('start', 0); if (!sizeof($post_id_list)) { @@ -364,13 +414,13 @@ function split_topic($action, $topic_id, $to_forum_id, $subject) return; } - if (!check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_split'))) + if (!phpbb_check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_split'))) { return; } $post_id = $post_id_list[0]; - $post_info = get_post_data(array($post_id)); + $post_info = phpbb_get_post_data(array($post_id)); if (!sizeof($post_info)) { @@ -394,7 +444,7 @@ function split_topic($action, $topic_id, $to_forum_id, $subject) return; } - $forum_info = get_forum_data(array($to_forum_id), 'f_post'); + $forum_info = phpbb_get_forum_data(array($to_forum_id), 'f_post'); if (!sizeof($forum_info)) { @@ -410,7 +460,7 @@ function split_topic($action, $topic_id, $to_forum_id, $subject) return; } - $redirect = request_var('redirect', build_url(array('quickmod'))); + $redirect = $request->variable('redirect', build_url(array('quickmod'))); $s_hidden_fields = build_hidden_fields(array( 'i' => 'main', @@ -423,9 +473,8 @@ function split_topic($action, $topic_id, $to_forum_id, $subject) 'redirect' => $redirect, 'subject' => $subject, 'to_forum_id' => $to_forum_id, - 'icon' => request_var('icon', 0)) + 'icon' => $request->variable('icon', 0)) ); - $success_msg = $return_link = ''; if (confirm_box(true)) { @@ -434,7 +483,7 @@ function split_topic($action, $topic_id, $to_forum_id, $subject) $sort_days = $total = 0; $sort_key = $sort_dir = ''; $sort_by_sql = $sort_order_sql = array(); - mcp_sorting('viewtopic', $sort_days, $sort_key, $sort_dir, $sort_by_sql, $sort_order_sql, $total, $forum_id, $topic_id); + phpbb_mcp_sorting('viewtopic', $sort_days, $sort_key, $sort_dir, $sort_by_sql, $sort_order_sql, $total, $forum_id, $topic_id); $limit_time_sql = ($sort_days) ? 'AND t.topic_last_post_time >= ' . (time() - ($sort_days * 86400)) : ''; @@ -462,7 +511,7 @@ function split_topic($action, $topic_id, $to_forum_id, $subject) while ($row = $db->sql_fetchrow($result)) { // If split from selected post (split_beyond), we split the unapproved items too. - if ($row['post_visibility'] == ITEM_UNAPPROVED && !$auth->acl_get('m_approve', $row['forum_id'])) + if (($row['post_visibility'] == ITEM_UNAPPROVED || $row['post_visibility'] == ITEM_REAPPROVE) && !$auth->acl_get('m_approve', $row['forum_id'])) { // continue; } @@ -486,7 +535,7 @@ function split_topic($action, $topic_id, $to_forum_id, $subject) trigger_error('NO_POST_SELECTED'); } - $icon_id = request_var('icon', 0); + $icon_id = $request->variable('icon', 0); $sql_ary = array( 'forum_id' => $to_forum_id, @@ -501,11 +550,19 @@ function split_topic($action, $topic_id, $to_forum_id, $subject) $to_topic_id = $db->sql_nextid(); move_posts($post_id_list, $to_topic_id); - $topic_info = get_topic_data(array($topic_id)); + $topic_info = phpbb_get_topic_data(array($topic_id)); $topic_info = $topic_info[$topic_id]; - add_log('mod', $to_forum_id, $to_topic_id, 'LOG_SPLIT_DESTINATION', $subject); - add_log('mod', $forum_id, $topic_id, 'LOG_SPLIT_SOURCE', $topic_info['topic_title']); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_SPLIT_DESTINATION', false, array( + 'forum_id' => $to_forum_id, + 'topic_id' => $to_topic_id, + $subject + )); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_SPLIT_SOURCE', false, array( + 'forum_id' => $forum_id, + 'topic_id' => $topic_id, + $topic_info['topic_title'] + )); // Change topic title of first post $sql = 'UPDATE ' . POSTS_TABLE . " @@ -559,11 +616,11 @@ function split_topic($action, $topic_id, $to_forum_id, $subject) $success_msg = 'TOPIC_SPLIT_SUCCESS'; // Update forum statistics - set_config_count('num_topics', 1, true); + $config->increment('num_topics', 1, false); // Link back to both topics $return_link = sprintf($user->lang['RETURN_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $post_info['forum_id'] . '&t=' . $post_info['topic_id']) . '">', '</a>') . '<br /><br />' . sprintf($user->lang['RETURN_NEW_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $to_forum_id . '&t=' . $to_topic_id) . '">', '</a>'); - $redirect = request_var('redirect', "{$phpbb_root_path}viewtopic.$phpEx?f=$to_forum_id&t=$to_topic_id"); + $redirect = $request->variable('redirect', "{$phpbb_root_path}viewtopic.$phpEx?f=$to_forum_id&t=$to_topic_id"); $redirect = reapply_sid($redirect); meta_refresh(3, $redirect); @@ -580,7 +637,7 @@ function split_topic($action, $topic_id, $to_forum_id, $subject) */ function merge_posts($topic_id, $to_topic_id) { - global $db, $template, $user, $phpEx, $phpbb_root_path, $auth; + global $db, $template, $user, $phpEx, $phpbb_root_path, $phpbb_log, $request; if (!$to_topic_id) { @@ -588,18 +645,26 @@ function merge_posts($topic_id, $to_topic_id) return; } - $topic_data = get_topic_data(array($to_topic_id), 'm_merge'); + $sync_topics = array($topic_id, $to_topic_id); + + $topic_data = phpbb_get_topic_data($sync_topics, 'm_merge'); - if (!sizeof($topic_data)) + if (!sizeof($topic_data) || empty($topic_data[$to_topic_id])) { $template->assign_var('MESSAGE', $user->lang['NO_FINAL_TOPIC_SELECTED']); return; } + $sync_forums = array(); + foreach ($topic_data as $data) + { + $sync_forums[$data['forum_id']] = $data['forum_id']; + } + $topic_data = $topic_data[$to_topic_id]; - $post_id_list = request_var('post_id_list', array(0)); - $start = request_var('start', 0); + $post_id_list = $request->variable('post_id_list', array(0)); + $start = $request->variable('start', 0); if (!sizeof($post_id_list)) { @@ -607,12 +672,12 @@ function merge_posts($topic_id, $to_topic_id) return; } - if (!check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_merge'))) + if (!phpbb_check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_merge'))) { return; } - $redirect = request_var('redirect', build_url(array('quickmod'))); + $redirect = $request->variable('redirect', build_url(array('quickmod'))); $s_hidden_fields = build_hidden_fields(array( 'i' => 'main', @@ -624,21 +689,26 @@ function merge_posts($topic_id, $to_topic_id) 'redirect' => $redirect, 't' => $topic_id) ); - $success_msg = $return_link = ''; + $return_link = ''; if (confirm_box(true)) { $to_forum_id = $topic_data['forum_id']; - move_posts($post_id_list, $to_topic_id); - add_log('mod', $to_forum_id, $to_topic_id, 'LOG_MERGE', $topic_data['topic_title']); + move_posts($post_id_list, $to_topic_id, false); + + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_MERGE', false, array( + 'forum_id' => $to_forum_id, + 'topic_id' => $to_topic_id, + $topic_data['topic_title'] + )); // Message and return links $success_msg = 'POSTS_MERGED_SUCCESS'; // Does the original topic still exist? If yes, link back to it $sql = 'SELECT forum_id - FROM ' . TOPICS_TABLE . ' + FROM ' . POSTS_TABLE . ' WHERE topic_id = ' . $topic_id; $result = $db->sql_query_limit($sql, 1); $row = $db->sql_fetchrow($result); @@ -662,9 +732,15 @@ function merge_posts($topic_id, $to_topic_id) phpbb_update_rows_avoiding_duplicates($db, BOOKMARKS_TABLE, 'topic_id', array($topic_id), $to_topic_id); } + // Re-sync the topics and forums because the auto-sync was deactivated in the call of move_posts() + sync('topic_reported', 'topic_id', $sync_topics); + sync('topic_attachment', 'topic_id', $sync_topics); + sync('topic', 'topic_id', $sync_topics, true); + sync('forum', 'forum_id', $sync_forums, true, true); + // Link to the new topic $return_link .= (($return_link) ? '<br /><br />' : '') . sprintf($user->lang['RETURN_NEW_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $to_forum_id . '&t=' . $to_topic_id) . '">', '</a>'); - $redirect = request_var('redirect', "{$phpbb_root_path}viewtopic.$phpEx?f=$to_forum_id&t=$to_topic_id"); + $redirect = $request->variable('redirect', "{$phpbb_root_path}viewtopic.$phpEx?f=$to_forum_id&t=$to_topic_id"); $redirect = reapply_sid($redirect); meta_refresh(3, $redirect); diff --git a/phpBB/includes/mcp/mcp_warn.php b/phpBB/includes/mcp/mcp_warn.php index d396d004dc..0b66aae030 100644 --- a/phpBB/includes/mcp/mcp_warn.php +++ b/phpBB/includes/mcp/mcp_warn.php @@ -1,9 +1,13 @@ <?php /** * -* @package mcp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -18,7 +22,6 @@ if (!defined('IN_PHPBB')) /** * mcp_warn * Handling warning the users -* @package mcp */ class mcp_warn { @@ -32,10 +35,9 @@ class mcp_warn function main($id, $mode) { - global $auth, $db, $user, $template; - global $config, $phpbb_root_path, $phpEx; + global $request; - $action = request_var('action', array('' => '')); + $action = $request->variable('action', array('' => '')); if (is_array($action)) { @@ -75,8 +77,8 @@ class mcp_warn */ function mcp_warn_front_view() { - global $phpEx, $phpbb_root_path, $config; - global $template, $db, $user, $auth; + global $phpEx, $phpbb_root_path; + global $template, $db, $user; $template->assign_vars(array( 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=mcp&field=username&select_single=true'), @@ -96,9 +98,6 @@ class mcp_warn 'U_NOTES' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=notes&mode=user_notes&u=' . $row['user_id']), 'USERNAME_FULL' => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour']), - 'USERNAME' => $row['username'], - 'USERNAME_COLOUR' => ($row['user_colour']) ? '#' . $row['user_colour'] : '', - 'U_USER' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&u=' . $row['user_id']), 'WARNING_TIME' => $user->format_date($row['user_last_warning']), 'WARNINGS' => $row['user_warnings'], @@ -118,9 +117,6 @@ class mcp_warn 'U_NOTES' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=notes&mode=user_notes&u=' . $row['user_id']), 'USERNAME_FULL' => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour']), - 'USERNAME' => $row['username'], - 'USERNAME_COLOUR' => ($row['user_colour']) ? '#' . $row['user_colour'] : '', - 'U_USER' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&u=' . $row['user_id']), 'WARNING_TIME' => $user->format_date($row['warning_time']), 'WARNINGS' => $row['user_warnings'], @@ -135,15 +131,16 @@ class mcp_warn function mcp_warn_list_view($action) { global $phpEx, $phpbb_root_path, $config, $phpbb_container; - global $template, $db, $user, $auth; + global $template, $user, $auth, $request; - $user->add_lang('memberlist'); + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); + $user->add_lang('memberlist'); - $start = request_var('start', 0); - $st = request_var('st', 0); - $sk = request_var('sk', 'b'); - $sd = request_var('sd', 'd'); + $start = $request->variable('start', 0); + $st = $request->variable('st', 0); + $sk = $request->variable('sk', 'b'); + $sd = $request->variable('sd', 'd'); $limit_days = array(0 => $user->lang['ALL_ENTRIES'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']); $sort_by_text = array('a' => $user->lang['SORT_USERNAME'], 'b' => $user->lang['SORT_DATE'], 'c' => $user->lang['SORT_WARNINGS']); @@ -167,9 +164,6 @@ class mcp_warn 'U_NOTES' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=notes&mode=user_notes&u=' . $row['user_id']), 'USERNAME_FULL' => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour']), - 'USERNAME' => $row['username'], - 'USERNAME_COLOUR' => ($row['user_colour']) ? '#' . $row['user_colour'] : '', - 'U_USER' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&u=' . $row['user_id']), 'WARNING_TIME' => $user->format_date($row['user_last_warning']), 'WARNINGS' => $row['user_warnings'], @@ -195,13 +189,13 @@ class mcp_warn */ function mcp_warn_post_view($action) { - global $phpEx, $phpbb_root_path, $config; - global $template, $db, $user, $auth; + global $phpEx, $phpbb_root_path, $config, $request; + global $template, $db, $user, $phpbb_dispatcher; - $post_id = request_var('p', 0); - $forum_id = request_var('f', 0); + $post_id = $request->variable('p', 0); + $forum_id = $request->variable('f', 0); $notify = (isset($_REQUEST['notify_user'])) ? true : false; - $warning = utf8_normalize_nfc(request_var('warning', '', true)); + $warning = $request->variable('warning', '', true); $sql = 'SELECT u.*, p.* FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . " u @@ -273,32 +267,81 @@ class mcp_warn { if (check_form_key('mcp_warn')) { - add_warning($user_row, $warning, $notify, $post_id); - $msg = $user->lang['USER_WARNING_ADDED']; + $s_mcp_warn_post = true; + + /** + * Event for before warning a user for a post. + * + * @event core.mcp_warn_post_before + * @var array user_row The entire user row + * @var string warning The warning message + * @var bool notify If true, we notify the user for the warning + * @var int post_id The post id for which the warning is added + * @var bool s_mcp_warn_post If true, we add the warning else we omit it + * @since 3.1.0-b4 + */ + $vars = array( + 'user_row', + 'warning', + 'notify', + 'post_id', + 's_mcp_warn_post', + ); + extract($phpbb_dispatcher->trigger_event('core.mcp_warn_post_before', compact($vars))); + + if ($s_mcp_warn_post) + { + add_warning($user_row, $warning, $notify, $post_id); + $message = $user->lang['USER_WARNING_ADDED']; + + /** + * Event for after warning a user for a post. + * + * @event core.mcp_warn_post_after + * @var array user_row The entire user row + * @var string warning The warning message + * @var bool notify If true, the user was notified for the warning + * @var int post_id The post id for which the warning is added + * @var string message Message displayed to the moderator + * @since 3.1.0-b4 + */ + $vars = array( + 'user_row', + 'warning', + 'notify', + 'post_id', + 'message', + ); + extract($phpbb_dispatcher->trigger_event('core.mcp_warn_post_after', compact($vars))); + } } else { - $msg = $user->lang['FORM_INVALID']; + $message = $user->lang['FORM_INVALID']; + } + + if (!empty($message)) + { + $redirect = append_sid("{$phpbb_root_path}mcp.$phpEx", "i=notes&mode=user_notes&u=$user_id"); + meta_refresh(2, $redirect); + trigger_error($message . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $redirect . '">', '</a>')); } - $redirect = append_sid("{$phpbb_root_path}mcp.$phpEx", "i=notes&mode=user_notes&u=$user_id"); - meta_refresh(2, $redirect); - trigger_error($msg . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $redirect . '">', '</a>')); } // OK, they didn't submit a warning so lets build the page for them to do so // We want to make the message available here as a reminder // Parse the message and subject - $parse_flags = OPTION_FLAG_SMILIES | ($row['bbcode_bitfield'] ? OPTION_FLAG_BBCODE : 0); + $parse_flags = OPTION_FLAG_SMILIES | ($user_row['bbcode_bitfield'] ? OPTION_FLAG_BBCODE : 0); $message = generate_text_for_display($user_row['post_text'], $user_row['bbcode_uid'], $user_row['bbcode_bitfield'], $parse_flags, true); // Generate the appropriate user information for the user we are looking at - if (!function_exists('phpbb_get_user_avatar')) + if (!function_exists('phpbb_get_user_rank')) { include($phpbb_root_path . 'includes/functions_display.' . $phpEx); } - get_user_rank($user_row['user_rank'], $user_row['user_posts'], $rank_title, $rank_img, $rank_img_src); + $user_rank_data = phpbb_get_user_rank($user_row, $user_row['user_posts']); $avatar_img = phpbb_get_user_avatar($user_row); $template->assign_vars(array( @@ -307,13 +350,13 @@ class mcp_warn 'POST' => $message, 'USERNAME' => $user_row['username'], 'USER_COLOR' => (!empty($user_row['user_colour'])) ? $user_row['user_colour'] : '', - 'RANK_TITLE' => $rank_title, + 'RANK_TITLE' => $user_rank_data['title'], 'JOINED' => $user->format_date($user_row['user_regdate']), 'POSTS' => ($user_row['user_posts']) ? $user_row['user_posts'] : 0, 'WARNINGS' => ($user_row['user_warnings']) ? $user_row['user_warnings'] : 0, 'AVATAR_IMG' => $avatar_img, - 'RANK_IMG' => $rank_img, + 'RANK_IMG' => $user_rank_data['img'], 'L_WARNING_POST_DEFAULT' => sprintf($user->lang['WARNING_POST_DEFAULT'], generate_board_url() . "/viewtopic.$phpEx?f=$forum_id&p=$post_id#p$post_id"), @@ -326,13 +369,13 @@ class mcp_warn */ function mcp_warn_user_view($action) { - global $phpEx, $phpbb_root_path, $config, $module; - global $template, $db, $user, $auth; + global $phpEx, $phpbb_root_path, $config, $request; + global $template, $db, $user, $phpbb_dispatcher; - $user_id = request_var('u', 0); - $username = request_var('username', '', true); + $user_id = $request->variable('u', 0); + $username = $request->variable('username', '', true); $notify = (isset($_REQUEST['notify_user'])) ? true : false; - $warning = utf8_normalize_nfc(request_var('warning', '', true)); + $warning = $request->variable('warning', '', true); $sql_where = ($user_id) ? "user_id = $user_id" : "username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'"; @@ -385,32 +428,76 @@ class mcp_warn { if (check_form_key('mcp_warn')) { - add_warning($user_row, $warning, $notify); - $msg = $user->lang['USER_WARNING_ADDED']; + $s_mcp_warn_user = true; + + /** + * Event for before warning a user from MCP. + * + * @event core.mcp_warn_user_before + * @var array user_row The entire user row + * @var string warning The warning message + * @var bool notify If true, we notify the user for the warning + * @var bool s_mcp_warn_user If true, we add the warning else we omit it + * @since 3.1.0-b4 + */ + $vars = array( + 'user_row', + 'warning', + 'notify', + 's_mcp_warn_user', + ); + extract($phpbb_dispatcher->trigger_event('core.mcp_warn_user_before', compact($vars))); + + if ($s_mcp_warn_user) + { + add_warning($user_row, $warning, $notify); + $message = $user->lang['USER_WARNING_ADDED']; + + /** + * Event for after warning a user from MCP. + * + * @event core.mcp_warn_user_after + * @var array user_row The entire user row + * @var string warning The warning message + * @var bool notify If true, the user was notified for the warning + * @var string message Message displayed to the moderator + * @since 3.1.0-b4 + */ + $vars = array( + 'user_row', + 'warning', + 'notify', + 'message', + ); + extract($phpbb_dispatcher->trigger_event('core.mcp_warn_user_after', compact($vars))); + } } else { - $msg = $user->lang['FORM_INVALID']; + $message = $user->lang['FORM_INVALID']; + } + + if (!empty($message)) + { + $redirect = append_sid("{$phpbb_root_path}mcp.$phpEx", "i=notes&mode=user_notes&u=$user_id"); + meta_refresh(2, $redirect); + trigger_error($message . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $redirect . '">', '</a>')); } - $redirect = append_sid("{$phpbb_root_path}mcp.$phpEx", "i=notes&mode=user_notes&u=$user_id"); - meta_refresh(2, $redirect); - trigger_error($msg . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $redirect . '">', '</a>')); } // Generate the appropriate user information for the user we are looking at - if (!function_exists('phpbb_get_user_avatar')) + if (!function_exists('phpbb_get_user_rank')) { include($phpbb_root_path . 'includes/functions_display.' . $phpEx); } - - get_user_rank($user_row['user_rank'], $user_row['user_posts'], $rank_title, $rank_img, $rank_img_src); + $user_rank_data = phpbb_get_user_rank($user_row, $user_row['user_posts']); $avatar_img = phpbb_get_user_avatar($user_row); // OK, they didn't submit a warning so lets build the page for them to do so $template->assign_vars(array( 'U_POST_ACTION' => $this->u_action, - 'RANK_TITLE' => $rank_title, + 'RANK_TITLE' => $user_rank_data['title'], 'JOINED' => $user->format_date($user_row['user_regdate']), 'POSTS' => ($user_row['user_posts']) ? $user_row['user_posts'] : 0, 'WARNINGS' => ($user_row['user_warnings']) ? $user_row['user_warnings'] : 0, @@ -421,7 +508,7 @@ class mcp_warn 'U_PROFILE' => get_username_string('profile', $user_row['user_id'], $user_row['username'], $user_row['user_colour']), 'AVATAR_IMG' => $avatar_img, - 'RANK_IMG' => $rank_img, + 'RANK_IMG' => $user_rank_data['img'], 'S_CAN_NOTIFY' => $s_can_notify, )); @@ -435,8 +522,8 @@ class mcp_warn */ function add_warning($user_row, $warning, $send_pm = true, $post_id = 0) { - global $phpEx, $phpbb_root_path, $config; - global $template, $db, $user, $auth; + global $phpEx, $phpbb_root_path, $config, $phpbb_log; + global $db, $user; if ($send_pm) { @@ -448,7 +535,7 @@ function add_warning($user_row, $warning, $send_pm = true, $post_id = 0) $message_parser = new parse_message(); - $message_parser->message = sprintf($lang['WARNING_PM_BODY'], $warning); + $message_parser->message = $user->lang('WARNING_PM_BODY', $warning); $message_parser->parse(true, true, true, false, false, true, true); $pm_data = array( @@ -466,11 +553,14 @@ function add_warning($user_row, $warning, $send_pm = true, $post_id = 0) 'address_list' => array('u' => array($user_row['user_id'] => 'to')), ); - submit_pm('post', $lang['WARNING_PM_SUBJECT'], $pm_data, false); + submit_pm('post', $user->lang('WARNING_PM_SUBJECT'), $pm_data, false); } - add_log('admin', 'LOG_USER_WARNING', $user_row['username']); - $log_id = add_log('user', $user_row['user_id'], 'LOG_USER_WARNING_BODY', $warning); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_WARNING', false, array($user_row['username'])); + $log_id = $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_WARNING_BODY', false, array( + 'reportee_id' => $user_row['user_id'], + $warning + )); $sql_ary = array( 'user_id' => $user_row['user_id'], @@ -495,5 +585,10 @@ function add_warning($user_row, $warning, $send_pm = true, $post_id = 0) $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); - add_log('mod', $row['forum_id'], $row['topic_id'], 'LOG_USER_WARNING', $user_row['username']); + $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_USER_WARNING', false, array( + 'forum_id' => $row['forum_id'], + 'topic_id' => $row['topic_id'], + 'post_id' => $post_id, + $user_row['username'] + )); } diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php index ad6743b3a3..97e0dd9f0d 100644 --- a/phpBB/includes/message_parser.php +++ b/phpBB/includes/message_parser.php @@ -1,9 +1,13 @@ <?php /** * -* @package phpBB3 -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -17,13 +21,25 @@ if (!defined('IN_PHPBB')) if (!class_exists('bbcode')) { + // The following lines are for extensions which include message_parser.php + // while $phpbb_root_path and $phpEx are out of the script scope + // which may lead to the 'Undefined variable' and 'failed to open stream' errors + if (!isset($phpbb_root_path)) + { + global $phpbb_root_path; + } + + if (!isset($phpEx)) + { + global $phpEx; + } + include($phpbb_root_path . 'includes/bbcode.' . $phpEx); } /** * BBCODE FIRSTPASS * BBCODE first pass class (functions for parsing messages for db storage) -* @package phpBB3 */ class bbcode_firstpass extends bbcode { @@ -67,7 +83,14 @@ class bbcode_firstpass extends bbcode // it should not demand recompilation if (preg_match($regexp, $this->message)) { - $this->message = preg_replace($regexp, $replacement, $this->message); + if (is_callable($replacement)) + { + $this->message = preg_replace_callback($regexp, $replacement, $this->message); + } + else + { + $this->message = preg_replace($regexp, $replacement, $this->message); + } $bitfield->set($bbcode_data['bbcode_id']); } } @@ -104,28 +127,85 @@ class bbcode_firstpass extends bbcode function bbcode_init($allow_custom_bbcode = true) { global $phpbb_dispatcher; - + static $rowset; + $bbcode_class = $this; + // This array holds all bbcode data. BBCodes will be processed in this // order, so it is important to keep [code] in first position and // [quote] in second position. // To parse multiline URL we enable dotall option setting only for URL text // but not for link itself, thus [url][/url] is not affected. + // + // To perform custom validation in extension, use $this->validate_bbcode_by_extension() + // method which accepts variable number of parameters $this->bbcodes = array( - 'code' => array('bbcode_id' => 8, 'regexp' => array('#\[code(?:=([a-z]+))?\](.+\[/code\])#uise' => "\$this->bbcode_code('\$1', '\$2')")), - 'quote' => array('bbcode_id' => 0, 'regexp' => array('#\[quote(?:="(.*?)")?\](.+)\[/quote\]#uise' => "\$this->bbcode_quote('\$0')")), - 'attachment' => array('bbcode_id' => 12, 'regexp' => array('#\[attachment=([0-9]+)\](.*?)\[/attachment\]#uise' => "\$this->bbcode_attachment('\$1', '\$2')")), - 'b' => array('bbcode_id' => 1, 'regexp' => array('#\[b\](.*?)\[/b\]#uise' => "\$this->bbcode_strong('\$1')")), - 'i' => array('bbcode_id' => 2, 'regexp' => array('#\[i\](.*?)\[/i\]#uise' => "\$this->bbcode_italic('\$1')")), - 'url' => array('bbcode_id' => 3, 'regexp' => array('#\[url(=(.*))?\](?(1)((?s).*(?-s))|(.*))\[/url\]#uiUe' => "\$this->validate_url('\$2', ('\$3') ? '\$3' : '\$4')")), - 'img' => array('bbcode_id' => 4, 'regexp' => array('#\[img\](.*)\[/img\]#uiUe' => "\$this->bbcode_img('\$1')")), - 'size' => array('bbcode_id' => 5, 'regexp' => array('#\[size=([\-\+]?\d+)\](.*?)\[/size\]#uise' => "\$this->bbcode_size('\$1', '\$2')")), - 'color' => array('bbcode_id' => 6, 'regexp' => array('!\[color=(#[0-9a-f]{3}|#[0-9a-f]{6}|[a-z\-]+)\](.*?)\[/color\]!uise' => "\$this->bbcode_color('\$1', '\$2')")), - 'u' => array('bbcode_id' => 7, 'regexp' => array('#\[u\](.*?)\[/u\]#uise' => "\$this->bbcode_underline('\$1')")), - 'list' => array('bbcode_id' => 9, 'regexp' => array('#\[list(?:=(?:[a-z0-9]|disc|circle|square))?].*\[/list]#uise' => "\$this->bbcode_parse_list('\$0')")), - 'email' => array('bbcode_id' => 10, 'regexp' => array('#\[email=?(.*?)?\](.*?)\[/email\]#uise' => "\$this->validate_email('\$1', '\$2')")), - 'flash' => array('bbcode_id' => 11, 'regexp' => array('#\[flash=([0-9]+),([0-9]+)\](.*?)\[/flash\]#uie' => "\$this->bbcode_flash('\$1', '\$2', '\$3')")) + 'code' => array('bbcode_id' => 8, 'regexp' => array('#\[code(?:=([a-z]+))?\](.+\[/code\])#uis' => function ($match) use($bbcode_class) + { + return $bbcode_class->bbcode_code($match[1], $match[2]); + } + )), + 'quote' => array('bbcode_id' => 0, 'regexp' => array('#\[quote(?:="(.*?)")?\](.+)\[/quote\]#uis' => function ($match) use($bbcode_class) + { + return $bbcode_class->bbcode_quote($match[0]); + } + )), + 'attachment' => array('bbcode_id' => 12, 'regexp' => array('#\[attachment=([0-9]+)\](.*?)\[/attachment\]#uis' => function ($match) use($bbcode_class) + { + return $bbcode_class->bbcode_attachment($match[1], $match[2]); + } + )), + 'b' => array('bbcode_id' => 1, 'regexp' => array('#\[b\](.*?)\[/b\]#uis' => function ($match) use($bbcode_class) + { + return $bbcode_class->bbcode_strong($match[1]); + } + )), + 'i' => array('bbcode_id' => 2, 'regexp' => array('#\[i\](.*?)\[/i\]#uis' => function ($match) use($bbcode_class) + { + return $bbcode_class->bbcode_italic($match[1]); + } + )), + 'url' => array('bbcode_id' => 3, 'regexp' => array('#\[url(=(.*))?\](?(1)((?s).*(?-s))|(.*))\[/url\]#uiU' => function ($match) use($bbcode_class) + { + return $bbcode_class->validate_url($match[2], ($match[3]) ? $match[3] : $match[4]); + } + )), + 'img' => array('bbcode_id' => 4, 'regexp' => array('#\[img\](.*)\[/img\]#uiU' => function ($match) use($bbcode_class) + { + return $bbcode_class->bbcode_img($match[1]); + } + )), + 'size' => array('bbcode_id' => 5, 'regexp' => array('#\[size=([\-\+]?\d+)\](.*?)\[/size\]#uis' => function ($match) use($bbcode_class) + { + return $bbcode_class->bbcode_size($match[1], $match[2]); + } + )), + 'color' => array('bbcode_id' => 6, 'regexp' => array('!\[color=(#[0-9a-f]{3}|#[0-9a-f]{6}|[a-z\-]+)\](.*?)\[/color\]!uis' => function ($match) use($bbcode_class) + { + return $bbcode_class->bbcode_color($match[1], $match[2]); + } + )), + 'u' => array('bbcode_id' => 7, 'regexp' => array('#\[u\](.*?)\[/u\]#uis' => function ($match) use($bbcode_class) + { + return $bbcode_class->bbcode_underline($match[1]); + } + )), + 'list' => array('bbcode_id' => 9, 'regexp' => array('#\[list(?:=(?:[a-z0-9]|disc|circle|square))?].*\[/list]#uis' => function ($match) use($bbcode_class) + { + return $bbcode_class->bbcode_parse_list($match[0]); + } + )), + 'email' => array('bbcode_id' => 10, 'regexp' => array('#\[email=?(.*?)?\](.*?)\[/email\]#uis' => function ($match) use($bbcode_class) + { + return $bbcode_class->validate_email($match[1], $match[2]); + } + )), + 'flash' => array('bbcode_id' => 11, 'regexp' => array('#\[flash=([0-9]+),([0-9]+)\](.*?)\[/flash\]#ui' => function ($match) use($bbcode_class) + { + return $bbcode_class->bbcode_flash($match[1], $match[2], $match[3]); + } + )) ); // Zero the parsed items array @@ -310,7 +390,7 @@ class bbcode_firstpass extends bbcode $in = str_replace(' ', '%20', $in); // Checking urls - if (!preg_match('#^' . get_preg_expression('url') . '$#i', $in) && !preg_match('#^' . get_preg_expression('www_url') . '$#i', $in)) + if (!preg_match('#^' . get_preg_expression('url') . '$#iu', $in) && !preg_match('#^' . get_preg_expression('www_url') . '$#iu', $in)) { return '[img]' . $in . '[/img]'; } @@ -323,22 +403,23 @@ class bbcode_firstpass extends bbcode if ($config['max_' . $this->mode . '_img_height'] || $config['max_' . $this->mode . '_img_width']) { - $stats = @getimagesize(htmlspecialchars_decode($in)); + $imagesize = new \FastImageSize\FastImageSize(); + $size_info = $imagesize->getImageSize(htmlspecialchars_decode($in)); - if ($stats === false) + if ($size_info === false) { $error = true; $this->warn_msg[] = $user->lang['UNABLE_GET_IMAGE_SIZE']; } else { - if ($config['max_' . $this->mode . '_img_height'] && $config['max_' . $this->mode . '_img_height'] < $stats[1]) + if ($config['max_' . $this->mode . '_img_height'] && $config['max_' . $this->mode . '_img_height'] < $size_info['height']) { $error = true; $this->warn_msg[] = $user->lang('MAX_IMG_HEIGHT_EXCEEDED', (int) $config['max_' . $this->mode . '_img_height']); } - if ($config['max_' . $this->mode . '_img_width'] && $config['max_' . $this->mode . '_img_width'] < $stats[0]) + if ($config['max_' . $this->mode . '_img_width'] && $config['max_' . $this->mode . '_img_width'] < $size_info['width']) { $error = true; $this->warn_msg[] = $user->lang('MAX_IMG_WIDTH_EXCEEDED', (int) $config['max_' . $this->mode . '_img_width']); @@ -378,8 +459,8 @@ class bbcode_firstpass extends bbcode $in = str_replace(' ', '%20', $in); // Make sure $in is a URL. - if (!preg_match('#^' . get_preg_expression('url') . '$#i', $in) && - !preg_match('#^' . get_preg_expression('www_url') . '$#i', $in)) + if (!preg_match('#^' . get_preg_expression('url') . '$#iu', $in) && + !preg_match('#^' . get_preg_expression('www_url') . '$#iu', $in)) { return '[flash=' . $width . ',' . $height . ']' . $in . '[/flash]'; } @@ -717,8 +798,6 @@ class bbcode_firstpass extends bbcode */ function bbcode_quote($in) { - global $config, $user; - $in = str_replace("\r\n", "\n", str_replace('\"', '"', trim($in))); if (!$in) @@ -727,7 +806,9 @@ class bbcode_firstpass extends bbcode } // To let the parser not catch tokens within quote_username quotes we encode them before we start this... - $in = preg_replace('#quote="(.*?)"\]#ie', "'quote="' . str_replace(array('[', ']', '\\\"'), array('[', ']', '\"'), '\$1') . '"]'", $in); + $in = preg_replace_callback('#quote="(.*?)"\]#i', function ($match) { + return 'quote="' . str_replace(array('[', ']', '\\\"'), array('[', ']', '\"'), $match[1]) . '"]'; + }, $in); $tok = ']'; $out = '['; @@ -772,20 +853,6 @@ class bbcode_firstpass extends bbcode else if (preg_match('#^quote(?:="(.*?)")?$#is', $buffer, $m) && substr($out, -1, 1) == '[') { $this->parsed_items['quote']++; - - // the buffer holds a valid opening tag - if ($config['max_quote_depth'] && sizeof($close_tags) >= $config['max_quote_depth']) - { - // there are too many nested quotes - $error_ary['quote_depth'] = $user->lang('QUOTE_DEPTH_EXCEEDED', (int) $config['max_quote_depth']); - - $out .= $buffer . $tok; - $tok = '[]'; - $buffer = ''; - - continue; - } - array_push($close_tags, '/quote:' . $this->bbcode_uid); if (isset($m[1]) && $m[1]) @@ -940,8 +1007,6 @@ class bbcode_firstpass extends bbcode */ function validate_url($var1, $var2) { - global $config; - $var1 = str_replace("\r\n", "\n", str_replace('\"', '"', trim($var1))); $var2 = str_replace("\r\n", "\n", str_replace('\"', '"', trim($var2))); @@ -962,9 +1027,9 @@ class bbcode_firstpass extends bbcode $url = str_replace(' ', '%20', $url); // Checking urls - if (preg_match('#^' . get_preg_expression('url') . '$#i', $url) || - preg_match('#^' . get_preg_expression('www_url') . '$#i', $url) || - preg_match('#^' . preg_quote(generate_board_url(), '#') . get_preg_expression('relative_url') . '$#i', $url)) + if (preg_match('#^' . get_preg_expression('url') . '$#iu', $url) || + preg_match('#^' . get_preg_expression('www_url') . '$#iu', $url) || + preg_match('#^' . preg_quote(generate_board_url(), '#') . get_preg_expression('relative_url') . '$#iu', $url)) { $valid = true; } @@ -1049,7 +1114,6 @@ class bbcode_firstpass extends bbcode /** * Main message parser for posting, pm, etc. takes raw message * and parses it for attachments, bbcode and smilies -* @package phpBB3 */ class parse_message extends bbcode_firstpass { @@ -1087,7 +1151,7 @@ class parse_message extends bbcode_firstpass */ function 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') { - global $config, $db, $user; + global $config, $user, $phpbb_dispatcher, $phpbb_container; $this->mode = $mode; @@ -1116,19 +1180,13 @@ class parse_message extends bbcode_firstpass $this->decode_message(); } - // Do some general 'cleanup' first before processing message, - // e.g. remove excessive newlines(?), smilies(?) - $match = array('#(script|about|applet|activex|chrome):#i'); - $replace = array("\\1:"); - $this->message = preg_replace($match, $replace, trim($this->message)); - // Store message length... $message_length = ($mode == 'post') ? utf8_strlen($this->message) : utf8_strlen(preg_replace('#\[\/?[a-z\*\+\-]+(=[\S]+)?\]#ius', ' ', $this->message)); // Maximum message length check. 0 disables this check completely. if ((int) $config['max_' . $mode . '_chars'] > 0 && $message_length > (int) $config['max_' . $mode . '_chars']) { - $this->warn_msg[] = $user->lang('TOO_MANY_CHARS_' . strtoupper($mode), $message_length, (int) $config['max_' . $mode . '_chars']); + $this->warn_msg[] = $user->lang('CHARS_' . strtoupper($mode) . '_CONTAINS', $message_length) . '<br />' . $user->lang('TOO_MANY_CHARS_LIMIT', (int) $config['max_' . $mode . '_chars']); return (!$update_this_message) ? $return_message : $this->warn_msg; } @@ -1137,51 +1195,91 @@ class parse_message extends bbcode_firstpass { if (!$message_length || $message_length < (int) $config['min_post_chars']) { - $this->warn_msg[] = (!$message_length) ? $user->lang['TOO_FEW_CHARS'] : $user->lang('TOO_FEW_CHARS_LIMIT', $message_length, (int) $config['min_post_chars']); + $this->warn_msg[] = (!$message_length) ? $user->lang['TOO_FEW_CHARS'] : ($user->lang('CHARS_POST_CONTAINS', $message_length) . '<br />' . $user->lang('TOO_FEW_CHARS_LIMIT', (int) $config['min_post_chars'])); return (!$update_this_message) ? $return_message : $this->warn_msg; } } - // Prepare BBcode (just prepares some tags for better parsing) - if ($allow_bbcode && strpos($this->message, '[') !== false) + /** + * This event can be used for additional message checks/cleanup before parsing + * + * @event core.message_parser_check_message + * @var bool allow_bbcode Do we allow BBCodes + * @var bool allow_magic_url Do we allow magic urls + * @var bool allow_smilies Do we allow smilies + * @var bool allow_img_bbcode Do we allow image BBCode + * @var bool allow_flash_bbcode Do we allow flash BBCode + * @var bool allow_quote_bbcode Do we allow quote BBCode + * @var bool allow_url_bbcode Do we allow url BBCode + * @var bool update_this_message Do we alter the parsed message + * @var string mode Posting mode + * @var string message The message text to parse + * @var string bbcode_bitfield The bbcode_bitfield before parsing + * @var string bbcode_uid The bbcode_uid before parsing + * @var bool return Do we return after the event is triggered if $warn_msg is not empty + * @var array warn_msg Array of the warning messages + * @since 3.1.2-RC1 + * @change 3.1.3-RC1 Added vars $bbcode_bitfield and $bbcode_uid + */ + $message = $this->message; + $warn_msg = $this->warn_msg; + $return = false; + $bbcode_bitfield = $this->bbcode_bitfield; + $bbcode_uid = $this->bbcode_uid; + $vars = array( + 'allow_bbcode', + 'allow_magic_url', + 'allow_smilies', + 'allow_img_bbcode', + 'allow_flash_bbcode', + 'allow_quote_bbcode', + 'allow_url_bbcode', + 'update_this_message', + 'mode', + 'message', + 'bbcode_bitfield', + 'bbcode_uid', + 'return', + 'warn_msg', + ); + extract($phpbb_dispatcher->trigger_event('core.message_parser_check_message', compact($vars))); + $this->message = $message; + $this->warn_msg = $warn_msg; + $this->bbcode_bitfield = $bbcode_bitfield; + $this->bbcode_uid = $bbcode_uid; + if ($return && !empty($this->warn_msg)) { - $this->bbcode_init(); - $disallow = array('img', 'flash', 'quote', 'url'); - foreach ($disallow as $bool) - { - if (!${'allow_' . $bool . '_bbcode'}) - { - $this->bbcodes[$bool]['disabled'] = true; - } - } - - $this->prepare_bbcodes(); + return (!$update_this_message) ? $return_message : $this->warn_msg; } - // Parse smilies - if ($allow_smilies) - { - $this->smilies($config['max_' . $mode . '_smilies']); - } + // Get the parser + $parser = $phpbb_container->get('text_formatter.parser'); - $num_urls = 0; + // Set the parser's options + ($allow_bbcode) ? $parser->enable_bbcodes() : $parser->disable_bbcodes(); + ($allow_magic_url) ? $parser->enable_magic_url() : $parser->disable_magic_url(); + ($allow_smilies) ? $parser->enable_smilies() : $parser->disable_smilies(); + ($allow_img_bbcode) ? $parser->enable_bbcode('img') : $parser->disable_bbcode('img'); + ($allow_flash_bbcode) ? $parser->enable_bbcode('flash') : $parser->disable_bbcode('flash'); + ($allow_quote_bbcode) ? $parser->enable_bbcode('quote') : $parser->disable_bbcode('quote'); + ($allow_url_bbcode) ? $parser->enable_bbcode('url') : $parser->disable_bbcode('url'); - // Parse BBCode - if ($allow_bbcode && strpos($this->message, '[') !== false) - { - $this->parse_bbcode(); - $num_urls += $this->parsed_items['url']; - } + // Set some config values + $parser->set_vars(array( + 'max_font_size' => $config['max_' . $this->mode . '_font_size'], + 'max_img_height' => $config['max_' . $this->mode . '_img_height'], + 'max_img_width' => $config['max_' . $this->mode . '_img_width'], + 'max_smilies' => $config['max_' . $this->mode . '_smilies'], + 'max_urls' => $config['max_' . $this->mode . '_urls'] + )); - // Parse URL's - if ($allow_magic_url) - { - $this->magic_url(generate_board_url()); + // Parse this message + $this->message = $parser->parse(htmlspecialchars_decode($this->message, ENT_QUOTES)); - if ($config['max_' . $mode . '_urls']) - { - $num_urls += preg_match_all('#\<!-- ([lmwe]) --\>.*?\<!-- \1 --\>#', $this->message, $matches); - } + // Remove quotes that are nested too deep + if ($config['max_quote_depth'] > 0) + { + $this->remove_nested_quotes($config['max_quote_depth']); } // Check for "empty" message. We do not check here for maximum length, because bbcode, smilies, etc. can add to the length. @@ -1192,10 +1290,27 @@ class parse_message extends bbcode_firstpass return (!$update_this_message) ? $return_message : $this->warn_msg; } - // Check number of links - if ($config['max_' . $mode . '_urls'] && $num_urls > $config['max_' . $mode . '_urls']) + // Remove quotes that are nested too deep + if ($config['max_quote_depth'] > 0) { - $this->warn_msg[] = sprintf($user->lang['TOO_MANY_URLS'], $config['max_' . $mode . '_urls']); + $this->message = $phpbb_container->get('text_formatter.utils')->remove_bbcode( + $this->message, + 'quote', + $config['max_quote_depth'] + ); + } + + // Check for errors + $errors = $parser->get_errors(); + if ($errors) + { + foreach ($errors as $i => $args) + { + // Translate each error with $user->lang() + $errors[$i] = call_user_func_array(array($user, 'lang'), $args); + } + $this->warn_msg = array_merge($this->warn_msg, $errors); + return (!$update_this_message) ? $return_message : $this->warn_msg; } @@ -1215,7 +1330,7 @@ class parse_message extends bbcode_firstpass */ function format_display($allow_bbcode, $allow_magic_url, $allow_smilies, $update_this_message = true) { - global $phpbb_dispatcher; + global $phpbb_container, $phpbb_dispatcher; // If false, then the parsed message get returned but internal message not processed. if (!$update_this_message) @@ -1224,26 +1339,48 @@ class parse_message extends bbcode_firstpass $return_message = &$this->message; } - if ($this->message_status == 'plain') + $text = $this->message; + $uid = $this->bbcode_uid; + + /** + * Event to modify the text before it is parsed + * + * @event core.modify_format_display_text_before + * @var string text The message text to parse + * @var string uid The bbcode uid + * @var bool allow_bbcode Do we allow bbcodes + * @var bool allow_magic_url Do we allow magic urls + * @var bool allow_smilies Do we allow smilies + * @var bool update_this_message Do we update the internal message + * with the parsed result + * @since 3.1.6-RC1 + */ + $vars = array('text', 'uid', 'allow_bbcode', 'allow_magic_url', 'allow_smilies', 'update_this_message'); + extract($phpbb_dispatcher->trigger_event('core.modify_format_display_text_before', compact($vars))); + + $this->message = $text; + $this->bbcode_uid = $uid; + unset($text, $uid); + + // NOTE: message_status is unreliable for detecting unparsed text because some callers + // change $this->message without resetting $this->message_status to 'plain' so we + // inspect the message instead + //if ($this->message_status == 'plain') + if (!preg_match('/^<[rt][ >]/', $this->message)) { // Force updating message - of course. $this->parse($allow_bbcode, $allow_magic_url, $allow_smilies, $this->allow_img_bbcode, $this->allow_flash_bbcode, $this->allow_quote_bbcode, $this->allow_url_bbcode, true); } - // Replace naughty words such as farty pants - $this->message = censor_text($this->message); - - // Parse BBcode - if ($allow_bbcode) + // There's a bug when previewing a topic with no poll, because the empty title of the poll + // gets parsed but $this->message still ends up empty. This fixes it, until a proper fix is + // devised + if ($this->message === '') { - $this->bbcode_cache_init(); - - // We are giving those parameters to be able to use the bbcode class on its own - $this->bbcode_second_pass($this->message, $this->bbcode_uid); + $this->message = $phpbb_container->get('text_formatter.parser')->parse($this->message); } - $this->message = bbcode_nl2br($this->message); - $this->message = smiley_text($this->message, !$allow_smilies); + $this->message = $phpbb_container->get('text_formatter.renderer')->render($this->message); $text = $this->message; $uid = $this->bbcode_uid; @@ -1331,7 +1468,7 @@ class parse_message extends bbcode_firstpass // NOTE: obtain_* function? chaching the table contents? // For now setting the ttl to 10 minutes - switch ($db->sql_layer) + switch ($db->get_sql_layer()) { case 'mssql': case 'mssql_odbc': @@ -1341,12 +1478,6 @@ class parse_message extends bbcode_firstpass ORDER BY LEN(code) DESC'; break; - case 'firebird': - $sql = 'SELECT * - FROM ' . SMILIES_TABLE . ' - ORDER BY CHAR_LENGTH(code) DESC'; - break; - // LENGTH supported by MySQL, IBM DB2, Oracle and Access for sure... default: $sql = 'SELECT * @@ -1400,11 +1531,12 @@ class parse_message extends bbcode_firstpass function parse_attachments($form_name, $mode, $forum_id, $submit, $preview, $refresh, $is_message = false) { global $config, $auth, $user, $phpbb_root_path, $phpEx, $db, $request; + global $phpbb_container; $error = array(); $num_attachments = sizeof($this->attachment_data); - $this->filename_data['filecomment'] = utf8_normalize_nfc(request_var('filecomment', '', true)); + $this->filename_data['filecomment'] = $request->variable('filecomment', '', true); $upload = $request->file($form_name); $upload_file = (!empty($upload) && $upload['name'] !== 'none' && trim($upload['name'])); @@ -1412,7 +1544,7 @@ class parse_message extends bbcode_firstpass $delete_file = (isset($_POST['delete_file'])) ? true : false; // First of all adjust comments if changed - $actual_comment_list = utf8_normalize_nfc(request_var('comment_list', array(''), true)); + $actual_comment_list = $request->variable('comment_list', array(''), true); foreach ($actual_comment_list as $comment_key => $comment) { @@ -1435,7 +1567,9 @@ class parse_message extends bbcode_firstpass { if ($num_attachments < $cfg['max_attachments'] || $auth->acl_get('a_') || $auth->acl_get('m_', $forum_id)) { - $filedata = upload_attachment($form_name, $forum_id, false, '', $is_message); + /** @var \phpbb\attachment\manager $attachment_manager */ + $attachment_manager = $phpbb_container->get('attachment.manager'); + $filedata = $attachment_manager->upload($form_name, $forum_id, false, '', $is_message); $error = $filedata['error']; if ($filedata['post_attach'] && !sizeof($error)) @@ -1465,7 +1599,9 @@ class parse_message extends bbcode_firstpass ); $this->attachment_data = array_merge(array(0 => $new_entry), $this->attachment_data); - $this->message = preg_replace('#\[attachment=([0-9]+)\](.*?)\[\/attachment\]#e', "'[attachment='.(\\1 + 1).']\\2[/attachment]'", $this->message); + $this->message = preg_replace_callback('#\[attachment=([0-9]+)\](.*?)\[\/attachment\]#', function ($match) { + return '[attachment='.($match[1] + 1).']' . $match[2] . '[/attachment]'; + }, $this->message); $this->filename_data['filecomment'] = ''; @@ -1498,11 +1634,14 @@ class parse_message extends bbcode_firstpass { include_once($phpbb_root_path . 'includes/functions_admin.' . $phpEx); - $index = array_keys(request_var('delete_file', array(0 => 0))); + $index = array_keys($request->variable('delete_file', array(0 => 0))); $index = (!empty($index)) ? $index[0] : false; if ($index !== false && !empty($this->attachment_data[$index])) { + /** @var \phpbb\attachment\manager $attachment_manager */ + $attachment_manager = $phpbb_container->get('attachment.manager'); + // delete selected attachment if ($this->attachment_data[$index]['is_orphan']) { @@ -1517,11 +1656,11 @@ class parse_message extends bbcode_firstpass if ($row) { - phpbb_unlink($row['physical_filename'], 'file'); + $attachment_manager->unlink($row['physical_filename'], 'file'); if ($row['thumbnail']) { - phpbb_unlink($row['physical_filename'], 'thumbnail'); + $attachment_manager->unlink($row['physical_filename'], 'thumbnail'); } $db->sql_query('DELETE FROM ' . ATTACHMENTS_TABLE . ' WHERE attach_id = ' . (int) $this->attachment_data[$index]['attach_id']); @@ -1529,11 +1668,13 @@ class parse_message extends bbcode_firstpass } else { - delete_attachments('attach', array(intval($this->attachment_data[$index]['attach_id']))); + $attachment_manager->delete('attach', $this->attachment_data[$index]['attach_id']); } unset($this->attachment_data[$index]); - $this->message = preg_replace('#\[attachment=([0-9]+)\](.*?)\[\/attachment\]#e', "(\\1 == \$index) ? '' : ((\\1 > \$index) ? '[attachment=' . (\\1 - 1) . ']\\2[/attachment]' : '\\0')", $this->message); + $this->message = preg_replace_callback('#\[attachment=([0-9]+)\](.*?)\[\/attachment\]#', function ($match) use($index) { + return ($match[1] == $index) ? '' : (($match[1] > $index) ? '[attachment=' . ($match[1] - 1) . ']' . $match[2] . '[/attachment]' : $match[0]); + }, $this->message); // Reindex Array $this->attachment_data = array_values($this->attachment_data); @@ -1547,7 +1688,9 @@ class parse_message extends bbcode_firstpass { if ($num_attachments < $cfg['max_attachments'] || $auth->acl_gets('m_', 'a_', $forum_id)) { - $filedata = upload_attachment($form_name, $forum_id, false, '', $is_message, false, $this->plupload); + /** @var \phpbb\attachment\manager $attachment_manager */ + $attachment_manager = $phpbb_container->get('attachment.manager'); + $filedata = $attachment_manager->upload($form_name, $forum_id, false, '', $is_message); $error = array_merge($error, $filedata['error']); if (!sizeof($error)) @@ -1577,7 +1720,9 @@ class parse_message extends bbcode_firstpass ); $this->attachment_data = array_merge(array(0 => $new_entry), $this->attachment_data); - $this->message = preg_replace('#\[attachment=([0-9]+)\](.*?)\[\/attachment\]#e', "'[attachment='.(\\1 + 1).']\\2[/attachment]'", $this->message); + $this->message = preg_replace_callback('#\[attachment=([0-9]+)\](.*?)\[\/attachment\]#', function ($match) { + return '[attachment=' . ($match[1] + 1) . ']' . $match[2] . '[/attachment]'; + }, $this->message); $this->filename_data['filecomment'] = ''; if (isset($this->plupload) && $this->plupload->is_active()) @@ -1621,10 +1766,10 @@ class parse_message extends bbcode_firstpass */ function get_submitted_attachment_data($check_user_id = false) { - global $user, $db, $phpbb_root_path, $phpEx, $config; + global $user, $db; global $request; - $this->filename_data['filecomment'] = utf8_normalize_nfc(request_var('filecomment', '', true)); + $this->filename_data['filecomment'] = $request->variable('filecomment', '', true); $attachment_data = $request->variable('attachment_data', array(0 => array('' => '')), true, \phpbb\request\request_interface::POST); $this->attachment_data = array(); @@ -1709,28 +1854,26 @@ class parse_message extends bbcode_firstpass */ function parse_poll(&$poll) { - global $auth, $user, $config; + global $user, $config; $poll_max_options = $poll['poll_max_options']; - // Parse Poll Option text ;) + // Parse Poll Option text $tmp_message = $this->message; - $this->message = $poll['poll_option_text']; - $bbcode_bitfield = $this->bbcode_bitfield; - $poll['poll_option_text'] = $this->parse($poll['enable_bbcode'], ($config['allow_post_links']) ? $poll['enable_urls'] : false, $poll['enable_smilies'], $poll['img_status'], false, false, $config['allow_post_links'], false, 'poll'); + $poll['poll_options'] = explode("\n", trim($poll['poll_option_text'])); + $poll['poll_options_size'] = sizeof($poll['poll_options']); - $bbcode_bitfield = base64_encode(base64_decode($bbcode_bitfield) | base64_decode($this->bbcode_bitfield)); - $this->message = $tmp_message; + foreach ($poll['poll_options'] as &$poll_option) + { + $this->message = $poll_option; + $poll_option = $this->parse($poll['enable_bbcode'], ($config['allow_post_links']) ? $poll['enable_urls'] : false, $poll['enable_smilies'], $poll['img_status'], false, false, $config['allow_post_links'], false, 'poll'); + } + unset($poll_option); + $poll['poll_option_text'] = implode("\n", $poll['poll_options']); // Parse Poll Title - $tmp_message = $this->message; $this->message = $poll['poll_title']; - $this->bbcode_bitfield = $bbcode_bitfield; - - $poll['poll_options'] = explode("\n", trim($poll['poll_option_text'])); - $poll['poll_options_size'] = sizeof($poll['poll_options']); - if (!$poll['poll_title'] && $poll['poll_options_size']) { $this->warn_msg[] = $user->lang['NO_POLL_TITLE']; @@ -1748,10 +1891,6 @@ class parse_message extends bbcode_firstpass } } - $this->bbcode_bitfield = base64_encode(base64_decode($bbcode_bitfield) | base64_decode($this->bbcode_bitfield)); - $this->message = $tmp_message; - unset($tmp_message); - if (sizeof($poll['poll_options']) == 1) { $this->warn_msg[] = $user->lang['TOO_FEW_POLL_OPTIONS']; @@ -1766,6 +1905,65 @@ class parse_message extends bbcode_firstpass } $poll['poll_max_options'] = ($poll['poll_max_options'] < 1) ? 1 : (($poll['poll_max_options'] > $config['max_poll_options']) ? $config['max_poll_options'] : $poll['poll_max_options']); + + $this->message = $tmp_message; + } + + /** + * Remove nested quotes at given depth in current parsed message + * + * @param integer $max_depth Depth limit + * @return null + */ + public function remove_nested_quotes($max_depth) + { + global $phpbb_container; + + if (preg_match('#^<[rt][ >]#', $this->message)) + { + $this->message = $phpbb_container->get('text_formatter.utils')->remove_bbcode( + $this->message, + 'quote', + $max_depth + ); + + return; + } + + // Capture all [quote] and [/quote] tags + preg_match_all('(\\[/?quote(?:="(.*?)")?:' . $this->bbcode_uid . '\\])', $this->message, $matches, PREG_OFFSET_CAPTURE); + + // Iterate over the quote tags to mark the ranges that must be removed + $depth = 0; + $ranges = array(); + $start_pos = 0; + foreach ($matches[0] as $match) + { + if ($match[0][1] === '/') + { + --$depth; + if ($depth == $max_depth) + { + $end_pos = $match[1] + strlen($match[0]); + $length = $end_pos - $start_pos; + $ranges[] = array($start_pos, $length); + } + } + else + { + ++$depth; + if ($depth == $max_depth + 1) + { + $start_pos = $match[1]; + } + } + } + + foreach (array_reverse($ranges) as $range) + { + list($start_pos, $length) = $range; + $this->message = substr_replace($this->message, '', $start_pos, $length); + } } /** @@ -1779,4 +1977,36 @@ class parse_message extends bbcode_firstpass { $this->plupload = $plupload; } + + /** + * Function to perform custom bbcode validation by extensions + * can be used in bbcode_init() to assign regexp replacement + * Example: 'regexp' => array('#\[b\](.*?)\[/b\]#uise' => "\$this->validate_bbcode_by_extension('\$1')") + * + * Accepts variable number of parameters + * + * @return mixed Validation result + */ + public function validate_bbcode_by_extension() + { + global $phpbb_dispatcher; + + $return = false; + $params_array = func_get_args(); + + /** + * Event to validate bbcode with the custom validating methods + * provided by extensions + * + * @event core.validate_bbcode_by_extension + * @var array params_array Array with the function parameters + * @var mixed return Validation result to return + * + * @since 3.1.5-RC1 + */ + $vars = array('params_array', 'return'); + extract($phpbb_dispatcher->trigger_event('core.validate_bbcode_by_extension', compact($vars))); + + return $return; + } } diff --git a/phpBB/includes/questionnaire/questionnaire.php b/phpBB/includes/questionnaire/questionnaire.php index 6f2727a38c..60e63eddc4 100644 --- a/phpBB/includes/questionnaire/questionnaire.php +++ b/phpBB/includes/questionnaire/questionnaire.php @@ -1,9 +1,13 @@ <?php /** * -* @package phpBB3 -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -87,7 +91,6 @@ class phpbb_questionnaire_data_collector /** * Questionnaire PHP data provider -* @package phpBB3 */ class phpbb_questionnaire_php_data_provider { @@ -131,7 +134,6 @@ class phpbb_questionnaire_php_data_provider /** * Questionnaire System data provider -* @package phpBB3 */ class phpbb_questionnaire_system_data_provider { @@ -211,7 +213,6 @@ class phpbb_questionnaire_system_data_provider /** * Questionnaire phpBB data provider -* @package phpBB3 */ class phpbb_questionnaire_phpbb_data_provider { @@ -229,7 +230,7 @@ class phpbb_questionnaire_phpbb_data_provider if (empty($config['questionnaire_unique_id'])) { $this->unique_id = unique_id(); - set_config('questionnaire_unique_id', $this->unique_id); + $config->set('questionnaire_unique_id', $this->unique_id); } else { @@ -256,11 +257,12 @@ class phpbb_questionnaire_phpbb_data_provider */ function get_data() { - global $phpbb_root_path, $phpEx; - include("{$phpbb_root_path}config.$phpEx"); + global $phpbb_config_php_file; + + extract($phpbb_config_php_file->get_all()); unset($dbhost, $dbport, $dbname, $dbuser, $dbpasswd); // Just a precaution - $dbms = phpbb_convert_30_dbms_to_31($dbms); + $dbms = $phpbb_config_php_file->convert_30_dbms_to_31($dbms); // Only send certain config vars $config_vars = array( diff --git a/phpBB/includes/sphinxapi.php b/phpBB/includes/sphinxapi.php index 6c3b66710c..5e1f131ac2 100644 --- a/phpBB/includes/sphinxapi.php +++ b/phpBB/includes/sphinxapi.php @@ -1659,7 +1659,6 @@ class SphinxClient return false; } - $res = substr ( $response, 4 ); // just ignore length, error handling, etc $p = 0; list ( $rows, $cols ) = array_values ( unpack ( "N*N*", substr ( $response, $p, 8 ) ) ); $p += 8; diff --git a/phpBB/includes/startup.php b/phpBB/includes/startup.php index 441eaec6b1..5900016c39 100644 --- a/phpBB/includes/startup.php +++ b/phpBB/includes/startup.php @@ -1,9 +1,13 @@ <?php /** * -* @package phpBB3 -* @copyright (c) 2011 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -15,10 +19,6 @@ if (!defined('IN_PHPBB')) } // Report all errors, except notices and deprecation messages -if (!defined('E_DEPRECATED')) -{ - define('E_DEPRECATED', 8192); -} $level = E_ALL & ~E_NOTICE & ~E_DEPRECATED; error_reporting($level); @@ -65,31 +65,13 @@ function deregister_globals() { if (isset($not_unset[$varname])) { - // Hacking attempt. No point in continuing unless it's a COOKIE (so a cookie called GLOBALS doesn't lock users out completely) - if ($varname !== 'GLOBALS' || isset($_GET['GLOBALS']) || isset($_POST['GLOBALS']) || isset($_SERVER['GLOBALS']) || isset($_SESSION['GLOBALS']) || isset($_ENV['GLOBALS']) || isset($_FILES['GLOBALS'])) - { - exit; - } - else + // Hacking attempt. No point in continuing. + if (isset($_COOKIE[$varname])) { - $cookie = &$_COOKIE; - while (isset($cookie['GLOBALS'])) - { - if (!is_array($cookie['GLOBALS'])) - { - break; - } - - foreach ($cookie['GLOBALS'] as $registered_var => $value) - { - if (!isset($not_unset[$registered_var])) - { - unset($GLOBALS[$registered_var]); - } - } - $cookie = &$cookie['GLOBALS']; - } + echo "Clear your cookies. "; } + echo "Malicious variable name detected. Contact the administrator and ask them to disable register_globals."; + exit; } unset($GLOBALS[$varname]); @@ -108,7 +90,11 @@ if (version_compare(PHP_VERSION, '5.4.0-dev', '>=')) } else { - @set_magic_quotes_runtime(0); + if (get_magic_quotes_runtime()) + { + // Deactivate + @set_magic_quotes_runtime(0); + } // Be paranoid with passed vars if (@ini_get('register_globals') == '1' || strtolower(@ini_get('register_globals')) == 'on' || !function_exists('ini_get')) @@ -119,33 +105,21 @@ else define('STRIP', (get_magic_quotes_gpc()) ? true : false); } -// Prevent date/time functions from throwing E_WARNING on PHP 5.3 by setting a default timezone -if (function_exists('date_default_timezone_set') && function_exists('date_default_timezone_get')) -{ - // For PHP 5.1.0 the date/time functions have been rewritten - // and setting a timezone is required prior to calling any date/time function. - - // Since PHP 5.2.0 calls to date/time functions without having a timezone set - // result in E_STRICT errors being thrown. - // Note: We already exclude E_STRICT errors - // (to be exact: they are not included in E_ALL in PHP 5.2) - - // In PHP 5.3.0 the error level has been raised to E_WARNING which causes problems - // because we show E_WARNING errors and do not set a default timezone. - // This is because we have our own timezone handling and work in UTC only anyway. +// In PHP 5.3.0 the error level has been raised to E_WARNING which causes problems +// because we show E_WARNING errors and do not set a default timezone. +// This is because we have our own timezone handling and work in UTC only anyway. - // So what we basically want to do is set our timezone to UTC, - // but we don't know what other scripts (such as bridges) are involved, - // so we check whether a timezone is already set by calling date_default_timezone_get(). +// So what we basically want to do is set our timezone to UTC, +// but we don't know what other scripts (such as bridges) are involved, +// so we check whether a timezone is already set by calling date_default_timezone_get(). - // Unfortunately, date_default_timezone_get() itself might throw E_WARNING - // if no timezone has been set, so we have to keep it quiet with @. +// Unfortunately, date_default_timezone_get() itself might throw E_WARNING +// if no timezone has been set, so we have to keep it quiet with @. - // date_default_timezone_get() tries to guess the correct timezone first - // and then falls back to UTC when everything fails. - // We just set the timezone to whatever date_default_timezone_get() returns. - date_default_timezone_set(@date_default_timezone_get()); -} +// date_default_timezone_get() tries to guess the correct timezone first +// and then falls back to UTC when everything fails. +// We just set the timezone to whatever date_default_timezone_get() returns. +date_default_timezone_set(@date_default_timezone_get()); // Autoloading of dependencies. // Three options are supported: @@ -173,10 +147,13 @@ else { if (!file_exists($phpbb_root_path . 'vendor/autoload.php')) { - trigger_error('You have not set up composer dependencies. See http://getcomposer.org/.', E_USER_ERROR); + trigger_error( + 'Composer dependencies have not been set up yet, run ' . + "'php ../composer.phar install' from the phpBB directory to do so.", + E_USER_ERROR + ); } require($phpbb_root_path . 'vendor/autoload.php'); } -$starttime = explode(' ', microtime()); -$starttime = $starttime[1] + $starttime[0]; +$starttime = microtime(true); diff --git a/phpBB/includes/ucp/info/ucp_attachments.php b/phpBB/includes/ucp/info/ucp_attachments.php index adc7b92920..96e7956db9 100644 --- a/phpBB/includes/ucp/info/ucp_attachments.php +++ b/phpBB/includes/ucp/info/ucp_attachments.php @@ -1,15 +1,16 @@ <?php /** * -* @package ucp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class ucp_attachments_info { function module() @@ -17,7 +18,6 @@ class ucp_attachments_info return array( 'filename' => 'ucp_attachments', 'title' => 'UCP_ATTACHMENTS', - 'version' => '1.0.0', 'modes' => array( 'attachments' => array('title' => 'UCP_MAIN_ATTACHMENTS', 'auth' => 'acl_u_attach', 'cat' => array('UCP_MAIN')), ), diff --git a/phpBB/includes/ucp/info/ucp_auth_link.php b/phpBB/includes/ucp/info/ucp_auth_link.php index ee88b15ea8..57c9269c5e 100644 --- a/phpBB/includes/ucp/info/ucp_auth_link.php +++ b/phpBB/includes/ucp/info/ucp_auth_link.php @@ -1,15 +1,16 @@ <?php /** * -* @package ucp -* @copyright (c) 2013 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class ucp_auth_link_info { function module() @@ -17,9 +18,8 @@ class ucp_auth_link_info return array( 'filename' => 'ucp_auth_link', 'title' => 'UCP_AUTH_LINK', - 'version' => '1.0.0', 'modes' => array( - 'auth_link' => array('title' => 'UCP_AUTH_LINK_MANAGE', 'auth' => '', 'cat' => array('UCP_PROFILE')), + 'auth_link' => array('title' => 'UCP_AUTH_LINK_MANAGE', 'auth' => 'authmethod_oauth', 'cat' => array('UCP_PROFILE')), ), ); } diff --git a/phpBB/includes/ucp/info/ucp_groups.php b/phpBB/includes/ucp/info/ucp_groups.php index b7ffcd0971..42eb285075 100644 --- a/phpBB/includes/ucp/info/ucp_groups.php +++ b/phpBB/includes/ucp/info/ucp_groups.php @@ -1,15 +1,16 @@ <?php /** * -* @package ucp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class ucp_groups_info { function module() @@ -17,7 +18,6 @@ class ucp_groups_info return array( 'filename' => 'ucp_groups', 'title' => 'UCP_USERGROUPS', - 'version' => '1.0.0', 'modes' => array( 'membership' => array('title' => 'UCP_USERGROUPS_MEMBER', 'auth' => '', 'cat' => array('UCP_USERGROUPS')), 'manage' => array('title' => 'UCP_USERGROUPS_MANAGE', 'auth' => '', 'cat' => array('UCP_USERGROUPS')), diff --git a/phpBB/includes/ucp/info/ucp_main.php b/phpBB/includes/ucp/info/ucp_main.php index e40a0cc1c5..e967b8445f 100644 --- a/phpBB/includes/ucp/info/ucp_main.php +++ b/phpBB/includes/ucp/info/ucp_main.php @@ -1,15 +1,16 @@ <?php /** * -* @package ucp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class ucp_main_info { function module() @@ -17,7 +18,6 @@ class ucp_main_info return array( 'filename' => 'ucp_main', 'title' => 'UCP_MAIN', - 'version' => '1.0.0', 'modes' => array( 'front' => array('title' => 'UCP_MAIN_FRONT', 'auth' => '', 'cat' => array('UCP_MAIN')), 'subscribed' => array('title' => 'UCP_MAIN_SUBSCRIBED', 'auth' => '', 'cat' => array('UCP_MAIN')), diff --git a/phpBB/includes/ucp/info/ucp_notifications.php b/phpBB/includes/ucp/info/ucp_notifications.php index 98d8b9db61..94e0467ccb 100644 --- a/phpBB/includes/ucp/info/ucp_notifications.php +++ b/phpBB/includes/ucp/info/ucp_notifications.php @@ -1,15 +1,16 @@ <?php /** * -* @package notifications -* @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class ucp_notifications_info { function module() @@ -17,10 +18,9 @@ class ucp_notifications_info return array( 'filename' => 'ucp_notifications', 'title' => 'UCP_NOTIFICATION_OPTIONS', - 'version' => '1.0.0', 'modes' => array( 'notification_options' => array('title' => 'UCP_NOTIFICATION_OPTIONS', 'auth' => '', 'cat' => array('UCP_PREFS')), - 'notification_list' => array('title' => 'UCP_NOTIFICATION_LIST', 'auth' => '', 'cat' => array('UCP_MAIN')), + 'notification_list' => array('title' => 'UCP_NOTIFICATION_LIST', 'auth' => 'cfg_allow_board_notifications', 'cat' => array('UCP_MAIN')), ), ); } diff --git a/phpBB/includes/ucp/info/ucp_pm.php b/phpBB/includes/ucp/info/ucp_pm.php index a80de21999..26bd670fc5 100644 --- a/phpBB/includes/ucp/info/ucp_pm.php +++ b/phpBB/includes/ucp/info/ucp_pm.php @@ -1,14 +1,16 @@ <?php /** -* @package ucp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +* 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. * */ -/** -* @package module_install -*/ class ucp_pm_info { function module() @@ -16,7 +18,6 @@ class ucp_pm_info return array( 'filename' => 'ucp_pm', 'title' => 'UCP_PM', - 'version' => '1.0.0', 'modes' => array( 'view' => array('title' => 'UCP_PM_VIEW', 'auth' => 'cfg_allow_privmsg', 'display' => false, 'cat' => array('UCP_PM')), 'compose' => array('title' => 'UCP_PM_COMPOSE', 'auth' => 'cfg_allow_privmsg', 'cat' => array('UCP_PM')), diff --git a/phpBB/includes/ucp/info/ucp_prefs.php b/phpBB/includes/ucp/info/ucp_prefs.php index 91fbd7a14c..4793aa2649 100644 --- a/phpBB/includes/ucp/info/ucp_prefs.php +++ b/phpBB/includes/ucp/info/ucp_prefs.php @@ -1,15 +1,16 @@ <?php /** * -* @package ucp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class ucp_prefs_info { function module() @@ -17,7 +18,6 @@ class ucp_prefs_info return array( 'filename' => 'ucp_prefs', 'title' => 'UCP_PREFS', - 'version' => '1.0.0', 'modes' => array( 'personal' => array('title' => 'UCP_PREFS_PERSONAL', 'auth' => '', 'cat' => array('UCP_PREFS')), 'post' => array('title' => 'UCP_PREFS_POST', 'auth' => '', 'cat' => array('UCP_PREFS')), diff --git a/phpBB/includes/ucp/info/ucp_profile.php b/phpBB/includes/ucp/info/ucp_profile.php index e974cea713..fc2792224d 100644 --- a/phpBB/includes/ucp/info/ucp_profile.php +++ b/phpBB/includes/ucp/info/ucp_profile.php @@ -1,15 +1,16 @@ <?php /** * -* @package ucp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class ucp_profile_info { function module() @@ -17,7 +18,6 @@ class ucp_profile_info return array( 'filename' => 'ucp_profile', 'title' => 'UCP_PROFILE', - 'version' => '1.0.0', 'modes' => array( 'profile_info' => array('title' => 'UCP_PROFILE_PROFILE_INFO', 'auth' => 'acl_u_chgprofileinfo', 'cat' => array('UCP_PROFILE')), 'signature' => array('title' => 'UCP_PROFILE_SIGNATURE', 'auth' => 'acl_u_sig', 'cat' => array('UCP_PROFILE')), diff --git a/phpBB/includes/ucp/info/ucp_zebra.php b/phpBB/includes/ucp/info/ucp_zebra.php index db57102aae..69274c2866 100644 --- a/phpBB/includes/ucp/info/ucp_zebra.php +++ b/phpBB/includes/ucp/info/ucp_zebra.php @@ -1,15 +1,16 @@ <?php /** * -* @package ucp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ -/** -* @package module_install -*/ class ucp_zebra_info { function module() @@ -17,7 +18,6 @@ class ucp_zebra_info return array( 'filename' => 'ucp_zebra', 'title' => 'UCP_ZEBRA', - 'version' => '1.0.0', 'modes' => array( 'friends' => array('title' => 'UCP_ZEBRA_FRIENDS', 'auth' => '', 'cat' => array('UCP_ZEBRA')), 'foes' => array('title' => 'UCP_ZEBRA_FOES', 'auth' => '', 'cat' => array('UCP_ZEBRA')), diff --git a/phpBB/includes/ucp/ucp_activate.php b/phpBB/includes/ucp/ucp_activate.php index 2a94acbe02..00044340df 100644 --- a/phpBB/includes/ucp/ucp_activate.php +++ b/phpBB/includes/ucp/ucp_activate.php @@ -1,9 +1,13 @@ <?php /** * -* @package ucp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -18,7 +22,6 @@ if (!defined('IN_PHPBB')) /** * ucp_activate * User activation -* @package ucp */ class ucp_activate { @@ -26,11 +29,11 @@ class ucp_activate function main($id, $mode) { - global $config, $phpbb_root_path, $phpEx; - global $db, $user, $auth, $template, $phpbb_container; + global $config, $phpbb_root_path, $phpEx, $request; + global $db, $user, $auth, $phpbb_container, $phpbb_log, $phpbb_dispatcher; - $user_id = request_var('u', 0); - $key = request_var('k', ''); + $user_id = $request->variable('u', 0); + $key = $request->variable('k', ''); $sql = 'SELECT user_id, username, user_type, user_email, user_newpasswd, user_lang, user_notify_type, user_actkey, user_inactive_reason FROM ' . USERS_TABLE . " @@ -75,7 +78,6 @@ class ucp_activate 'user_actkey' => '', 'user_password' => $user_row['user_newpasswd'], 'user_newpasswd' => '', - 'user_pass_convert' => 0, 'user_login_attempts' => 0, ); @@ -84,7 +86,10 @@ class ucp_activate WHERE user_id = ' . $user_row['user_id']; $db->sql_query($sql); - add_log('user', $user_row['user_id'], 'LOG_USER_NEW_PASSWORD', $user_row['username']); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_NEW_PASSWORD', false, array( + 'reportee_id' => $user_row['user_id'], + $user_row['username'] + )); } if (!$update_password) @@ -99,17 +104,21 @@ class ucp_activate $db->sql_query($sql); // Create the correct logs - add_log('user', $user_row['user_id'], 'LOG_USER_ACTIVE_USER'); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_ACTIVE_USER', false, array( + 'reportee_id' => $user_row['user_id'] + )); + if ($auth->acl_get('a_user')) { - add_log('admin', 'LOG_USER_ACTIVE', $user_row['username']); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_ACTIVE', false, array($user_row['username'])); } } if ($config['require_activation'] == USER_ACTIVATION_ADMIN && !$update_password) { + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); - $phpbb_notifications->delete_notifications('admin_activate_user', $user_row['user_id']); + $phpbb_notifications->delete_notifications('notification.type.admin_activate_user', $user_row['user_id']); include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); @@ -141,6 +150,17 @@ class ucp_activate } } + /** + * This event can be used to modify data after user account's activation + * + * @event core.ucp_activate_after + * @var array user_row Array with some user data + * @var string message Language string of the message that will be displayed to the user + * @since 3.1.6-RC1 + */ + $vars = array('user_row', 'message'); + extract($phpbb_dispatcher->trigger_event('core.ucp_activate_after', compact($vars))); + meta_refresh(3, append_sid("{$phpbb_root_path}index.$phpEx")); trigger_error($user->lang[$message]); } diff --git a/phpBB/includes/ucp/ucp_attachments.php b/phpBB/includes/ucp/ucp_attachments.php index 6a5b48a181..66c3109b3d 100644 --- a/phpBB/includes/ucp/ucp_attachments.php +++ b/phpBB/includes/ucp/ucp_attachments.php @@ -1,9 +1,13 @@ <?php /** * -* @package ucp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -18,7 +22,6 @@ if (!defined('IN_PHPBB')) /** * ucp_attachments * User attachments -* @package ucp */ class ucp_attachments { @@ -26,15 +29,14 @@ class ucp_attachments function main($id, $mode) { - global $template, $user, $db, $config, $phpEx, $phpbb_root_path, $phpbb_container; + global $template, $user, $db, $config, $phpEx, $phpbb_root_path, $phpbb_container, $request; - $start = request_var('start', 0); - $sort_key = request_var('sk', 'a'); - $sort_dir = request_var('sd', 'a'); + $start = $request->variable('start', 0); + $sort_key = $request->variable('sk', 'a'); + $sort_dir = $request->variable('sd', 'a'); $delete = (isset($_POST['delete'])) ? true : false; - $confirm = (isset($_POST['confirm'])) ? true : false; - $delete_ids = array_keys(request_var('attachment', array(0))); + $delete_ids = array_keys($request->variable('attachment', array(0))); if ($delete && sizeof($delete_ids)) { @@ -67,12 +69,10 @@ class ucp_attachments if (confirm_box(true)) { - if (!function_exists('delete_attachments')) - { - include_once($phpbb_root_path . 'includes/functions_admin.' . $phpEx); - } - - delete_attachments('attach', $delete_ids); + /** @var \phpbb\attachment\manager $attachment_manager */ + $attachment_manager = $phpbb_container->get('attachment.manager'); + $attachment_manager->delete('attach', $delete_ids); + unset($attachment_manager); meta_refresh(3, $this->u_action); $message = ((sizeof($delete_ids) == 1) ? $user->lang['ATTACHMENT_DELETED'] : $user->lang['ATTACHMENTS_DELETED']) . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>'); @@ -120,6 +120,7 @@ class ucp_attachments $db->sql_freeresult($result); // Ensure start is a valid value + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); $start = $pagination->validate_start($start, $config['topics_per_page'], $num_attachments); @@ -179,6 +180,7 @@ class ucp_attachments $template->assign_vars(array( 'TOTAL_ATTACHMENTS' => $num_attachments, + 'NUM_ATTACHMENTS' => $user->lang('NUM_ATTACHMENTS', $num_attachments), 'L_TITLE' => $user->lang['UCP_ATTACHMENTS'], diff --git a/phpBB/includes/ucp/ucp_auth_link.php b/phpBB/includes/ucp/ucp_auth_link.php index b86c4c8d52..08aacdef3a 100644 --- a/phpBB/includes/ucp/ucp_auth_link.php +++ b/phpBB/includes/ucp/ucp_auth_link.php @@ -1,9 +1,13 @@ <?php /** * -* @package ucp -* @copyright (c) 2013 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -30,11 +34,13 @@ class ucp_auth_link */ public function main($id, $mode) { - global $config, $request, $template, $phpbb_container, $user; + global $request, $template, $phpbb_container, $user; $error = array(); - $auth_provider = $phpbb_container->get('auth.provider.' . $config['auth_method']); + /* @var $provider_collection \phpbb\auth\provider_collection */ + $provider_collection = $phpbb_container->get('auth.provider_collection'); + $auth_provider = $provider_collection->get_provider(); // confirm that the auth provider supports this page $provider_data = $auth_provider->get_auth_link_data(); diff --git a/phpBB/includes/ucp/ucp_confirm.php b/phpBB/includes/ucp/ucp_confirm.php index aafb92d8e4..cdf4de65fd 100644 --- a/phpBB/includes/ucp/ucp_confirm.php +++ b/phpBB/includes/ucp/ucp_confirm.php @@ -1,9 +1,13 @@ <?php /** * -* @package VC -* @copyright (c) 2005 2008 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -25,8 +29,6 @@ if (!defined('IN_PHPBB')) * to that licence. Do not incorporate this within software * released or distributed in any way under a licence other * than the GPL. We will be watching ... ;) -* -* @package VC */ class ucp_confirm { @@ -34,11 +36,10 @@ class ucp_confirm function main($id, $mode) { - global $db, $user, $phpbb_root_path, $config, $phpEx; + global $config, $phpbb_container, $request; - include($phpbb_root_path . 'includes/captcha/captcha_factory.' . $phpEx); - $captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']); - $captcha->init(request_var('type', 0)); + $captcha = $phpbb_container->get('captcha.factory')->get_instance($config['captcha_plugin']); + $captcha->init($request->variable('type', 0)); $captcha->execute(); garbage_collection(); diff --git a/phpBB/includes/ucp/ucp_groups.php b/phpBB/includes/ucp/ucp_groups.php index 373d9433b2..1273ea9723 100644 --- a/phpBB/includes/ucp/ucp_groups.php +++ b/phpBB/includes/ucp/ucp_groups.php @@ -1,9 +1,13 @@ <?php /** * -* @package ucp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -17,7 +21,6 @@ if (!defined('IN_PHPBB')) /** * ucp_groups -* @package ucp */ class ucp_groups { @@ -27,16 +30,17 @@ class ucp_groups { global $config, $phpbb_root_path, $phpEx, $phpbb_admin_path; global $db, $user, $auth, $cache, $template; - global $request, $phpbb_container; + global $request, $phpbb_container, $phpbb_log; $user->add_lang('groups'); $return_page = '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $this->u_action . '">', '</a>'); - $mark_ary = request_var('mark', array(0)); + $mark_ary = $request->variable('mark', array(0)); $submit = $request->variable('submit', false, false, \phpbb\request\request_interface::POST); - $delete = $request->variable('delete', false, false, \phpbb\request\request_interface::POST); - $error = $data = array(); + + /** @var \phpbb\group\helper $group_helper */ + $group_helper = $phpbb_container->get('group_helper'); switch ($mode) { @@ -46,8 +50,8 @@ class ucp_groups if ($submit || isset($_POST['change_default'])) { - $action = (isset($_POST['change_default'])) ? 'change_default' : request_var('action', ''); - $group_id = ($action == 'change_default') ? request_var('default', 0) : request_var('selected', 0); + $action = (isset($_POST['change_default'])) ? 'change_default' : $request->variable('action', ''); + $group_id = ($action == 'change_default') ? $request->variable('default', 0) : $request->variable('selected', 0); if (!$group_id) { @@ -62,7 +66,7 @@ class ucp_groups $group_row = array(); while ($row = $db->sql_fetchrow($result)) { - $row['group_name'] = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']; + $row['group_name'] = $group_helper->get_name($row['group_name']); $group_row[$row['group_id']] = $row; } $db->sql_freeresult($result); @@ -96,7 +100,10 @@ class ucp_groups { group_user_attributes('default', $group_id, $user->data['user_id']); - add_log('user', $user->data['user_id'], 'LOG_USER_GROUP_CHANGE', sprintf($user->lang['USER_GROUP_CHANGE'], $group_row[$user->data['group_id']]['group_name'], $group_row[$group_id]['group_name'])); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_GROUP_CHANGE', false, array( + 'reportee_id' => $user->data['user_id'], + sprintf($user->lang['USER_GROUP_CHANGE'], $group_row[$user->data['group_id']]['group_name'], $group_row[$group_id]['group_name']) + )); meta_refresh(3, $this->u_action); trigger_error($user->lang['CHANGED_DEFAULT_GROUP'] . $return_page); @@ -143,7 +150,10 @@ class ucp_groups { group_user_del($group_id, $user->data['user_id']); - add_log('user', $user->data['user_id'], 'LOG_USER_GROUP_RESIGN', $group_row[$group_id]['group_name']); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_GROUP_RESIGN', false, array( + 'reportee_id' => $user->data['user_id'], + $group_row[$group_id]['group_name'] + )); meta_refresh(3, $this->u_action); trigger_error($user->lang[($row['user_pending']) ? 'GROUP_RESIGNED_PENDING' : 'GROUP_RESIGNED_MEMBERSHIP'] . $return_page); @@ -199,7 +209,10 @@ class ucp_groups group_user_add($group_id, $user->data['user_id'], false, false, false, 0, 1); } - add_log('user', $user->data['user_id'], 'LOG_USER_GROUP_JOIN' . (($group_row[$group_id]['group_type'] == GROUP_FREE) ? '' : '_PENDING'), $group_row[$group_id]['group_name']); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_GROUP_JOIN' . (($group_row[$group_id]['group_type'] == GROUP_FREE) ? '' : '_PENDING'), false, array( + 'reportee_id' => $user->data['user_id'], + $group_row[$group_id]['group_name'] + )); meta_refresh(3, $this->u_action); trigger_error($user->lang[($group_row[$group_id]['group_type'] == GROUP_FREE) ? 'GROUP_JOINED' : 'GROUP_JOINED_PENDING'] . $return_page); @@ -234,7 +247,10 @@ class ucp_groups { group_user_attributes('demote', $group_id, $user->data['user_id']); - add_log('user', $user->data['user_id'], 'LOG_USER_GROUP_DEMOTE', $group_row[$group_id]['group_name']); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_GROUP_DEMOTE', false, array( + 'reportee_id' => $user->data['user_id'], + $group_row[$group_id]['group_name'] + )); meta_refresh(3, $this->u_action); trigger_error($user->lang['USER_GROUP_DEMOTED'] . $return_page); @@ -292,7 +308,7 @@ class ucp_groups $template->assign_block_vars($block, array( 'GROUP_ID' => $row['group_id'], - 'GROUP_NAME' => ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'], + 'GROUP_NAME' => $group_helper->get_name($row['group_name']), 'GROUP_DESC' => ($row['group_type'] <> GROUP_SPECIAL) ? generate_text_for_display($row['group_desc'], $row['group_desc_uid'], $row['group_desc_bitfield'], $row['group_desc_options']) : $user->lang['GROUP_IS_SPECIAL'], 'GROUP_SPECIAL' => ($row['group_type'] <> GROUP_SPECIAL) ? false : true, 'GROUP_STATUS' => $user->lang['GROUP_IS_' . $group_status], @@ -346,7 +362,7 @@ class ucp_groups $template->assign_block_vars('nonmember', array( 'GROUP_ID' => $row['group_id'], - 'GROUP_NAME' => ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'], + 'GROUP_NAME' => $group_helper->get_name($row['group_name']), 'GROUP_DESC' => ($row['group_type'] <> GROUP_SPECIAL) ? generate_text_for_display($row['group_desc'], $row['group_desc_uid'], $row['group_desc_bitfield'], $row['group_desc_options']) : $user->lang['GROUP_IS_SPECIAL'], 'GROUP_SPECIAL' => ($row['group_type'] <> GROUP_SPECIAL) ? false : true, 'GROUP_CLOSED' => ($row['group_type'] <> GROUP_CLOSED || $auth->acl_gets('a_group', 'a_groupadd', 'a_groupdel')) ? false : true, @@ -376,8 +392,8 @@ class ucp_groups case 'manage': $this->page_title = 'UCP_USERGROUPS_MANAGE'; - $action = (isset($_POST['addusers'])) ? 'addusers' : request_var('action', ''); - $group_id = request_var('g', 0); + $action = (isset($_POST['addusers'])) ? 'addusers' : $request->variable('action', ''); + $group_id = $request->variable('g', 0); include($phpbb_root_path . 'includes/functions_display.' . $phpEx); @@ -411,7 +427,7 @@ class ucp_groups $avatar = phpbb_get_group_avatar($group_row, 'GROUP_AVATAR', true); $template->assign_vars(array( - 'GROUP_NAME' => ($group_type == GROUP_SPECIAL) ? $user->lang['G_' . $group_name] : $group_name, + 'GROUP_NAME' => $group_helper->get_name($group_name), 'GROUP_INTERNAL_NAME' => $group_name, 'GROUP_COLOUR' => (isset($group_row['group_colour'])) ? $group_row['group_colour'] : '', 'GROUP_DESC_DISP' => generate_text_for_display($group_row['group_desc'], $group_row['group_desc_uid'], $group_row['group_desc_bitfield'], $group_row['group_desc_options']), @@ -444,11 +460,8 @@ class ucp_groups trigger_error($user->lang['NOT_LEADER_OF_GROUP'] . $return_page); } - $file_uploads = (@ini_get('file_uploads') || strtolower(@ini_get('file_uploads')) == 'on') ? true : false; $user->add_lang(array('acp/groups', 'acp/common')); - $data = $submit_ary = array(); - $update = (isset($_POST['update'])) ? true : false; $error = array(); @@ -461,6 +474,7 @@ class ucp_groups if ($config['allow_avatar']) { + /* @var $phpbb_avatar_manager \phpbb\avatar\manager */ $phpbb_avatar_manager = $phpbb_container->get('avatar.manager'); $avatar_drivers = $phpbb_avatar_manager->get_enabled_drivers(); @@ -468,23 +482,46 @@ class ucp_groups $avatar_data = \phpbb\avatar\manager::clean_row($group_row, 'group'); } + // Handle deletion of avatars + if ($request->is_set_post('avatar_delete')) + { + if (confirm_box(true)) + { + $phpbb_avatar_manager->handle_avatar_delete($db, $user, $avatar_data, GROUPS_TABLE, 'group_'); + $cache->destroy('sql', GROUPS_TABLE); + + $message = ($action == 'edit') ? 'GROUP_UPDATED' : 'GROUP_CREATED'; + trigger_error($user->lang[$message] . $return_page); + } + else + { + confirm_box(false, $user->lang('CONFIRM_AVATAR_DELETE'), build_hidden_fields(array( + 'avatar_delete' => true, + 'i' => $id, + 'mode' => $mode, + 'g' => $group_id, + 'action' => $action)) + ); + } + } + // Did we submit? if ($update) { - $group_name = utf8_normalize_nfc(request_var('group_name', '', true)); - $group_desc = utf8_normalize_nfc(request_var('group_desc', '', true)); - $group_type = request_var('group_type', GROUP_FREE); + $group_name = $request->variable('group_name', '', true); + $group_desc = $request->variable('group_desc', '', true); + $group_type = $request->variable('group_type', GROUP_FREE); - $allow_desc_bbcode = request_var('desc_parse_bbcode', false); - $allow_desc_urls = request_var('desc_parse_urls', false); - $allow_desc_smilies = request_var('desc_parse_smilies', false); + $allow_desc_bbcode = $request->variable('desc_parse_bbcode', false); + $allow_desc_urls = $request->variable('desc_parse_urls', false); + $allow_desc_smilies = $request->variable('desc_parse_smilies', false); $submit_ary = array( - 'colour' => request_var('group_colour', ''), - 'rank' => request_var('group_rank', 0), + 'colour' => $request->variable('group_colour', ''), + 'rank' => $request->variable('group_rank', 0), 'receive_pm' => isset($_REQUEST['group_receive_pm']) ? 1 : 0, - 'message_limit' => request_var('group_message_limit', 0), - 'max_recipients'=> request_var('group_max_recipients', 0), + 'message_limit' => $request->variable('group_message_limit', 0), + 'max_recipients'=> $request->variable('group_max_recipients', 0), 'legend' => $group_row['group_legend'], 'teampage' => $group_row['group_teampage'], ); @@ -493,7 +530,6 @@ class ucp_groups { // Handle avatar $driver_name = $phpbb_avatar_manager->clean_driver_name($request->variable('avatar_driver', '')); - $config_name = preg_replace('#^avatar\.driver.#', '', $driver_name); if (in_array($driver_name, $avatar_drivers) && !$request->is_set_post('avatar_delete')) { @@ -507,19 +543,6 @@ class ucp_groups $submit_ary = array_merge($submit_ary, $result); } } - else - { - if ($driver = $phpbb_avatar_manager->get_driver($avatar_data['avatar_type'])) - { - $driver->delete($avatar_data); - } - - // Removing the avatar - $submit_ary['avatar_type'] = ''; - $submit_ary['avatar'] = ''; - $submit_ary['avatar_width'] = 0; - $submit_ary['avatar_height'] = 0; - } // Merge any avatars errors into the primary error array $error = array_merge($error, $phpbb_avatar_manager->localize_errors($user, $avatar_error)); @@ -595,7 +618,6 @@ class ucp_groups } else if (!$group_id) { - $group_name = utf8_normalize_nfc(request_var('group_name', '', true)); $group_desc_data = array( 'text' => '', 'allow_bbcode' => true, @@ -724,7 +746,7 @@ class ucp_groups } $user->add_lang(array('acp/groups', 'acp/common')); - $start = request_var('start', 0); + $start = $request->variable('start', 0); // Grab the leaders - always, on every page... $sql = 'SELECT u.user_id, u.username, u.username_clean, u.user_colour, u.user_regdate, u.user_posts, u.group_id, ug.group_leader, ug.user_pending @@ -813,6 +835,7 @@ class ucp_groups $s_action_options .= '<option value="' . $option . '">' . $user->lang['GROUP_' . $lang] . '</option>'; } + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); $base_url = $this->u_action . "&action=$action&g=$group_id"; $start = $pagination->validate_start($start, $config['topics_per_page'], $total_members); @@ -874,7 +897,7 @@ class ucp_groups trigger_error($user->lang['NOT_LEADER_OF_GROUP'] . $return_page); } - $group_row['group_name'] = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name']; + $group_row['group_name'] = $group_helper->get_name($group_row['group_name']); if (confirm_box(true)) { @@ -953,7 +976,7 @@ class ucp_groups trigger_error($user->lang['NOT_LEADER_OF_GROUP'] . $return_page); } - $group_row['group_name'] = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name']; + $group_row['group_name'] = $group_helper->get_name($group_row['group_name']); if (confirm_box(true)) { @@ -991,7 +1014,7 @@ class ucp_groups $user->add_lang(array('acp/groups', 'acp/common')); - $names = utf8_normalize_nfc(request_var('usernames', '', true)); + $names = $request->variable('usernames', '', true); if (!$group_id) { @@ -1015,9 +1038,9 @@ class ucp_groups } $name_ary = array_unique(explode("\n", $names)); - $group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name']; + $group_name = $group_helper->get_name($group_row['group_name']); - $default = request_var('default', 0); + $default = $request->variable('default', 0); if (confirm_box(true)) { @@ -1061,7 +1084,7 @@ class ucp_groups while ($value = $db->sql_fetchrow($result)) { $template->assign_block_vars('leader', array( - 'GROUP_NAME' => ($value['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $value['group_name']] : $value['group_name'], + 'GROUP_NAME' => $group_helper->get_name($value['group_name']), 'GROUP_DESC' => generate_text_for_display($value['group_desc'], $value['group_desc_uid'], $value['group_desc_bitfield'], $value['group_desc_options']), 'GROUP_TYPE' => $value['group_type'], 'GROUP_ID' => $value['group_id'], diff --git a/phpBB/includes/ucp/ucp_login_link.php b/phpBB/includes/ucp/ucp_login_link.php index 80a553953d..f4d47e30bb 100644 --- a/phpBB/includes/ucp/ucp_login_link.php +++ b/phpBB/includes/ucp/ucp_login_link.php @@ -1,9 +1,13 @@ <?php /** * -* @package ucp -* @copyright (c) 2013 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -19,7 +23,6 @@ if (!defined('IN_PHPBB')) * ucp_login_link * Allows users of external accounts link those accounts to their phpBB accounts * during an attempted login. -* @package ucp */ class ucp_login_link { @@ -36,7 +39,7 @@ class ucp_login_link */ function main($id, $mode) { - global $config, $phpbb_container, $request, $template, $user; + global $phpbb_container, $request, $template, $user; global $phpbb_root_path, $phpEx; // Initialize necessary variables @@ -54,8 +57,9 @@ class ucp_login_link } // Use the auth_provider requested even if different from configured - $auth_provider = 'auth.provider.' . $request->variable('auth_provider', $config['auth_method']); - $auth_provider = $phpbb_container->get($auth_provider); + /* @var $provider_collection \phpbb\auth\provider_collection */ + $provider_collection = $phpbb_container->get('auth.provider_collection'); + $auth_provider = $provider_collection->get_provider($request->variable('auth_provider', '')); // Set the link_method to login_link $data['link_method'] = 'login_link'; @@ -72,7 +76,7 @@ class ucp_login_link { if ($request->is_set_post('login')) { - $login_username = $request->variable('login_username', '', false, \phpbb\request\request_interface::POST); + $login_username = $request->variable('login_username', '', true, \phpbb\request\request_interface::POST); $login_password = $request->untrimmed_variable('login_password', '', true, \phpbb\request\request_interface::POST); $login_result = $auth_provider->login($login_username, $login_password); @@ -95,7 +99,7 @@ class ucp_login_link else { // Finish login - $result = $user->session_create($login_result['user_row']['user_id'], false, false, true); + $user->session_create($login_result['user_row']['user_id'], false, false, true); // Perform a redirect as the account has been linked $this->perform_redirect(); @@ -178,7 +182,7 @@ class ucp_login_link */ protected function process_login_result($result) { - global $config, $request, $template, $user; + global $config, $template, $user, $phpbb_container; $login_error = null; @@ -194,7 +198,7 @@ class ucp_login_link { case LOGIN_ERROR_ATTEMPTS: - $captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']); + $captcha = $phpbb_container->get('captcha.factory')->get_instance($config['captcha_plugin']); $captcha->init(CONFIRM_LOGIN); $template->assign_vars(array( diff --git a/phpBB/includes/ucp/ucp_main.php b/phpBB/includes/ucp/ucp_main.php index 3ccf3e3545..217d46b767 100644 --- a/phpBB/includes/ucp/ucp_main.php +++ b/phpBB/includes/ucp/ucp_main.php @@ -1,9 +1,13 @@ <?php /** * -* @package ucp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -18,7 +22,6 @@ if (!defined('IN_PHPBB')) /** * ucp_main * UCP Front Panel -* @package ucp */ class ucp_main { @@ -78,7 +81,7 @@ class ucp_main FROM $sql_from WHERE t.topic_type = " . POST_GLOBAL . ' AND ' . $db->sql_in_set('t.forum_id', $forum_ary) . ' - ORDER BY t.topic_last_post_time DESC'; + ORDER BY t.topic_last_post_time DESC, t.topic_last_post_id DESC'; $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) @@ -189,7 +192,7 @@ class ucp_main $template->assign_vars(array( 'USER_COLOR' => (!empty($user->data['user_colour'])) ? $user->data['user_colour'] : '', 'JOINED' => $user->format_date($user->data['user_regdate']), - 'VISITED' => (empty($last_visit)) ? ' - ' : $user->format_date($last_visit), + 'LAST_ACTIVE' => (empty($last_active)) ? ' - ' : $user->format_date($last_active), 'WARNINGS' => ($user->data['user_warnings']) ? $user->data['user_warnings'] : 0, 'POSTS' => ($user->data['user_posts']) ? $user->data['user_posts'] : 0, 'POSTS_DAY' => $user->lang('POST_DAY', $posts_per_day), @@ -216,9 +219,8 @@ class ucp_main { if (check_form_key('ucp_front_subscribed')) { - $forums = array_keys(request_var('f', array(0 => 0))); - $topics = array_keys(request_var('t', array(0 => 0))); - $msg = ''; + $forums = array_keys($request->variable('f', array(0 => 0))); + $topics = array_keys($request->variable('t', array(0 => 0))); if (sizeof($forums) || sizeof($topics)) { @@ -354,6 +356,8 @@ class ucp_main 'LAST_POST_AUTHOR_FULL' => get_username_string('full', $row['forum_last_poster_id'], $row['forum_last_poster_name'], $row['forum_last_poster_colour']), 'U_LAST_POST_AUTHOR' => get_username_string('profile', $row['forum_last_poster_id'], $row['forum_last_poster_name'], $row['forum_last_poster_colour']), + 'S_UNREAD_FORUM' => $unread_forum, + 'U_LAST_POST' => $last_post_url, 'U_VIEWFORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $row['forum_id'])) ); @@ -396,7 +400,7 @@ class ucp_main if (isset($_POST['unbookmark'])) { $s_hidden_fields = array('unbookmark' => 1); - $topics = (isset($_POST['t'])) ? array_keys(request_var('t', array(0 => 0))) : array(); + $topics = (isset($_POST['t'])) ? array_keys($request->variable('t', array(0 => 0))) : array(); $url = $this->u_action; if (!sizeof($topics)) @@ -452,7 +456,7 @@ class ucp_main { if (check_form_key('ucp_draft')) { - $drafts = array_keys(request_var('d', array(0 => 0))); + $drafts = array_keys($request->variable('d', array(0 => 0))); if (sizeof($drafts)) { @@ -475,8 +479,8 @@ class ucp_main if ($submit && $edit) { - $draft_subject = utf8_normalize_nfc(request_var('subject', '', true)); - $draft_message = utf8_normalize_nfc(request_var('message', '', true)); + $draft_subject = $request->variable('subject', '', true); + $draft_message = $request->variable('message', '', true); if (check_form_key('ucp_draft')) { if ($draft_message && $draft_subject) @@ -617,7 +621,6 @@ class ucp_main break; } - $template->assign_vars(array( 'L_TITLE' => $user->lang['UCP_MAIN_' . strtoupper($mode)], @@ -639,11 +642,12 @@ class ucp_main */ function assign_topiclist($mode = 'subscribed', $forbidden_forum_ary = array()) { - global $user, $db, $template, $config, $cache, $auth, $phpbb_root_path, $phpEx, $phpbb_container; + global $user, $db, $template, $config, $cache, $auth, $phpbb_root_path, $phpEx, $phpbb_container, $request; - $table = ($mode == 'subscribed') ? TOPICS_WATCH_TABLE : BOOKMARKS_TABLE; - $start = request_var('start', 0); + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); + $table = ($mode == 'subscribed') ? TOPICS_WATCH_TABLE : BOOKMARKS_TABLE; + $start = $request->variable('start', 0); // Grab icons $icons = $cache->obtain_icons(); @@ -689,8 +693,7 @@ class ucp_main AND t.topic_id = tw.topic_id AND ' . $db->sql_in_set('t.forum_id', $forbidden_forum_ary, true, true), - - 'ORDER_BY' => 't.topic_last_post_time DESC' + 'ORDER_BY' => 't.topic_last_post_time DESC, t.topic_last_post_id DESC' ); $sql_array['LEFT_JOIN'] = array(); @@ -707,7 +710,7 @@ class ucp_main 'WHERE' => 'b.user_id = ' . $user->data['user_id'] . ' AND ' . $db->sql_in_set('f.forum_id', $forbidden_forum_ary, true, true), - 'ORDER_BY' => 't.topic_last_post_time DESC' + 'ORDER_BY' => 't.topic_last_post_time DESC, t.topic_last_post_id DESC' ); $sql_array['LEFT_JOIN'] = array(); @@ -766,6 +769,7 @@ class ucp_main } } + /* @var $phpbb_content_visibility \phpbb\content_visibility */ $phpbb_content_visibility = $phpbb_container->get('content.visibility'); foreach ($topic_list as $topic_id) diff --git a/phpBB/includes/ucp/ucp_notifications.php b/phpBB/includes/ucp/ucp_notifications.php index 7c487b9073..51bd77bd4c 100644 --- a/phpBB/includes/ucp/ucp_notifications.php +++ b/phpBB/includes/ucp/ucp_notifications.php @@ -1,9 +1,13 @@ <?php /** * -* @package notifications -* @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -30,7 +34,10 @@ class ucp_notifications $form_time = $request->variable('form_time', 0); $form_time = ($form_time <= 0 || $form_time > time()) ? time() : $form_time; + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); + + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); switch ($mode) @@ -48,30 +55,21 @@ class ucp_notifications $notification_methods = $phpbb_notifications->get_subscription_methods(); - foreach($phpbb_notifications->get_subscription_types() as $group => $subscription_types) + foreach ($phpbb_notifications->get_subscription_types() as $group => $subscription_types) { - foreach($subscription_types as $type => $data) + foreach ($subscription_types as $type => $data) { - foreach($notification_methods as $method => $method_data) + foreach ($notification_methods as $method => $method_data) { - if ($request->is_set_post($type . '_' . $method_data['id']) && (!isset($subscriptions[$type]) || !in_array($method_data['id'], $subscriptions[$type]))) + if ($request->is_set_post(str_replace('.', '_', $type . '_' . $method_data['id'])) && (!isset($subscriptions[$type]) || !in_array($method_data['id'], $subscriptions[$type]))) { $phpbb_notifications->add_subscription($type, 0, $method_data['id']); } - else if (!$request->is_set_post($type . '_' . $method_data['id']) && isset($subscriptions[$type]) && in_array($method_data['id'], $subscriptions[$type])) + else if (!$request->is_set_post(str_replace('.', '_', $type . '_' . $method_data['id'])) && isset($subscriptions[$type]) && in_array($method_data['id'], $subscriptions[$type])) { $phpbb_notifications->delete_subscription($type, 0, $method_data['id']); } } - - if ($request->is_set_post($type . '_notification') && !isset($subscriptions[$type])) - { - $phpbb_notifications->add_subscription($type); - } - else if (!$request->is_set_post($type . '_notification') && isset($subscriptions[$type])) - { - $phpbb_notifications->delete_subscription($type); - } } } @@ -91,35 +89,25 @@ class ucp_notifications case 'notification_list': default: // Mark all items read - if ($request->variable('mark', '') == 'all' && (confirm_box(true) || check_link_hash($request->variable('token', ''), 'mark_all_notifications_read'))) + if ($request->variable('mark', '') == 'all' && check_link_hash($request->variable('token', ''), 'mark_all_notifications_read')) { - if (confirm_box(true)) - { - $phpbb_notifications->mark_notifications_read(false, false, $user->data['user_id'], $form_time); + $phpbb_notifications->mark_notifications(false, false, $user->data['user_id'], $form_time); - meta_refresh(3, $this->u_action); - $message = $user->lang['NOTIFICATIONS_MARK_ALL_READ_SUCCESS']; - - if ($request->is_ajax()) - { - $json_response = new \phpbb\json_response(); - $json_response->send(array( - 'MESSAGE_TITLE' => $user->lang['INFORMATION'], - 'MESSAGE_TEXT' => $message, - 'success' => true, - )); - } - $message .= '<br /><br />' . $user->lang('RETURN_UCP', '<a href="' . $this->u_action . '">', '</a>'); + meta_refresh(3, $this->u_action); + $message = $user->lang['NOTIFICATIONS_MARK_ALL_READ_SUCCESS']; - trigger_error($message); - } - else + if ($request->is_ajax()) { - confirm_box(false, 'NOTIFICATIONS_MARK_ALL_READ', build_hidden_fields(array( - 'mark' => 'all', - 'form_time' => $form_time, - ))); + $json_response = new \phpbb\json_response(); + $json_response->send(array( + 'MESSAGE_TITLE' => $user->lang['INFORMATION'], + 'MESSAGE_TEXT' => $message, + 'success' => true, + )); } + $message .= '<br /><br />' . $user->lang('RETURN_UCP', '<a href="' . $this->u_action . '">', '</a>'); + + trigger_error($message); } // Mark specific notifications read @@ -134,11 +122,11 @@ class ucp_notifications if (!empty($mark_read)) { - $phpbb_notifications->mark_notifications_read_by_id($mark_read, $form_time); + $phpbb_notifications->mark_notifications_by_id('notification.method.board', $mark_read, $form_time); } } - $notifications = $phpbb_notifications->load_notifications(array( + $notifications = $phpbb_notifications->load_notifications('notification.method.board', array( 'start' => $start, 'limit' => $config['topics_per_page'], 'count_total' => true, @@ -186,24 +174,22 @@ class ucp_notifications { $notification_methods = $phpbb_notifications->get_subscription_methods(); - foreach($phpbb_notifications->get_subscription_types() as $group => $subscription_types) + foreach ($phpbb_notifications->get_subscription_types() as $group => $subscription_types) { $template->assign_block_vars($block, array( 'GROUP_NAME' => $user->lang($group), )); - foreach($subscription_types as $type => $data) + foreach ($subscription_types as $type => $data) { $template->assign_block_vars($block, array( 'TYPE' => $type, 'NAME' => $user->lang($data['lang']), 'EXPLAIN' => (isset($user->lang[$data['lang'] . '_EXPLAIN'])) ? $user->lang($data['lang'] . '_EXPLAIN') : '', - - 'SUBSCRIBED' => (isset($subscriptions[$type])) ? true : false, )); - foreach($notification_methods as $method => $method_data) + foreach ($notification_methods as $method => $method_data) { $template->assign_block_vars($block . '.notification_methods', array( 'METHOD' => $method_data['id'], @@ -233,7 +219,7 @@ class ucp_notifications { $notification_methods = $phpbb_notifications->get_subscription_methods(); - foreach($notification_methods as $method => $method_data) + foreach ($notification_methods as $method => $method_data) { $template->assign_block_vars($block, array( 'METHOD' => $method_data['id'], diff --git a/phpBB/includes/ucp/ucp_pm.php b/phpBB/includes/ucp/ucp_pm.php index 517ae0b08c..33dff97fe6 100644 --- a/phpBB/includes/ucp/ucp_pm.php +++ b/phpBB/includes/ucp/ucp_pm.php @@ -1,8 +1,13 @@ <?php /** -* @package ucp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +* 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. * */ @@ -33,8 +38,6 @@ if (!defined('IN_PHPBB')) * Quoting a post (action=quotepost&p=[post_id]) * Quoting a PM (action=quote&p=[msg_id]) * Forwarding a PM (action=forward&p=[msg_id]) -* -* @package ucp */ class ucp_pm { @@ -42,7 +45,7 @@ class ucp_pm function main($id, $mode) { - global $user, $template, $phpbb_root_path, $auth, $phpEx, $db, $config; + global $user, $template, $phpbb_root_path, $auth, $phpEx, $db, $config, $request; if (!$user->data['is_registered']) { @@ -59,7 +62,7 @@ class ucp_pm $template->assign_var('S_PRIVMSGS', true); // Folder directly specified? - $folder_specified = request_var('folder', ''); + $folder_specified = $request->variable('folder', ''); if (!in_array($folder_specified, array('inbox', 'outbox', 'sentbox'))) { @@ -72,7 +75,7 @@ class ucp_pm if (!$folder_specified) { - $mode = (!$mode) ? request_var('mode', 'view') : $mode; + $mode = (!$mode) ? $request->variable('mode', 'view') : $mode; } else { @@ -85,11 +88,11 @@ class ucp_pm { // Compose message case 'compose': - $action = request_var('action', 'post'); + $action = $request->variable('action', 'post'); $user_folders = get_folder($user->data['user_id']); - if (!$auth->acl_get('u_sendpm')) + if ($action != 'delete' && !$auth->acl_get('u_sendpm')) { // trigger_error('NO_AUTH_SEND_MESSAGE'); $template->assign_vars(array( @@ -148,12 +151,12 @@ class ucp_pm } else { - $folder_id = request_var('f', PRIVMSGS_NO_BOX); - $action = request_var('action', 'view_folder'); + $folder_id = $request->variable('f', PRIVMSGS_NO_BOX); + $action = $request->variable('action', 'view_folder'); } - $msg_id = request_var('p', 0); - $view = request_var('view', ''); + $msg_id = $request->variable('p', 0); + $view = $request->variable('view', ''); // View message if specified if ($msg_id) @@ -172,12 +175,11 @@ class ucp_pm trigger_error('NO_AUTH_READ_HOLD_MESSAGE'); } - // First Handle Mark actions and moving messages $submit_mark = (isset($_POST['submit_mark'])) ? true : false; $move_pm = (isset($_POST['move_pm'])) ? true : false; - $mark_option = request_var('mark_option', ''); - $dest_folder = request_var('dest_folder', PRIVMSGS_NO_BOX); + $mark_option = $request->variable('mark_option', ''); + $dest_folder = $request->variable('dest_folder', PRIVMSGS_NO_BOX); // Is moving PM triggered through mark options? if (!in_array($mark_option, array('mark_important', 'delete_marked')) && $submit_mark) @@ -190,8 +192,8 @@ class ucp_pm // Move PM if ($move_pm) { - $move_msg_ids = (isset($_POST['marked_msg_id'])) ? request_var('marked_msg_id', array(0)) : array(); - $cur_folder_id = request_var('cur_folder_id', PRIVMSGS_NO_BOX); + $move_msg_ids = (isset($_POST['marked_msg_id'])) ? $request->variable('marked_msg_id', array(0)) : array(); + $cur_folder_id = $request->variable('cur_folder_id', PRIVMSGS_NO_BOX); if (move_pm($user->data['user_id'], $user->data['message_limit'], $move_msg_ids, $dest_folder, $cur_folder_id)) { @@ -199,7 +201,7 @@ class ucp_pm if ($action == 'view_message') { $msg_id = 0; - $folder_id = request_var('cur_folder_id', PRIVMSGS_NO_BOX); + $folder_id = $request->variable('cur_folder_id', PRIVMSGS_NO_BOX); $action = 'view_folder'; } } @@ -213,7 +215,7 @@ class ucp_pm // If new messages arrived, place them into the appropriate folder $num_not_moved = $num_removed = 0; - $release = request_var('release', 0); + $release = $request->variable('release', 0); if ($user->data['user_new_privmsg'] && ($action == 'view_folder' || $action == 'view_message')) { @@ -244,6 +246,27 @@ class ucp_pm $folder_id = (int) $row['folder_id']; } + if ($request->variable('mark', '') == 'all' && check_link_hash($request->variable('token', ''), 'mark_all_pms_read')) + { + mark_folder_read($user->data['user_id'], $folder_id); + + meta_refresh(3, $this->u_action); + $message = $user->lang['PM_MARK_ALL_READ_SUCCESS']; + + if ($request->is_ajax()) + { + $json_response = new \phpbb\json_response(); + $json_response->send(array( + 'MESSAGE_TITLE' => $user->lang['INFORMATION'], + 'MESSAGE_TEXT' => $message, + 'success' => true, + )); + } + $message .= '<br /><br />' . $user->lang('RETURN_UCP', '<a href="' . $this->u_action . '">', '</a>'); + + trigger_error($message); + } + $message_row = array(); if ($action == 'view_message' && $msg_id) { @@ -330,6 +353,7 @@ class ucp_pm 'U_SENTBOX' => $this->u_action . '&folder=sentbox', 'U_CREATE_FOLDER' => $this->u_action . '&mode=options', 'U_CURRENT_FOLDER' => $this->u_action . '&folder=' . $folder_id, + 'U_MARK_ALL' => $this->u_action . '&folder=' . $folder_id . '&mark=all&token=' . generate_link_hash('mark_all_pms_read'), 'S_IN_INBOX' => ($folder_id == PRIVMSGS_INBOX) ? true : false, 'S_IN_OUTBOX' => ($folder_id == PRIVMSGS_OUTBOX) ? true : false, @@ -352,9 +376,10 @@ class ucp_pm else if ($action == 'view_message') { $template->assign_vars(array( - 'S_VIEW_MESSAGE' => true, - 'MSG_ID' => $msg_id) - ); + 'S_VIEW_MESSAGE' => true, + 'L_RETURN_TO_FOLDER' => $user->lang('RETURN_TO', $folder_status['folder_name']), + 'MSG_ID' => $msg_id, + )); if (!$msg_id) { diff --git a/phpBB/includes/ucp/ucp_pm_compose.php b/phpBB/includes/ucp/ucp_pm_compose.php index 87dfdf902b..e707c251fe 100644 --- a/phpBB/includes/ucp/ucp_pm_compose.php +++ b/phpBB/includes/ucp/ucp_pm_compose.php @@ -1,9 +1,13 @@ <?php /** * -* @package ucp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -23,8 +27,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) { global $template, $db, $auth, $user, $cache; global $phpbb_root_path, $phpEx, $config; - global $request; - global $phpbb_container; + global $request, $phpbb_dispatcher, $phpbb_container; // Damn php and globals - i know, this is horrible // Needed for handle_message_list_actions() @@ -41,18 +44,17 @@ function compose_pm($id, $mode, $action, $user_folders = array()) add_form_key('ucp_pm_compose'); // Grab only parameters needed here - $to_user_id = request_var('u', 0); - $to_group_id = request_var('g', 0); - $msg_id = request_var('p', 0); - $draft_id = request_var('d', 0); - $lastclick = request_var('lastclick', 0); + $to_user_id = $request->variable('u', 0); + $to_group_id = $request->variable('g', 0); + $msg_id = $request->variable('p', 0); + $draft_id = $request->variable('d', 0); + $lastclick = $request->variable('lastclick', 0); // Reply to all triggered (quote/reply) - $reply_to_all = request_var('reply_to_all', 0); + $reply_to_all = $request->variable('reply_to_all', 0); $address_list = $request->variable('address_list', array('' => array(0 => ''))); - $submit = (isset($_POST['post'])) ? true : false; $preview = (isset($_POST['preview'])) ? true : false; $save = (isset($_POST['save'])) ? true : false; $load = (isset($_POST['load'])) ? true : false; @@ -66,6 +68,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) $refresh = isset($_POST['add_file']) || isset($_POST['delete_file']) || $save || $load || $remove_u || $remove_g || $add_to || $add_bcc; + $submit = $request->is_set_post('post') && !$refresh && !$preview; $action = ($delete && !$preview && !$refresh && $submit) ? 'delete' : $action; $select_single = ($config['allow_mass_pm'] && $auth->acl_get('u_masspm')) ? false : true; @@ -73,6 +76,9 @@ function compose_pm($id, $mode, $action, $user_folders = array()) $error = array(); $current_time = time(); + /** @var \phpbb\group\helper $group_helper */ + $group_helper = $phpbb_container->get('group_helper'); + // Was cancel pressed? If so then redirect to the appropriate page if ($cancel || ($current_time - $lastclick < 2 && $submit)) { @@ -87,6 +93,32 @@ function compose_pm($id, $mode, $action, $user_folders = array()) // we include the language file here $user->add_lang('viewtopic'); + /** + * Modify the default vars before composing a PM + * + * @event core.ucp_pm_compose_modify_data + * @var int msg_id post_id in the page request + * @var int to_user_id The id of whom the message is to + * @var int to_group_id The id of the group the message is to + * @var bool submit Whether the form has been submitted + * @var bool preview Whether the user is previewing the PM or not + * @var string action One of: post, reply, quote, forward, quotepost, edit, delete, smilies + * @var bool delete Whether the user is deleting the PM + * @var int reply_to_all Value of reply_to_all request variable. + * @since 3.1.4-RC1 + */ + $vars = array( + 'msg_id', + 'to_user_id', + 'to_group_id', + 'submit', + 'preview', + 'action', + 'delete', + 'reply_to_all', + ); + extract($phpbb_dispatcher->trigger_event('core.ucp_pm_compose_modify_data', compact($vars))); + // Output PM_TO box if message composing if ($action != 'edit') { @@ -116,7 +148,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) $group_options = ''; while ($row = $db->sql_fetchrow($result)) { - $group_options .= '<option' . (($row['group_type'] == GROUP_SPECIAL) ? ' class="sep"' : '') . ' value="' . $row['group_id'] . '">' . (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']) . '</option>'; + $group_options .= '<option' . (($row['group_type'] == GROUP_SPECIAL) ? ' class="sep"' : '') . ' value="' . $row['group_id'] . '">' . $group_helper->get_name($row['group_name']) . '</option>'; } $db->sql_freeresult($result); } @@ -229,6 +261,35 @@ function compose_pm($id, $mode, $action, $user_folders = array()) if ($sql) { + /** + * Alter sql query to get message for user to write the PM + * + * @event core.ucp_pm_compose_compose_pm_basic_info_query_before + * @var string sql String with the query to be executed + * @var int msg_id topic_id in the page request + * @var int to_user_id The id of whom the message is to + * @var int to_group_id The id of the group whom the message is to + * @var bool submit Whether the user is sending the PM or not + * @var bool preview Whether the user is previewing the PM or not + * @var string action One of: post, reply, quote, forward, quotepost, edit, delete, smilies + * @var bool delete Whether the user is deleting the PM + * @var int reply_to_all Value of reply_to_all request variable. + * @since 3.1.0-RC5 + * @change 3.2.0-a1 Removed undefined variables + */ + $vars = array( + 'sql', + 'msg_id', + 'to_user_id', + 'to_group_id', + 'submit', + 'preview', + 'action', + 'delete', + 'reply_to_all', + ); + extract($phpbb_dispatcher->trigger_event('core.ucp_pm_compose_compose_pm_basic_info_query_before', compact($vars))); + $result = $db->sql_query($sql); $post = $db->sql_fetchrow($result); $db->sql_freeresult($result); @@ -263,6 +324,37 @@ function compose_pm($id, $mode, $action, $user_folders = array()) trigger_error('NOT_AUTHORISED'); } + /** + * Get the result of querying for the post to be quoted in the pm message + * + * @event core.ucp_pm_compose_quotepost_query_after + * @var string sql The original SQL used in the query + * @var array post Associative array with the data of the quoted post + * @var array msg_id The post_id that was searched to get the message for quoting + * @var int to_user_id Users the message is sent to + * @var int to_group_id Groups the message is sent to + * @var bool submit Whether the user is sending the PM or not + * @var bool preview Whether the user is previewing the PM or not + * @var string action One of: post, reply, quote, forward, quotepost, edit, delete, smilies + * @var bool delete If deleting message + * @var int reply_to_all Value of reply_to_all request variable. + * @since 3.1.0-RC5 + * @change 3.2.0-a1 Removed undefined variables + */ + $vars = array( + 'sql', + 'post', + 'msg_id', + 'to_user_id', + 'to_group_id', + 'submit', + 'preview', + 'action', + 'delete', + 'reply_to_all', + ); + extract($phpbb_dispatcher->trigger_event('core.ucp_pm_compose_quotepost_query_after', compact($vars))); + // Passworded forum? if ($post['forum_id']) { @@ -385,8 +477,9 @@ function compose_pm($id, $mode, $action, $user_folders = array()) $icon_id = 0; } - $message_parser = new parse_message(); + /* @var $plupload \phpbb\plupload\plupload */ $plupload = $phpbb_container->get('plupload'); + $message_parser = new parse_message(); $message_parser->set_plupload($plupload); $message_parser->message = ($action == 'reply') ? '' : $message_text; @@ -399,7 +492,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) if ($action == 'delete') { // Folder id has been determined by the SQL Statement - // $folder_id = request_var('f', PRIVMSGS_NO_BOX); + // $folder_id = $request->variable('f', PRIVMSGS_NO_BOX); // Do we need to confirm ? if (confirm_box(true)) @@ -430,15 +523,9 @@ function compose_pm($id, $mode, $action, $user_folders = array()) } // Get maximum number of allowed recipients - $sql = 'SELECT MAX(g.group_max_recipients) as max_recipients - FROM ' . GROUPS_TABLE . ' g, ' . USER_GROUP_TABLE . ' ug - WHERE ug.user_id = ' . $user->data['user_id'] . ' - AND ug.user_pending = 0 - AND ug.group_id = g.group_id'; - $result = $db->sql_query($sql); - $max_recipients = (int) $db->sql_fetchfield('max_recipients'); - $db->sql_freeresult($result); + $max_recipients = phpbb_get_max_setting_from_group($db, $user->data['user_id'], 'max_recipients'); + // If it is 0, there is no limit set and we use the maximum value within the config. $max_recipients = (!$max_recipients) ? $config['pm_max_recipients'] : $max_recipients; // If this is a quote/reply "to all"... we may increase the max_recpients to the number of original recipients @@ -492,7 +579,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) if ($message_attachment && !$submit && !$refresh && !$preview && $action == 'edit') { // Do not change to SELECT * - $sql = 'SELECT attach_id, is_orphan, attach_comment, real_filename + $sql = 'SELECT attach_id, is_orphan, attach_comment, real_filename, filesize FROM ' . ATTACHMENTS_TABLE . " WHERE post_msg_id = $msg_id AND in_message = 1 @@ -511,7 +598,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) $enable_urls = true; } - $enable_magic_url = $drafts = false; + $drafts = false; // User own some drafts? if ($auth->acl_get('u_savedrafts') && $action != 'delete') @@ -546,9 +633,9 @@ function compose_pm($id, $mode, $action, $user_folders = array()) // Save Draft if ($save && $auth->acl_get('u_savedrafts')) { - $subject = utf8_normalize_nfc(request_var('subject', '', true)); + $subject = $request->variable('subject', '', true); $subject = (!$subject && $action != 'post') ? $user->lang['NEW_MESSAGE'] : $subject; - $message = utf8_normalize_nfc(request_var('message', '', true)); + $message = $request->variable('message', '', true); if ($subject && $message) { @@ -586,7 +673,6 @@ function compose_pm($id, $mode, $action, $user_folders = array()) ); $s_hidden_fields .= build_address_field($address_list); - confirm_box(false, 'SAVE_DRAFT', $s_hidden_fields); } } @@ -643,26 +729,16 @@ function compose_pm($id, $mode, $action, $user_folders = array()) { $error[] = $user->lang['FORM_INVALID']; } - $subject = utf8_normalize_nfc(request_var('subject', '', true)); - $message_parser->message = utf8_normalize_nfc(request_var('message', '', true)); + $subject = $request->variable('subject', '', true); + $message_parser->message = $request->variable('message', '', true); - $icon_id = request_var('icon', 0); + $icon_id = $request->variable('icon', 0); $enable_bbcode = (!$bbcode_status || isset($_POST['disable_bbcode'])) ? false : true; $enable_smilies = (!$smilies_status || isset($_POST['disable_smilies'])) ? false : true; $enable_urls = (isset($_POST['disable_magic_url'])) ? 0 : 1; $enable_sig = (!$config['allow_sig'] ||!$config['allow_sig_pm']) ? false : ((isset($_POST['attach_sig'])) ? true : false); - if ($submit) - { - $status_switch = (($enable_bbcode+1) << 8) + (($enable_smilies+1) << 4) + (($enable_urls+1) << 2) + (($enable_sig+1) << 1); - $status_switch = ($status_switch != $check_value); - } - else - { - $status_switch = 1; - } - // Parse Attachments - before checksum is calculated $message_parser->parse_attachments('fileupload', $action, 0, $submit, $preview, $refresh, true); @@ -748,7 +824,6 @@ function compose_pm($id, $mode, $action, $user_folders = array()) $return_box_url = ($action === 'post' || $action === 'edit') ? $outbox_folder_url : $inbox_folder_url; $return_box_lang = ($action === 'post' || $action === 'edit') ? 'PM_OUTBOX' : 'PM_INBOX'; - $save_message = ($action === 'edit') ? $user->lang['MESSAGE_EDITED'] : $user->lang['MESSAGE_STORED']; $message = $save_message . '<br /><br />' . $user->lang('VIEW_PRIVATE_MESSAGE', '<a href="' . $return_message_url . '">', '</a>'); @@ -835,7 +910,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) { if ($action == 'quotepost') { - $post_id = request_var('p', 0); + $post_id = $request->variable('p', 0); if ($config['allow_post_links']) { $message_link = "[url=" . generate_board_url() . "/viewtopic.$phpEx?p={$post_id}#p{$post_id}]{$user->lang['SUBJECT']}{$user->lang['COLON']} {$message_subject}[/url]\n\n"; @@ -849,7 +924,20 @@ function compose_pm($id, $mode, $action, $user_folders = array()) { $message_link = ''; } - $message_parser->message = $message_link . '[quote="' . $quote_username . '"]' . censor_text(trim($message_parser->message)) . "[/quote]\n"; + $quote_attributes = array( + 'author' => $quote_username, + 'time' => $post['message_time'], + 'user_id' => $post['author_id'], + ); + if ($action === 'quotepost') + { + $quote_attributes['post_id'] = $post['msg_id']; + } + $quote_text = $phpbb_container->get('text_formatter.utils')->generate_quote( + censor_text($message_parser->message), + $quote_attributes + ); + $message_parser->message = $message_link . $quote_text . "\n\n"; } if (($action == 'reply' || $action == 'quote' || $action == 'quotepost') && !$preview && !$refresh) @@ -877,7 +965,11 @@ function compose_pm($id, $mode, $action, $user_folders = array()) $forward_text[] = sprintf($user->lang['FWD_FROM'], $quote_username_text); $forward_text[] = sprintf($user->lang['FWD_TO'], implode($user->lang['COMMA_SEPARATOR'], $fwd_to_field['to'])); - $message_parser->message = implode("\n", $forward_text) . "\n\n[quote="{$quote_username}"]\n" . censor_text(trim($message_parser->message)) . "\n[/quote]"; + $quote_text = $phpbb_container->get('text_formatter.utils')->generate_quote( + censor_text($message_parser->message), + array('author' => $quote_username) + ); + $message_parser->message = implode("\n", $forward_text) . "\n\n" . $quote_text; $message_subject = ((!preg_match('/^Fwd:/', $message_subject)) ? 'Fwd: ' : '') . censor_text($message_subject); } @@ -950,7 +1042,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) { if ($type == 'g') { - $row['name'] = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['name']] : $row['name']; + $row['name'] = $group_helper->get_name($row['name']); } ${$type}[$row['id']] = array('name' => $row['name'], 'colour' => $row['colour']); @@ -960,7 +1052,6 @@ function compose_pm($id, $mode, $action, $user_folders = array()) } // Now Build the address list - $plain_address_field = ''; foreach ($address_list as $type => $adr_ary) { foreach ($adr_ary as $id => $field) @@ -1006,7 +1097,6 @@ function compose_pm($id, $mode, $action, $user_folders = array()) // Build hidden address list $s_hidden_address_field = build_address_field($address_list); - $bbcode_checked = (isset($enable_bbcode)) ? !$enable_bbcode : (($config['allow_bbcode'] && $auth->acl_get('u_pm_bbcode')) ? !$user->optionget('bbcode') : 1); $smilies_checked = (isset($enable_smilies)) ? !$enable_smilies : (($config['allow_smilies'] && $auth->acl_get('u_pm_smilies')) ? !$user->optionget('smilies') : 1); $urls_checked = (isset($enable_urls)) ? !$enable_urls : 0; @@ -1049,6 +1139,9 @@ function compose_pm($id, $mode, $action, $user_folders = array()) $form_enctype = (@ini_get('file_uploads') == '0' || strtolower(@ini_get('file_uploads')) == 'off' || !$config['allow_pm_attach'] || !$auth->acl_get('u_pm_attach')) ? '' : ' enctype="multipart/form-data"'; + /** @var \phpbb\controller\helper $controller_helper */ + $controller_helper = $phpbb_container->get('controller.helper'); + // Start assigning vars for main posting page ... $template->assign_vars(array( 'L_POST_A' => $page_title, @@ -1057,7 +1150,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) 'SUBJECT' => (isset($message_subject)) ? $message_subject : '', 'MESSAGE' => $message_text, - 'BBCODE_STATUS' => ($bbcode_status) ? sprintf($user->lang['BBCODE_IS_ON'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '">', '</a>') : sprintf($user->lang['BBCODE_IS_OFF'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '">', '</a>'), + 'BBCODE_STATUS' => $user->lang(($bbcode_status ? 'BBCODE_IS_ON' : 'BBCODE_IS_OFF'), '<a href="' . $controller_helper->route('phpbb_help_bbcode_controller') . '">', '</a>'), 'IMG_STATUS' => ($img_status) ? $user->lang['IMAGES_ARE_ON'] : $user->lang['IMAGES_ARE_OFF'], 'FLASH_STATUS' => ($flash_status) ? $user->lang['FLASH_IS_ON'] : $user->lang['FLASH_IS_OFF'], 'SMILIES_STATUS' => ($smilies_status) ? $user->lang['SMILIES_ARE_ON'] : $user->lang['SMILIES_ARE_OFF'], @@ -1081,6 +1174,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) 'S_SAVE_ALLOWED' => ($auth->acl_get('u_savedrafts') && $action != 'edit') ? true : false, 'S_HAS_DRAFTS' => ($auth->acl_get('u_savedrafts') && $drafts), 'S_FORM_ENCTYPE' => $form_enctype, + 'S_ATTACH_DATA' => json_encode($message_parser->attachment_data), 'S_BBCODE_IMG' => $img_status, 'S_BBCODE_FLASH' => $flash_status, @@ -1104,7 +1198,8 @@ function compose_pm($id, $mode, $action, $user_folders = array()) if ($allowed) { - $plupload->configure($cache, $template, $s_action, false); + $max_files = ($auth->acl_gets('a_', 'm_')) ? 0 : (int) $config['max_attachments_pm']; + $plupload->configure($cache, $template, $s_action, false, $max_files); } // Attachment entry @@ -1151,13 +1246,13 @@ function handle_message_list_actions(&$address_list, &$error, $remove_u, $remove } // Add Selected Groups - $group_list = request_var('group_list', array(0)); + $group_list = $request->variable('group_list', array(0)); // Build usernames to add - $usernames = request_var('username', '', true); + $usernames = $request->variable('username', '', true); $usernames = (empty($usernames)) ? array() : array($usernames); - $username_list = request_var('username_list', '', true); + $username_list = $request->variable('username_list', '', true); if ($username_list) { $usernames = array_merge($usernames, explode("\n", $username_list)); @@ -1174,7 +1269,7 @@ function handle_message_list_actions(&$address_list, &$error, $remove_u, $remove $submit = false; // Preview is only true if there was also a message entered - if (request_var('message', '')) + if ($request->variable('message', '')) { $preview = true; } @@ -1227,35 +1322,86 @@ function handle_message_list_actions(&$address_list, &$error, $remove_u, $remove // Check for disallowed recipients if (!empty($address_list['u'])) { - // We need to check their PM status (do they want to receive PM's?) - // Only check if not a moderator or admin, since they are allowed to override this user setting - if (!$auth->acl_gets('a_', 'm_') && !$auth->acl_getf_global('m_')) + $can_ignore_allow_pm = $auth->acl_gets('a_', 'm_') || $auth->acl_getf_global('m_'); + + // Administrator deactivated users check and we need to check their + // PM status (do they want to receive PM's?) + // Only check PM status if not a moderator or admin, since they + // are allowed to override this user setting + $sql = 'SELECT user_id, user_allow_pm + FROM ' . USERS_TABLE . ' + WHERE ' . $db->sql_in_set('user_id', array_keys($address_list['u'])) . ' + AND ( + (user_type = ' . USER_INACTIVE . ' + AND user_inactive_reason = ' . INACTIVE_MANUAL . ') + ' . ($can_ignore_allow_pm ? '' : ' OR user_allow_pm = 0') . ' + )'; + + $result = $db->sql_query($sql); + + $removed_no_pm = $removed_no_permission = false; + while ($row = $db->sql_fetchrow($result)) { - $sql = 'SELECT user_id - FROM ' . USERS_TABLE . ' - WHERE ' . $db->sql_in_set('user_id', array_keys($address_list['u'])) . ' - AND user_allow_pm = 0'; - $result = $db->sql_query($sql); + if (!$can_ignore_allow_pm && !$row['user_allow_pm']) + { + $removed_no_pm = true; + } + else + { + $removed_no_permission = true; + } - $removed = false; - while ($row = $db->sql_fetchrow($result)) + unset($address_list['u'][$row['user_id']]); + } + $db->sql_freeresult($result); + + // print a notice about users not being added who do not want to receive pms + if ($removed_no_pm) + { + $error[] = $user->lang['PM_USERS_REMOVED_NO_PM']; + } + + // print a notice about users not being added who do not have permission to receive PMs + if ($removed_no_permission) + { + $error[] = $user->lang['PM_USERS_REMOVED_NO_PERMISSION']; + } + + if (!sizeof(array_keys($address_list['u']))) + { + return; + } + + // Check if users have permission to read PMs + $can_read = $auth->acl_get_list(array_keys($address_list['u']), 'u_readpm'); + $can_read = (empty($can_read) || !isset($can_read[0]['u_readpm'])) ? array() : $can_read[0]['u_readpm']; + $cannot_read_list = array_diff(array_keys($address_list['u']), $can_read); + if (!empty($cannot_read_list)) + { + foreach ($cannot_read_list as $cannot_read) { - $removed = true; - unset($address_list['u'][$row['user_id']]); + unset($address_list['u'][$cannot_read]); } - $db->sql_freeresult($result); - // print a notice about users not being added who do not want to receive pms - if ($removed) + $error[] = $user->lang['PM_USERS_REMOVED_NO_PERMISSION']; + } + + // Check if users are banned + $banned_user_list = phpbb_get_banned_user_ids(array_keys($address_list['u']), false); + if (!empty($banned_user_list)) + { + foreach ($banned_user_list as $banned_user) { - $error[] = $user->lang['PM_USERS_REMOVED_NO_PM']; + unset($address_list['u'][$banned_user]); } + + $error[] = $user->lang['PM_USERS_REMOVED_NO_PERMISSION']; } } } /** -* Build the hidden field for the recipients. Needed, as the variable is not read via request_var. +* Build the hidden field for the recipients. Needed, as the variable is not read via $request->variable(). */ function build_address_field($address_list) { diff --git a/phpBB/includes/ucp/ucp_pm_options.php b/phpBB/includes/ucp/ucp_pm_options.php index bf7334b307..2458c4118d 100644 --- a/phpBB/includes/ucp/ucp_pm_options.php +++ b/phpBB/includes/ucp/ucp_pm_options.php @@ -1,9 +1,13 @@ <?php /** * -* @package ucp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -20,7 +24,7 @@ if (!defined('IN_PHPBB')) */ function message_options($id, $mode, $global_privmsgs_rules, $global_rule_conditions) { - global $phpbb_root_path, $phpEx, $user, $template, $auth, $config, $db; + global $phpbb_root_path, $phpEx, $user, $template, $config, $db, $request; $redirect_url = append_sid("{$phpbb_root_path}ucp.$phpEx", "i=pm&mode=options"); @@ -28,8 +32,12 @@ function message_options($id, $mode, $global_privmsgs_rules, $global_rule_condit // Change "full folder" setting - what to do if folder is full if (isset($_POST['fullfolder'])) { - check_form_key('ucp_pm_options', $config['form_token_lifetime'], $redirect_url); - $full_action = request_var('full_action', 0); + if (!check_form_key('ucp_pm_options')) + { + trigger_error('FORM_INVALID'); + } + + $full_action = $request->variable('full_action', 0); $set_folder_id = 0; switch ($full_action) @@ -39,7 +47,7 @@ function message_options($id, $mode, $global_privmsgs_rules, $global_rule_condit break; case 2: - $set_folder_id = request_var('full_move_to', PRIVMSGS_INBOX); + $set_folder_id = $request->variable('full_move_to', PRIVMSGS_INBOX); break; case 3: @@ -65,14 +73,13 @@ function message_options($id, $mode, $global_privmsgs_rules, $global_rule_condit trigger_error($message); } } - + // Add Folder if (isset($_POST['addfolder'])) { if (check_form_key('ucp_pm_options')) { - $folder_name = utf8_normalize_nfc(request_var('foldername', '', true)); - $msg = ''; + $folder_name = $request->variable('foldername', '', true); if ($folder_name) { @@ -127,8 +134,8 @@ function message_options($id, $mode, $global_privmsgs_rules, $global_rule_condit { if (check_form_key('ucp_pm_options')) { - $new_folder_name = utf8_normalize_nfc(request_var('new_folder_name', '', true)); - $rename_folder_id= request_var('rename_folder_id', 0); + $new_folder_name = $request->variable('new_folder_name', '', true); + $rename_folder_id= $request->variable('rename_folder_id', 0); if (!$new_folder_name) { @@ -170,11 +177,11 @@ function message_options($id, $mode, $global_privmsgs_rules, $global_rule_condit // Remove Folder if (isset($_POST['remove_folder'])) { - $remove_folder_id = request_var('remove_folder_id', 0); + $remove_folder_id = $request->variable('remove_folder_id', 0); // Default to "move all messages to inbox" - $remove_action = request_var('remove_action', 1); - $move_to = request_var('move_to', PRIVMSGS_INBOX); + $remove_action = $request->variable('remove_action', 1); + $move_to = $request->variable('move_to', PRIVMSGS_INBOX); // Move to same folder? if ($remove_action == 1 && $remove_folder_id == $move_to) @@ -226,11 +233,11 @@ function message_options($id, $mode, $global_privmsgs_rules, $global_rule_condit // Move Messages case 1: $num_moved = move_pm($user->data['user_id'], $user->data['message_limit'], $msg_ids, $move_to, $remove_folder_id); - + // Something went wrong, only partially moved? if ($num_moved != $folder_row['pm_count']) { - trigger_error($user->lang('MOVE_PM_ERROR', (int) $folder_row['pm_count'], $num_moved)); + trigger_error($user->lang('MOVE_PM_ERROR', $user->lang('MESSAGES_COUNT', (int) $folder_row['pm_count']), $num_moved)); } break; @@ -283,13 +290,13 @@ function message_options($id, $mode, $global_privmsgs_rules, $global_rule_condit { if (check_form_key('ucp_pm_options')) { - $check_option = request_var('check_option', 0); - $rule_option = request_var('rule_option', 0); - $cond_option = request_var('cond_option', ''); - $action_option = explode('|', request_var('action_option', '')); - $rule_string = ($cond_option != 'none') ? utf8_normalize_nfc(request_var('rule_string', '', true)) : ''; - $rule_user_id = ($cond_option != 'none') ? request_var('rule_user_id', 0) : 0; - $rule_group_id = ($cond_option != 'none') ? request_var('rule_group_id', 0) : 0; + $check_option = $request->variable('check_option', 0); + $rule_option = $request->variable('rule_option', 0); + $cond_option = $request->variable('cond_option', ''); + $action_option = explode('|', $request->variable('action_option', '')); + $rule_string = ($cond_option != 'none') ? $request->variable('rule_string', '', true) : ''; + $rule_user_id = ($cond_option != 'none') ? $request->variable('rule_user_id', 0) : 0; + $rule_group_id = ($cond_option != 'none') ? $request->variable('rule_group_id', 0) : 0; $action = (int) $action_option[0]; $folder_id = (int) $action_option[1]; @@ -363,7 +370,7 @@ function message_options($id, $mode, $global_privmsgs_rules, $global_rule_condit // Remove Rule if (isset($_POST['delete_rule']) && !isset($_POST['cancel'])) { - $delete_id = array_keys(request_var('delete_rule', array(0 => 0))); + $delete_id = array_keys($request->variable('delete_rule', array(0 => 0))); $delete_id = (!empty($delete_id[0])) ? $delete_id[0] : 0; if (!$delete_id) @@ -418,10 +425,10 @@ function message_options($id, $mode, $global_privmsgs_rules, $global_rule_condit $result = $db->sql_query($sql); $num_messages = (int) $db->sql_fetchfield('num_messages'); $db->sql_freeresult($result); - + $folder[PRIVMSGS_INBOX] = array( 'folder_name' => $user->lang['PM_INBOX'], - 'message_status' => $user->lang('FOLDER_MESSAGE_STATUS', (int) $user->data['message_limit'], $num_messages), + 'message_status' => $user->lang('FOLDER_MESSAGE_STATUS', $user->lang('MESSAGES_COUNT', (int) $user->data['message_limit']), $num_messages), ); $sql = 'SELECT folder_id, folder_name, pm_count @@ -435,7 +442,7 @@ function message_options($id, $mode, $global_privmsgs_rules, $global_rule_condit $num_user_folder++; $folder[$row['folder_id']] = array( 'folder_name' => $row['folder_name'], - 'message_status' => $user->lang('FOLDER_MESSAGE_STATUS', (int) $user->data['message_limit'], $row['pm_count']), + 'message_status' => $user->lang('FOLDER_MESSAGE_STATUS', $user->lang('MESSAGES_COUNT', (int) $user->data['message_limit']), (int) $row['pm_count']), ); } $db->sql_freeresult($result); @@ -499,18 +506,20 @@ function message_options($id, $mode, $global_privmsgs_rules, $global_rule_condit $rule_lang = $action_lang = $check_lang = array(); // Build all three language arrays - preg_replace('#^((RULE|ACTION|CHECK)_([A-Z0-9_]+))$#e', "\${strtolower('\\2') . '_lang'}[constant('\\1')] = \$user->lang['PM_\\2']['\\3']", array_keys(get_defined_constants())); + preg_replace_callback('#^((RULE|ACTION|CHECK)_([A-Z0-9_]+))$#', function ($match) use(&$rule_lang, &$action_lang, &$check_lang, $user) { + ${strtolower($match[2]) . '_lang'}[constant($match[1])] = $user->lang['PM_' . $match[2]][$match[3]]; + }, array_keys(get_defined_constants())); /* Rule Ordering: -> CHECK_* -> RULE_* [IN $global_privmsgs_rules:CHECK_*] -> [IF $rule_conditions[RULE_*] [|text|bool|user|group|own_group]] -> ACTION_* */ - $check_option = request_var('check_option', 0); - $rule_option = request_var('rule_option', 0); - $cond_option = request_var('cond_option', ''); - $action_option = request_var('action_option', ''); - $back = (isset($_REQUEST['back'])) ? request_var('back', array('' => 0)) : array(); + $check_option = $request->variable('check_option', 0); + $rule_option = $request->variable('rule_option', 0); + $cond_option = $request->variable('cond_option', ''); + $action_option = $request->variable('action_option', ''); + $back = (isset($_REQUEST['back'])) ? $request->variable('back', array('' => 0)) : array(); if (sizeof($back)) { @@ -601,7 +610,7 @@ function define_check_option($hardcoded, $check_option, $check_lang) */ function define_action_option($hardcoded, $action_option, $action_lang, $folder) { - global $db, $template, $user; + global $template; $l_action = $s_action_options = ''; if ($hardcoded) @@ -690,8 +699,11 @@ function define_rule_option($hardcoded, $rule_option, $rule_lang, $check_ary) */ function define_cond_option($hardcoded, $cond_option, $rule_option, $global_rule_conditions) { - global $db, $template, $auth, $user; - + global $db, $template, $auth, $user, $request, $phpbb_container; + + /** @var \phpbb\group\helper $group_helper */ + $group_helper = $phpbb_container->get('group_helper'); + $template->assign_vars(array( 'S_COND_DEFINED' => true, 'S_COND_SELECT' => (!$hardcoded && isset($global_rule_conditions[$rule_option])) ? true : false) @@ -709,13 +721,12 @@ function define_cond_option($hardcoded, $cond_option, $rule_option, $global_rule // Define Condition $condition = $global_rule_conditions[$rule_option]; - $current_value = ''; switch ($condition) { case 'text': - $rule_string = utf8_normalize_nfc(request_var('rule_string', '', true)); - + $rule_string = $request->variable('rule_string', '', true); + $template->assign_vars(array( 'S_TEXT_CONDITION' => true, 'CURRENT_STRING' => $rule_string, @@ -727,9 +738,9 @@ function define_cond_option($hardcoded, $cond_option, $rule_option, $global_rule break; case 'user': - $rule_user_id = request_var('rule_user_id', 0); - $rule_string = utf8_normalize_nfc(request_var('rule_string', '', true)); - + $rule_user_id = $request->variable('rule_user_id', 0); + $rule_string = $request->variable('rule_string', '', true); + if ($rule_string && !$rule_user_id) { $sql = 'SELECT user_id @@ -770,8 +781,8 @@ function define_cond_option($hardcoded, $cond_option, $rule_option, $global_rule break; case 'group': - $rule_group_id = request_var('rule_group_id', 0); - $rule_string = utf8_normalize_nfc(request_var('rule_string', '', true)); + $rule_group_id = $request->variable('rule_group_id', 0); + $rule_string = $request->variable('rule_string', '', true); $sql = 'SELECT g.group_id, g.group_name, g.group_type FROM ' . GROUPS_TABLE . ' g '; @@ -791,10 +802,10 @@ function define_cond_option($hardcoded, $cond_option, $rule_option, $global_rule { $sql .= 'WHERE'; } - - $sql .= " (g.group_name NOT IN ('GUESTS', 'BOTS') OR g.group_type <> " . GROUP_SPECIAL . ') + + $sql .= " (g.group_name NOT IN ('GUESTS', 'BOTS') OR g.group_type <> " . GROUP_SPECIAL . ') ORDER BY g.group_type DESC, g.group_name ASC'; - + $result = $db->sql_query($sql); $s_group_options = ''; @@ -802,13 +813,13 @@ function define_cond_option($hardcoded, $cond_option, $rule_option, $global_rule { if ($rule_group_id && ($row['group_id'] == $rule_group_id)) { - $rule_string = (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']); + $rule_string = $group_helper->get_name($row['group_name']); } $s_class = ($row['group_type'] == GROUP_SPECIAL) ? ' class="sep"' : ''; $s_selected = ($row['group_id'] == $rule_group_id) ? ' selected="selected"' : ''; - - $s_group_options .= '<option value="' . $row['group_id'] . '"' . $s_class . $s_selected . '>' . (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']) . '</option>'; + + $s_group_options .= '<option value="' . $row['group_id'] . '"' . $s_class . $s_selected . '>' . $group_helper->get_name($row['group_name']) . '</option>'; } $db->sql_freeresult($result); @@ -845,7 +856,7 @@ function show_defined_rules($user_id, $check_lang, $rule_lang, $action_lang, $fo WHERE user_id = ' . $user_id . ' ORDER BY rule_id ASC'; $result = $db->sql_query($sql); - + $count = 0; while ($row = $db->sql_fetchrow($result)) { diff --git a/phpBB/includes/ucp/ucp_pm_viewfolder.php b/phpBB/includes/ucp/ucp_pm_viewfolder.php index a567283543..af2126c83d 100644 --- a/phpBB/includes/ucp/ucp_pm_viewfolder.php +++ b/phpBB/includes/ucp/ucp_pm_viewfolder.php @@ -1,9 +1,13 @@ <?php /** * -* @package ucp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -21,7 +25,7 @@ if (!defined('IN_PHPBB')) */ function view_folder($id, $mode, $folder_id, $folder) { - global $user, $template, $auth, $db, $cache; + global $user, $template, $auth, $db, $cache, $request; global $phpbb_root_path, $config, $phpEx; $submit_export = (isset($_POST['submit_export'])) ? true : false; @@ -37,9 +41,6 @@ function view_folder($id, $mode, $folder_id, $folder) $color_rows = array('marked', 'replied'); - // only show the friend/foe color rows if the module is enabled - $zebra_enabled = false; - $_module = new p_master(); $_module->list_modules('ucp'); $_module->set_active('zebra'); @@ -192,9 +193,9 @@ function view_folder($id, $mode, $folder_id, $folder) } else { - $export_type = request_var('export_option', ''); - $enclosure = request_var('enclosure', ''); - $delimiter = request_var('delimiter', ''); + $export_type = $request->variable('export_option', ''); + $enclosure = $request->variable('enclosure', ''); + $delimiter = $request->variable('delimiter', ''); if ($export_type == 'CSV' && ($delimiter === '' || $enclosure === '')) { @@ -379,7 +380,7 @@ function view_folder($id, $mode, $folder_id, $folder) break; } - header('Pragma: no-cache'); + header('Cache-Control: private, no-cache'); header("Content-Type: $mimetype; name=\"data.$filetype\""); header("Content-disposition: attachment; filename=data.$filetype"); echo $string; @@ -393,15 +394,16 @@ function view_folder($id, $mode, $folder_id, $folder) */ function get_pm_from($folder_id, $folder, $user_id) { - global $user, $db, $template, $config, $auth, $phpbb_container, $phpbb_root_path, $phpEx; + global $user, $db, $template, $config, $auth, $phpbb_container, $phpbb_root_path, $phpEx, $request; - $start = request_var('start', 0); + $start = $request->variable('start', 0); // Additional vars later, pm ordering is mostly different from post ordering. :/ - $sort_days = request_var('st', 0); - $sort_key = request_var('sk', 't'); - $sort_dir = request_var('sd', 'd'); + $sort_days = $request->variable('st', 0); + $sort_key = $request->variable('sk', 't'); + $sort_dir = $request->variable('sd', 'd'); + /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); // PM ordering options diff --git a/phpBB/includes/ucp/ucp_pm_viewmessage.php b/phpBB/includes/ucp/ucp_pm_viewmessage.php index e513b8ade2..2457ea9a2e 100644 --- a/phpBB/includes/ucp/ucp_pm_viewmessage.php +++ b/phpBB/includes/ucp/ucp_pm_viewmessage.php @@ -1,9 +1,13 @@ <?php /** * -* @package ucp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -20,7 +24,7 @@ if (!defined('IN_PHPBB')) */ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row) { - global $user, $template, $auth, $db, $cache, $phpbb_container; + global $user, $template, $auth, $db, $phpbb_container; global $phpbb_root_path, $request, $phpEx, $config, $phpbb_dispatcher; $user->add_lang(array('viewtopic', 'memberlist')); @@ -28,7 +32,7 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row) $msg_id = (int) $msg_id; $folder_id = (int) $folder_id; $author_id = (int) $message_row['author_id']; - $view = request_var('view', ''); + $view = $request->variable('view', ''); // Not able to view message, it was deleted by the sender if ($message_row['pm_deleted']) @@ -46,24 +50,13 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row) trigger_error('NO_AUTH_READ_HOLD_MESSAGE'); } - // Grab icons - $icons = $cache->obtain_icons(); - - $bbcode = false; - - // Instantiate BBCode if need be - if ($message_row['bbcode_bitfield']) - { - include($phpbb_root_path . 'includes/bbcode.' . $phpEx); - $bbcode = new bbcode($message_row['bbcode_bitfield']); - } - // Load the custom profile fields if ($config['load_cpf_pm']) { + /* @var $cp \phpbb\profilefields\manager */ $cp = $phpbb_container->get('profilefields.manager'); - $profile_fields = $cp->generate_profile_fields_template('grab', $author_id); + $profile_fields = $cp->grab_profile_fields_data($author_id); } // Assign TO/BCC Addresses to template @@ -81,7 +74,16 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row) // Editing information if ($message_row['message_edit_count'] && $config['display_last_edited']) { - $l_edited_by = '<br /><br />' . $user->lang('EDITED_TIMES_TOTAL', (int) $message_row['message_edit_count'], (!$message_row['message_edit_user']) ? $message_row['username'] : $message_row['message_edit_user'], $user->format_date($message_row['message_edit_time'], false, true)); + if (!$message_row['message_edit_user']) + { + $display_username = get_username_string('full', $author_id, $user_info['username'], $user_info['user_colour']); + } + else + { + $edit_user_info = get_user_information($message_row['message_edit_user'], false); + $display_username = get_username_string('full', $message_row['message_edit_user'], $edit_user_info['username'], $edit_user_info['user_colour']); + } + $l_edited_by = '<br /><br />' . $user->lang('EDITED_TIMES_TOTAL', (int) $message_row['message_edit_count'], $display_username, $user->format_date($message_row['message_edit_time'], false, true)); } else { @@ -173,10 +175,22 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row) if (isset($profile_fields[$author_id])) { - $cp_row = $cp->generate_profile_fields_template('show', false, $profile_fields[$author_id]); + $cp_row = $cp->generate_profile_fields_template_data($profile_fields[$author_id]); } } + $u_pm = $u_jabber = ''; + + if ($config['allow_privmsg'] && $auth->acl_get('u_sendpm') && ($user_info['user_allow_pm'] || $auth->acl_gets('a_', 'm_') || $auth->acl_getf_global('m_'))) + { + $u_pm = append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&mode=compose&u=' . $author_id); + } + + if ($config['jab_enable'] && $user_info['user_jabber'] && $auth->acl_get('u_sendim')) + { + $u_jabber = append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=contact&action=jabber&u=' . $author_id); + } + $msg_data = array( 'MESSAGE_AUTHOR_FULL' => get_username_string('full', $author_id, $user_info['username'], $user_info['user_colour'], $user_info['username']), 'MESSAGE_AUTHOR_COLOUR' => get_username_string('colour', $author_id, $user_info['username'], $user_info['user_colour'], $user_info['username']), @@ -188,6 +202,8 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row) 'AUTHOR_AVATAR' => (isset($user_info['avatar'])) ? $user_info['avatar'] : '', 'AUTHOR_JOINED' => $user->format_date($user_info['user_regdate']), 'AUTHOR_POSTS' => (int) $user_info['user_posts'], + 'U_AUTHOR_POSTS' => ($config['load_search'] && $auth->acl_get('u_search')) ? append_sid("{$phpbb_root_path}search.$phpEx", "author_id=$author_id&sr=posts") : '', + 'CONTACT_USER' => $user->lang('CONTACT_USER', get_username_string('username', $author_id, $user_info['username'], $user_info['user_colour'], $user_info['username'])), 'ONLINE_IMG' => (!$config['load_onlinetrack']) ? '' : ((isset($user_info['online']) && $user_info['online']) ? $user->img('icon_user_online', $user->lang['ONLINE']) : $user->img('icon_user_offline', $user->lang['OFFLINE'])), 'S_ONLINE' => (!$config['load_onlinetrack']) ? false : ((isset($user_info['online']) && $user_info['online']) ? true : false), @@ -208,17 +224,12 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row) 'EDITED_MESSAGE' => $l_edited_by, 'MESSAGE_ID' => $message_row['msg_id'], - 'U_PM' => ($config['allow_privmsg'] && $auth->acl_get('u_sendpm') && ($user_info['user_allow_pm'] || $auth->acl_gets('a_', 'm_') || $auth->acl_getf_global('m_'))) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&mode=compose&u=' . $author_id) : '', - 'U_WWW' => (!empty($user_info['user_website'])) ? $user_info['user_website'] : '', - 'U_ICQ' => ($user_info['user_icq']) ? 'http://www.icq.com/people/' . urlencode($user_info['user_icq']) . '/' : '', - 'U_AIM' => ($user_info['user_aim'] && $auth->acl_get('u_sendim')) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=contact&action=aim&u=' . $author_id) : '', - 'U_YIM' => ($user_info['user_yim']) ? 'http://edit.yahoo.com/config/send_webmesg?.target=' . urlencode($user_info['user_yim']) . '&.src=pg' : '', - 'U_MSN' => ($user_info['user_msnm'] && $auth->acl_get('u_sendim')) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=contact&action=msnm&u=' . $author_id) : '', - 'U_JABBER' => ($user_info['user_jabber'] && $auth->acl_get('u_sendim')) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=contact&action=jabber&u=' . $author_id) : '', + 'U_PM' => $u_pm, + 'U_JABBER' => $u_jabber, 'U_DELETE' => ($auth->acl_get('u_pm_delete')) ? "$url&mode=compose&action=delete&f=$folder_id&p=" . $message_row['msg_id'] : '', 'U_EMAIL' => $user_info['email'], - 'U_REPORT' => ($config['allow_pm_report']) ? append_sid("{$phpbb_root_path}report.$phpEx", "pm=" . $message_row['msg_id']) : '', + 'U_REPORT' => ($config['allow_pm_report']) ? $phpbb_container->get('controller.helper')->route('phpbb_report_pm_controller', array('id' => $message_row['msg_id'])) : '', 'U_QUOTE' => ($auth->acl_get('u_sendpm') && $author_id != ANONYMOUS) ? "$url&mode=compose&action=quote&f=$folder_id&p=" . $message_row['msg_id'] : '', 'U_EDIT' => (($message_row['message_time'] > time() - ($config['pm_edit_time'] * 60) || !$config['pm_edit_time']) && $folder_id == PRIVMSGS_OUTBOX && $auth->acl_get('u_pm_edit')) ? "$url&mode=compose&action=edit&f=$folder_id&p=" . $message_row['msg_id'] : '', 'U_POST_REPLY_PM' => ($auth->acl_get('u_sendpm') && $author_id != ANONYMOUS) ? "$url&mode=compose&action=reply&f=$folder_id&p=" . $message_row['msg_id'] : '', @@ -229,7 +240,6 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row) 'U_PM_ACTION' => $url . '&mode=compose&f=' . $folder_id . '&p=' . $message_row['msg_id'], 'S_HAS_ATTACHMENTS' => (sizeof($attachments)) ? true : false, - 'S_HAS_MULTIPLE_ATTACHMENTS' => (sizeof($attachments) > 1), 'S_DISPLAY_NOTICE' => $display_notice && $message_row['message_attachment'], 'S_AUTHOR_DELETED' => ($author_id == ANONYMOUS) ? true : false, 'S_SPECIAL_FOLDER' => in_array($folder_id, array(PRIVMSGS_NO_BOX, PRIVMSGS_OUTBOX)), @@ -253,13 +263,51 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row) * @var array message_row Array with message data * @var array cp_row Array with senders custom profile field data * @var array msg_data Template array with message data - * @since 3.1-A1 + * @var array user_info User data of the sender + * @since 3.1.0-a1 + * @changed 3.1.6-RC1 Added user_info into event */ - $vars = array('id', 'mode', 'folder_id', 'msg_id', 'folder', 'message_row', 'cp_row', 'msg_data'); + $vars = array( + 'id', + 'mode', + 'folder_id', + 'msg_id', + 'folder', + 'message_row', + 'cp_row', + 'msg_data', + 'user_info', + ); extract($phpbb_dispatcher->trigger_event('core.ucp_pm_view_messsage', compact($vars))); $template->assign_vars($msg_data); + $contact_fields = array( + array( + 'ID' => 'pm', + 'NAME' => $user->lang['SEND_PRIVATE_MESSAGE'], + 'U_CONTACT' => $u_pm, + ), + array( + 'ID' => 'email', + 'NAME' => $user->lang['SEND_EMAIL'], + 'U_CONTACT' => $user_info['email'], + ), + array( + 'ID' => 'jabber', + 'NAME' => $user->lang['JABBER'], + 'U_CONTACT' => $u_jabber, + ), + ); + + foreach ($contact_fields as $field) + { + if ($field['U_CONTACT']) + { + $template->assign_block_vars('contact', $field); + } + } + // Display the custom profile fields if (!empty($cp_row['row'])) { @@ -268,18 +316,21 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row) foreach ($cp_row['blockrow'] as $cp_block_row) { $template->assign_block_vars('custom_fields', $cp_block_row); + + if ($cp_block_row['S_PROFILE_CONTACT']) + { + $template->assign_block_vars('contact', array( + 'ID' => $cp_block_row['PROFILE_FIELD_IDENT'], + 'NAME' => $cp_block_row['PROFILE_FIELD_NAME'], + 'U_CONTACT' => $cp_block_row['PROFILE_FIELD_CONTACT'], + )); + } } } // Display not already displayed Attachments for this post, we already parsed them. ;) if (isset($attachments) && sizeof($attachments)) { - $methods = phpbb_gen_download_links('msg_id', $msg_id, $phpbb_root_path, $phpEx); - foreach ($methods as $method) - { - $template->assign_block_vars('dl_method', $method); - } - foreach ($attachments as $attachment) { $template->assign_block_vars('attachment', array( @@ -303,7 +354,7 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row) */ function get_user_information($user_id, $user_row) { - global $db, $auth, $user, $cache; + global $db, $auth, $user; global $phpbb_root_path, $phpEx, $config; if (!$user_id) @@ -343,14 +394,17 @@ function get_user_information($user_id, $user_row) } } - if (!function_exists('phpbb_get_user_avatar')) + $user_row['avatar'] = ($user->optionget('viewavatars')) ? phpbb_get_user_avatar($user_row) : ''; + + if (!function_exists('phpbb_get_user_rank')) { include($phpbb_root_path . 'includes/functions_display.' . $phpEx); } - $user_row['avatar'] = ($user->optionget('viewavatars')) ? phpbb_get_user_avatar($user_row) : ''; - - get_user_rank($user_row['user_rank'], $user_row['user_posts'], $user_row['rank_title'], $user_row['rank_image'], $user_row['rank_image_src']); + $user_rank_data = phpbb_get_user_rank($user_row, $user_row['user_posts']); + $user_row['rank_title'] = $user_rank_data['title']; + $user_row['rank_image'] = $user_rank_data['img']; + $user_row['rank_image_src'] = $user_rank_data['img_src']; if ((!empty($user_row['user_allow_viewemail']) && $auth->acl_get('u_sendemail')) || $auth->acl_get('a_email')) { diff --git a/phpBB/includes/ucp/ucp_prefs.php b/phpBB/includes/ucp/ucp_prefs.php index e80cc2dce3..c2aa910ed0 100644 --- a/phpBB/includes/ucp/ucp_prefs.php +++ b/phpBB/includes/ucp/ucp_prefs.php @@ -1,9 +1,13 @@ <?php /** * -* @package ucp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -18,7 +22,6 @@ if (!defined('IN_PHPBB')) /** * ucp_prefs * Changing user preferences -* @package ucp */ class ucp_prefs { @@ -26,7 +29,7 @@ class ucp_prefs function main($id, $mode) { - global $config, $db, $user, $auth, $template, $phpbb_dispatcher, $phpbb_root_path, $phpEx; + global $config, $db, $user, $auth, $template, $phpbb_dispatcher, $request; $submit = (isset($_POST['submit'])) ? true : false; $error = $data = array(); @@ -37,16 +40,16 @@ class ucp_prefs case 'personal': add_form_key('ucp_prefs_personal'); $data = array( - 'notifymethod' => request_var('notifymethod', $user->data['user_notify_type']), - 'dateformat' => request_var('dateformat', $user->data['user_dateformat'], true), - 'lang' => basename(request_var('lang', $user->data['user_lang'])), - 'style' => request_var('style', (int) $user->data['user_style']), - 'tz' => request_var('tz', $user->data['user_timezone']), - - 'viewemail' => request_var('viewemail', (bool) $user->data['user_allow_viewemail']), - 'massemail' => request_var('massemail', (bool) $user->data['user_allow_massemail']), - 'hideonline' => request_var('hideonline', (bool) !$user->data['user_allow_viewonline']), - 'allowpm' => request_var('allowpm', (bool) $user->data['user_allow_pm']), + 'notifymethod' => $request->variable('notifymethod', $user->data['user_notify_type']), + 'dateformat' => $request->variable('dateformat', $user->data['user_dateformat'], true), + 'lang' => basename($request->variable('lang', $user->data['user_lang'])), + 'user_style' => $request->variable('user_style', (int) $user->data['user_style']), + 'tz' => $request->variable('tz', $user->data['user_timezone']), + + 'viewemail' => $request->variable('viewemail', (bool) $user->data['user_allow_viewemail']), + 'massemail' => $request->variable('massemail', (bool) $user->data['user_allow_massemail']), + 'hideonline' => $request->variable('hideonline', (bool) !$user->data['user_allow_viewonline']), + 'allowpm' => $request->variable('allowpm', (bool) $user->data['user_allow_pm']), ); if ($data['notifymethod'] == NOTIFY_IM && (!$config['jab_enable'] || !$user->data['user_jabber'] || !@extension_loaded('xml'))) @@ -64,27 +67,29 @@ class ucp_prefs * @var bool submit Do we display the form only * or did the user press submit * @var array data Array with current ucp options data - * @since 3.1-A1 + * @var array error Array with list of errors + * @since 3.1.0-a1 + * @changed 3.1.4-RC1 Added error variable to the event */ - $vars = array('submit', 'data'); + $vars = array('submit', 'data', 'error'); extract($phpbb_dispatcher->trigger_event('core.ucp_prefs_personal_data', compact($vars))); if ($submit) { if ($config['override_user_style']) { - $data['style'] = (int) $config['default_style']; + $data['user_style'] = (int) $config['default_style']; } - else if (!phpbb_style_is_active($data['style'])) + else if (!phpbb_style_is_active($data['user_style'])) { - $data['style'] = (int) $user->data['user_style']; + $data['user_style'] = (int) $user->data['user_style']; } - $error = validate_data($data, array( - 'dateformat' => array('string', false, 1, 30), + $error = array_merge(validate_data($data, array( + 'dateformat' => array('string', false, 1, 64), 'lang' => array('language_iso_name'), 'tz' => array('timezone'), - )); + )), $error); if (!check_form_key('ucp_prefs_personal')) { @@ -104,7 +109,7 @@ class ucp_prefs 'user_dateformat' => $data['dateformat'], 'user_lang' => $data['lang'], 'user_timezone' => $data['tz'], - 'user_style' => $data['style'], + 'user_style' => $data['user_style'], ); /** @@ -112,8 +117,8 @@ class ucp_prefs * * @event core.ucp_prefs_personal_update_data * @var array data Submitted display options data - * @var array sql_ary Display options data we udpate - * @since 3.1-A1 + * @var array sql_ary Display options data we update + * @since 3.1.0-a1 */ $vars = array('data', 'sql_ary'); extract($phpbb_dispatcher->trigger_event('core.ucp_prefs_personal_update_data', compact($vars))); @@ -151,7 +156,7 @@ class ucp_prefs } $dateformat_options .= '>' . $user->lang['CUSTOM_DATEFORMAT'] . '</option>'; - $timezone_selects = phpbb_timezone_select($user, $data['tz'], true); + phpbb_timezone_select($template, $user, $data['tz'], true); // check if there are any user-selectable languages $sql = 'SELECT COUNT(lang_id) as languages_count @@ -204,9 +209,7 @@ class ucp_prefs 'S_MORE_STYLES' => $s_more_styles, 'S_LANG_OPTIONS' => language_select($data['lang']), - 'S_STYLE_OPTIONS' => ($config['override_user_style']) ? '' : style_select($data['style']), - 'S_TZ_OPTIONS' => $timezone_selects['tz_select'], - 'S_TZ_DATE_OPTIONS' => $timezone_selects['tz_dates'], + 'S_STYLE_OPTIONS' => ($config['override_user_style']) ? '' : style_select($data['user_style']), 'S_CAN_HIDE_ONLINE' => ($auth->acl_get('u_hideonline')) ? true : false, 'S_SELECT_NOTIFY' => ($config['jab_enable'] && $user->data['user_jabber'] && @extension_loaded('xml')) ? true : false) ); @@ -218,20 +221,20 @@ class ucp_prefs add_form_key('ucp_prefs_view'); $data = array( - 'topic_sk' => request_var('topic_sk', (!empty($user->data['user_topic_sortby_type'])) ? $user->data['user_topic_sortby_type'] : 't'), - 'topic_sd' => request_var('topic_sd', (!empty($user->data['user_topic_sortby_dir'])) ? $user->data['user_topic_sortby_dir'] : 'd'), - 'topic_st' => request_var('topic_st', (!empty($user->data['user_topic_show_days'])) ? $user->data['user_topic_show_days'] : 0), - - 'post_sk' => request_var('post_sk', (!empty($user->data['user_post_sortby_type'])) ? $user->data['user_post_sortby_type'] : 't'), - 'post_sd' => request_var('post_sd', (!empty($user->data['user_post_sortby_dir'])) ? $user->data['user_post_sortby_dir'] : 'a'), - 'post_st' => request_var('post_st', (!empty($user->data['user_post_show_days'])) ? $user->data['user_post_show_days'] : 0), - - 'images' => request_var('images', (bool) $user->optionget('viewimg')), - 'flash' => request_var('flash', (bool) $user->optionget('viewflash')), - 'smilies' => request_var('smilies', (bool) $user->optionget('viewsmilies')), - 'sigs' => request_var('sigs', (bool) $user->optionget('viewsigs')), - 'avatars' => request_var('avatars', (bool) $user->optionget('viewavatars')), - 'wordcensor' => request_var('wordcensor', (bool) $user->optionget('viewcensors')), + 'topic_sk' => $request->variable('topic_sk', (!empty($user->data['user_topic_sortby_type'])) ? $user->data['user_topic_sortby_type'] : 't'), + 'topic_sd' => $request->variable('topic_sd', (!empty($user->data['user_topic_sortby_dir'])) ? $user->data['user_topic_sortby_dir'] : 'd'), + 'topic_st' => $request->variable('topic_st', (!empty($user->data['user_topic_show_days'])) ? (int) $user->data['user_topic_show_days'] : 0), + + 'post_sk' => $request->variable('post_sk', (!empty($user->data['user_post_sortby_type'])) ? $user->data['user_post_sortby_type'] : 't'), + 'post_sd' => $request->variable('post_sd', (!empty($user->data['user_post_sortby_dir'])) ? $user->data['user_post_sortby_dir'] : 'a'), + 'post_st' => $request->variable('post_st', (!empty($user->data['user_post_show_days'])) ? (int) $user->data['user_post_show_days'] : 0), + + 'images' => $request->variable('images', (bool) $user->optionget('viewimg')), + 'flash' => $request->variable('flash', (bool) $user->optionget('viewflash')), + 'smilies' => $request->variable('smilies', (bool) $user->optionget('viewsmilies')), + 'sigs' => $request->variable('sigs', (bool) $user->optionget('viewsigs')), + 'avatars' => $request->variable('avatars', (bool) $user->optionget('viewavatars')), + 'wordcensor' => $request->variable('wordcensor', (bool) $user->optionget('viewcensors')), ); /** @@ -243,7 +246,7 @@ class ucp_prefs * @var bool submit Do we display the form only * or did the user press submit * @var array data Array with current ucp options data - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('submit', 'data'); extract($phpbb_dispatcher->trigger_event('core.ucp_prefs_view_data', compact($vars))); @@ -251,10 +254,22 @@ class ucp_prefs if ($submit) { $error = validate_data($data, array( - 'topic_sk' => array('string', false, 1, 1), - 'topic_sd' => array('string', false, 1, 1), - 'post_sk' => array('string', false, 1, 1), - 'post_sd' => array('string', false, 1, 1), + 'topic_sk' => array( + array('string', false, 1, 1), + array('match', false, '#(a|r|s|t|v)#'), + ), + 'topic_sd' => array( + array('string', false, 1, 1), + array('match', false, '#(a|d)#'), + ), + 'post_sk' => array( + array('string', false, 1, 1), + array('match', false, '#(a|s|t)#'), + ), + 'post_sd' => array( + array('string', false, 1, 1), + array('match', false, '#(a|d)#'), + ), )); if (!check_form_key('ucp_prefs_view')) @@ -291,8 +306,8 @@ class ucp_prefs * * @event core.ucp_prefs_view_update_data * @var array data Submitted display options data - * @var array sql_ary Display options data we udpate - * @since 3.1-A1 + * @var array sql_ary Display options data we update + * @since 3.1.0-a1 */ $vars = array('data', 'sql_ary'); extract($phpbb_dispatcher->trigger_event('core.ucp_prefs_view_update_data', compact($vars))); @@ -317,7 +332,7 @@ class ucp_prefs $limit_topic_days = array(0 => $user->lang['ALL_TOPICS'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']); $sort_by_topic_text = array('a' => $user->lang['AUTHOR'], 't' => $user->lang['POST_TIME'], 'r' => $user->lang['REPLIES'], 's' => $user->lang['SUBJECT'], 'v' => $user->lang['VIEWS']); - $sort_by_topic_sql = array('a' => 't.topic_first_poster_name', 't' => 't.topic_last_post_time', 'r' => 't.topic_posts_approved', 's' => 't.topic_title', 'v' => 't.topic_views'); + $sort_by_topic_sql = array('a' => 't.topic_first_poster_name', 't' => array('t.topic_last_post_time', 't.topic_last_post_id'), 'r' => 't.topic_posts_approved', 's' => 't.topic_title', 'v' => 't.topic_views'); // Post ordering options $limit_post_days = array(0 => $user->lang['ALL_POSTS'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']); @@ -353,6 +368,49 @@ class ucp_prefs ${'s_sort_' . $sort_option . '_dir'} .= '</select>'; } + /** + * Run code before view form is displayed + * + * @event core.ucp_prefs_view_after + * @var bool submit Do we display the form only + * or did the user press submit + * @var array data Array with current ucp options data + * @var array sort_dir_text Array with sort dir language strings + * @var array limit_topic_days Topic ordering options + * @var array sort_by_topic_text Topic ordering language strings + * @var array sort_by_topic_sql Topic ordering sql + * @var array limit_post_days Post ordering options + * @var array sort_by_post_text Post ordering language strings + * @var array sort_by_post_sql Post ordering sql + * @var array _options Sort options + * @var string s_limit_topic_days Sort limit topic by days select box + * @var string s_sort_topic_key Sort topic key select box + * @var string s_sort_topic_dir Sort topic dir select box + * @var string s_limit_post_days Sort limit post by days select box + * @var string s_sort_post_key Sort post key select box + * @var string s_sort_post_dir Sort post dir select box + * @since 3.1.8-RC1 + */ + $vars = array( + 'submit', + 'data', + 'sort_dir_text', + 'limit_topic_days', + 'sort_by_topic_text', + 'sort_by_topic_sql', + 'limit_post_days', + 'sort_by_post_text', + 'sort_by_post_sql', + '_options', + 's_limit_topic_days', + 's_sort_topic_key', + 's_sort_topic_dir', + 's_limit_post_days', + 's_sort_post_key', + 's_sort_post_dir', + ); + extract($phpbb_dispatcher->trigger_event('core.ucp_prefs_view_after', compact($vars))); + $template->assign_vars(array( 'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '', @@ -378,10 +436,10 @@ class ucp_prefs case 'post': $data = array( - 'bbcode' => request_var('bbcode', $user->optionget('bbcode')), - 'smilies' => request_var('smilies', $user->optionget('smilies')), - 'sig' => request_var('sig', $user->optionget('attachsig')), - 'notify' => request_var('notify', (bool) $user->data['user_notify']), + 'bbcode' => $request->variable('bbcode', $user->optionget('bbcode')), + 'smilies' => $request->variable('smilies', $user->optionget('smilies')), + 'sig' => $request->variable('sig', $user->optionget('attachsig')), + 'notify' => $request->variable('notify', (bool) $user->data['user_notify']), ); add_form_key('ucp_prefs_post'); @@ -394,7 +452,7 @@ class ucp_prefs * @var bool submit Do we display the form only * or did the user press submit * @var array data Array with current ucp options data - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('submit', 'data'); extract($phpbb_dispatcher->trigger_event('core.ucp_prefs_post_data', compact($vars))); @@ -417,8 +475,8 @@ class ucp_prefs * * @event core.ucp_prefs_post_update_data * @var array data Submitted display options data - * @var array sql_ary Display options data we udpate - * @since 3.1-A1 + * @var array sql_ary Display options data we update + * @since 3.1.0-a1 */ $vars = array('data', 'sql_ary'); extract($phpbb_dispatcher->trigger_event('core.ucp_prefs_post_update_data', compact($vars))); @@ -448,6 +506,24 @@ class ucp_prefs break; } + /** + * Modify UCP preferences data before the page load + * + * @event core.ucp_prefs_modify_common + * @var array data Array with current/submitted UCP options data + * @var array error Errors data + * @var string mode UCP prefs operation mode + * @var string s_hidden_fields Hidden fields data + * @since 3.1.0-RC3 + */ + $vars = array( + 'data', + 'error', + 'mode', + 's_hidden_fields', + ); + extract($phpbb_dispatcher->trigger_event('core.ucp_prefs_modify_common', compact($vars))); + $template->assign_vars(array( 'L_TITLE' => $user->lang['UCP_PREFS_' . strtoupper($mode)], diff --git a/phpBB/includes/ucp/ucp_profile.php b/phpBB/includes/ucp/ucp_profile.php index 8def48b1b4..4ac8e0f17d 100644 --- a/phpBB/includes/ucp/ucp_profile.php +++ b/phpBB/includes/ucp/ucp_profile.php @@ -1,9 +1,13 @@ <?php /** * -* @package ucp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -20,7 +24,6 @@ if (!defined('IN_PHPBB')) * Changing profile settings * * @todo what about pertaining user_sig_options? -* @package ucp */ class ucp_profile { @@ -28,14 +31,12 @@ class ucp_profile function main($id, $mode) { - global $cache, $config, $db, $user, $auth, $template, $phpbb_root_path, $phpEx; - global $request, $phpbb_container; + global $config, $db, $user, $auth, $template, $phpbb_root_path, $phpEx; + global $request, $phpbb_container, $phpbb_log, $phpbb_dispatcher; $user->add_lang('posting'); - $preview = $request->variable('preview', false, false, \phpbb\request\request_interface::POST); $submit = $request->variable('submit', false, false, \phpbb\request\request_interface::POST); - $delete = $request->variable('delete', false, false, \phpbb\request\request_interface::POST); $error = $data = array(); $s_hidden_fields = ''; @@ -44,13 +45,24 @@ class ucp_profile case 'reg_details': $data = array( - 'username' => utf8_normalize_nfc(request_var('username', $user->data['username'], true)), - 'email' => strtolower(request_var('email', $user->data['user_email'])), + 'username' => $request->variable('username', $user->data['username'], true), + 'email' => strtolower($request->variable('email', $user->data['user_email'])), 'new_password' => $request->variable('new_password', '', true), 'cur_password' => $request->variable('cur_password', '', true), 'password_confirm' => $request->variable('password_confirm', '', true), ); + /** + * Modify user registration data on editing account settings in UCP + * + * @event core.ucp_profile_reg_details_data + * @var array data Array with current or updated user registration data + * @var bool submit Flag indicating if submit button has been pressed + * @since 3.1.4-RC1 + */ + $vars = array('data', 'submit'); + extract($phpbb_dispatcher->trigger_event('core.ucp_profile_reg_details_data', compact($vars))); + add_form_key('ucp_reg_details'); if ($submit) @@ -63,7 +75,7 @@ class ucp_profile 'password_confirm' => array('string', true, $config['min_pass_chars'], $config['max_pass_chars']), 'email' => array( array('string', false, 6, 60), - array('email')), + array('user_email')), ); if ($auth->acl_get('u_chgname') && $config['allow_namechange']) @@ -82,6 +94,7 @@ class ucp_profile } // Instantiate passwords manager + /* @var $passwords_manager \phpbb\passwords\manager */ $passwords_manager = $phpbb_container->get('passwords.manager'); // Only check the new password against the previous password if there have been no errors @@ -100,6 +113,18 @@ class ucp_profile $error[] = 'FORM_INVALID'; } + /** + * Validate user data on editing registration data in UCP + * + * @event core.ucp_profile_reg_details_validate + * @var array data Array with user profile data + * @var bool submit Flag indicating if submit button has been pressed + * @var array error Array of any generated errors + * @since 3.1.4-RC1 + */ + $vars = array('data', 'submit', 'error'); + extract($phpbb_dispatcher->trigger_event('core.ucp_profile_reg_details_validate', compact($vars))); + if (!sizeof($error)) { $sql_ary = array( @@ -113,18 +138,30 @@ class ucp_profile if ($auth->acl_get('u_chgname') && $config['allow_namechange'] && $data['username'] != $user->data['username']) { - add_log('user', $user->data['user_id'], 'LOG_USER_UPDATE_NAME', $user->data['username'], $data['username']); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_UPDATE_NAME', false, array( + 'reportee_id' => $user->data['user_id'], + $user->data['username'], + $data['username'] + )); } if ($auth->acl_get('u_chgpasswd') && $data['new_password'] && !$passwords_manager->check($data['new_password'], $user->data['user_password'])) { $user->reset_login_keys(); - add_log('user', $user->data['user_id'], 'LOG_USER_NEW_PASSWORD', $data['username']); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_NEW_PASSWORD', false, array( + 'reportee_id' => $user->data['user_id'], + $user->data['username'] + )); } if ($auth->acl_get('u_chgemail') && $data['email'] != $user->data['user_email']) { - add_log('user', $user->data['user_id'], 'LOG_USER_UPDATE_EMAIL', $data['username'], $user->data['user_email'], $data['email']); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_UPDATE_EMAIL', false, array( + 'reportee_id' => $user->data['user_id'], + $user->data['username'], + $data['user_email'], + $data['email'] + )); } $message = 'PROFILE_UPDATED'; @@ -157,37 +194,12 @@ class ucp_profile if ($config['require_activation'] == USER_ACTIVATION_ADMIN) { - // Grab an array of user_id's with a_user permissions ... these users can activate a user - $admin_ary = $auth->acl_get_list(false, 'a_user', false); - $admin_ary = (!empty($admin_ary[0]['a_user'])) ? $admin_ary[0]['a_user'] : array(); - - // Also include founders - $where_sql = ' WHERE user_type = ' . USER_FOUNDER; - - if (sizeof($admin_ary)) - { - $where_sql .= ' OR ' . $db->sql_in_set('user_id', $admin_ary); - } - - $sql = 'SELECT user_id, username, user_email, user_lang, user_jabber, user_notify_type - FROM ' . USERS_TABLE . ' ' . - $where_sql; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - $messenger->template('admin_activate', $row['user_lang']); - $messenger->set_addresses($row); - - $messenger->assign_vars(array( - 'USERNAME' => htmlspecialchars_decode($data['username']), - 'U_USER_DETAILS' => "$server_url/memberlist.$phpEx?mode=viewprofile&u={$user->data['user_id']}", - 'U_ACTIVATE' => "$server_url/ucp.$phpEx?mode=activate&u={$user->data['user_id']}&k=$user_actkey") - ); - - $messenger->send($row['user_notify_type']); - } - $db->sql_freeresult($result); + $notifications_manager = $phpbb_container->get('notification_manager'); + $notifications_manager->add_notifications('notification.type.admin_activate_user', array( + 'user_id' => $user->data['user_id'], + 'user_actkey' => $user_actkey, + 'user_regdate' => time(), // Notification time + )); } user_active_flip('deactivate', $user->data['user_id'], INACTIVE_PROFILE); @@ -197,6 +209,17 @@ class ucp_profile $sql_ary['user_newpasswd'] = ''; } + /** + * Modify user registration data before submitting it to the database + * + * @event core.ucp_profile_reg_details_sql_ary + * @var array data Array with current or updated user registration data + * @var array sql_ary Array with user registration data to submit to the database + * @since 3.1.4-RC1 + */ + $vars = array('data', 'sql_ary'); + extract($phpbb_dispatcher->trigger_event('core.ucp_profile_reg_details_sql_ary', compact($vars))); + if (sizeof($sql_ary)) { $sql = 'UPDATE ' . USERS_TABLE . ' @@ -259,17 +282,13 @@ class ucp_profile trigger_error('NO_AUTH_PROFILEINFO'); } + /* @var $cp \phpbb\profilefields\manager */ $cp = $phpbb_container->get('profilefields.manager'); $cp_data = $cp_error = array(); $data = array( - 'icq' => request_var('icq', $user->data['user_icq']), - 'aim' => request_var('aim', $user->data['user_aim']), - 'msn' => request_var('msn', $user->data['user_msnm']), - 'yim' => request_var('yim', $user->data['user_yim']), - 'jabber' => utf8_normalize_nfc(request_var('jabber', $user->data['user_jabber'], true)), - 'website' => request_var('website', $user->data['user_website']), + 'jabber' => $request->variable('jabber', $user->data['user_jabber'], true), ); if ($config['allow_birthdays']) @@ -281,29 +300,31 @@ class ucp_profile list($data['bday_day'], $data['bday_month'], $data['bday_year']) = explode('-', $user->data['user_birthday']); } - $data['bday_day'] = request_var('bday_day', $data['bday_day']); - $data['bday_month'] = request_var('bday_month', $data['bday_month']); - $data['bday_year'] = request_var('bday_year', $data['bday_year']); + $data['bday_day'] = $request->variable('bday_day', $data['bday_day']); + $data['bday_month'] = $request->variable('bday_month', $data['bday_month']); + $data['bday_year'] = $request->variable('bday_year', $data['bday_year']); $data['user_birthday'] = sprintf('%2d-%2d-%4d', $data['bday_day'], $data['bday_month'], $data['bday_year']); } + /** + * Modify user data on editing profile in UCP + * + * @event core.ucp_profile_modify_profile_info + * @var array data Array with user profile data + * @var bool submit Flag indicating if submit button has been pressed + * @since 3.1.4-RC1 + */ + $vars = array('data', 'submit'); + extract($phpbb_dispatcher->trigger_event('core.ucp_profile_modify_profile_info', compact($vars))); + add_form_key('ucp_profile_info'); if ($submit) { $validate_array = array( - 'icq' => array( - array('string', true, 3, 15), - array('match', true, '#^[0-9]+$#i')), - 'aim' => array('string', true, 3, 255), - 'msn' => array('string', true, 5, 255), 'jabber' => array( array('string', true, 5, 255), array('jabber')), - 'yim' => array('string', true, 5, 255), - 'website' => array( - array('string', true, 12, 255), - array('match', true, '#^http[s]?://(.*?\.)*?[a-z0-9\-]+\.[a-z]{2,4}#i')), ); if ($config['allow_birthdays']) @@ -331,6 +352,18 @@ class ucp_profile $error[] = 'FORM_INVALID'; } + /** + * Validate user data on editing profile in UCP + * + * @event core.ucp_profile_validate_profile_info + * @var array data Array with user profile data + * @var bool submit Flag indicating if submit button has been pressed + * @var array error Array of any generated errors + * @since 3.1.4-RC1 + */ + $vars = array('data', 'submit', 'error'); + extract($phpbb_dispatcher->trigger_event('core.ucp_profile_validate_profile_info', compact($vars))); + if (!sizeof($error)) { $data['notify'] = $user->data['user_notify_type']; @@ -343,12 +376,7 @@ class ucp_profile } $sql_ary = array( - 'user_icq' => $data['icq'], - 'user_aim' => $data['aim'], - 'user_msnm' => $data['msn'], - 'user_yim' => $data['yim'], 'user_jabber' => $data['jabber'], - 'user_website' => $data['website'], 'user_notify_type' => $data['notify'], ); @@ -357,6 +385,18 @@ class ucp_profile $sql_ary['user_birthday'] = $data['user_birthday']; } + /** + * Modify profile data in UCP before submitting to the database + * + * @event core.ucp_profile_info_modify_sql_ary + * @var array cp_data Array with the user custom profile fields data + * @var array data Array with user profile data + * @var array sql_ary user options data we update + * @since 3.1.4-RC1 + */ + $vars = array('cp_data', 'data', 'sql_ary'); + extract($phpbb_dispatcher->trigger_event('core.ucp_profile_info_modify_sql_ary', compact($vars))); + $sql = 'UPDATE ' . USERS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' WHERE user_id = ' . $user->data['user_id']; @@ -389,7 +429,6 @@ class ucp_profile $selected = ($i == $data['bday_month']) ? ' selected="selected"' : ''; $s_birthday_month_options .= "<option value=\"$i\"$selected>$i</option>"; } - $s_birthday_year_options = ''; $now = getdate(); $s_birthday_year_options = '<option value="0"' . ((!$data['bday_year']) ? ' selected="selected"' : '') . '>--</option>'; @@ -409,14 +448,9 @@ class ucp_profile } $template->assign_vars(array( - 'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '', - - 'ICQ' => $data['icq'], - 'YIM' => $data['yim'], - 'AIM' => $data['aim'], - 'MSN' => $data['msn'], - 'JABBER' => $data['jabber'], - 'WEBSITE' => $data['website'], + 'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '', + 'S_JABBER_ENABLED' => $config['jab_enable'], + 'JABBER' => $data['jabber'], )); // Get additional profile fields and assign them to the template block var 'profile_fields' @@ -436,86 +470,95 @@ class ucp_profile include($phpbb_root_path . 'includes/functions_posting.' . $phpEx); include($phpbb_root_path . 'includes/functions_display.' . $phpEx); - $enable_bbcode = ($config['allow_sig_bbcode']) ? (bool) $user->optionget('sig_bbcode') : false; - $enable_smilies = ($config['allow_sig_smilies']) ? (bool) $user->optionget('sig_smilies') : false; - $enable_urls = ($config['allow_sig_links']) ? (bool) $user->optionget('sig_links') : false; - - $signature = utf8_normalize_nfc(request_var('signature', (string) $user->data['user_sig'], true)); + $enable_bbcode = ($config['allow_sig_bbcode']) ? $user->optionget('sig_bbcode') : false; + $enable_smilies = ($config['allow_sig_smilies']) ? $user->optionget('sig_smilies') : false; + $enable_urls = ($config['allow_sig_links']) ? $user->optionget('sig_links') : false; - add_form_key('ucp_sig'); + $decoded_message = generate_text_for_edit($user->data['user_sig'], $user->data['user_sig_bbcode_uid'], $user->data['user_sig_bbcode_bitfield']); + $signature = $request->variable('signature', $decoded_message['text'], true); + $signature_preview = ''; - if ($submit || $preview) + if ($submit || $request->is_set_post('preview')) { - include($phpbb_root_path . 'includes/message_parser.' . $phpEx); - - $enable_bbcode = ($config['allow_sig_bbcode']) ? ((request_var('disable_bbcode', false)) ? false : true) : false; - $enable_smilies = ($config['allow_sig_smilies']) ? ((request_var('disable_smilies', false)) ? false : true) : false; - $enable_urls = ($config['allow_sig_links']) ? ((request_var('disable_magic_url', false)) ? false : true) : false; + $enable_bbcode = ($config['allow_sig_bbcode']) ? !$request->variable('disable_bbcode', false) : false; + $enable_smilies = ($config['allow_sig_smilies']) ? !$request->variable('disable_smilies', false) : false; + $enable_urls = ($config['allow_sig_links']) ? !$request->variable('disable_magic_url', false) : false; - if (!sizeof($error)) + if (!check_form_key('ucp_sig')) { - $message_parser = new parse_message($signature); + $error[] = 'FORM_INVALID'; + } + } - // Allowing Quote BBCode - $message_parser->parse($enable_bbcode, $enable_urls, $enable_smilies, $config['allow_sig_img'], $config['allow_sig_flash'], true, $config['allow_sig_links'], true, 'sig'); + $bbcode_uid = $bbcode_bitfield = $bbcode_flags = ''; + $warn_msg = generate_text_for_storage( + $signature, + $bbcode_uid, + $bbcode_bitfield, + $bbcode_flags, + $enable_bbcode, + $enable_urls, + $enable_smilies, + $config['allow_sig_img'], + $config['allow_sig_flash'], + true, + $config['allow_sig_links'], + 'sig' + ); - if (sizeof($message_parser->warn_msg)) - { - $error[] = implode('<br />', $message_parser->warn_msg); - } + if (sizeof($warn_msg)) + { + $error += $warn_msg; + } - if (!check_form_key('ucp_sig')) - { - $error[] = 'FORM_INVALID'; - } + if (!$submit) + { + // Parse it for displaying + $signature_preview = generate_text_for_display($signature, $bbcode_uid, $bbcode_bitfield, $bbcode_flags); + } + else + { + if (!sizeof($error)) + { + $user->optionset('sig_bbcode', $enable_bbcode); + $user->optionset('sig_smilies', $enable_smilies); + $user->optionset('sig_links', $enable_urls); - if (!sizeof($error) && $submit) - { - $user->optionset('sig_bbcode', $enable_bbcode); - $user->optionset('sig_smilies', $enable_smilies); - $user->optionset('sig_links', $enable_urls); - - $sql_ary = array( - 'user_sig' => (string) $message_parser->message, - 'user_options' => $user->data['user_options'], - 'user_sig_bbcode_uid' => (string) $message_parser->bbcode_uid, - 'user_sig_bbcode_bitfield' => $message_parser->bbcode_bitfield - ); + $sql_ary = array( + 'user_sig' => $signature, + 'user_options' => $user->data['user_options'], + 'user_sig_bbcode_uid' => $bbcode_uid, + 'user_sig_bbcode_bitfield' => $bbcode_bitfield + ); - $sql = 'UPDATE ' . USERS_TABLE . ' - SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' - WHERE user_id = ' . $user->data['user_id']; - $db->sql_query($sql); + $sql = 'UPDATE ' . USERS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE user_id = ' . $user->data['user_id']; + $db->sql_query($sql); - $message = $user->lang['PROFILE_UPDATED'] . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>'); - trigger_error($message); - } + $message = $user->lang['PROFILE_UPDATED'] . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>'); + trigger_error($message); } - - // Replace "error" strings with their real, localised form - $error = array_map(array($user, 'lang'), $error); } - $signature_preview = ''; - if ($preview) - { - // Now parse it for displaying - $signature_preview = $message_parser->format_display($enable_bbcode, $enable_urls, $enable_smilies, false); - unset($message_parser); - } + // Replace "error" strings with their real, localised form + $error = array_map(array($user, 'lang'), $error); + + $decoded_message = generate_text_for_edit($signature, $bbcode_uid, $bbcode_bitfield); - decode_message($signature, $user->data['user_sig_bbcode_uid']); + /** @var \phpbb\controller\helper $controller_helper */ + $controller_helper = $phpbb_container->get('controller.helper'); $template->assign_vars(array( 'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '', - 'SIGNATURE' => $signature, + 'SIGNATURE' => $decoded_message['text'], 'SIGNATURE_PREVIEW' => $signature_preview, 'S_BBCODE_CHECKED' => (!$enable_bbcode) ? ' checked="checked"' : '', 'S_SMILIES_CHECKED' => (!$enable_smilies) ? ' checked="checked"' : '', 'S_MAGIC_URL_CHECKED' => (!$enable_urls) ? ' checked="checked"' : '', - 'BBCODE_STATUS' => ($config['allow_sig_bbcode']) ? sprintf($user->lang['BBCODE_IS_ON'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '">', '</a>') : sprintf($user->lang['BBCODE_IS_OFF'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '">', '</a>'), + 'BBCODE_STATUS' => $user->lang(($config['allow_sig_bbcode'] ? 'BBCODE_IS_ON' : 'BBCODE_IS_OFF'), '<a href="' . $controller_helper->route('phpbb_help_bbcode_controller') . '">', '</a>'), 'SMILIES_STATUS' => ($config['allow_sig_smilies']) ? $user->lang['SMILIES_ARE_ON'] : $user->lang['SMILIES_ARE_OFF'], 'IMG_STATUS' => ($config['allow_sig_img']) ? $user->lang['IMAGES_ARE_ON'] : $user->lang['IMAGES_ARE_OFF'], 'FLASH_STATUS' => ($config['allow_sig_flash']) ? $user->lang['FLASH_IS_ON'] : $user->lang['FLASH_IS_OFF'], @@ -531,6 +574,8 @@ class ucp_profile 'S_LINKS_ALLOWED' => ($config['allow_sig_links']) ? true : false) ); + add_form_key('ucp_sig'); + // Build custom bbcodes array display_custom_bbcodes(); @@ -540,10 +585,6 @@ class ucp_profile break; case 'avatar': - if (!function_exists('phpbb_get_user_avatar')) - { - include($phpbb_root_path . 'includes/functions_display.' . $phpEx); - } add_form_key('ucp_avatar'); @@ -551,6 +592,7 @@ class ucp_profile if ($config['allow_avatar'] && $auth->acl_get('u_chgavatar')) { + /* @var $phpbb_avatar_manager \phpbb\avatar\manager */ $phpbb_avatar_manager = $phpbb_container->get('avatar.manager'); $avatar_drivers = $phpbb_avatar_manager->get_enabled_drivers(); @@ -589,30 +631,6 @@ class ucp_profile trigger_error($message); } } - else - { - if ($driver = $phpbb_avatar_manager->get_driver($avatar_data['avatar_type'])) - { - $driver->delete($avatar_data); - } - - $result = array( - 'user_avatar' => '', - 'user_avatar_type' => '', - 'user_avatar_width' => 0, - 'user_avatar_height' => 0, - ); - - $sql = 'UPDATE ' . USERS_TABLE . ' - SET ' . $db->sql_build_array('UPDATE', $result) . ' - WHERE user_id = ' . (int) $user->data['user_id']; - - $db->sql_query($sql); - - meta_refresh(3, $this->u_action); - $message = $user->lang['PROFILE_UPDATED'] . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>'); - trigger_error($message); - } } else { @@ -620,6 +638,27 @@ class ucp_profile } } + // Handle deletion of avatars + if ($request->is_set_post('avatar_delete')) + { + if (!confirm_box(true)) + { + confirm_box(false, $user->lang('CONFIRM_AVATAR_DELETE'), build_hidden_fields(array( + 'avatar_delete' => true, + 'i' => $id, + 'mode' => $mode)) + ); + } + else + { + $phpbb_avatar_manager->handle_avatar_delete($db, $user, $avatar_data, USERS_TABLE, 'user_'); + + meta_refresh(3, $this->u_action); + $message = $user->lang['PROFILE_UPDATED'] . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>'); + trigger_error($message); + } + } + $selected_driver = $phpbb_avatar_manager->clean_driver_name($request->variable('avatar_driver', $user->data['user_avatar_type'])); foreach ($avatar_drivers as $current_driver) @@ -672,7 +711,7 @@ class ucp_profile if ($submit) { - $keys = request_var('keys', array('')); + $keys = $request->variable('keys', array('')); if (!check_form_key('ucp_autologin_keys')) { @@ -683,9 +722,14 @@ class ucp_profile { if (!empty($keys)) { + foreach ($keys as $key => $id) + { + $keys[$key] = $db->sql_like_expression($id . $db->get_any_char()); + } + $sql_where = '(key_id ' . implode(' OR key_id ', $keys) . ')'; $sql = 'DELETE FROM ' . SESSIONS_KEYS_TABLE . ' WHERE user_id = ' . (int) $user->data['user_id'] . ' - AND ' . $db->sql_in_set('key_id', $keys) ; + AND ' . $sql_where ; $db->sql_query($sql); @@ -701,16 +745,15 @@ class ucp_profile $sql = 'SELECT key_id, last_ip, last_login FROM ' . SESSIONS_KEYS_TABLE . ' - WHERE user_id = ' . (int) $user->data['user_id']; + WHERE user_id = ' . (int) $user->data['user_id'] . ' + ORDER BY last_login ASC'; $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) { $template->assign_block_vars('sessions', array( - 'errors' => $error, - - 'KEY' => $row['key_id'], + 'KEY' => substr($row['key_id'], 0, 8), 'IP' => $row['last_ip'], 'LOGIN_TIME' => $user->format_date($row['last_login']), )); @@ -722,6 +765,8 @@ class ucp_profile } $template->assign_vars(array( + 'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '', + 'L_TITLE' => $user->lang['UCP_PROFILE_' . strtoupper($mode)], 'S_HIDDEN_FIELDS' => $s_hidden_fields, diff --git a/phpBB/includes/ucp/ucp_register.php b/phpBB/includes/ucp/ucp_register.php index ff51ca7b3c..1b62790700 100644 --- a/phpBB/includes/ucp/ucp_register.php +++ b/phpBB/includes/ucp/ucp_register.php @@ -1,9 +1,13 @@ <?php /** * -* @package ucp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -18,7 +22,6 @@ if (!defined('IN_PHPBB')) /** * ucp_register * Board registration -* @package ucp */ class ucp_register { @@ -26,11 +29,12 @@ class ucp_register function main($id, $mode) { - global $config, $db, $user, $auth, $template, $phpbb_root_path, $phpEx; - global $request, $phpbb_container; + global $config, $db, $user, $template, $phpbb_root_path, $phpEx; + global $request, $phpbb_container, $phpbb_dispatcher; // - if ($config['require_activation'] == USER_ACTIVATION_DISABLE) + if ($config['require_activation'] == USER_ACTIVATION_DISABLE || + (in_array($config['require_activation'], array(USER_ACTIVATION_SELF, USER_ACTIVATION_ADMIN)) && !$config['email_enable'])) { trigger_error('UCP_REGISTER_DISABLE'); } @@ -38,8 +42,8 @@ class ucp_register $coppa = $request->is_set('coppa') ? (int) $request->variable('coppa', false) : false; $agreed = $request->variable('agreed', false); $submit = $request->is_set_post('submit'); - $change_lang = request_var('change_lang', ''); - $user_lang = request_var('lang', $user->lang_name); + $change_lang = $request->variable('change_lang', ''); + $user_lang = $request->variable('lang', $user->lang_name); if ($agreed) { @@ -64,10 +68,7 @@ class ucp_register $agreed = false; } - $user->lang_name = $user_lang = $use_lang; - $user->lang = array(); - $user->data['user_lang'] = $user->lang_name; - $user->add_lang(array('common', 'ucp')); + $user_lang = $use_lang; } else { @@ -76,6 +77,7 @@ class ucp_register } } + /* @var $cp \phpbb\profilefields\manager */ $cp = $phpbb_container->get('profilefields.manager'); $error = $cp_data = $cp_error = array(); @@ -87,8 +89,9 @@ class ucp_register if (!empty($login_link_data)) { // Confirm that we have all necessary data - $auth_provider = 'auth.provider.' . $request->variable('auth_provider', $config['auth_method']); - $auth_provider = $phpbb_container->get($auth_provider); + /* @var $provider_collection \phpbb\auth\provider_collection */ + $provider_collection = $phpbb_container->get('auth.provider_collection'); + $auth_provider = $provider_collection->get_provider($request->variable('auth_provider', '')); $result = $auth_provider->login_link_has_necessary_data($login_link_data); if ($result !== null) @@ -101,7 +104,6 @@ class ucp_register if (!$agreed || ($coppa === false && $config['coppa_enable']) || ($coppa && !$config['coppa_enable'])) { - $add_lang = ($change_lang) ? '&change_lang=' . urlencode($change_lang) : ''; $add_coppa = ($coppa !== false) ? '&coppa=' . $coppa : ''; $s_hidden_fields = array_merge($s_hidden_fields, array( @@ -113,10 +115,10 @@ class ucp_register { // We do not include the password $s_hidden_fields = array_merge($s_hidden_fields, array( - 'username' => utf8_normalize_nfc(request_var('username', '', true)), - 'email' => strtolower(request_var('email', '')), + 'username' => $request->variable('username', '', true), + 'email' => strtolower($request->variable('email', '')), 'lang' => $user->lang_name, - 'tz' => request_var('tz', $config['board_timezone']), + 'tz' => $request->variable('tz', $config['board_timezone']), )); } @@ -147,12 +149,15 @@ class ucp_register 'L_COPPA_NO' => sprintf($user->lang['UCP_COPPA_BEFORE'], $coppa_birthday), 'L_COPPA_YES' => sprintf($user->lang['UCP_COPPA_ON_AFTER'], $coppa_birthday), - 'U_COPPA_NO' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=register&coppa=0' . $add_lang), - 'U_COPPA_YES' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=register&coppa=1' . $add_lang), + 'U_COPPA_NO' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=register&coppa=0'), + 'U_COPPA_YES' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=register&coppa=1'), 'S_SHOW_COPPA' => true, 'S_HIDDEN_FIELDS' => build_hidden_fields($s_hidden_fields), - 'S_UCP_ACTION' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=register' . $add_lang), + 'S_UCP_ACTION' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=register'), + + 'COOKIE_NAME' => $config['cookie_name'], + 'COOKIE_PATH' => $config['cookie_path'], )); } else @@ -164,12 +169,25 @@ class ucp_register 'S_SHOW_COPPA' => false, 'S_REGISTRATION' => true, 'S_HIDDEN_FIELDS' => build_hidden_fields($s_hidden_fields), - 'S_UCP_ACTION' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=register' . $add_lang . $add_coppa), + 'S_UCP_ACTION' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=register' . $add_coppa), + + 'COOKIE_NAME' => $config['cookie_name'], + 'COOKIE_PATH' => $config['cookie_path'], ) ); } unset($lang_row); + /** + * Allows to modify the agreements. + * + * To assign data to the template, use $template->assign_vars() + * + * @event core.ucp_register_agreement + * @since 3.1.6-RC1 + */ + $phpbb_dispatcher->dispatch('core.ucp_register_agreement'); + $this->tpl_name = 'ucp_agreement'; return; } @@ -177,21 +195,33 @@ class ucp_register // The CAPTCHA kicks in here. We can't help that the information gets lost on language change. if ($config['enable_confirm']) { - include($phpbb_root_path . 'includes/captcha/captcha_factory.' . $phpEx); - $captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']); + $captcha = $phpbb_container->get('captcha.factory')->get_instance($config['captcha_plugin']); $captcha->init(CONFIRM_REG); } $timezone = $config['board_timezone']; $data = array( - 'username' => utf8_normalize_nfc(request_var('username', '', true)), + 'username' => $request->variable('username', '', true), 'new_password' => $request->variable('new_password', '', true), 'password_confirm' => $request->variable('password_confirm', '', true), - 'email' => strtolower(request_var('email', '')), - 'lang' => basename(request_var('lang', $user->lang_name)), - 'tz' => request_var('tz', $timezone), + 'email' => strtolower($request->variable('email', '')), + 'lang' => basename($request->variable('lang', $user->lang_name)), + 'tz' => $request->variable('tz', $timezone), ); + /** + * Add UCP register data before they are assigned to the template or submitted + * + * To assign data to the template, use $template->assign_vars() + * + * @event core.ucp_register_data_before + * @var bool submit Do we display the form only + * or did the user press submit + * @var array data Array with current ucp registration data + * @since 3.1.4-RC1 + */ + $vars = array('submit', 'data'); + extract($phpbb_dispatcher->trigger_event('core.ucp_register_data_before', compact($vars))); // Check and initialize some variables if needed if ($submit) @@ -206,7 +236,7 @@ class ucp_register 'password_confirm' => array('string', false, $config['min_pass_chars'], $config['max_pass_chars']), 'email' => array( array('string', false, 6, 60), - array('email')), + array('user_email')), 'tz' => array('timezone'), 'lang' => array('language_iso_name'), )); @@ -252,6 +282,19 @@ class ucp_register $error[] = $user->lang['NEW_PASSWORD_ERROR']; } } + /** + * Check UCP registration data after they are submitted + * + * @event core.ucp_register_data_after + * @var bool submit Do we display the form only + * or did the user press submit + * @var array data Array with current ucp registration data + * @var array cp_data Array with custom profile fields data + * @var array error Array with list of errors + * @since 3.1.4-RC1 + */ + $vars = array('submit', 'data', 'cp_data', 'error'); + extract($phpbb_dispatcher->trigger_event('core.ucp_register_data_after', compact($vars))); if (!sizeof($error)) { @@ -293,6 +336,7 @@ class ucp_register } // Instantiate passwords manager + /* @var $passwords_manager \phpbb\passwords\manager */ $passwords_manager = $phpbb_container->get('passwords.manager'); $user_row = array( @@ -314,6 +358,20 @@ class ucp_register { $user_row['user_new'] = 1; } + /** + * Add into $user_row before user_add + * + * user_add allows adding more data into the users table + * + * @event core.ucp_register_user_row_after + * @var bool submit Do we display the form only + * or did the user press submit + * @var array cp_data Array with custom profile fields data + * @var array user_row Array with current ucp registration data + * @since 3.1.4-RC1 + */ + $vars = array('submit', 'cp_data', 'user_row'); + extract($phpbb_dispatcher->trigger_event('core.ucp_register_user_row_after', compact($vars))); // Register user... $user_id = user_add($user_row, $cp_data); @@ -384,8 +442,9 @@ class ucp_register if ($config['require_activation'] == USER_ACTIVATION_ADMIN) { + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); - $phpbb_notifications->add_notifications('admin_activate_user', array( + $phpbb_notifications->add_notifications('notification.type.admin_activate_user', array( 'user_id' => $user_id, 'user_actkey' => $user_row['user_actkey'], 'user_regdate' => $user_row['user_regdate'], @@ -425,7 +484,6 @@ class ucp_register $s_hidden_fields = array_merge($s_hidden_fields, $captcha->get_hidden_fields()); } $s_hidden_fields = build_hidden_fields($s_hidden_fields); - $confirm_image = ''; // Visual Confirmation - Show images if ($config['enable_confirm']) @@ -448,7 +506,9 @@ class ucp_register break; } - $timezone_selects = phpbb_timezone_select($user, $data['tz'], true); + // Assign template vars for timezone select + phpbb_timezone_select($template, $user, $data['tz'], true); + $template->assign_vars(array( 'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '', 'USERNAME' => $data['username'], @@ -461,14 +521,15 @@ class ucp_register 'L_PASSWORD_EXPLAIN' => $user->lang($config['pass_complex'] . '_EXPLAIN', $user->lang('CHARACTERS', (int) $config['min_pass_chars']), $user->lang('CHARACTERS', (int) $config['max_pass_chars'])), 'S_LANG_OPTIONS' => language_select($data['lang']), - 'S_TZ_OPTIONS' => $timezone_selects['tz_select'], - 'S_TZ_DATE_OPTIONS' => $timezone_selects['tz_dates'], 'S_TZ_PRESELECT' => !$submit, 'S_CONFIRM_REFRESH' => ($config['enable_confirm'] && $config['confirm_refresh']) ? true : false, 'S_REGISTRATION' => true, 'S_COPPA' => $coppa, 'S_HIDDEN_FIELDS' => $s_hidden_fields, 'S_UCP_ACTION' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=register'), + + 'COOKIE_NAME' => $config['cookie_name'], + 'COOKIE_PATH' => $config['cookie_path'], )); // diff --git a/phpBB/includes/ucp/ucp_remind.php b/phpBB/includes/ucp/ucp_remind.php index 99e945eeae..0a46674fb1 100644 --- a/phpBB/includes/ucp/ucp_remind.php +++ b/phpBB/includes/ucp/ucp_remind.php @@ -1,9 +1,13 @@ <?php /** * -* @package ucp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -18,7 +22,6 @@ if (!defined('IN_PHPBB')) /** * ucp_remind * Sending password reminders -* @package ucp */ class ucp_remind { @@ -26,16 +29,16 @@ class ucp_remind function main($id, $mode) { - global $config, $phpbb_root_path, $phpEx; - global $db, $user, $auth, $template, $phpbb_container; + global $config, $phpbb_root_path, $phpEx, $request; + global $db, $user, $template, $phpbb_container; if (!$config['allow_password_reset']) { trigger_error($user->lang('UCP_PASSWORD_RESET_DISABLED', '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>')); } - $username = request_var('username', '', true); - $email = strtolower(request_var('email', '')); + $username = $request->variable('username', '', true); + $email = strtolower($request->variable('email', '')); $submit = (isset($_POST['submit'])) ? true : false; if ($submit) @@ -89,6 +92,7 @@ class ucp_remind $user_actkey = gen_rand_string(mt_rand(6, 10)); // Instantiate passwords manager + /* @var $manager \phpbb\passwords\manager */ $passwords_manager = $phpbb_container->get('passwords.manager'); $sql = 'UPDATE ' . USERS_TABLE . " diff --git a/phpBB/includes/ucp/ucp_resend.php b/phpBB/includes/ucp/ucp_resend.php index ab396cdec9..44c54100cd 100644 --- a/phpBB/includes/ucp/ucp_resend.php +++ b/phpBB/includes/ucp/ucp_resend.php @@ -1,9 +1,13 @@ <?php /** * -* @package ucp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -18,7 +22,6 @@ if (!defined('IN_PHPBB')) /** * ucp_resend * Resending activation emails -* @package ucp */ class ucp_resend { @@ -27,10 +30,10 @@ class ucp_resend function main($id, $mode) { global $config, $phpbb_root_path, $phpEx; - global $db, $user, $auth, $template; + global $db, $user, $auth, $template, $request; - $username = request_var('username', '', true); - $email = strtolower(request_var('email', '')); + $username = $request->variable('username', '', true); + $email = strtolower($request->variable('email', '')); $submit = (isset($_POST['submit'])) ? true : false; add_form_key('ucp_resend'); diff --git a/phpBB/includes/ucp/ucp_zebra.php b/phpBB/includes/ucp/ucp_zebra.php index 090f9bf34c..fa6a03f87c 100644 --- a/phpBB/includes/ucp/ucp_zebra.php +++ b/phpBB/includes/ucp/ucp_zebra.php @@ -1,9 +1,13 @@ <?php /** * -* @package ucp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -15,17 +19,13 @@ if (!defined('IN_PHPBB')) exit; } -/** -* ucp_zebra -* @package ucp -*/ class ucp_zebra { var $u_action; function main($id, $mode) { - global $config, $db, $user, $auth, $template, $phpbb_root_path, $phpEx, $request, $phpbb_dispatcher; + global $db, $user, $auth, $template, $phpbb_root_path, $phpEx, $request, $phpbb_dispatcher; $submit = (isset($_POST['submit']) || isset($_GET['add']) || isset($_GET['remove'])) ? true : false; $s_hidden_fields = ''; @@ -44,7 +44,7 @@ class ucp_zebra foreach ($var_ary as $var => $default) { - $data[$var] = request_var($var, $default, true); + $data[$var] = $request->variable($var, $default, true); } if (!empty($data['add']) || sizeof($data['usernames'])) @@ -62,7 +62,7 @@ class ucp_zebra * @event core.ucp_remove_zebra * @var string mode Zebra type: friends|foes * @var array user_ids User ids we remove - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('mode', 'user_ids'); extract($phpbb_dispatcher->trigger_event('core.ucp_remove_zebra', compact($vars))); @@ -207,7 +207,7 @@ class ucp_zebra * friends|foes * @var array sql_ary Array of * entries we add - * @since 3.1-A1 + * @since 3.1.0-a1 */ $vars = array('mode', 'sql_ary'); extract($phpbb_dispatcher->trigger_event('core.ucp_add_zebra', compact($vars))); @@ -224,15 +224,15 @@ class ucp_zebra } } } - + if ($request->is_ajax()) { $message = ($updated) ? $user->lang[$l_mode . '_UPDATED'] : implode('<br />', $error); - + $json_response = new \phpbb\json_response; $json_response->send(array( 'success' => $updated, - + 'MESSAGE_TITLE' => $user->lang['INFORMATION'], 'MESSAGE_TEXT' => $message, 'REFRESH_DATA' => array( diff --git a/phpBB/includes/utf/data/utf_canonical_comp.php b/phpBB/includes/utf/data/utf_canonical_comp.php deleted file mode 100644 index 2de3149ee8..0000000000 --- a/phpBB/includes/utf/data/utf_canonical_comp.php +++ /dev/null @@ -1,2 +0,0 @@ -<?php -$GLOBALS['utf_canonical_comp']=array('AÌ€'=>'À','AÌ'=>'Ã','AÌ‚'=>'Â','Ã'=>'Ã','Ä'=>'Ä','AÌŠ'=>'Ã…','Ç'=>'Ç','EÌ€'=>'È','EÌ'=>'É','EÌ‚'=>'Ê','Ë'=>'Ë','IÌ€'=>'ÃŒ','IÌ'=>'Ã','IÌ‚'=>'ÃŽ','Ï'=>'Ã','Ñ'=>'Ñ','OÌ€'=>'Ã’','OÌ'=>'Ó','OÌ‚'=>'Ô','Õ'=>'Õ','Ö'=>'Ö','UÌ€'=>'Ù','UÌ'=>'Ú','UÌ‚'=>'Û','Ü'=>'Ü','YÌ'=>'Ã','aÌ€'=>'à ','aÌ'=>'á','aÌ‚'=>'â','ã'=>'ã','ä'=>'ä','aÌŠ'=>'Ã¥','ç'=>'ç','eÌ€'=>'è','eÌ'=>'é','eÌ‚'=>'ê','ë'=>'ë','iÌ€'=>'ì','iÌ'=>'Ã','iÌ‚'=>'î','ï'=>'ï','ñ'=>'ñ','oÌ€'=>'ò','oÌ'=>'ó','oÌ‚'=>'ô','õ'=>'õ','ö'=>'ö','uÌ€'=>'ù','uÌ'=>'ú','uÌ‚'=>'û','ü'=>'ü','yÌ'=>'ý','ÿ'=>'ÿ','AÌ„'=>'Ä€','aÌ„'=>'Ä','Ă'=>'Ä‚','ă'=>'ă','Ą'=>'Ä„','ą'=>'Ä…','CÌ'=>'Ć','cÌ'=>'ć','CÌ‚'=>'Ĉ','cÌ‚'=>'ĉ','Ċ'=>'ÄŠ','ċ'=>'Ä‹','CÌŒ'=>'ÄŒ','cÌŒ'=>'Ä','DÌŒ'=>'ÄŽ','dÌŒ'=>'Ä','EÌ„'=>'Ä’','eÌ„'=>'Ä“','Ĕ'=>'Ä”','ĕ'=>'Ä•','Ė'=>'Ä–','ė'=>'Ä—','Ę'=>'Ę','ę'=>'Ä™','EÌŒ'=>'Äš','eÌŒ'=>'Ä›','GÌ‚'=>'Äœ','gÌ‚'=>'Ä','Ğ'=>'Äž','ğ'=>'ÄŸ','Ġ'=>'Ä ','ġ'=>'Ä¡','Ģ'=>'Ä¢','ģ'=>'Ä£','HÌ‚'=>'Ĥ','hÌ‚'=>'Ä¥','Ĩ'=>'Ĩ','ĩ'=>'Ä©','IÌ„'=>'Ī','iÌ„'=>'Ä«','Ĭ'=>'Ĭ','ĭ'=>'Ä','Į'=>'Ä®','į'=>'į','İ'=>'İ','JÌ‚'=>'Ä´','jÌ‚'=>'ĵ','Ķ'=>'Ķ','ķ'=>'Ä·','LÌ'=>'Ĺ','lÌ'=>'ĺ','Ļ'=>'Ä»','ļ'=>'ļ','LÌŒ'=>'Ľ','lÌŒ'=>'ľ','NÌ'=>'Ń','nÌ'=>'Å„','Ņ'=>'Å…','ņ'=>'ņ','NÌŒ'=>'Ň','nÌŒ'=>'ň','OÌ„'=>'ÅŒ','oÌ„'=>'Å','Ŏ'=>'ÅŽ','ŏ'=>'Å','OÌ‹'=>'Å','oÌ‹'=>'Å‘','RÌ'=>'Å”','rÌ'=>'Å•','Ŗ'=>'Å–','ŗ'=>'Å—','RÌŒ'=>'Ř','rÌŒ'=>'Å™','SÌ'=>'Åš','sÌ'=>'Å›','SÌ‚'=>'Åœ','sÌ‚'=>'Å','Ş'=>'Åž','ş'=>'ÅŸ','SÌŒ'=>'Å ','sÌŒ'=>'Å¡','Ţ'=>'Å¢','ţ'=>'Å£','TÌŒ'=>'Ť','tÌŒ'=>'Å¥','Ũ'=>'Ũ','ũ'=>'Å©','UÌ„'=>'Ū','uÌ„'=>'Å«','Ŭ'=>'Ŭ','ŭ'=>'Å','UÌŠ'=>'Å®','uÌŠ'=>'ů','UÌ‹'=>'Ű','uÌ‹'=>'ű','Ų'=>'Ų','ų'=>'ų','WÌ‚'=>'Å´','wÌ‚'=>'ŵ','YÌ‚'=>'Ŷ','yÌ‚'=>'Å·','Ÿ'=>'Ÿ','ZÌ'=>'Ź','zÌ'=>'ź','Ż'=>'Å»','ż'=>'ż','ZÌŒ'=>'Ž','zÌŒ'=>'ž','OÌ›'=>'Æ ','oÌ›'=>'Æ¡','UÌ›'=>'Ư','uÌ›'=>'ư','AÌŒ'=>'Ç','aÌŒ'=>'ÇŽ','IÌŒ'=>'Ç','iÌŒ'=>'Ç','OÌŒ'=>'Ç‘','oÌŒ'=>'Ç’','UÌŒ'=>'Ç“','uÌŒ'=>'Ç”','Ǖ'=>'Ç•','ǖ'=>'Ç–','ÜÌ'=>'Ç—','üÌ'=>'ǘ','Ǚ'=>'Ç™','ǚ'=>'Çš','Ǜ'=>'Ç›','ǜ'=>'Çœ','Ǟ'=>'Çž','ǟ'=>'ÇŸ','Ǡ'=>'Ç ','ǡ'=>'Ç¡','Ǣ'=>'Ç¢','ǣ'=>'Ç£','GÌŒ'=>'Ǧ','gÌŒ'=>'ǧ','KÌŒ'=>'Ǩ','kÌŒ'=>'Ç©','Ǫ'=>'Ǫ','ǫ'=>'Ç«','Ǭ'=>'Ǭ','ǭ'=>'Ç','Æ·ÌŒ'=>'Ç®','Ê’ÌŒ'=>'ǯ','jÌŒ'=>'ǰ','GÌ'=>'Ç´','gÌ'=>'ǵ','NÌ€'=>'Ǹ','nÌ€'=>'ǹ','Ã…Ì'=>'Ǻ','Ã¥Ì'=>'Ç»','ÆÌ'=>'Ǽ','æÌ'=>'ǽ','ØÌ'=>'Ǿ','øÌ'=>'Ç¿','AÌ'=>'È€','aÌ'=>'È','AÌ‘'=>'È‚','aÌ‘'=>'ȃ','EÌ'=>'È„','eÌ'=>'È…','EÌ‘'=>'Ȇ','eÌ‘'=>'ȇ','IÌ'=>'Ȉ','iÌ'=>'ȉ','IÌ‘'=>'ÈŠ','iÌ‘'=>'È‹','OÌ'=>'ÈŒ','oÌ'=>'È','OÌ‘'=>'ÈŽ','oÌ‘'=>'È','RÌ'=>'È','rÌ'=>'È‘','RÌ‘'=>'È’','rÌ‘'=>'È“','UÌ'=>'È”','uÌ'=>'È•','UÌ‘'=>'È–','uÌ‘'=>'È—','Ș'=>'Ș','ș'=>'È™','Ț'=>'Èš','ț'=>'È›','HÌŒ'=>'Èž','hÌŒ'=>'ÈŸ','Ȧ'=>'Ȧ','ȧ'=>'ȧ','Ȩ'=>'Ȩ','ȩ'=>'È©','Ȫ'=>'Ȫ','ȫ'=>'È«','Ȭ'=>'Ȭ','ȭ'=>'È','Ȯ'=>'È®','ȯ'=>'ȯ','Ȱ'=>'Ȱ','ȱ'=>'ȱ','YÌ„'=>'Ȳ','yÌ„'=>'ȳ','̈Ì'=>'Í„','¨Ì'=>'Î…','ΑÌ'=>'Ά','ΕÌ'=>'Έ','ΗÌ'=>'Ή','ΙÌ'=>'Ί','ΟÌ'=>'ÎŒ','Î¥Ì'=>'ÎŽ','ΩÌ'=>'Î','ÏŠÌ'=>'Î','Ϊ'=>'Ϊ','Ϋ'=>'Ϋ','αÌ'=>'ά','εÌ'=>'Î','ηÌ'=>'ή','ιÌ'=>'ί','Ï‹Ì'=>'ΰ','ϊ'=>'ÏŠ','ϋ'=>'Ï‹','οÌ'=>'ÏŒ','Ï…Ì'=>'Ï','ωÌ'=>'ÏŽ','Ï’Ì'=>'Ï“','ϔ'=>'Ï”','Ѐ'=>'Ѐ','Ё'=>'Ð','ГÌ'=>'Ѓ','Ї'=>'Ї','КÌ'=>'ÐŒ','Ѝ'=>'Ð','Ў'=>'ÐŽ','Й'=>'Й','й'=>'й','ѐ'=>'Ñ','ё'=>'Ñ‘','гÌ'=>'Ñ“','ї'=>'Ñ—','кÌ'=>'Ñœ','ѝ'=>'Ñ','ў'=>'Ñž','Ñ´Ì'=>'Ѷ','ѵÌ'=>'Ñ·','Ӂ'=>'Ó','ӂ'=>'Ó‚','Ð̆'=>'Ó','ӑ'=>'Ó‘','Ð̈'=>'Ó’','ӓ'=>'Ó“','Ӗ'=>'Ó–','ӗ'=>'Ó—','Ӛ'=>'Óš','ӛ'=>'Ó›','Ӝ'=>'Óœ','ӝ'=>'Ó','Ӟ'=>'Óž','ӟ'=>'ÓŸ','Ӣ'=>'Ó¢','ӣ'=>'Ó£','Ӥ'=>'Ó¤','ӥ'=>'Ó¥','Ӧ'=>'Ó¦','ӧ'=>'Ó§','Ӫ'=>'Óª','ӫ'=>'Ó«','Ð̈'=>'Ó¬','Ñ̈'=>'Ó','Ӯ'=>'Ó®','ӯ'=>'Ó¯','Ӱ'=>'Ó°','ӱ'=>'Ó±','Ӳ'=>'Ó²','ӳ'=>'Ó³','Ӵ'=>'Ó´','ӵ'=>'Óµ','Ӹ'=>'Ó¸','ӹ'=>'Ó¹','آ'=>'Ø¢','أ'=>'Ø£','ÙˆÙ”'=>'ؤ','إ'=>'Ø¥','ÙŠÙ”'=>'ئ','Û•Ù”'=>'Û€','ÛÙ”'=>'Û‚','Û’Ù”'=>'Û“','ऩ'=>'ऩ','ऱ'=>'ऱ','ऴ'=>'ऴ','ো'=>'à§‹','ৌ'=>'à§Œ','à‡à–'=>'àˆ','à‡à¬¾'=>'à‹','à‡à—'=>'àŒ','ஔ'=>'à®”','ொ'=>'ொ','ோ'=>'ோ','ௌ'=>'ௌ','ై'=>'ై','ೀ'=>'à³€','ೇ'=>'ೇ','ೈ'=>'ೈ','ೊ'=>'ೊ','ೋ'=>'ೋ','ൊ'=>'ൊ','ോ'=>'ോ','ൌ'=>'ൌ','ේ'=>'à·š','à·™à·'=>'à·œ','ෝ'=>'à·','ෞ'=>'à·ž','ཱི'=>'ཱི','ཱུ'=>'ཱུ','ཱྀ'=>'à¾','ဦ'=>'ဦ','ᬆ'=>'ᬆ','ᬈ'=>'ᬈ','ᬊ'=>'ᬊ','ᬌ'=>'ᬌ','á¬á¬µ'=>'ᬎ','ᬒ'=>'ᬒ','ᬻ'=>'ᬻ','ᬽ'=>'ᬽ','ᭀ'=>'á€','ᭁ'=>'á','á‚ᬵ'=>'áƒ','AÌ¥'=>'Ḁ','aÌ¥'=>'á¸','Ḃ'=>'Ḃ','ḃ'=>'ḃ','BÌ£'=>'Ḅ','bÌ£'=>'ḅ','Ḇ'=>'Ḇ','ḇ'=>'ḇ','ÇÌ'=>'Ḉ','çÌ'=>'ḉ','Ḋ'=>'Ḋ','ḋ'=>'ḋ','DÌ£'=>'Ḍ','dÌ£'=>'á¸','Ḏ'=>'Ḏ','ḏ'=>'á¸','Ḑ'=>'á¸','ḑ'=>'ḑ','DÌ'=>'Ḓ','dÌ'=>'ḓ','Ä’Ì€'=>'Ḕ','ḕ'=>'ḕ','Ä’Ì'=>'Ḗ','Ä“Ì'=>'ḗ','EÌ'=>'Ḙ','eÌ'=>'ḙ','Ḛ'=>'Ḛ','ḛ'=>'ḛ','Ḝ'=>'Ḝ','ḝ'=>'á¸','Ḟ'=>'Ḟ','ḟ'=>'ḟ','GÌ„'=>'Ḡ','gÌ„'=>'ḡ','Ḣ'=>'Ḣ','ḣ'=>'ḣ','HÌ£'=>'Ḥ','hÌ£'=>'ḥ','Ḧ'=>'Ḧ','ḧ'=>'ḧ','Ḩ'=>'Ḩ','ḩ'=>'ḩ','HÌ®'=>'Ḫ','hÌ®'=>'ḫ','Ḭ'=>'Ḭ','ḭ'=>'á¸','ÃÌ'=>'Ḯ','ïÌ'=>'ḯ','KÌ'=>'Ḱ','kÌ'=>'ḱ','KÌ£'=>'Ḳ','kÌ£'=>'ḳ','Ḵ'=>'Ḵ','ḵ'=>'ḵ','LÌ£'=>'Ḷ','lÌ£'=>'ḷ','Ḹ'=>'Ḹ','ḹ'=>'ḹ','Ḻ'=>'Ḻ','ḻ'=>'ḻ','LÌ'=>'Ḽ','lÌ'=>'ḽ','MÌ'=>'Ḿ','mÌ'=>'ḿ','Ṁ'=>'á¹€','ṁ'=>'á¹','MÌ£'=>'Ṃ','mÌ£'=>'ṃ','Ṅ'=>'Ṅ','ṅ'=>'á¹…','NÌ£'=>'Ṇ','nÌ£'=>'ṇ','Ṉ'=>'Ṉ','ṉ'=>'ṉ','NÌ'=>'Ṋ','nÌ'=>'ṋ','ÕÌ'=>'Ṍ','õÌ'=>'á¹','Ṏ'=>'Ṏ','ṏ'=>'á¹','Ṑ'=>'á¹','ÅÌ€'=>'ṑ','ÅŒÌ'=>'á¹’','ÅÌ'=>'ṓ','PÌ'=>'á¹”','pÌ'=>'ṕ','Ṗ'=>'á¹–','ṗ'=>'á¹—','Ṙ'=>'Ṙ','ṙ'=>'á¹™','RÌ£'=>'Ṛ','rÌ£'=>'á¹›','Ṝ'=>'Ṝ','ṝ'=>'á¹','Ṟ'=>'Ṟ','ṟ'=>'ṟ','Ṡ'=>'á¹ ','ṡ'=>'ṡ','SÌ£'=>'á¹¢','sÌ£'=>'á¹£','Ṥ'=>'Ṥ','ṥ'=>'á¹¥','Ṧ'=>'Ṧ','ṧ'=>'á¹§','Ṩ'=>'Ṩ','ṩ'=>'ṩ','Ṫ'=>'Ṫ','ṫ'=>'ṫ','TÌ£'=>'Ṭ','tÌ£'=>'á¹','Ṯ'=>'á¹®','ṯ'=>'ṯ','TÌ'=>'á¹°','tÌ'=>'á¹±','Ṳ'=>'á¹²','ṳ'=>'á¹³','Ṵ'=>'á¹´','ṵ'=>'á¹µ','UÌ'=>'á¹¶','uÌ'=>'á¹·','ŨÌ'=>'Ṹ','Å©Ì'=>'á¹¹','Ṻ'=>'Ṻ','ṻ'=>'á¹»','Ṽ'=>'á¹¼','ṽ'=>'á¹½','VÌ£'=>'á¹¾','vÌ£'=>'ṿ','WÌ€'=>'Ẁ','wÌ€'=>'áº','WÌ'=>'Ẃ','wÌ'=>'ẃ','Ẅ'=>'Ẅ','ẅ'=>'ẅ','Ẇ'=>'Ẇ','ẇ'=>'ẇ','WÌ£'=>'Ẉ','wÌ£'=>'ẉ','Ẋ'=>'Ẋ','ẋ'=>'ẋ','Ẍ'=>'Ẍ','ẍ'=>'áº','Ẏ'=>'Ẏ','ẏ'=>'áº','ZÌ‚'=>'áº','zÌ‚'=>'ẑ','ZÌ£'=>'Ẓ','zÌ£'=>'ẓ','Ẕ'=>'Ẕ','ẕ'=>'ẕ','ẖ'=>'ẖ','ẗ'=>'ẗ','wÌŠ'=>'ẘ','yÌŠ'=>'ẙ','ẛ'=>'ẛ','AÌ£'=>'Ạ','aÌ£'=>'ạ','Ả'=>'Ả','ả'=>'ả','ÂÌ'=>'Ấ','âÌ'=>'ấ','Ầ'=>'Ầ','ầ'=>'ầ','Ẩ'=>'Ẩ','ẩ'=>'ẩ','Ẫ'=>'Ẫ','ẫ'=>'ẫ','Ậ'=>'Ậ','ậ'=>'áº','Ä‚Ì'=>'Ắ','ăÌ'=>'ắ','Ằ'=>'Ằ','ằ'=>'ằ','Ẳ'=>'Ẳ','ẳ'=>'ẳ','Ẵ'=>'Ẵ','ẵ'=>'ẵ','Ặ'=>'Ặ','ặ'=>'ặ','EÌ£'=>'Ẹ','eÌ£'=>'ẹ','Ẻ'=>'Ẻ','ẻ'=>'ẻ','Ẽ'=>'Ẽ','ẽ'=>'ẽ','ÊÌ'=>'Ế','êÌ'=>'ế','Ề'=>'Ề','ề'=>'á»','Ể'=>'Ể','ể'=>'ể','Ễ'=>'Ễ','ễ'=>'á»…','Ệ'=>'Ệ','ệ'=>'ệ','Ỉ'=>'Ỉ','ỉ'=>'ỉ','IÌ£'=>'Ị','iÌ£'=>'ị','OÌ£'=>'Ọ','oÌ£'=>'á»','Ỏ'=>'Ỏ','ỏ'=>'á»','ÔÌ'=>'á»','ôÌ'=>'ố','Ồ'=>'á»’','ồ'=>'ồ','Ổ'=>'á»”','ổ'=>'ổ','Ỗ'=>'á»–','ỗ'=>'á»—','Ộ'=>'Ộ','á»Ì‚'=>'á»™','Æ Ì'=>'Ớ','Æ¡Ì'=>'á»›','Æ Ì€'=>'Ờ','ờ'=>'á»','Æ Ì‰'=>'Ở','ở'=>'ở','Æ Ìƒ'=>'á» ','ỡ'=>'ỡ','Æ Ì£'=>'Ợ','ợ'=>'ợ','UÌ£'=>'Ụ','uÌ£'=>'ụ','Ủ'=>'Ủ','ủ'=>'á»§','ƯÌ'=>'Ứ','ưÌ'=>'ứ','Ừ'=>'Ừ','ừ'=>'ừ','Ử'=>'Ử','ử'=>'á»','Ữ'=>'á»®','ữ'=>'ữ','Ự'=>'á»°','ự'=>'á»±','YÌ€'=>'Ỳ','yÌ€'=>'ỳ','YÌ£'=>'á»´','yÌ£'=>'ỵ','Ỷ'=>'á»¶','ỷ'=>'á»·','Ỹ'=>'Ỹ','ỹ'=>'ỹ','ἀ'=>'á¼€','ἁ'=>'á¼','ἂ'=>'ἂ','á¼Ì€'=>'ἃ','á¼€Ì'=>'ἄ','á¼Ì'=>'á¼…','ἆ'=>'ἆ','á¼Í‚'=>'ἇ','Ἀ'=>'Ἀ','Ἁ'=>'Ἁ','Ἂ'=>'Ἂ','Ἃ'=>'Ἃ','ἈÌ'=>'Ἄ','ἉÌ'=>'á¼','Ἆ'=>'Ἆ','Ἇ'=>'á¼','ἐ'=>'á¼','ἑ'=>'ἑ','á¼Ì€'=>'á¼’','ἓ'=>'ἓ','á¼Ì'=>'á¼”','ἑÌ'=>'ἕ','Ἐ'=>'Ἐ','Ἑ'=>'á¼™','Ἒ'=>'Ἒ','Ἓ'=>'á¼›','ἘÌ'=>'Ἔ','á¼™Ì'=>'á¼','ἠ'=>'á¼ ','ἡ'=>'ἡ','ἢ'=>'á¼¢','ἣ'=>'á¼£','á¼ Ì'=>'ἤ','ἡÌ'=>'á¼¥','á¼ Í‚'=>'ἦ','ἧ'=>'á¼§','Ἠ'=>'Ἠ','Ἡ'=>'Ἡ','Ἢ'=>'Ἢ','Ἣ'=>'Ἣ','ἨÌ'=>'Ἤ','ἩÌ'=>'á¼','Ἦ'=>'á¼®','Ἧ'=>'Ἧ','ἰ'=>'á¼°','ἱ'=>'á¼±','á¼°Ì€'=>'á¼²','ἳ'=>'á¼³','á¼°Ì'=>'á¼´','á¼±Ì'=>'á¼µ','á¼°Í‚'=>'á¼¶','ἷ'=>'á¼·','Ἰ'=>'Ἰ','Ἱ'=>'á¼¹','Ἲ'=>'Ἲ','Ἳ'=>'á¼»','ἸÌ'=>'á¼¼','á¼¹Ì'=>'á¼½','Ἶ'=>'á¼¾','Ἷ'=>'Ἷ','ὀ'=>'á½€','ὁ'=>'á½','ὂ'=>'ὂ','á½Ì€'=>'ὃ','á½€Ì'=>'ὄ','á½Ì'=>'á½…','Ὀ'=>'Ὀ','Ὁ'=>'Ὁ','Ὂ'=>'Ὂ','Ὃ'=>'Ὃ','ὈÌ'=>'Ὄ','ὉÌ'=>'á½','Ï…Ì“'=>'á½','Ï…Ì”'=>'ὑ','á½Ì€'=>'á½’','ὓ'=>'ὓ','á½Ì'=>'á½”','ὑÌ'=>'ὕ','á½Í‚'=>'á½–','ὗ'=>'á½—','Ὑ'=>'á½™','Ὓ'=>'á½›','á½™Ì'=>'á½','Ὗ'=>'Ὗ','ὠ'=>'á½ ','ὡ'=>'ὡ','ὢ'=>'á½¢','ὣ'=>'á½£','á½ Ì'=>'ὤ','ὡÌ'=>'á½¥','á½ Í‚'=>'ὦ','ὧ'=>'á½§','Ὠ'=>'Ὠ','Ὡ'=>'Ὡ','Ὢ'=>'Ὢ','Ὣ'=>'Ὣ','ὨÌ'=>'Ὤ','ὩÌ'=>'á½','Ὦ'=>'á½®','Ὧ'=>'Ὧ','ὰ'=>'á½°','ὲ'=>'á½²','ὴ'=>'á½´','ὶ'=>'á½¶','ὸ'=>'ὸ','Ï…Ì€'=>'ὺ','ὼ'=>'á½¼','ᾀ'=>'á¾€','á¼Í…'=>'á¾','ᾂ'=>'ᾂ','ᾃ'=>'ᾃ','ᾄ'=>'ᾄ','á¼…Í…'=>'á¾…','ᾆ'=>'ᾆ','ᾇ'=>'ᾇ','ᾈ'=>'ᾈ','ᾉ'=>'ᾉ','ᾊ'=>'ᾊ','ᾋ'=>'ᾋ','ᾌ'=>'ᾌ','á¼Í…'=>'á¾','ᾎ'=>'ᾎ','á¼Í…'=>'á¾','á¼ Í…'=>'á¾','ᾑ'=>'ᾑ','ᾒ'=>'á¾’','ᾓ'=>'ᾓ','ᾔ'=>'á¾”','ᾕ'=>'ᾕ','ᾖ'=>'á¾–','á¼§Í…'=>'á¾—','ᾘ'=>'ᾘ','ᾙ'=>'á¾™','ᾚ'=>'ᾚ','ᾛ'=>'á¾›','ᾜ'=>'ᾜ','á¼Í…'=>'á¾','ᾞ'=>'ᾞ','ᾟ'=>'ᾟ','á½ Í…'=>'á¾ ','ᾡ'=>'ᾡ','ᾢ'=>'á¾¢','ᾣ'=>'á¾£','ᾤ'=>'ᾤ','ᾥ'=>'á¾¥','ᾦ'=>'ᾦ','á½§Í…'=>'á¾§','ᾨ'=>'ᾨ','ᾩ'=>'ᾩ','ᾪ'=>'ᾪ','ᾫ'=>'ᾫ','ᾬ'=>'ᾬ','á½Í…'=>'á¾','ᾮ'=>'á¾®','ᾯ'=>'ᾯ','ᾰ'=>'á¾°','ᾱ'=>'á¾±','á½°Í…'=>'á¾²','ᾳ'=>'á¾³','ᾴ'=>'á¾´','ᾶ'=>'á¾¶','á¾¶Í…'=>'á¾·','Ᾰ'=>'Ᾰ','Ᾱ'=>'á¾¹','Ὰ'=>'Ὰ','ᾼ'=>'á¾¼','῁'=>'á¿','á½´Í…'=>'á¿‚','ῃ'=>'ῃ','ῄ'=>'á¿„','ῆ'=>'ῆ','ῇ'=>'ῇ','Ὲ'=>'Ὲ','Ὴ'=>'Ὴ','ῌ'=>'ῌ','῍'=>'á¿','᾿Ì'=>'῎','῏'=>'á¿','ῐ'=>'á¿','ῑ'=>'á¿‘','ÏŠÌ€'=>'á¿’','ῖ'=>'á¿–','ÏŠÍ‚'=>'á¿—','Ῐ'=>'Ῐ','Ῑ'=>'á¿™','Ὶ'=>'Ὶ','῝'=>'á¿','῾Ì'=>'῞','῟'=>'῟','ῠ'=>'á¿ ','Ï…Ì„'=>'á¿¡','ῢ'=>'á¿¢','ÏÌ“'=>'ῤ','ÏÌ”'=>'á¿¥','Ï…Í‚'=>'ῦ','ῧ'=>'á¿§','Ῠ'=>'Ῠ','Ῡ'=>'á¿©','Ὺ'=>'Ὺ','Ῥ'=>'Ῥ','῭'=>'á¿','ῲ'=>'ῲ','ῳ'=>'ῳ','ÏŽÍ…'=>'á¿´','ῶ'=>'á¿¶','á¿¶Í…'=>'á¿·','Ὸ'=>'Ὸ','Ὼ'=>'Ὼ','ῼ'=>'ῼ','â†Ì¸'=>'↚','↛'=>'↛','↮'=>'↮','â‡Ì¸'=>'â‡','⇎'=>'⇎','⇏'=>'â‡','∄'=>'∄','∉'=>'∉','∌'=>'∌','∤'=>'∤','∦'=>'∦','≁'=>'â‰','≄'=>'≄','≇'=>'≇','≉'=>'≉','≠'=>'≠','≢'=>'≢','â‰Ì¸'=>'â‰','≮'=>'≮','≯'=>'≯','≰'=>'≰','≱'=>'≱','≴'=>'≴','≵'=>'≵','≸'=>'≸','≹'=>'≹','⊀'=>'⊀','⊁'=>'âŠ','⊄'=>'⊄','⊅'=>'⊅','⊈'=>'⊈','⊉'=>'⊉','⊬'=>'⊬','⊭'=>'âŠ','⊮'=>'⊮','⊯'=>'⊯','⋠'=>'â‹ ','⋡'=>'â‹¡','⋢'=>'â‹¢','⋣'=>'â‹£','⋪'=>'⋪','⋫'=>'â‹«','⋬'=>'⋬','⋭'=>'â‹','ã‹ã‚™'=>'ãŒ','ãã‚™'=>'ãŽ','ãã‚™'=>'ã','ã‘ã‚™'=>'ã’','ã“ã‚™'=>'ã”','ã•ã‚™'=>'ã–','ã—ã‚™'=>'ã˜','ã™ã‚™'=>'ãš','ã›ã‚™'=>'ãœ','ãã‚™'=>'ãž','ãŸã‚™'=>'ã ','ã¡ã‚™'=>'ã¢','ã¤ã‚™'=>'ã¥','ã¦ã‚™'=>'ã§','ã¨ã‚™'=>'ã©','ã¯ã‚™'=>'ã°','ã¯ã‚š'=>'ã±','ã²ã‚™'=>'ã³','ã²ã‚š'=>'ã´','ãµã‚™'=>'ã¶','ãµã‚š'=>'ã·','ã¸ã‚™'=>'ã¹','ã¸ã‚š'=>'ãº','ã»ã‚™'=>'ã¼','ã»ã‚š'=>'ã½','ã†ã‚™'=>'ã‚”','ã‚ã‚™'=>'ゞ','ã‚«ã‚™'=>'ガ','ã‚ã‚™'=>'ã‚®','グ'=>'ã‚°','ゲ'=>'ゲ','ゴ'=>'ã‚´','ザ'=>'ã‚¶','ã‚·ã‚™'=>'ジ','ズ'=>'ズ','ゼ'=>'ゼ','ゾ'=>'ゾ','ã‚¿ã‚™'=>'ダ','ãƒã‚™'=>'ヂ','ヅ'=>'ヅ','デ'=>'デ','ド'=>'ド','ãƒã‚™'=>'ãƒ','ãƒã‚š'=>'パ','ビ'=>'ビ','ピ'=>'ピ','ブ'=>'ブ','プ'=>'プ','ベ'=>'ベ','ペ'=>'ペ','ボ'=>'ボ','ポ'=>'ãƒ','ヴ'=>'ヴ','ヷ'=>'ヷ','ヸ'=>'ヸ','ヹ'=>'ヹ','ヺ'=>'ヺ','ヾ'=>'ヾ'); diff --git a/phpBB/includes/utf/data/utf_canonical_decomp.php b/phpBB/includes/utf/data/utf_canonical_decomp.php deleted file mode 100644 index 9fb90803e2..0000000000 --- a/phpBB/includes/utf/data/utf_canonical_decomp.php +++ /dev/null @@ -1,2 +0,0 @@ -<?php -$GLOBALS['utf_canonical_decomp']=array('À'=>'AÌ€','Ã'=>'AÌ','Â'=>'AÌ‚','Ã'=>'Ã','Ä'=>'Ä','Ã…'=>'AÌŠ','Ç'=>'Ç','È'=>'EÌ€','É'=>'EÌ','Ê'=>'EÌ‚','Ë'=>'Ë','ÃŒ'=>'IÌ€','Ã'=>'IÌ','ÃŽ'=>'IÌ‚','Ã'=>'Ï','Ñ'=>'Ñ','Ã’'=>'OÌ€','Ó'=>'OÌ','Ô'=>'OÌ‚','Õ'=>'Õ','Ö'=>'Ö','Ù'=>'UÌ€','Ú'=>'UÌ','Û'=>'UÌ‚','Ü'=>'Ü','Ã'=>'YÌ','à '=>'aÌ€','á'=>'aÌ','â'=>'aÌ‚','ã'=>'ã','ä'=>'ä','Ã¥'=>'aÌŠ','ç'=>'ç','è'=>'eÌ€','é'=>'eÌ','ê'=>'eÌ‚','ë'=>'ë','ì'=>'iÌ€','Ã'=>'iÌ','î'=>'iÌ‚','ï'=>'ï','ñ'=>'ñ','ò'=>'oÌ€','ó'=>'oÌ','ô'=>'oÌ‚','õ'=>'õ','ö'=>'ö','ù'=>'uÌ€','ú'=>'uÌ','û'=>'uÌ‚','ü'=>'ü','ý'=>'yÌ','ÿ'=>'ÿ','Ä€'=>'AÌ„','Ä'=>'aÌ„','Ä‚'=>'Ă','ă'=>'ă','Ä„'=>'Ą','Ä…'=>'ą','Ć'=>'CÌ','ć'=>'cÌ','Ĉ'=>'CÌ‚','ĉ'=>'cÌ‚','ÄŠ'=>'Ċ','Ä‹'=>'ċ','ÄŒ'=>'CÌŒ','Ä'=>'cÌŒ','ÄŽ'=>'DÌŒ','Ä'=>'dÌŒ','Ä’'=>'EÌ„','Ä“'=>'eÌ„','Ä”'=>'Ĕ','Ä•'=>'ĕ','Ä–'=>'Ė','Ä—'=>'ė','Ę'=>'Ę','Ä™'=>'ę','Äš'=>'EÌŒ','Ä›'=>'eÌŒ','Äœ'=>'GÌ‚','Ä'=>'gÌ‚','Äž'=>'Ğ','ÄŸ'=>'ğ','Ä '=>'Ġ','Ä¡'=>'ġ','Ä¢'=>'Ģ','Ä£'=>'ģ','Ĥ'=>'HÌ‚','Ä¥'=>'hÌ‚','Ĩ'=>'Ĩ','Ä©'=>'ĩ','Ī'=>'IÌ„','Ä«'=>'iÌ„','Ĭ'=>'Ĭ','Ä'=>'ĭ','Ä®'=>'Į','į'=>'į','İ'=>'İ','Ä´'=>'JÌ‚','ĵ'=>'jÌ‚','Ķ'=>'Ķ','Ä·'=>'ķ','Ĺ'=>'LÌ','ĺ'=>'lÌ','Ä»'=>'Ļ','ļ'=>'ļ','Ľ'=>'LÌŒ','ľ'=>'lÌŒ','Ń'=>'NÌ','Å„'=>'nÌ','Å…'=>'Ņ','ņ'=>'ņ','Ň'=>'NÌŒ','ň'=>'nÌŒ','ÅŒ'=>'OÌ„','Å'=>'oÌ„','ÅŽ'=>'Ŏ','Å'=>'ŏ','Å'=>'OÌ‹','Å‘'=>'oÌ‹','Å”'=>'RÌ','Å•'=>'rÌ','Å–'=>'Ŗ','Å—'=>'ŗ','Ř'=>'RÌŒ','Å™'=>'rÌŒ','Åš'=>'SÌ','Å›'=>'sÌ','Åœ'=>'SÌ‚','Å'=>'sÌ‚','Åž'=>'Ş','ÅŸ'=>'ş','Å '=>'SÌŒ','Å¡'=>'sÌŒ','Å¢'=>'Ţ','Å£'=>'ţ','Ť'=>'TÌŒ','Å¥'=>'tÌŒ','Ũ'=>'Ũ','Å©'=>'ũ','Ū'=>'UÌ„','Å«'=>'uÌ„','Ŭ'=>'Ŭ','Å'=>'ŭ','Å®'=>'UÌŠ','ů'=>'uÌŠ','Ű'=>'UÌ‹','ű'=>'uÌ‹','Ų'=>'Ų','ų'=>'ų','Å´'=>'WÌ‚','ŵ'=>'wÌ‚','Ŷ'=>'YÌ‚','Å·'=>'yÌ‚','Ÿ'=>'Ÿ','Ź'=>'ZÌ','ź'=>'zÌ','Å»'=>'Ż','ż'=>'ż','Ž'=>'ZÌŒ','ž'=>'zÌŒ','Æ '=>'OÌ›','Æ¡'=>'oÌ›','Ư'=>'UÌ›','ư'=>'uÌ›','Ç'=>'AÌŒ','ÇŽ'=>'aÌŒ','Ç'=>'IÌŒ','Ç'=>'iÌŒ','Ç‘'=>'OÌŒ','Ç’'=>'oÌŒ','Ç“'=>'UÌŒ','Ç”'=>'uÌŒ','Ç•'=>'Ǖ','Ç–'=>'ǖ','Ç—'=>'ÜÌ','ǘ'=>'üÌ','Ç™'=>'Ǚ','Çš'=>'ǚ','Ç›'=>'Ǜ','Çœ'=>'ǜ','Çž'=>'Ǟ','ÇŸ'=>'ǟ','Ç '=>'Ǡ','Ç¡'=>'ǡ','Ç¢'=>'Ǣ','Ç£'=>'ǣ','Ǧ'=>'GÌŒ','ǧ'=>'gÌŒ','Ǩ'=>'KÌŒ','Ç©'=>'kÌŒ','Ǫ'=>'Ǫ','Ç«'=>'ǫ','Ǭ'=>'Ǭ','Ç'=>'ǭ','Ç®'=>'Æ·ÌŒ','ǯ'=>'Ê’ÌŒ','ǰ'=>'jÌŒ','Ç´'=>'GÌ','ǵ'=>'gÌ','Ǹ'=>'NÌ€','ǹ'=>'nÌ€','Ǻ'=>'AÌŠÌ','Ç»'=>'aÌŠÌ','Ǽ'=>'ÆÌ','ǽ'=>'æÌ','Ǿ'=>'ØÌ','Ç¿'=>'øÌ','È€'=>'AÌ','È'=>'aÌ','È‚'=>'AÌ‘','ȃ'=>'aÌ‘','È„'=>'EÌ','È…'=>'eÌ','Ȇ'=>'EÌ‘','ȇ'=>'eÌ‘','Ȉ'=>'IÌ','ȉ'=>'iÌ','ÈŠ'=>'IÌ‘','È‹'=>'iÌ‘','ÈŒ'=>'OÌ','È'=>'oÌ','ÈŽ'=>'OÌ‘','È'=>'oÌ‘','È'=>'RÌ','È‘'=>'rÌ','È’'=>'RÌ‘','È“'=>'rÌ‘','È”'=>'UÌ','È•'=>'uÌ','È–'=>'UÌ‘','È—'=>'uÌ‘','Ș'=>'Ș','È™'=>'ș','Èš'=>'Ț','È›'=>'ț','Èž'=>'HÌŒ','ÈŸ'=>'hÌŒ','Ȧ'=>'Ȧ','ȧ'=>'ȧ','Ȩ'=>'Ȩ','È©'=>'ȩ','Ȫ'=>'Ȫ','È«'=>'ȫ','Ȭ'=>'Ȭ','È'=>'ȭ','È®'=>'Ȯ','ȯ'=>'ȯ','Ȱ'=>'Ȱ','ȱ'=>'ȱ','Ȳ'=>'YÌ„','ȳ'=>'yÌ„','Í€'=>'Ì€','Í'=>'Ì','̓'=>'Ì“','Í„'=>'̈Ì','Í´'=>'ʹ',';'=>';','Î…'=>'¨Ì','Ά'=>'ΑÌ','·'=>'·','Έ'=>'ΕÌ','Ή'=>'ΗÌ','Ί'=>'ΙÌ','ÎŒ'=>'ΟÌ','ÎŽ'=>'Î¥Ì','Î'=>'ΩÌ','Î'=>'ϊÌ','Ϊ'=>'Ϊ','Ϋ'=>'Ϋ','ά'=>'αÌ','Î'=>'εÌ','ή'=>'ηÌ','ί'=>'ιÌ','ΰ'=>'ϋÌ','ÏŠ'=>'ϊ','Ï‹'=>'ϋ','ÏŒ'=>'οÌ','Ï'=>'Ï…Ì','ÏŽ'=>'ωÌ','Ï“'=>'Ï’Ì','Ï”'=>'ϔ','Ѐ'=>'Ѐ','Ð'=>'Ё','Ѓ'=>'ГÌ','Ї'=>'Ї','ÐŒ'=>'КÌ','Ð'=>'Ѝ','ÐŽ'=>'Ў','Й'=>'Й','й'=>'й','Ñ'=>'ѐ','Ñ‘'=>'ё','Ñ“'=>'гÌ','Ñ—'=>'ї','Ñœ'=>'кÌ','Ñ'=>'ѝ','Ñž'=>'ў','Ѷ'=>'Ñ´Ì','Ñ·'=>'ѵÌ','Ó'=>'Ӂ','Ó‚'=>'ӂ','Ó'=>'Ð̆','Ó‘'=>'ӑ','Ó’'=>'Ð̈','Ó“'=>'ӓ','Ó–'=>'Ӗ','Ó—'=>'ӗ','Óš'=>'Ӛ','Ó›'=>'ӛ','Óœ'=>'Ӝ','Ó'=>'ӝ','Óž'=>'Ӟ','ÓŸ'=>'ӟ','Ó¢'=>'Ӣ','Ó£'=>'ӣ','Ó¤'=>'Ӥ','Ó¥'=>'ӥ','Ó¦'=>'Ӧ','Ó§'=>'ӧ','Óª'=>'Ӫ','Ó«'=>'ӫ','Ó¬'=>'Ð̈','Ó'=>'Ñ̈','Ó®'=>'Ӯ','Ó¯'=>'ӯ','Ó°'=>'Ӱ','Ó±'=>'ӱ','Ó²'=>'Ӳ','Ó³'=>'ӳ','Ó´'=>'Ӵ','Óµ'=>'ӵ','Ó¸'=>'Ӹ','Ó¹'=>'ӹ','Ø¢'=>'آ','Ø£'=>'أ','ؤ'=>'ÙˆÙ”','Ø¥'=>'إ','ئ'=>'ÙŠÙ”','Û€'=>'Û•Ù”','Û‚'=>'ÛÙ”','Û“'=>'Û’Ù”','ऩ'=>'ऩ','ऱ'=>'ऱ','ऴ'=>'ऴ','क़'=>'क़','ख़'=>'ख़','ग़'=>'ग़','ज़'=>'ज़','ड़'=>'ड़','à¥'=>'ढ़','फ़'=>'फ़','य़'=>'य़','à§‹'=>'ো','à§Œ'=>'ৌ','à§œ'=>'ড়','à§'=>'ঢ়','à§Ÿ'=>'য়','ਲ਼'=>'ਲ਼','ਸ਼'=>'ਸ਼','à©™'=>'ਖ਼','ਗ਼'=>'ਗ਼','à©›'=>'ਜ਼','ਫ਼'=>'ਫ਼','àˆ'=>'à‡à–','à‹'=>'à‡à¬¾','àŒ'=>'à‡à—','àœ'=>'ଡ଼','à'=>'ଢ଼','à®”'=>'ஔ','ொ'=>'ொ','ோ'=>'ோ','ௌ'=>'ௌ','ై'=>'ై','à³€'=>'ೀ','ೇ'=>'ೇ','ೈ'=>'ೈ','ೊ'=>'ೊ','ೋ'=>'ೋ','ൊ'=>'ൊ','ോ'=>'ോ','ൌ'=>'ൌ','à·š'=>'ේ','à·œ'=>'à·™à·','à·'=>'à·™à·à·Š','à·ž'=>'ෞ','གྷ'=>'གྷ','à½'=>'ཌྷ','དྷ'=>'དྷ','བྷ'=>'བྷ','ཛྷ'=>'ཛྷ','ཀྵ'=>'ཀྵ','ཱི'=>'ཱི','ཱུ'=>'ཱུ','ྲྀ'=>'ྲྀ','ླྀ'=>'ླྀ','à¾'=>'ཱྀ','ྒྷ'=>'ྒྷ','à¾'=>'ྜྷ','ྡྷ'=>'ྡྷ','ྦྷ'=>'ྦྷ','ྫྷ'=>'ྫྷ','ྐྵ'=>'à¾à¾µ','ဦ'=>'ဦ','ᬆ'=>'ᬆ','ᬈ'=>'ᬈ','ᬊ'=>'ᬊ','ᬌ'=>'ᬌ','ᬎ'=>'á¬á¬µ','ᬒ'=>'ᬒ','ᬻ'=>'ᬻ','ᬽ'=>'ᬽ','á€'=>'ᭀ','á'=>'ᭁ','áƒ'=>'á‚ᬵ','Ḁ'=>'AÌ¥','á¸'=>'aÌ¥','Ḃ'=>'Ḃ','ḃ'=>'ḃ','Ḅ'=>'BÌ£','ḅ'=>'bÌ£','Ḇ'=>'Ḇ','ḇ'=>'ḇ','Ḉ'=>'ÇÌ','ḉ'=>'çÌ','Ḋ'=>'Ḋ','ḋ'=>'ḋ','Ḍ'=>'DÌ£','á¸'=>'dÌ£','Ḏ'=>'Ḏ','á¸'=>'ḏ','á¸'=>'Ḑ','ḑ'=>'ḑ','Ḓ'=>'DÌ','ḓ'=>'dÌ','Ḕ'=>'Ḕ','ḕ'=>'ḕ','Ḗ'=>'EÌ„Ì','ḗ'=>'eÌ„Ì','Ḙ'=>'EÌ','ḙ'=>'eÌ','Ḛ'=>'Ḛ','ḛ'=>'ḛ','Ḝ'=>'Ḝ','á¸'=>'ḝ','Ḟ'=>'Ḟ','ḟ'=>'ḟ','Ḡ'=>'GÌ„','ḡ'=>'gÌ„','Ḣ'=>'Ḣ','ḣ'=>'ḣ','Ḥ'=>'HÌ£','ḥ'=>'hÌ£','Ḧ'=>'Ḧ','ḧ'=>'ḧ','Ḩ'=>'Ḩ','ḩ'=>'ḩ','Ḫ'=>'HÌ®','ḫ'=>'hÌ®','Ḭ'=>'Ḭ','á¸'=>'ḭ','Ḯ'=>'ÏÌ','ḯ'=>'ïÌ','Ḱ'=>'KÌ','ḱ'=>'kÌ','Ḳ'=>'KÌ£','ḳ'=>'kÌ£','Ḵ'=>'Ḵ','ḵ'=>'ḵ','Ḷ'=>'LÌ£','ḷ'=>'lÌ£','Ḹ'=>'Ḹ','ḹ'=>'ḹ','Ḻ'=>'Ḻ','ḻ'=>'ḻ','Ḽ'=>'LÌ','ḽ'=>'lÌ','Ḿ'=>'MÌ','ḿ'=>'mÌ','á¹€'=>'Ṁ','á¹'=>'ṁ','Ṃ'=>'MÌ£','ṃ'=>'mÌ£','Ṅ'=>'Ṅ','á¹…'=>'ṅ','Ṇ'=>'NÌ£','ṇ'=>'nÌ£','Ṉ'=>'Ṉ','ṉ'=>'ṉ','Ṋ'=>'NÌ','ṋ'=>'nÌ','Ṍ'=>'ÕÌ','á¹'=>'õÌ','Ṏ'=>'Ṏ','á¹'=>'ṏ','á¹'=>'Ṑ','ṑ'=>'ṑ','á¹’'=>'OÌ„Ì','ṓ'=>'oÌ„Ì','á¹”'=>'PÌ','ṕ'=>'pÌ','á¹–'=>'Ṗ','á¹—'=>'ṗ','Ṙ'=>'Ṙ','á¹™'=>'ṙ','Ṛ'=>'RÌ£','á¹›'=>'rÌ£','Ṝ'=>'Ṝ','á¹'=>'ṝ','Ṟ'=>'Ṟ','ṟ'=>'ṟ','á¹ '=>'Ṡ','ṡ'=>'ṡ','á¹¢'=>'SÌ£','á¹£'=>'sÌ£','Ṥ'=>'SÌ̇','á¹¥'=>'sÌ̇','Ṧ'=>'Ṧ','á¹§'=>'ṧ','Ṩ'=>'Ṩ','ṩ'=>'ṩ','Ṫ'=>'Ṫ','ṫ'=>'ṫ','Ṭ'=>'TÌ£','á¹'=>'tÌ£','á¹®'=>'Ṯ','ṯ'=>'ṯ','á¹°'=>'TÌ','á¹±'=>'tÌ','á¹²'=>'Ṳ','á¹³'=>'ṳ','á¹´'=>'Ṵ','á¹µ'=>'ṵ','á¹¶'=>'UÌ','á¹·'=>'uÌ','Ṹ'=>'ŨÌ','á¹¹'=>'ũÌ','Ṻ'=>'Ṻ','á¹»'=>'ṻ','á¹¼'=>'Ṽ','á¹½'=>'ṽ','á¹¾'=>'VÌ£','ṿ'=>'vÌ£','Ẁ'=>'WÌ€','áº'=>'wÌ€','Ẃ'=>'WÌ','ẃ'=>'wÌ','Ẅ'=>'Ẅ','ẅ'=>'ẅ','Ẇ'=>'Ẇ','ẇ'=>'ẇ','Ẉ'=>'WÌ£','ẉ'=>'wÌ£','Ẋ'=>'Ẋ','ẋ'=>'ẋ','Ẍ'=>'Ẍ','áº'=>'ẍ','Ẏ'=>'Ẏ','áº'=>'ẏ','áº'=>'ZÌ‚','ẑ'=>'zÌ‚','Ẓ'=>'ZÌ£','ẓ'=>'zÌ£','Ẕ'=>'Ẕ','ẕ'=>'ẕ','ẖ'=>'ẖ','ẗ'=>'ẗ','ẘ'=>'wÌŠ','ẙ'=>'yÌŠ','ẛ'=>'ẛ','Ạ'=>'AÌ£','ạ'=>'aÌ£','Ả'=>'Ả','ả'=>'ả','Ấ'=>'AÌ‚Ì','ấ'=>'aÌ‚Ì','Ầ'=>'Ầ','ầ'=>'ầ','Ẩ'=>'Ẩ','ẩ'=>'ẩ','Ẫ'=>'Ẫ','ẫ'=>'ẫ','Ậ'=>'Ậ','áº'=>'ậ','Ắ'=>'ĂÌ','ắ'=>'ăÌ','Ằ'=>'Ằ','ằ'=>'ằ','Ẳ'=>'Ẳ','ẳ'=>'ẳ','Ẵ'=>'Ẵ','ẵ'=>'ẵ','Ặ'=>'Ặ','ặ'=>'ặ','Ẹ'=>'EÌ£','ẹ'=>'eÌ£','Ẻ'=>'Ẻ','ẻ'=>'ẻ','Ẽ'=>'Ẽ','ẽ'=>'ẽ','Ế'=>'EÌ‚Ì','ế'=>'eÌ‚Ì','Ề'=>'Ề','á»'=>'ề','Ể'=>'Ể','ể'=>'ể','Ễ'=>'Ễ','á»…'=>'ễ','Ệ'=>'Ệ','ệ'=>'ệ','Ỉ'=>'Ỉ','ỉ'=>'ỉ','Ị'=>'IÌ£','ị'=>'iÌ£','Ọ'=>'OÌ£','á»'=>'oÌ£','Ỏ'=>'Ỏ','á»'=>'ỏ','á»'=>'OÌ‚Ì','ố'=>'oÌ‚Ì','á»’'=>'Ồ','ồ'=>'ồ','á»”'=>'Ổ','ổ'=>'ổ','á»–'=>'Ỗ','á»—'=>'ỗ','Ộ'=>'Ộ','á»™'=>'ộ','Ớ'=>'OÌ›Ì','á»›'=>'oÌ›Ì','Ờ'=>'Ờ','á»'=>'ờ','Ở'=>'Ở','ở'=>'ở','á» '=>'Ỡ','ỡ'=>'ỡ','Ợ'=>'Ợ','ợ'=>'ợ','Ụ'=>'UÌ£','ụ'=>'uÌ£','Ủ'=>'Ủ','á»§'=>'ủ','Ứ'=>'UÌ›Ì','ứ'=>'uÌ›Ì','Ừ'=>'Ừ','ừ'=>'ừ','Ử'=>'Ử','á»'=>'ử','á»®'=>'Ữ','ữ'=>'ữ','á»°'=>'Ự','á»±'=>'ự','Ỳ'=>'YÌ€','ỳ'=>'yÌ€','á»´'=>'YÌ£','ỵ'=>'yÌ£','á»¶'=>'Ỷ','á»·'=>'ỷ','Ỹ'=>'Ỹ','ỹ'=>'ỹ','á¼€'=>'ἀ','á¼'=>'ἁ','ἂ'=>'ἂ','ἃ'=>'ἃ','ἄ'=>'ἀÌ','á¼…'=>'ἁÌ','ἆ'=>'ἆ','ἇ'=>'ἇ','Ἀ'=>'Ἀ','Ἁ'=>'Ἁ','Ἂ'=>'Ἂ','Ἃ'=>'Ἃ','Ἄ'=>'ἈÌ','á¼'=>'ἉÌ','Ἆ'=>'Ἆ','á¼'=>'Ἇ','á¼'=>'ἐ','ἑ'=>'ἑ','á¼’'=>'ἒ','ἓ'=>'ἓ','á¼”'=>'ἐÌ','ἕ'=>'ἑÌ','Ἐ'=>'Ἐ','á¼™'=>'Ἑ','Ἒ'=>'Ἒ','á¼›'=>'Ἓ','Ἔ'=>'ἘÌ','á¼'=>'ἙÌ','á¼ '=>'ἠ','ἡ'=>'ἡ','á¼¢'=>'ἢ','á¼£'=>'ἣ','ἤ'=>'ἠÌ','á¼¥'=>'ἡÌ','ἦ'=>'ἦ','á¼§'=>'ἧ','Ἠ'=>'Ἠ','Ἡ'=>'Ἡ','Ἢ'=>'Ἢ','Ἣ'=>'Ἣ','Ἤ'=>'ἨÌ','á¼'=>'ἩÌ','á¼®'=>'Ἦ','Ἧ'=>'Ἧ','á¼°'=>'ἰ','á¼±'=>'ἱ','á¼²'=>'ἲ','á¼³'=>'ἳ','á¼´'=>'ἰÌ','á¼µ'=>'ἱÌ','á¼¶'=>'ἶ','á¼·'=>'ἷ','Ἰ'=>'Ἰ','á¼¹'=>'Ἱ','Ἲ'=>'Ἲ','á¼»'=>'Ἳ','á¼¼'=>'ἸÌ','á¼½'=>'ἹÌ','á¼¾'=>'Ἶ','Ἷ'=>'Ἷ','á½€'=>'ὀ','á½'=>'ὁ','ὂ'=>'ὂ','ὃ'=>'ὃ','ὄ'=>'ὀÌ','á½…'=>'ὁÌ','Ὀ'=>'Ὀ','Ὁ'=>'Ὁ','Ὂ'=>'Ὂ','Ὃ'=>'Ὃ','Ὄ'=>'ὈÌ','á½'=>'ὉÌ','á½'=>'Ï…Ì“','ὑ'=>'Ï…Ì”','á½’'=>'ὒ','ὓ'=>'ὓ','á½”'=>'Ï…Ì“Ì','ὕ'=>'Ï…Ì”Ì','á½–'=>'ὖ','á½—'=>'ὗ','á½™'=>'Ὑ','á½›'=>'Ὓ','á½'=>'ὙÌ','Ὗ'=>'Ὗ','á½ '=>'ὠ','ὡ'=>'ὡ','á½¢'=>'ὢ','á½£'=>'ὣ','ὤ'=>'ὠÌ','á½¥'=>'ὡÌ','ὦ'=>'ὦ','á½§'=>'ὧ','Ὠ'=>'Ὠ','Ὡ'=>'Ὡ','Ὢ'=>'Ὢ','Ὣ'=>'Ὣ','Ὤ'=>'ὨÌ','á½'=>'ὩÌ','á½®'=>'Ὦ','Ὧ'=>'Ὧ','á½°'=>'ὰ','á½±'=>'αÌ','á½²'=>'ὲ','á½³'=>'εÌ','á½´'=>'ὴ','á½µ'=>'ηÌ','á½¶'=>'ὶ','á½·'=>'ιÌ','ὸ'=>'ὸ','á½¹'=>'οÌ','ὺ'=>'Ï…Ì€','á½»'=>'Ï…Ì','á½¼'=>'ὼ','á½½'=>'ωÌ','á¾€'=>'ᾀ','á¾'=>'ᾁ','ᾂ'=>'ᾂ','ᾃ'=>'ᾃ','ᾄ'=>'ἀÌÍ…','á¾…'=>'ἁÌÍ…','ᾆ'=>'ᾆ','ᾇ'=>'ᾇ','ᾈ'=>'ᾈ','ᾉ'=>'ᾉ','ᾊ'=>'ᾊ','ᾋ'=>'ᾋ','ᾌ'=>'ἈÌÍ…','á¾'=>'ἉÌÍ…','ᾎ'=>'ᾎ','á¾'=>'ᾏ','á¾'=>'ᾐ','ᾑ'=>'ᾑ','á¾’'=>'ᾒ','ᾓ'=>'ᾓ','á¾”'=>'ἠÌÍ…','ᾕ'=>'ἡÌÍ…','á¾–'=>'ᾖ','á¾—'=>'ᾗ','ᾘ'=>'ᾘ','á¾™'=>'ᾙ','ᾚ'=>'ᾚ','á¾›'=>'ᾛ','ᾜ'=>'ἨÌÍ…','á¾'=>'ἩÌÍ…','ᾞ'=>'ᾞ','ᾟ'=>'ᾟ','á¾ '=>'ᾠ','ᾡ'=>'ᾡ','á¾¢'=>'ᾢ','á¾£'=>'ᾣ','ᾤ'=>'ὠÌÍ…','á¾¥'=>'ὡÌÍ…','ᾦ'=>'ᾦ','á¾§'=>'ᾧ','ᾨ'=>'ᾨ','ᾩ'=>'ᾩ','ᾪ'=>'ᾪ','ᾫ'=>'ᾫ','ᾬ'=>'ὨÌÍ…','á¾'=>'ὩÌÍ…','á¾®'=>'ᾮ','ᾯ'=>'ᾯ','á¾°'=>'ᾰ','á¾±'=>'ᾱ','á¾²'=>'ᾲ','á¾³'=>'ᾳ','á¾´'=>'αÌÍ…','á¾¶'=>'ᾶ','á¾·'=>'ᾷ','Ᾰ'=>'Ᾰ','á¾¹'=>'Ᾱ','Ὰ'=>'Ὰ','á¾»'=>'ΑÌ','á¾¼'=>'ᾼ','á¾¾'=>'ι','á¿'=>'῁','á¿‚'=>'ῂ','ῃ'=>'ῃ','á¿„'=>'ηÌÍ…','ῆ'=>'ῆ','ῇ'=>'ῇ','Ὲ'=>'Ὲ','Έ'=>'ΕÌ','Ὴ'=>'Ὴ','á¿‹'=>'ΗÌ','ῌ'=>'ῌ','á¿'=>'῍','῎'=>'᾿Ì','á¿'=>'῏','á¿'=>'ῐ','á¿‘'=>'ῑ','á¿’'=>'ῒ','á¿“'=>'ϊÌ','á¿–'=>'ῖ','á¿—'=>'ῗ','Ῐ'=>'Ῐ','á¿™'=>'Ῑ','Ὶ'=>'Ὶ','á¿›'=>'ΙÌ','á¿'=>'῝','῞'=>'῾Ì','῟'=>'῟','á¿ '=>'ῠ','á¿¡'=>'Ï…Ì„','á¿¢'=>'ῢ','á¿£'=>'ϋÌ','ῤ'=>'ÏÌ“','á¿¥'=>'ÏÌ”','ῦ'=>'Ï…Í‚','á¿§'=>'ῧ','Ῠ'=>'Ῠ','á¿©'=>'Ῡ','Ὺ'=>'Ὺ','á¿«'=>'Î¥Ì','Ῥ'=>'Ῥ','á¿'=>'῭','á¿®'=>'¨Ì','`'=>'`','ῲ'=>'ῲ','ῳ'=>'ῳ','á¿´'=>'ωÌÍ…','á¿¶'=>'ῶ','á¿·'=>'ῷ','Ὸ'=>'Ὸ','Ό'=>'ΟÌ','Ὼ'=>'Ὼ','á¿»'=>'ΩÌ','ῼ'=>'ῼ','´'=>'´',' '=>' ','â€'=>' ','Ω'=>'Ω','K'=>'K','â„«'=>'AÌŠ','↚'=>'â†Ì¸','↛'=>'↛','↮'=>'↮','â‡'=>'â‡Ì¸','⇎'=>'⇎','â‡'=>'⇏','∄'=>'∄','∉'=>'∉','∌'=>'∌','∤'=>'∤','∦'=>'∦','â‰'=>'≁','≄'=>'≄','≇'=>'≇','≉'=>'≉','≠'=>'≠','≢'=>'≢','â‰'=>'â‰Ì¸','≮'=>'≮','≯'=>'≯','≰'=>'≰','≱'=>'≱','≴'=>'≴','≵'=>'≵','≸'=>'≸','≹'=>'≹','⊀'=>'⊀','âŠ'=>'⊁','⊄'=>'⊄','⊅'=>'⊅','⊈'=>'⊈','⊉'=>'⊉','⊬'=>'⊬','âŠ'=>'⊭','⊮'=>'⊮','⊯'=>'⊯','â‹ '=>'⋠','â‹¡'=>'⋡','â‹¢'=>'⋢','â‹£'=>'⋣','⋪'=>'⋪','â‹«'=>'⋫','⋬'=>'⋬','â‹'=>'⋭','〈'=>'〈','〉'=>'〉','⫝̸'=>'â«Ì¸','ãŒ'=>'ã‹ã‚™','ãŽ'=>'ãã‚™','ã'=>'ãã‚™','ã’'=>'ã‘ã‚™','ã”'=>'ã“ã‚™','ã–'=>'ã•ã‚™','ã˜'=>'ã—ã‚™','ãš'=>'ã™ã‚™','ãœ'=>'ã›ã‚™','ãž'=>'ãã‚™','ã '=>'ãŸã‚™','ã¢'=>'ã¡ã‚™','ã¥'=>'ã¤ã‚™','ã§'=>'ã¦ã‚™','ã©'=>'ã¨ã‚™','ã°'=>'ã¯ã‚™','ã±'=>'ã¯ã‚š','ã³'=>'ã²ã‚™','ã´'=>'ã²ã‚š','ã¶'=>'ãµã‚™','ã·'=>'ãµã‚š','ã¹'=>'ã¸ã‚™','ãº'=>'ã¸ã‚š','ã¼'=>'ã»ã‚™','ã½'=>'ã»ã‚š','ã‚”'=>'ã†ã‚™','ゞ'=>'ã‚ã‚™','ガ'=>'ã‚«ã‚™','ã‚®'=>'ã‚ã‚™','ã‚°'=>'グ','ゲ'=>'ゲ','ã‚´'=>'ゴ','ã‚¶'=>'ザ','ジ'=>'ã‚·ã‚™','ズ'=>'ズ','ゼ'=>'ゼ','ゾ'=>'ゾ','ダ'=>'ã‚¿ã‚™','ヂ'=>'ãƒã‚™','ヅ'=>'ヅ','デ'=>'デ','ド'=>'ド','ãƒ'=>'ãƒã‚™','パ'=>'ãƒã‚š','ビ'=>'ビ','ピ'=>'ピ','ブ'=>'ブ','プ'=>'プ','ベ'=>'ベ','ペ'=>'ペ','ボ'=>'ボ','ãƒ'=>'ポ','ヴ'=>'ヴ','ヷ'=>'ヷ','ヸ'=>'ヸ','ヹ'=>'ヹ','ヺ'=>'ヺ','ヾ'=>'ヾ','豈'=>'豈','ï¤'=>'æ›´','車'=>'車','賈'=>'賈','滑'=>'滑','串'=>'串','句'=>'å¥','龜'=>'龜','龜'=>'龜','契'=>'契','金'=>'金','喇'=>'å–‡','奈'=>'奈','ï¤'=>'懶','癩'=>'癩','ï¤'=>'ç¾…','ï¤'=>'蘿','螺'=>'螺','裸'=>'裸','邏'=>'é‚','樂'=>'樂','洛'=>'æ´›','烙'=>'烙','珞'=>'çž','落'=>'è½','酪'=>'é…ª','駱'=>'é§±','亂'=>'亂','卵'=>'åµ','ï¤'=>'欄','爛'=>'爛','蘭'=>'è˜','ï¤ '=>'鸞','嵐'=>'åµ','濫'=>'æ¿«','藍'=>'è—','襤'=>'襤','拉'=>'拉','臘'=>'臘','蠟'=>'è Ÿ','廊'=>'廊','朗'=>'朗','浪'=>'浪','狼'=>'狼','郎'=>'郎','ï¤'=>'來','冷'=>'冷','勞'=>'勞','擄'=>'æ“„','櫓'=>'æ«“','爐'=>'çˆ','盧'=>'ç›§','老'=>'è€','蘆'=>'蘆','虜'=>'虜','路'=>'è·¯','露'=>'露','魯'=>'é¯','鷺'=>'é·º','碌'=>'碌','祿'=>'祿','綠'=>'ç¶ ','菉'=>'è‰','錄'=>'錄','鹿'=>'鹿','ï¥'=>'è«–','壟'=>'壟','弄'=>'弄','籠'=>'ç± ','聾'=>'è¾','牢'=>'牢','磊'=>'磊','賂'=>'賂','雷'=>'é›·','壘'=>'壘','屢'=>'å±¢','樓'=>'樓','ï¥'=>'æ·š','漏'=>'æ¼','ï¥'=>'ç´¯','ï¥'=>'縷','陋'=>'陋','勒'=>'å‹’','肋'=>'è‚‹','凜'=>'凜','凌'=>'凌','稜'=>'稜','綾'=>'ç¶¾','菱'=>'è±','陵'=>'陵','讀'=>'讀','拏'=>'æ‹','樂'=>'樂','ï¥'=>'諾','丹'=>'丹','寧'=>'寧','ï¥ '=>'怒','率'=>'率','異'=>'ç•°','北'=>'北','磻'=>'磻','便'=>'便','復'=>'復','不'=>'ä¸','泌'=>'泌','數'=>'數','索'=>'ç´¢','參'=>'åƒ','塞'=>'塞','ï¥'=>'çœ','葉'=>'葉','說'=>'說','殺'=>'殺','辰'=>'è¾°','沈'=>'沈','拾'=>'拾','若'=>'è‹¥','掠'=>'æŽ ','略'=>'ç•¥','亮'=>'亮','兩'=>'å…©','凉'=>'凉','梁'=>'æ¢','糧'=>'ç³§','良'=>'良','諒'=>'è«’','量'=>'é‡','勵'=>'勵','呂'=>'å‘‚','ï¦'=>'女','廬'=>'廬','旅'=>'æ—…','濾'=>'濾','礪'=>'礪','閭'=>'é–','驪'=>'驪','麗'=>'麗','黎'=>'黎','力'=>'力','曆'=>'曆','歷'=>'æ·','ï¦'=>'è½¢','年'=>'å¹´','ï¦'=>'æ†','ï¦'=>'戀','撚'=>'æ’š','漣'=>'æ¼£','煉'=>'ç…‰','璉'=>'ç’‰','秊'=>'ç§Š','練'=>'ç·´','聯'=>'è¯','輦'=>'輦','蓮'=>'è“®','連'=>'連','鍊'=>'éŠ','列'=>'列','ï¦'=>'劣','咽'=>'å’½','烈'=>'烈','ï¦ '=>'裂','說'=>'說','廉'=>'廉','念'=>'念','捻'=>'æ»','殮'=>'æ®®','簾'=>'ç°¾','獵'=>'çµ','令'=>'令','囹'=>'囹','寧'=>'寧','嶺'=>'嶺','怜'=>'怜','ï¦'=>'玲','瑩'=>'ç‘©','羚'=>'羚','聆'=>'è†','鈴'=>'鈴','零'=>'é›¶','靈'=>'éˆ','領'=>'é ˜','例'=>'例','禮'=>'禮','醴'=>'醴','隸'=>'隸','惡'=>'惡','了'=>'了','僚'=>'僚','寮'=>'寮','尿'=>'å°¿','料'=>'æ–™','樂'=>'樂','ï§€'=>'燎','ï§'=>'療','ï§‚'=>'蓼','遼'=>'é¼','ï§„'=>'é¾','ï§…'=>'暈','阮'=>'阮','劉'=>'劉','杻'=>'æ»','柳'=>'柳','ï§Š'=>'æµ','ï§‹'=>'溜','ï§Œ'=>'ç‰','ï§'=>'ç•™','ï§Ž'=>'ç¡«','ï§'=>'ç´','ï§'=>'類','ï§‘'=>'å…','ï§’'=>'戮','ï§“'=>'陸','ï§”'=>'倫','ï§•'=>'å´™','ï§–'=>'æ·ª','ï§—'=>'輪','律'=>'律','ï§™'=>'æ…„','ï§š'=>'æ —','ï§›'=>'率','ï§œ'=>'隆','ï§'=>'利','ï§ž'=>'å','ï§Ÿ'=>'å±¥','ï§ '=>'易','ï§¡'=>'æŽ','ï§¢'=>'梨','ï§£'=>'æ³¥','理'=>'ç†','ï§¥'=>'ç—¢','罹'=>'ç½¹','ï§§'=>'è£','裡'=>'裡','ï§©'=>'里','離'=>'離','ï§«'=>'匿','溺'=>'溺','ï§'=>'å','ï§®'=>'ç‡','璘'=>'ç’˜','ï§°'=>'è—º','ï§±'=>'隣','ï§²'=>'é±—','ï§³'=>'麟','ï§´'=>'æž—','ï§µ'=>'æ·‹','ï§¶'=>'臨','ï§·'=>'ç«‹','笠'=>'ç¬ ','ï§¹'=>'ç²’','狀'=>'ç‹€','ï§»'=>'ç‚™','ï§¼'=>'è˜','ï§½'=>'什','ï§¾'=>'茶','ï§¿'=>'刺','切'=>'切','ï¨'=>'度','拓'=>'æ‹“','糖'=>'ç³–','宅'=>'å®…','洞'=>'æ´ž','暴'=>'æš´','輻'=>'è¼»','行'=>'行','降'=>'é™','見'=>'見','廓'=>'廓','兀'=>'å…€','ï¨'=>'å—€','ï¨'=>'塚','晴'=>'æ™´','凞'=>'凞','猪'=>'猪','益'=>'益','礼'=>'礼','神'=>'神','祥'=>'祥','福'=>'ç¦','靖'=>'é–','ï¨'=>'ç²¾','羽'=>'ç¾½','ï¨ '=>'蘒','諸'=>'諸','逸'=>'逸','都'=>'都','飯'=>'飯','飼'=>'飼','館'=>'館','ï¨'=>'é¶´','侮'=>'ä¾®','僧'=>'僧','免'=>'å…','勉'=>'勉','勤'=>'勤','卑'=>'å‘','喝'=>'å–','嘆'=>'嘆','器'=>'器','塀'=>'å¡€','墨'=>'墨','層'=>'層','屮'=>'å±®','悔'=>'æ‚”','慨'=>'æ…¨','憎'=>'憎','ï©€'=>'懲','ï©'=>'æ•','ï©‚'=>'æ—¢','暑'=>'æš‘','ï©„'=>'梅','ï©…'=>'æµ·','渚'=>'渚','漢'=>'æ¼¢','煮'=>'ç…®','爫'=>'爫','琢'=>'ç¢','ï©‹'=>'碑','社'=>'社','ï©'=>'祉','祈'=>'祈','ï©'=>'ç¥','ï©'=>'祖','ï©‘'=>'ç¥','ï©’'=>'ç¦','ï©“'=>'禎','ï©”'=>'ç©€','ï©•'=>'çª','ï©–'=>'節','ï©—'=>'ç·´','縉'=>'縉','ï©™'=>'ç¹','署'=>'ç½²','ï©›'=>'者','臭'=>'è‡','ï©'=>'艹','艹'=>'艹','著'=>'è‘—','ï© '=>'è¤','ï©¡'=>'視','ï©¢'=>'è¬','ï©£'=>'謹','賓'=>'賓','ï©¥'=>'è´ˆ','辶'=>'è¾¶','ï©§'=>'逸','難'=>'難','ï©©'=>'響','頻'=>'é »','ï©°'=>'並','况'=>'况','全'=>'å…¨','侀'=>'ä¾€','ï©´'=>'å……','冀'=>'冀','ï©¶'=>'勇','ï©·'=>'勺','喝'=>'å–','啕'=>'å••','喙'=>'å–™','ï©»'=>'å—¢','塚'=>'塚','墳'=>'墳','奄'=>'奄','ï©¿'=>'奔','婢'=>'å©¢','ïª'=>'嬨','廒'=>'å»’','廙'=>'å»™','彩'=>'彩','徭'=>'å¾','惘'=>'惘','慎'=>'æ…Ž','愈'=>'愈','憎'=>'憎','慠'=>'æ… ','懲'=>'懲','戴'=>'戴','ïª'=>'æ„','搜'=>'æœ','ïª'=>'æ‘’','ïª'=>'æ•–','晴'=>'æ™´','朗'=>'朗','望'=>'望','杖'=>'æ–','歹'=>'æ¹','殺'=>'殺','流'=>'æµ','滛'=>'æ»›','滋'=>'滋','漢'=>'æ¼¢','瀞'=>'瀞','煮'=>'ç…®','ïª'=>'çž§','爵'=>'爵','犯'=>'犯','ïª '=>'猪','瑱'=>'瑱','甆'=>'甆','画'=>'ç”»','瘝'=>'ç˜','瘟'=>'瘟','益'=>'益','盛'=>'ç››','直'=>'ç›´','睊'=>'çŠ','着'=>'ç€','磌'=>'磌','窱'=>'窱','ïª'=>'節','类'=>'ç±»','絛'=>'çµ›','練'=>'ç·´','缾'=>'ç¼¾','者'=>'者','荒'=>'è’','華'=>'è¯','蝹'=>'è¹','襁'=>'è¥','覆'=>'覆','視'=>'視','調'=>'調','諸'=>'諸','請'=>'è«‹','謁'=>'è¬','諾'=>'諾','諭'=>'è«','謹'=>'謹','ï«€'=>'變','ï«'=>'è´ˆ','ï«‚'=>'輸','遲'=>'é²','ï«„'=>'醙','ï«…'=>'鉶','陼'=>'陼','難'=>'難','靖'=>'é–','韛'=>'韛','響'=>'響','ï«‹'=>'é ‹','頻'=>'é »','ï«'=>'鬒','龜'=>'龜','ï«'=>'𢡊','ï«'=>'𢡄','ï«‘'=>'ð£•','ï«’'=>'ã®','ï«“'=>'䀘','ï«”'=>'䀹','ï«•'=>'𥉉','ï«–'=>'ð¥³','ï«—'=>'𧻓','齃'=>'齃','ï«™'=>'龎','ï¬'=>'×™Ö´','ײַ'=>'ײַ','שׁ'=>'ש×','שׂ'=>'שׂ','שּׁ'=>'שּ×','ï¬'=>'שּׂ','אַ'=>'×Ö·','אָ'=>'×Ö¸','אּ'=>'×Ö¼','בּ'=>'בּ','גּ'=>'×’Ö¼','דּ'=>'דּ','הּ'=>'×”Ö¼','וּ'=>'וּ','זּ'=>'×–Ö¼','טּ'=>'טּ','יּ'=>'×™Ö¼','ךּ'=>'ךּ','כּ'=>'×›Ö¼','לּ'=>'לּ','מּ'=>'מּ','ï€'=>'× Ö¼','ï'=>'סּ','ïƒ'=>'×£Ö¼','ï„'=>'פּ','ï†'=>'צּ','ï‡'=>'×§Ö¼','ïˆ'=>'רּ','ï‰'=>'שּ','ïŠ'=>'תּ','ï‹'=>'וֹ','ïŒ'=>'בֿ','ï'=>'×›Ö¿','ïŽ'=>'פֿ','ð…ž'=>'ð…—ð…¥','ð…Ÿ'=>'ð…˜ð…¥','ð… '=>'ð…˜ð…¥ð…®','ð…¡'=>'ð…˜ð…¥ð…¯','ð…¢'=>'ð…˜ð…¥ð…°','ð…£'=>'ð…˜ð…¥ð…±','ð…¤'=>'ð…˜ð…¥ð…²','ð†»'=>'ð†¹ð…¥','ð†¼'=>'ð†ºð…¥','ð†½'=>'ð†¹ð…¥ð…®','ð†¾'=>'ð†ºð…¥ð…®','ð†¿'=>'ð†¹ð…¥ð…¯','ð‡€'=>'ð†ºð…¥ð…¯','丽'=>'丽','ð¯ '=>'丸','乁'=>'ä¹','𠄢'=>'ð „¢','你'=>'ä½ ','侮'=>'ä¾®','侻'=>'ä¾»','倂'=>'倂','偺'=>'åº','備'=>'å‚™','僧'=>'僧','像'=>'åƒ','㒞'=>'ã’ž','ð¯ '=>'𠘺','免'=>'å…','ð¯ '=>'å…”','ð¯ '=>'å…¤','具'=>'å…·','𠔜'=>'𠔜','㒹'=>'ã’¹','內'=>'å…§','再'=>'å†','𠕋'=>'ð •‹','冗'=>'冗','冤'=>'冤','仌'=>'仌','冬'=>'冬','况'=>'况','𩇟'=>'𩇟','ð¯ '=>'凵','刃'=>'刃','㓟'=>'㓟','ð¯ '=>'刻','剆'=>'剆','割'=>'割','剷'=>'剷','㔕'=>'㔕','勇'=>'勇','勉'=>'勉','勤'=>'勤','勺'=>'勺','包'=>'包','匆'=>'匆','北'=>'北','卉'=>'å‰','ð¯ '=>'å‘','博'=>'åš','即'=>'å³','卽'=>'å½','卿'=>'å¿','卿'=>'å¿','卿'=>'å¿','𠨬'=>'𠨬','灰'=>'ç°','及'=>'åŠ','叟'=>'åŸ','𠭣'=>'ð £','叫'=>'å«','叱'=>'å±','吆'=>'å†','咞'=>'å’ž','吸'=>'å¸','呈'=>'呈','周'=>'周','咢'=>'å’¢','ð¯¡'=>'å“¶','唐'=>'å”','啓'=>'å•“','啣'=>'å•£','善'=>'å–„','善'=>'å–„','喙'=>'å–™','喫'=>'å–«','喳'=>'å–³','嗂'=>'å—‚','圖'=>'圖','嘆'=>'嘆','ð¯¡'=>'圗','噑'=>'噑','ð¯¡'=>'å™´','ð¯¡'=>'切','壮'=>'壮','城'=>'城','埴'=>'埴','堍'=>'å ','型'=>'åž‹','堲'=>'å ²','報'=>'å ±','墬'=>'墬','𡓤'=>'𡓤','売'=>'売','壷'=>'壷','夆'=>'夆','ð¯¡'=>'多','夢'=>'夢','奢'=>'奢','𡚨'=>'𡚨','𡛪'=>'𡛪','姬'=>'姬','娛'=>'娛','娧'=>'娧','姘'=>'姘','婦'=>'婦','㛮'=>'ã›®','㛼'=>'㛼','嬈'=>'嬈','嬾'=>'嬾','嬾'=>'嬾','𡧈'=>'𡧈','ð¯¡'=>'寃','寘'=>'寘','寧'=>'寧','寳'=>'寳','𡬘'=>'𡬘','寿'=>'寿','将'=>'å°†','当'=>'当','尢'=>'å°¢','㞁'=>'ãž','屠'=>'å± ','屮'=>'å±®','峀'=>'å³€','岍'=>'å²','𡷤'=>'ð¡·¤','嵃'=>'嵃','𡷦'=>'ð¡·¦','嵮'=>'åµ®','嵫'=>'嵫','嵼'=>'åµ¼','ð¯¢'=>'å·¡','巢'=>'å·¢','㠯'=>'ã ¯','巽'=>'å·½','帨'=>'帨','帽'=>'帽','幩'=>'幩','㡢'=>'ã¡¢','𢆃'=>'𢆃','㡼'=>'㡼','庰'=>'庰','庳'=>'庳','ð¯¢'=>'庶','廊'=>'廊','ð¯¢'=>'𪎒','ð¯¢'=>'廾','𢌱'=>'𢌱','𢌱'=>'𢌱','舁'=>'èˆ','弢'=>'å¼¢','弢'=>'å¼¢','㣇'=>'㣇','𣊸'=>'𣊸','𦇚'=>'𦇚','形'=>'å½¢','彫'=>'彫','㣣'=>'㣣','徚'=>'徚','ð¯¢'=>'å¿','志'=>'å¿—','忹'=>'忹','悁'=>'æ‚','㤺'=>'㤺','㤜'=>'㤜','悔'=>'æ‚”','𢛔'=>'𢛔','惇'=>'惇','慈'=>'æ…ˆ','慌'=>'æ…Œ','慎'=>'æ…Ž','慌'=>'æ…Œ','慺'=>'æ…º','憎'=>'憎','憲'=>'憲','ð¯¢'=>'憤','憯'=>'憯','懞'=>'懞','懲'=>'懲','懶'=>'懶','成'=>'æˆ','戛'=>'戛','扝'=>'æ‰','抱'=>'抱','拔'=>'æ‹”','捐'=>'æ','𢬌'=>'𢬌','挽'=>'挽','拼'=>'拼','捨'=>'æ¨','掃'=>'掃','揤'=>'æ¤','𢯱'=>'𢯱','搢'=>'æ¢','揅'=>'æ…','ð¯£'=>'掩','㨮'=>'㨮','摩'=>'æ‘©','摾'=>'摾','撝'=>'æ’','摷'=>'æ‘·','㩬'=>'㩬','敏'=>'æ•','敬'=>'敬','𣀊'=>'𣀊','旣'=>'æ—£','書'=>'書','ð¯£'=>'晉','㬙'=>'㬙','ð¯£'=>'æš‘','ð¯£'=>'㬈','㫤'=>'㫤','冒'=>'冒','冕'=>'冕','最'=>'最','暜'=>'æšœ','肭'=>'è‚','䏙'=>'ä™','朗'=>'朗','望'=>'望','朡'=>'朡','杞'=>'æž','杓'=>'æ“','ð¯£'=>'ð£ƒ','㭉'=>'ã‰','柺'=>'柺','枅'=>'æž…','桒'=>'æ¡’','梅'=>'梅','𣑭'=>'ð£‘','梎'=>'梎','栟'=>'æ Ÿ','椔'=>'椔','㮝'=>'ã®','楂'=>'楂','榣'=>'榣','槪'=>'槪','檨'=>'檨','𣚣'=>'𣚣','ð¯£'=>'æ«›','㰘'=>'ã°˜','次'=>'次','𣢧'=>'𣢧','歔'=>'æ”','㱎'=>'㱎','歲'=>'æ²','殟'=>'殟','殺'=>'殺','殻'=>'æ®»','𣪍'=>'ð£ª','𡴋'=>'ð¡´‹','𣫺'=>'𣫺','汎'=>'汎','𣲼'=>'𣲼','沿'=>'沿','泍'=>'æ³','汧'=>'æ±§','洖'=>'æ´–','派'=>'æ´¾','ð¯¤'=>'æµ·','流'=>'æµ','浩'=>'浩','浸'=>'浸','涅'=>'æ¶…','𣴞'=>'𣴞','洴'=>'æ´´','港'=>'港','湮'=>'æ¹®','㴳'=>'ã´³','滋'=>'滋','滇'=>'滇','ð¯¤'=>'𣻑','淹'=>'æ·¹','ð¯¤'=>'æ½®','ð¯¤'=>'𣽞','𣾎'=>'𣾎','濆'=>'濆','瀹'=>'瀹','瀞'=>'瀞','瀛'=>'瀛','㶖'=>'ã¶–','灊'=>'çŠ','災'=>'ç½','灷'=>'ç·','炭'=>'ç‚','𠔥'=>'𠔥','煅'=>'ç……','ð¯¤'=>'𤉣','熜'=>'熜','𤎫'=>'𤎫','爨'=>'爨','爵'=>'爵','牐'=>'ç‰','𤘈'=>'𤘈','犀'=>'犀','犕'=>'犕','𤜵'=>'𤜵','𤠔'=>'𤠔','獺'=>'çº','王'=>'王','㺬'=>'㺬','玥'=>'玥','㺸'=>'㺸','ð¯¤'=>'㺸','瑇'=>'瑇','瑜'=>'瑜','瑱'=>'瑱','璅'=>'ç’…','瓊'=>'瓊','㼛'=>'ã¼›','甤'=>'甤','𤰶'=>'𤰶','甾'=>'甾','𤲒'=>'𤲒','異'=>'ç•°','𢆟'=>'𢆟','瘐'=>'ç˜','𤾡'=>'𤾡','𤾸'=>'𤾸','𥁄'=>'ð¥„','㿼'=>'㿼','䀈'=>'䀈','直'=>'ç›´','ð¯¥'=>'𥃳','𥃲'=>'𥃲','𥄙'=>'𥄙','𥄳'=>'𥄳','眞'=>'眞','真'=>'真','真'=>'真','睊'=>'çŠ','䀹'=>'䀹','瞋'=>'çž‹','䁆'=>'ä†','䂖'=>'ä‚–','ð¯¥'=>'ð¥','硎'=>'硎','ð¯¥'=>'碌','ð¯¥'=>'磌','䃣'=>'䃣','𥘦'=>'𥘦','祖'=>'祖','𥚚'=>'𥚚','𥛅'=>'𥛅','福'=>'ç¦','秫'=>'ç§«','䄯'=>'䄯','穀'=>'ç©€','穊'=>'穊','穏'=>'ç©','𥥼'=>'𥥼','ð¯¥'=>'𥪧','𥪧'=>'𥪧','竮'=>'ç«®','䈂'=>'䈂','𥮫'=>'𥮫','篆'=>'篆','築'=>'築','䈧'=>'䈧','𥲀'=>'𥲀','糒'=>'ç³’','䊠'=>'äŠ ','糨'=>'糨','糣'=>'ç³£','紀'=>'ç´€','𥾆'=>'𥾆','絣'=>'çµ£','ð¯¥'=>'äŒ','緇'=>'ç·‡','縂'=>'縂','繅'=>'ç¹…','䌴'=>'䌴','𦈨'=>'𦈨','𦉇'=>'𦉇','䍙'=>'ä™','𦋙'=>'𦋙','罺'=>'罺','𦌾'=>'𦌾','羕'=>'羕','翺'=>'翺','者'=>'者','𦓚'=>'𦓚','𦔣'=>'𦔣','聠'=>'è ','𦖨'=>'𦖨','聰'=>'è°','𣍟'=>'ð£Ÿ','ð¯¦'=>'ä•','育'=>'育','脃'=>'脃','䐋'=>'ä‹','脾'=>'脾','媵'=>'媵','𦞧'=>'𦞧','𦞵'=>'𦞵','𣎓'=>'𣎓','𣎜'=>'𣎜','舁'=>'èˆ','舄'=>'舄','ð¯¦'=>'辞','䑫'=>'ä‘«','ð¯¦'=>'芑','ð¯¦'=>'芋','芝'=>'èŠ','劳'=>'劳','花'=>'花','芳'=>'芳','芽'=>'芽','苦'=>'苦','𦬼'=>'𦬼','若'=>'è‹¥','茝'=>'èŒ','荣'=>'è£','莭'=>'èŽ','茣'=>'茣','ð¯¦'=>'莽','菧'=>'è§','著'=>'è‘—','荓'=>'è“','菊'=>'èŠ','菌'=>'èŒ','菜'=>'èœ','𦰶'=>'𦰶','𦵫'=>'𦵫','𦳕'=>'𦳕','䔫'=>'䔫','蓱'=>'蓱','蓳'=>'蓳','蔖'=>'è”–','𧏊'=>'ð§Š','蕤'=>'蕤','ð¯¦'=>'𦼬','䕝'=>'ä•','䕡'=>'ä•¡','𦾱'=>'𦾱','𧃒'=>'𧃒','䕫'=>'ä•«','虐'=>'è™','虜'=>'虜','虧'=>'è™§','虩'=>'虩','蚩'=>'èš©','蚈'=>'蚈','蜎'=>'蜎','蛢'=>'蛢','蝹'=>'è¹','蜨'=>'蜨','蝫'=>'è«','螆'=>'螆','䗗'=>'ä——','蟡'=>'蟡','ð¯§'=>'è ','䗹'=>'ä—¹','衠'=>'è¡ ','衣'=>'è¡£','𧙧'=>'ð§™§','裗'=>'裗','裞'=>'裞','䘵'=>'䘵','裺'=>'裺','㒻'=>'ã’»','𧢮'=>'ð§¢®','𧥦'=>'𧥦','ð¯§'=>'äš¾','䛇'=>'䛇','ð¯§'=>'èª ','ð¯§'=>'è«','變'=>'變','豕'=>'豕','𧲨'=>'𧲨','貫'=>'貫','賁'=>'è³','贛'=>'è´›','起'=>'èµ·','𧼯'=>'𧼯','𠠄'=>'ð „','跋'=>'è·‹','趼'=>'è¶¼','跰'=>'è·°','ð¯§'=>'𠣞','軔'=>'è»”','輸'=>'輸','𨗒'=>'𨗒','𨗭'=>'ð¨—','邔'=>'é‚”','郱'=>'郱','鄑'=>'é„‘','𨜮'=>'𨜮','鄛'=>'é„›','鈸'=>'鈸','鋗'=>'é‹—','鋘'=>'鋘','鉼'=>'鉼','鏹'=>'é¹','鐕'=>'é•','ð¯§'=>'𨯺','開'=>'é–‹','䦕'=>'䦕','閷'=>'é–·','𨵷'=>'𨵷','䧦'=>'䧦','雃'=>'雃','嶲'=>'å¶²','霣'=>'霣','𩅅'=>'ð©……','𩈚'=>'𩈚','䩮'=>'ä©®','䩶'=>'ä©¶','韠'=>'éŸ ','𩐊'=>'ð©Š','䪲'=>'䪲','𩒖'=>'ð©’–','頋'=>'é ‹','頋'=>'é ‹','頩'=>'é ©','ð¯¨'=>'ð©–¶','飢'=>'飢','䬳'=>'䬳','餩'=>'餩','馧'=>'馧','駂'=>'é§‚','駾'=>'é§¾','䯎'=>'䯎','𩬰'=>'𩬰','鬒'=>'鬒','鱀'=>'é±€','鳽'=>'é³½','ð¯¨'=>'䳎','䳭'=>'ä³','ð¯¨'=>'éµ§','ð¯¨'=>'𪃎','䳸'=>'䳸','𪄅'=>'𪄅','𪈎'=>'𪈎','𪊑'=>'𪊑','麻'=>'麻','䵖'=>'äµ–','黹'=>'黹','黾'=>'黾','鼅'=>'é¼…','鼏'=>'é¼','鼖'=>'é¼–','鼻'=>'é¼»','ð¯¨'=>'𪘀'); diff --git a/phpBB/includes/utf/data/utf_compatibility_decomp.php b/phpBB/includes/utf/data/utf_compatibility_decomp.php deleted file mode 100644 index c62948e81a..0000000000 --- a/phpBB/includes/utf/data/utf_compatibility_decomp.php +++ /dev/null @@ -1,2 +0,0 @@ -<?php -$GLOBALS['utf_compatibility_decomp']=array(' '=>' ','¨'=>' ̈','ª'=>'a','¯'=>' Ì„','²'=>'2','³'=>'3','´'=>' Ì','µ'=>'μ','¸'=>' ̧','¹'=>'1','º'=>'o','¼'=>'1â„4','½'=>'1â„2','¾'=>'3â„4','À'=>'AÌ€','Ã'=>'AÌ','Â'=>'AÌ‚','Ã'=>'Ã','Ä'=>'Ä','Ã…'=>'AÌŠ','Ç'=>'Ç','È'=>'EÌ€','É'=>'EÌ','Ê'=>'EÌ‚','Ë'=>'Ë','ÃŒ'=>'IÌ€','Ã'=>'IÌ','ÃŽ'=>'IÌ‚','Ã'=>'Ï','Ñ'=>'Ñ','Ã’'=>'OÌ€','Ó'=>'OÌ','Ô'=>'OÌ‚','Õ'=>'Õ','Ö'=>'Ö','Ù'=>'UÌ€','Ú'=>'UÌ','Û'=>'UÌ‚','Ü'=>'Ü','Ã'=>'YÌ','à '=>'aÌ€','á'=>'aÌ','â'=>'aÌ‚','ã'=>'ã','ä'=>'ä','Ã¥'=>'aÌŠ','ç'=>'ç','è'=>'eÌ€','é'=>'eÌ','ê'=>'eÌ‚','ë'=>'ë','ì'=>'iÌ€','Ã'=>'iÌ','î'=>'iÌ‚','ï'=>'ï','ñ'=>'ñ','ò'=>'oÌ€','ó'=>'oÌ','ô'=>'oÌ‚','õ'=>'õ','ö'=>'ö','ù'=>'uÌ€','ú'=>'uÌ','û'=>'uÌ‚','ü'=>'ü','ý'=>'yÌ','ÿ'=>'ÿ','Ä€'=>'AÌ„','Ä'=>'aÌ„','Ä‚'=>'Ă','ă'=>'ă','Ä„'=>'Ą','Ä…'=>'ą','Ć'=>'CÌ','ć'=>'cÌ','Ĉ'=>'CÌ‚','ĉ'=>'cÌ‚','ÄŠ'=>'Ċ','Ä‹'=>'ċ','ÄŒ'=>'CÌŒ','Ä'=>'cÌŒ','ÄŽ'=>'DÌŒ','Ä'=>'dÌŒ','Ä’'=>'EÌ„','Ä“'=>'eÌ„','Ä”'=>'Ĕ','Ä•'=>'ĕ','Ä–'=>'Ė','Ä—'=>'ė','Ę'=>'Ę','Ä™'=>'ę','Äš'=>'EÌŒ','Ä›'=>'eÌŒ','Äœ'=>'GÌ‚','Ä'=>'gÌ‚','Äž'=>'Ğ','ÄŸ'=>'ğ','Ä '=>'Ġ','Ä¡'=>'ġ','Ä¢'=>'Ģ','Ä£'=>'ģ','Ĥ'=>'HÌ‚','Ä¥'=>'hÌ‚','Ĩ'=>'Ĩ','Ä©'=>'ĩ','Ī'=>'IÌ„','Ä«'=>'iÌ„','Ĭ'=>'Ĭ','Ä'=>'ĭ','Ä®'=>'Į','į'=>'į','İ'=>'İ','IJ'=>'IJ','ij'=>'ij','Ä´'=>'JÌ‚','ĵ'=>'jÌ‚','Ķ'=>'Ķ','Ä·'=>'ķ','Ĺ'=>'LÌ','ĺ'=>'lÌ','Ä»'=>'Ļ','ļ'=>'ļ','Ľ'=>'LÌŒ','ľ'=>'lÌŒ','Ä¿'=>'L·','Å€'=>'l·','Ń'=>'NÌ','Å„'=>'nÌ','Å…'=>'Ņ','ņ'=>'ņ','Ň'=>'NÌŒ','ň'=>'nÌŒ','ʼn'=>'ʼn','ÅŒ'=>'OÌ„','Å'=>'oÌ„','ÅŽ'=>'Ŏ','Å'=>'ŏ','Å'=>'OÌ‹','Å‘'=>'oÌ‹','Å”'=>'RÌ','Å•'=>'rÌ','Å–'=>'Ŗ','Å—'=>'ŗ','Ř'=>'RÌŒ','Å™'=>'rÌŒ','Åš'=>'SÌ','Å›'=>'sÌ','Åœ'=>'SÌ‚','Å'=>'sÌ‚','Åž'=>'Ş','ÅŸ'=>'ş','Å '=>'SÌŒ','Å¡'=>'sÌŒ','Å¢'=>'Ţ','Å£'=>'ţ','Ť'=>'TÌŒ','Å¥'=>'tÌŒ','Ũ'=>'Ũ','Å©'=>'ũ','Ū'=>'UÌ„','Å«'=>'uÌ„','Ŭ'=>'Ŭ','Å'=>'ŭ','Å®'=>'UÌŠ','ů'=>'uÌŠ','Ű'=>'UÌ‹','ű'=>'uÌ‹','Ų'=>'Ų','ų'=>'ų','Å´'=>'WÌ‚','ŵ'=>'wÌ‚','Ŷ'=>'YÌ‚','Å·'=>'yÌ‚','Ÿ'=>'Ÿ','Ź'=>'ZÌ','ź'=>'zÌ','Å»'=>'Ż','ż'=>'ż','Ž'=>'ZÌŒ','ž'=>'zÌŒ','Å¿'=>'s','Æ '=>'OÌ›','Æ¡'=>'oÌ›','Ư'=>'UÌ›','ư'=>'uÌ›','Ç„'=>'DZÌŒ','Ç…'=>'DzÌŒ','dž'=>'dzÌŒ','LJ'=>'LJ','Lj'=>'Lj','lj'=>'lj','ÇŠ'=>'NJ','Ç‹'=>'Nj','ÇŒ'=>'nj','Ç'=>'AÌŒ','ÇŽ'=>'aÌŒ','Ç'=>'IÌŒ','Ç'=>'iÌŒ','Ç‘'=>'OÌŒ','Ç’'=>'oÌŒ','Ç“'=>'UÌŒ','Ç”'=>'uÌŒ','Ç•'=>'Ǖ','Ç–'=>'ǖ','Ç—'=>'ÜÌ','ǘ'=>'üÌ','Ç™'=>'Ǚ','Çš'=>'ǚ','Ç›'=>'Ǜ','Çœ'=>'ǜ','Çž'=>'Ǟ','ÇŸ'=>'ǟ','Ç '=>'Ǡ','Ç¡'=>'ǡ','Ç¢'=>'Ǣ','Ç£'=>'ǣ','Ǧ'=>'GÌŒ','ǧ'=>'gÌŒ','Ǩ'=>'KÌŒ','Ç©'=>'kÌŒ','Ǫ'=>'Ǫ','Ç«'=>'ǫ','Ǭ'=>'Ǭ','Ç'=>'ǭ','Ç®'=>'Æ·ÌŒ','ǯ'=>'Ê’ÌŒ','ǰ'=>'jÌŒ','DZ'=>'DZ','Dz'=>'Dz','dz'=>'dz','Ç´'=>'GÌ','ǵ'=>'gÌ','Ǹ'=>'NÌ€','ǹ'=>'nÌ€','Ǻ'=>'AÌŠÌ','Ç»'=>'aÌŠÌ','Ǽ'=>'ÆÌ','ǽ'=>'æÌ','Ǿ'=>'ØÌ','Ç¿'=>'øÌ','È€'=>'AÌ','È'=>'aÌ','È‚'=>'AÌ‘','ȃ'=>'aÌ‘','È„'=>'EÌ','È…'=>'eÌ','Ȇ'=>'EÌ‘','ȇ'=>'eÌ‘','Ȉ'=>'IÌ','ȉ'=>'iÌ','ÈŠ'=>'IÌ‘','È‹'=>'iÌ‘','ÈŒ'=>'OÌ','È'=>'oÌ','ÈŽ'=>'OÌ‘','È'=>'oÌ‘','È'=>'RÌ','È‘'=>'rÌ','È’'=>'RÌ‘','È“'=>'rÌ‘','È”'=>'UÌ','È•'=>'uÌ','È–'=>'UÌ‘','È—'=>'uÌ‘','Ș'=>'Ș','È™'=>'ș','Èš'=>'Ț','È›'=>'ț','Èž'=>'HÌŒ','ÈŸ'=>'hÌŒ','Ȧ'=>'Ȧ','ȧ'=>'ȧ','Ȩ'=>'Ȩ','È©'=>'ȩ','Ȫ'=>'Ȫ','È«'=>'ȫ','Ȭ'=>'Ȭ','È'=>'ȭ','È®'=>'Ȯ','ȯ'=>'ȯ','Ȱ'=>'Ȱ','ȱ'=>'ȱ','Ȳ'=>'YÌ„','ȳ'=>'yÌ„','ʰ'=>'h','ʱ'=>'ɦ','ʲ'=>'j','ʳ'=>'r','Ê´'=>'ɹ','ʵ'=>'É»','ʶ'=>'Ê','Ê·'=>'w','ʸ'=>'y','˘'=>' ̆','Ë™'=>' ̇','Ëš'=>' ÌŠ','Ë›'=>' ̨','Ëœ'=>' ̃','Ë'=>' Ì‹','Ë '=>'É£','Ë¡'=>'l','Ë¢'=>'s','Ë£'=>'x','ˤ'=>'Ê•','Í€'=>'Ì€','Í'=>'Ì','̓'=>'Ì“','Í„'=>'̈Ì','Í´'=>'ʹ','ͺ'=>' Í…',';'=>';','΄'=>' Ì','Î…'=>' ̈Ì','Ά'=>'ΑÌ','·'=>'·','Έ'=>'ΕÌ','Ή'=>'ΗÌ','Ί'=>'ΙÌ','ÎŒ'=>'ΟÌ','ÎŽ'=>'Î¥Ì','Î'=>'ΩÌ','Î'=>'ϊÌ','Ϊ'=>'Ϊ','Ϋ'=>'Ϋ','ά'=>'αÌ','Î'=>'εÌ','ή'=>'ηÌ','ί'=>'ιÌ','ΰ'=>'ϋÌ','ÏŠ'=>'ϊ','Ï‹'=>'ϋ','ÏŒ'=>'οÌ','Ï'=>'Ï…Ì','ÏŽ'=>'ωÌ','Ï'=>'β','Ï‘'=>'θ','Ï’'=>'Î¥','Ï“'=>'Î¥Ì','Ï”'=>'Ϋ','Ï•'=>'φ','Ï–'=>'Ï€','ϰ'=>'κ','ϱ'=>'Ï','ϲ'=>'Ï‚','Ï´'=>'Θ','ϵ'=>'ε','Ϲ'=>'Σ','Ѐ'=>'Ѐ','Ð'=>'Ё','Ѓ'=>'ГÌ','Ї'=>'Ї','ÐŒ'=>'КÌ','Ð'=>'Ѝ','ÐŽ'=>'Ў','Й'=>'Й','й'=>'й','Ñ'=>'ѐ','Ñ‘'=>'ё','Ñ“'=>'гÌ','Ñ—'=>'ї','Ñœ'=>'кÌ','Ñ'=>'ѝ','Ñž'=>'ў','Ѷ'=>'Ñ´Ì','Ñ·'=>'ѵÌ','Ó'=>'Ӂ','Ó‚'=>'ӂ','Ó'=>'Ð̆','Ó‘'=>'ӑ','Ó’'=>'Ð̈','Ó“'=>'ӓ','Ó–'=>'Ӗ','Ó—'=>'ӗ','Óš'=>'Ӛ','Ó›'=>'ӛ','Óœ'=>'Ӝ','Ó'=>'ӝ','Óž'=>'Ӟ','ÓŸ'=>'ӟ','Ó¢'=>'Ӣ','Ó£'=>'ӣ','Ó¤'=>'Ӥ','Ó¥'=>'ӥ','Ó¦'=>'Ӧ','Ó§'=>'ӧ','Óª'=>'Ӫ','Ó«'=>'ӫ','Ó¬'=>'Ð̈','Ó'=>'Ñ̈','Ó®'=>'Ӯ','Ó¯'=>'ӯ','Ó°'=>'Ӱ','Ó±'=>'ӱ','Ó²'=>'Ӳ','Ó³'=>'ӳ','Ó´'=>'Ӵ','Óµ'=>'ӵ','Ó¸'=>'Ӹ','Ó¹'=>'ӹ','Ö‡'=>'Õ¥Ö‚','Ø¢'=>'آ','Ø£'=>'أ','ؤ'=>'ÙˆÙ”','Ø¥'=>'إ','ئ'=>'ÙŠÙ”','Ùµ'=>'اٴ','Ù¶'=>'وٴ','Ù·'=>'Û‡Ù´','Ù¸'=>'يٴ','Û€'=>'Û•Ù”','Û‚'=>'ÛÙ”','Û“'=>'Û’Ù”','ऩ'=>'ऩ','ऱ'=>'ऱ','ऴ'=>'ऴ','क़'=>'क़','ख़'=>'ख़','ग़'=>'ग़','ज़'=>'ज़','ड़'=>'ड़','à¥'=>'ढ़','फ़'=>'फ़','य़'=>'य़','à§‹'=>'ো','à§Œ'=>'ৌ','à§œ'=>'ড়','à§'=>'ঢ়','à§Ÿ'=>'য়','ਲ਼'=>'ਲ਼','ਸ਼'=>'ਸ਼','à©™'=>'ਖ਼','ਗ਼'=>'ਗ਼','à©›'=>'ਜ਼','ਫ਼'=>'ਫ਼','àˆ'=>'à‡à–','à‹'=>'à‡à¬¾','àŒ'=>'à‡à—','àœ'=>'ଡ଼','à'=>'ଢ଼','à®”'=>'ஔ','ொ'=>'ொ','ோ'=>'ோ','ௌ'=>'ௌ','ై'=>'ై','à³€'=>'ೀ','ೇ'=>'ೇ','ೈ'=>'ೈ','ೊ'=>'ೊ','ೋ'=>'ೋ','ൊ'=>'ൊ','ോ'=>'ോ','ൌ'=>'ൌ','à·š'=>'ේ','à·œ'=>'à·™à·','à·'=>'à·™à·à·Š','à·ž'=>'ෞ','ำ'=>'à¹à¸²','ຳ'=>'à»àº²','ໜ'=>'ຫນ','à»'=>'ຫມ','༌'=>'་','གྷ'=>'གྷ','à½'=>'ཌྷ','དྷ'=>'དྷ','བྷ'=>'བྷ','ཛྷ'=>'ཛྷ','ཀྵ'=>'ཀྵ','ཱི'=>'ཱི','ཱུ'=>'ཱུ','ྲྀ'=>'ྲྀ','ཷ'=>'ྲཱྀ','ླྀ'=>'ླྀ','ཹ'=>'ླཱྀ','à¾'=>'ཱྀ','ྒྷ'=>'ྒྷ','à¾'=>'ྜྷ','ྡྷ'=>'ྡྷ','ྦྷ'=>'ྦྷ','ྫྷ'=>'ྫྷ','ྐྵ'=>'à¾à¾µ','ဦ'=>'ဦ','ჼ'=>'ნ','ᬆ'=>'ᬆ','ᬈ'=>'ᬈ','ᬊ'=>'ᬊ','ᬌ'=>'ᬌ','ᬎ'=>'á¬á¬µ','ᬒ'=>'ᬒ','ᬻ'=>'ᬻ','ᬽ'=>'ᬽ','á€'=>'ᭀ','á'=>'ᭁ','áƒ'=>'á‚ᬵ','á´¬'=>'A','á´'=>'Æ','á´®'=>'B','á´°'=>'D','á´±'=>'E','á´²'=>'ÆŽ','á´³'=>'G','á´´'=>'H','á´µ'=>'I','á´¶'=>'J','á´·'=>'K','á´¸'=>'L','á´¹'=>'M','á´º'=>'N','á´¼'=>'O','á´½'=>'È¢','á´¾'=>'P','á´¿'=>'R','áµ€'=>'T','áµ'=>'U','ᵂ'=>'W','ᵃ'=>'a','ᵄ'=>'É','áµ…'=>'É‘','ᵆ'=>'á´‚','ᵇ'=>'b','ᵈ'=>'d','ᵉ'=>'e','ᵊ'=>'É™','ᵋ'=>'É›','ᵌ'=>'Éœ','áµ'=>'g','áµ'=>'k','áµ'=>'m','ᵑ'=>'Å‹','áµ’'=>'o','ᵓ'=>'É”','áµ”'=>'á´–','ᵕ'=>'á´—','áµ–'=>'p','áµ—'=>'t','ᵘ'=>'u','áµ™'=>'á´','ᵚ'=>'ɯ','áµ›'=>'v','ᵜ'=>'á´¥','áµ'=>'β','ᵞ'=>'γ','ᵟ'=>'δ','áµ '=>'φ','ᵡ'=>'χ','áµ¢'=>'i','áµ£'=>'r','ᵤ'=>'u','áµ¥'=>'v','ᵦ'=>'β','áµ§'=>'γ','ᵨ'=>'Ï','ᵩ'=>'φ','ᵪ'=>'χ','ᵸ'=>'н','á¶›'=>'É’','á¶œ'=>'c','á¶'=>'É•','á¶ž'=>'ð','á¶Ÿ'=>'Éœ','á¶ '=>'f','á¶¡'=>'ÉŸ','á¶¢'=>'É¡','á¶£'=>'É¥','ᶤ'=>'ɨ','á¶¥'=>'É©','ᶦ'=>'ɪ','á¶§'=>'áµ»','ᶨ'=>'Ê','á¶©'=>'É','ᶪ'=>'á¶…','á¶«'=>'ÊŸ','ᶬ'=>'ɱ','á¶'=>'ɰ','á¶®'=>'ɲ','ᶯ'=>'ɳ','á¶°'=>'É´','á¶±'=>'ɵ','á¶²'=>'ɸ','á¶³'=>'Ê‚','á¶´'=>'ʃ','á¶µ'=>'Æ«','á¶¶'=>'ʉ','á¶·'=>'ÊŠ','ᶸ'=>'á´œ','á¶¹'=>'Ê‹','ᶺ'=>'ÊŒ','á¶»'=>'z','á¶¼'=>'Ê','á¶½'=>'Ê‘','á¶¾'=>'Ê’','á¶¿'=>'θ','Ḁ'=>'AÌ¥','á¸'=>'aÌ¥','Ḃ'=>'Ḃ','ḃ'=>'ḃ','Ḅ'=>'BÌ£','ḅ'=>'bÌ£','Ḇ'=>'Ḇ','ḇ'=>'ḇ','Ḉ'=>'ÇÌ','ḉ'=>'çÌ','Ḋ'=>'Ḋ','ḋ'=>'ḋ','Ḍ'=>'DÌ£','á¸'=>'dÌ£','Ḏ'=>'Ḏ','á¸'=>'ḏ','á¸'=>'Ḑ','ḑ'=>'ḑ','Ḓ'=>'DÌ','ḓ'=>'dÌ','Ḕ'=>'Ḕ','ḕ'=>'ḕ','Ḗ'=>'EÌ„Ì','ḗ'=>'eÌ„Ì','Ḙ'=>'EÌ','ḙ'=>'eÌ','Ḛ'=>'Ḛ','ḛ'=>'ḛ','Ḝ'=>'Ḝ','á¸'=>'ḝ','Ḟ'=>'Ḟ','ḟ'=>'ḟ','Ḡ'=>'GÌ„','ḡ'=>'gÌ„','Ḣ'=>'Ḣ','ḣ'=>'ḣ','Ḥ'=>'HÌ£','ḥ'=>'hÌ£','Ḧ'=>'Ḧ','ḧ'=>'ḧ','Ḩ'=>'Ḩ','ḩ'=>'ḩ','Ḫ'=>'HÌ®','ḫ'=>'hÌ®','Ḭ'=>'Ḭ','á¸'=>'ḭ','Ḯ'=>'ÏÌ','ḯ'=>'ïÌ','Ḱ'=>'KÌ','ḱ'=>'kÌ','Ḳ'=>'KÌ£','ḳ'=>'kÌ£','Ḵ'=>'Ḵ','ḵ'=>'ḵ','Ḷ'=>'LÌ£','ḷ'=>'lÌ£','Ḹ'=>'Ḹ','ḹ'=>'ḹ','Ḻ'=>'Ḻ','ḻ'=>'ḻ','Ḽ'=>'LÌ','ḽ'=>'lÌ','Ḿ'=>'MÌ','ḿ'=>'mÌ','á¹€'=>'Ṁ','á¹'=>'ṁ','Ṃ'=>'MÌ£','ṃ'=>'mÌ£','Ṅ'=>'Ṅ','á¹…'=>'ṅ','Ṇ'=>'NÌ£','ṇ'=>'nÌ£','Ṉ'=>'Ṉ','ṉ'=>'ṉ','Ṋ'=>'NÌ','ṋ'=>'nÌ','Ṍ'=>'ÕÌ','á¹'=>'õÌ','Ṏ'=>'Ṏ','á¹'=>'ṏ','á¹'=>'Ṑ','ṑ'=>'ṑ','á¹’'=>'OÌ„Ì','ṓ'=>'oÌ„Ì','á¹”'=>'PÌ','ṕ'=>'pÌ','á¹–'=>'Ṗ','á¹—'=>'ṗ','Ṙ'=>'Ṙ','á¹™'=>'ṙ','Ṛ'=>'RÌ£','á¹›'=>'rÌ£','Ṝ'=>'Ṝ','á¹'=>'ṝ','Ṟ'=>'Ṟ','ṟ'=>'ṟ','á¹ '=>'Ṡ','ṡ'=>'ṡ','á¹¢'=>'SÌ£','á¹£'=>'sÌ£','Ṥ'=>'SÌ̇','á¹¥'=>'sÌ̇','Ṧ'=>'Ṧ','á¹§'=>'ṧ','Ṩ'=>'Ṩ','ṩ'=>'ṩ','Ṫ'=>'Ṫ','ṫ'=>'ṫ','Ṭ'=>'TÌ£','á¹'=>'tÌ£','á¹®'=>'Ṯ','ṯ'=>'ṯ','á¹°'=>'TÌ','á¹±'=>'tÌ','á¹²'=>'Ṳ','á¹³'=>'ṳ','á¹´'=>'Ṵ','á¹µ'=>'ṵ','á¹¶'=>'UÌ','á¹·'=>'uÌ','Ṹ'=>'ŨÌ','á¹¹'=>'ũÌ','Ṻ'=>'Ṻ','á¹»'=>'ṻ','á¹¼'=>'Ṽ','á¹½'=>'ṽ','á¹¾'=>'VÌ£','ṿ'=>'vÌ£','Ẁ'=>'WÌ€','áº'=>'wÌ€','Ẃ'=>'WÌ','ẃ'=>'wÌ','Ẅ'=>'Ẅ','ẅ'=>'ẅ','Ẇ'=>'Ẇ','ẇ'=>'ẇ','Ẉ'=>'WÌ£','ẉ'=>'wÌ£','Ẋ'=>'Ẋ','ẋ'=>'ẋ','Ẍ'=>'Ẍ','áº'=>'ẍ','Ẏ'=>'Ẏ','áº'=>'ẏ','áº'=>'ZÌ‚','ẑ'=>'zÌ‚','Ẓ'=>'ZÌ£','ẓ'=>'zÌ£','Ẕ'=>'Ẕ','ẕ'=>'ẕ','ẖ'=>'ẖ','ẗ'=>'ẗ','ẘ'=>'wÌŠ','ẙ'=>'yÌŠ','ẚ'=>'aʾ','ẛ'=>'ṡ','Ạ'=>'AÌ£','ạ'=>'aÌ£','Ả'=>'Ả','ả'=>'ả','Ấ'=>'AÌ‚Ì','ấ'=>'aÌ‚Ì','Ầ'=>'Ầ','ầ'=>'ầ','Ẩ'=>'Ẩ','ẩ'=>'ẩ','Ẫ'=>'Ẫ','ẫ'=>'ẫ','Ậ'=>'Ậ','áº'=>'ậ','Ắ'=>'ĂÌ','ắ'=>'ăÌ','Ằ'=>'Ằ','ằ'=>'ằ','Ẳ'=>'Ẳ','ẳ'=>'ẳ','Ẵ'=>'Ẵ','ẵ'=>'ẵ','Ặ'=>'Ặ','ặ'=>'ặ','Ẹ'=>'EÌ£','ẹ'=>'eÌ£','Ẻ'=>'Ẻ','ẻ'=>'ẻ','Ẽ'=>'Ẽ','ẽ'=>'ẽ','Ế'=>'EÌ‚Ì','ế'=>'eÌ‚Ì','Ề'=>'Ề','á»'=>'ề','Ể'=>'Ể','ể'=>'ể','Ễ'=>'Ễ','á»…'=>'ễ','Ệ'=>'Ệ','ệ'=>'ệ','Ỉ'=>'Ỉ','ỉ'=>'ỉ','Ị'=>'IÌ£','ị'=>'iÌ£','Ọ'=>'OÌ£','á»'=>'oÌ£','Ỏ'=>'Ỏ','á»'=>'ỏ','á»'=>'OÌ‚Ì','ố'=>'oÌ‚Ì','á»’'=>'Ồ','ồ'=>'ồ','á»”'=>'Ổ','ổ'=>'ổ','á»–'=>'Ỗ','á»—'=>'ỗ','Ộ'=>'Ộ','á»™'=>'ộ','Ớ'=>'OÌ›Ì','á»›'=>'oÌ›Ì','Ờ'=>'Ờ','á»'=>'ờ','Ở'=>'Ở','ở'=>'ở','á» '=>'Ỡ','ỡ'=>'ỡ','Ợ'=>'Ợ','ợ'=>'ợ','Ụ'=>'UÌ£','ụ'=>'uÌ£','Ủ'=>'Ủ','á»§'=>'ủ','Ứ'=>'UÌ›Ì','ứ'=>'uÌ›Ì','Ừ'=>'Ừ','ừ'=>'ừ','Ử'=>'Ử','á»'=>'ử','á»®'=>'Ữ','ữ'=>'ữ','á»°'=>'Ự','á»±'=>'ự','Ỳ'=>'YÌ€','ỳ'=>'yÌ€','á»´'=>'YÌ£','ỵ'=>'yÌ£','á»¶'=>'Ỷ','á»·'=>'ỷ','Ỹ'=>'Ỹ','ỹ'=>'ỹ','á¼€'=>'ἀ','á¼'=>'ἁ','ἂ'=>'ἂ','ἃ'=>'ἃ','ἄ'=>'ἀÌ','á¼…'=>'ἁÌ','ἆ'=>'ἆ','ἇ'=>'ἇ','Ἀ'=>'Ἀ','Ἁ'=>'Ἁ','Ἂ'=>'Ἂ','Ἃ'=>'Ἃ','Ἄ'=>'ἈÌ','á¼'=>'ἉÌ','Ἆ'=>'Ἆ','á¼'=>'Ἇ','á¼'=>'ἐ','ἑ'=>'ἑ','á¼’'=>'ἒ','ἓ'=>'ἓ','á¼”'=>'ἐÌ','ἕ'=>'ἑÌ','Ἐ'=>'Ἐ','á¼™'=>'Ἑ','Ἒ'=>'Ἒ','á¼›'=>'Ἓ','Ἔ'=>'ἘÌ','á¼'=>'ἙÌ','á¼ '=>'ἠ','ἡ'=>'ἡ','á¼¢'=>'ἢ','á¼£'=>'ἣ','ἤ'=>'ἠÌ','á¼¥'=>'ἡÌ','ἦ'=>'ἦ','á¼§'=>'ἧ','Ἠ'=>'Ἠ','Ἡ'=>'Ἡ','Ἢ'=>'Ἢ','Ἣ'=>'Ἣ','Ἤ'=>'ἨÌ','á¼'=>'ἩÌ','á¼®'=>'Ἦ','Ἧ'=>'Ἧ','á¼°'=>'ἰ','á¼±'=>'ἱ','á¼²'=>'ἲ','á¼³'=>'ἳ','á¼´'=>'ἰÌ','á¼µ'=>'ἱÌ','á¼¶'=>'ἶ','á¼·'=>'ἷ','Ἰ'=>'Ἰ','á¼¹'=>'Ἱ','Ἲ'=>'Ἲ','á¼»'=>'Ἳ','á¼¼'=>'ἸÌ','á¼½'=>'ἹÌ','á¼¾'=>'Ἶ','Ἷ'=>'Ἷ','á½€'=>'ὀ','á½'=>'ὁ','ὂ'=>'ὂ','ὃ'=>'ὃ','ὄ'=>'ὀÌ','á½…'=>'ὁÌ','Ὀ'=>'Ὀ','Ὁ'=>'Ὁ','Ὂ'=>'Ὂ','Ὃ'=>'Ὃ','Ὄ'=>'ὈÌ','á½'=>'ὉÌ','á½'=>'Ï…Ì“','ὑ'=>'Ï…Ì”','á½’'=>'ὒ','ὓ'=>'ὓ','á½”'=>'Ï…Ì“Ì','ὕ'=>'Ï…Ì”Ì','á½–'=>'ὖ','á½—'=>'ὗ','á½™'=>'Ὑ','á½›'=>'Ὓ','á½'=>'ὙÌ','Ὗ'=>'Ὗ','á½ '=>'ὠ','ὡ'=>'ὡ','á½¢'=>'ὢ','á½£'=>'ὣ','ὤ'=>'ὠÌ','á½¥'=>'ὡÌ','ὦ'=>'ὦ','á½§'=>'ὧ','Ὠ'=>'Ὠ','Ὡ'=>'Ὡ','Ὢ'=>'Ὢ','Ὣ'=>'Ὣ','Ὤ'=>'ὨÌ','á½'=>'ὩÌ','á½®'=>'Ὦ','Ὧ'=>'Ὧ','á½°'=>'ὰ','á½±'=>'αÌ','á½²'=>'ὲ','á½³'=>'εÌ','á½´'=>'ὴ','á½µ'=>'ηÌ','á½¶'=>'ὶ','á½·'=>'ιÌ','ὸ'=>'ὸ','á½¹'=>'οÌ','ὺ'=>'Ï…Ì€','á½»'=>'Ï…Ì','á½¼'=>'ὼ','á½½'=>'ωÌ','á¾€'=>'ᾀ','á¾'=>'ᾁ','ᾂ'=>'ᾂ','ᾃ'=>'ᾃ','ᾄ'=>'ἀÌÍ…','á¾…'=>'ἁÌÍ…','ᾆ'=>'ᾆ','ᾇ'=>'ᾇ','ᾈ'=>'ᾈ','ᾉ'=>'ᾉ','ᾊ'=>'ᾊ','ᾋ'=>'ᾋ','ᾌ'=>'ἈÌÍ…','á¾'=>'ἉÌÍ…','ᾎ'=>'ᾎ','á¾'=>'ᾏ','á¾'=>'ᾐ','ᾑ'=>'ᾑ','á¾’'=>'ᾒ','ᾓ'=>'ᾓ','á¾”'=>'ἠÌÍ…','ᾕ'=>'ἡÌÍ…','á¾–'=>'ᾖ','á¾—'=>'ᾗ','ᾘ'=>'ᾘ','á¾™'=>'ᾙ','ᾚ'=>'ᾚ','á¾›'=>'ᾛ','ᾜ'=>'ἨÌÍ…','á¾'=>'ἩÌÍ…','ᾞ'=>'ᾞ','ᾟ'=>'ᾟ','á¾ '=>'ᾠ','ᾡ'=>'ᾡ','á¾¢'=>'ᾢ','á¾£'=>'ᾣ','ᾤ'=>'ὠÌÍ…','á¾¥'=>'ὡÌÍ…','ᾦ'=>'ᾦ','á¾§'=>'ᾧ','ᾨ'=>'ᾨ','ᾩ'=>'ᾩ','ᾪ'=>'ᾪ','ᾫ'=>'ᾫ','ᾬ'=>'ὨÌÍ…','á¾'=>'ὩÌÍ…','á¾®'=>'ᾮ','ᾯ'=>'ᾯ','á¾°'=>'ᾰ','á¾±'=>'ᾱ','á¾²'=>'ᾲ','á¾³'=>'ᾳ','á¾´'=>'αÌÍ…','á¾¶'=>'ᾶ','á¾·'=>'ᾷ','Ᾰ'=>'Ᾰ','á¾¹'=>'Ᾱ','Ὰ'=>'Ὰ','á¾»'=>'ΑÌ','á¾¼'=>'ᾼ','á¾½'=>' Ì“','á¾¾'=>'ι','᾿'=>' Ì“','á¿€'=>' Í‚','á¿'=>' ̈͂','á¿‚'=>'ῂ','ῃ'=>'ῃ','á¿„'=>'ηÌÍ…','ῆ'=>'ῆ','ῇ'=>'ῇ','Ὲ'=>'Ὲ','Έ'=>'ΕÌ','Ὴ'=>'Ὴ','á¿‹'=>'ΗÌ','ῌ'=>'ῌ','á¿'=>' ̓̀','῎'=>' Ì“Ì','á¿'=>' ̓͂','á¿'=>'ῐ','á¿‘'=>'ῑ','á¿’'=>'ῒ','á¿“'=>'ϊÌ','á¿–'=>'ῖ','á¿—'=>'ῗ','Ῐ'=>'Ῐ','á¿™'=>'Ῑ','Ὶ'=>'Ὶ','á¿›'=>'ΙÌ','á¿'=>' ̔̀','῞'=>' Ì”Ì','῟'=>' ̔͂','á¿ '=>'ῠ','á¿¡'=>'Ï…Ì„','á¿¢'=>'ῢ','á¿£'=>'ϋÌ','ῤ'=>'ÏÌ“','á¿¥'=>'ÏÌ”','ῦ'=>'Ï…Í‚','á¿§'=>'ῧ','Ῠ'=>'Ῠ','á¿©'=>'Ῡ','Ὺ'=>'Ὺ','á¿«'=>'Î¥Ì','Ῥ'=>'Ῥ','á¿'=>' ̈̀','á¿®'=>' ̈Ì','`'=>'`','ῲ'=>'ῲ','ῳ'=>'ῳ','á¿´'=>'ωÌÍ…','á¿¶'=>'ῶ','á¿·'=>'ῷ','Ὸ'=>'Ὸ','Ό'=>'ΟÌ','Ὼ'=>'Ὼ','á¿»'=>'ΩÌ','ῼ'=>'ῼ','´'=>' Ì','῾'=>' Ì”',' '=>' ','â€'=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ','‑'=>'â€','‗'=>' ̳','․'=>'.','‥'=>'..','…'=>'...',' '=>' ','″'=>'′′','‴'=>'′′′','‶'=>'‵‵','‷'=>'‵‵‵','‼'=>'!!','‾'=>' Ì…','â‡'=>'??','âˆ'=>'?!','â‰'=>'!?','â—'=>'′′′′','âŸ'=>' ','â°'=>'0','â±'=>'i','â´'=>'4','âµ'=>'5','â¶'=>'6','â·'=>'7','â¸'=>'8','â¹'=>'9','âº'=>'+','â»'=>'−','â¼'=>'=','â½'=>'(','â¾'=>')','â¿'=>'n','â‚€'=>'0','â‚'=>'1','â‚‚'=>'2','₃'=>'3','â‚„'=>'4','â‚…'=>'5','₆'=>'6','₇'=>'7','₈'=>'8','₉'=>'9','₊'=>'+','â‚‹'=>'−','₌'=>'=','â‚'=>'(','₎'=>')','â‚'=>'a','â‚‘'=>'e','â‚’'=>'o','â‚“'=>'x','â‚”'=>'É™','₨'=>'Rs','â„€'=>'a/c','â„'=>'a/s','â„‚'=>'C','℃'=>'°C','â„…'=>'c/o','℆'=>'c/u','ℇ'=>'Æ','℉'=>'°F','ℊ'=>'g','â„‹'=>'H','ℌ'=>'H','â„'=>'H','ℎ'=>'h','â„'=>'ħ','â„'=>'I','â„‘'=>'I','â„’'=>'L','â„“'=>'l','â„•'=>'N','â„–'=>'No','â„™'=>'P','ℚ'=>'Q','â„›'=>'R','ℜ'=>'R','â„'=>'R','â„ '=>'SM','â„¡'=>'TEL','â„¢'=>'TM','ℤ'=>'Z','Ω'=>'Ω','ℨ'=>'Z','K'=>'K','â„«'=>'AÌŠ','ℬ'=>'B','â„'=>'C','ℯ'=>'e','â„°'=>'E','ℱ'=>'F','ℳ'=>'M','â„´'=>'o','ℵ'=>'×','â„¶'=>'ב','â„·'=>'×’','ℸ'=>'ד','ℹ'=>'i','â„»'=>'FAX','ℼ'=>'Ï€','ℽ'=>'γ','ℾ'=>'Γ','â„¿'=>'Î ','â…€'=>'∑','â……'=>'D','â…†'=>'d','â…‡'=>'e','â…ˆ'=>'i','â…‰'=>'j','â…“'=>'1â„3','â…”'=>'2â„3','â…•'=>'1â„5','â…–'=>'2â„5','â…—'=>'3â„5','â…˜'=>'4â„5','â…™'=>'1â„6','â…š'=>'5â„6','â…›'=>'1â„8','â…œ'=>'3â„8','â…'=>'5â„8','â…ž'=>'7â„8','â…Ÿ'=>'1â„','â… '=>'I','â…¡'=>'II','â…¢'=>'III','â…£'=>'IV','â…¤'=>'V','â…¥'=>'VI','â…¦'=>'VII','â…§'=>'VIII','â…¨'=>'IX','â…©'=>'X','â…ª'=>'XI','â…«'=>'XII','â…¬'=>'L','â…'=>'C','â…®'=>'D','â…¯'=>'M','â…°'=>'i','â…±'=>'ii','â…²'=>'iii','â…³'=>'iv','â…´'=>'v','â…µ'=>'vi','â…¶'=>'vii','â…·'=>'viii','â…¸'=>'ix','â…¹'=>'x','â…º'=>'xi','â…»'=>'xii','â…¼'=>'l','â…½'=>'c','â…¾'=>'d','â…¿'=>'m','↚'=>'â†Ì¸','↛'=>'↛','↮'=>'↮','â‡'=>'â‡Ì¸','⇎'=>'⇎','â‡'=>'⇏','∄'=>'∄','∉'=>'∉','∌'=>'∌','∤'=>'∤','∦'=>'∦','∬'=>'∫∫','âˆ'=>'∫∫∫','∯'=>'∮∮','∰'=>'∮∮∮','â‰'=>'≁','≄'=>'≄','≇'=>'≇','≉'=>'≉','≠'=>'≠','≢'=>'≢','â‰'=>'â‰Ì¸','≮'=>'≮','≯'=>'≯','≰'=>'≰','≱'=>'≱','≴'=>'≴','≵'=>'≵','≸'=>'≸','≹'=>'≹','⊀'=>'⊀','âŠ'=>'⊁','⊄'=>'⊄','⊅'=>'⊅','⊈'=>'⊈','⊉'=>'⊉','⊬'=>'⊬','âŠ'=>'⊭','⊮'=>'⊮','⊯'=>'⊯','â‹ '=>'⋠','â‹¡'=>'⋡','â‹¢'=>'⋢','â‹£'=>'⋣','⋪'=>'⋪','â‹«'=>'⋫','⋬'=>'⋬','â‹'=>'⋭','〈'=>'〈','〉'=>'〉','â‘ '=>'1','â‘¡'=>'2','â‘¢'=>'3','â‘£'=>'4','⑤'=>'5','â‘¥'=>'6','⑦'=>'7','â‘§'=>'8','⑨'=>'9','â‘©'=>'10','⑪'=>'11','â‘«'=>'12','⑬'=>'13','â‘'=>'14','â‘®'=>'15','⑯'=>'16','â‘°'=>'17','⑱'=>'18','⑲'=>'19','⑳'=>'20','â‘´'=>'(1)','⑵'=>'(2)','â‘¶'=>'(3)','â‘·'=>'(4)','⑸'=>'(5)','⑹'=>'(6)','⑺'=>'(7)','â‘»'=>'(8)','⑼'=>'(9)','⑽'=>'(10)','⑾'=>'(11)','â‘¿'=>'(12)','â’€'=>'(13)','â’'=>'(14)','â’‚'=>'(15)','â’ƒ'=>'(16)','â’„'=>'(17)','â’…'=>'(18)','â’†'=>'(19)','â’‡'=>'(20)','â’ˆ'=>'1.','â’‰'=>'2.','â’Š'=>'3.','â’‹'=>'4.','â’Œ'=>'5.','â’'=>'6.','â’Ž'=>'7.','â’'=>'8.','â’'=>'9.','â’‘'=>'10.','â’’'=>'11.','â’“'=>'12.','â’”'=>'13.','â’•'=>'14.','â’–'=>'15.','â’—'=>'16.','â’˜'=>'17.','â’™'=>'18.','â’š'=>'19.','â’›'=>'20.','â’œ'=>'(a)','â’'=>'(b)','â’ž'=>'(c)','â’Ÿ'=>'(d)','â’ '=>'(e)','â’¡'=>'(f)','â’¢'=>'(g)','â’£'=>'(h)','â’¤'=>'(i)','â’¥'=>'(j)','â’¦'=>'(k)','â’§'=>'(l)','â’¨'=>'(m)','â’©'=>'(n)','â’ª'=>'(o)','â’«'=>'(p)','â’¬'=>'(q)','â’'=>'(r)','â’®'=>'(s)','â’¯'=>'(t)','â’°'=>'(u)','â’±'=>'(v)','â’²'=>'(w)','â’³'=>'(x)','â’´'=>'(y)','â’µ'=>'(z)','â’¶'=>'A','â’·'=>'B','â’¸'=>'C','â’¹'=>'D','â’º'=>'E','â’»'=>'F','â’¼'=>'G','â’½'=>'H','â’¾'=>'I','â’¿'=>'J','â“€'=>'K','â“'=>'L','â“‚'=>'M','Ⓝ'=>'N','â“„'=>'O','â“…'=>'P','Ⓠ'=>'Q','Ⓡ'=>'R','Ⓢ'=>'S','Ⓣ'=>'T','Ⓤ'=>'U','â“‹'=>'V','Ⓦ'=>'W','â“'=>'X','Ⓨ'=>'Y','â“'=>'Z','â“'=>'a','â“‘'=>'b','â“’'=>'c','â““'=>'d','â“”'=>'e','â“•'=>'f','â“–'=>'g','â“—'=>'h','ⓘ'=>'i','â“™'=>'j','ⓚ'=>'k','â“›'=>'l','ⓜ'=>'m','â“'=>'n','ⓞ'=>'o','ⓟ'=>'p','â“ '=>'q','â“¡'=>'r','â“¢'=>'s','â“£'=>'t','ⓤ'=>'u','â“¥'=>'v','ⓦ'=>'w','â“§'=>'x','ⓨ'=>'y','â“©'=>'z','⓪'=>'0','⨌'=>'∫∫∫∫','â©´'=>'::=','⩵'=>'==','â©¶'=>'===','⫝̸'=>'â«Ì¸','ⵯ'=>'ⵡ','⺟'=>'æ¯','⻳'=>'龟','â¼€'=>'一','â¼'=>'丨','⼂'=>'丶','⼃'=>'丿','⼄'=>'ä¹™','â¼…'=>'亅','⼆'=>'二','⼇'=>'äº ','⼈'=>'人','⼉'=>'å„¿','⼊'=>'å…¥','⼋'=>'å…«','⼌'=>'冂','â¼'=>'冖','⼎'=>'冫','â¼'=>'å‡ ','â¼'=>'凵','⼑'=>'刀','â¼’'=>'力','⼓'=>'勹','â¼”'=>'匕','⼕'=>'匚','â¼–'=>'匸','â¼—'=>'å','⼘'=>'åœ','â¼™'=>'å©','⼚'=>'厂','â¼›'=>'厶','⼜'=>'åˆ','â¼'=>'å£','⼞'=>'å›—','⼟'=>'土','â¼ '=>'士','⼡'=>'夂','â¼¢'=>'夊','â¼£'=>'夕','⼤'=>'大','â¼¥'=>'女','⼦'=>'å','â¼§'=>'宀','⼨'=>'寸','⼩'=>'å°','⼪'=>'å°¢','⼫'=>'å°¸','⼬'=>'å±®','â¼'=>'å±±','â¼®'=>'å·›','⼯'=>'å·¥','â¼°'=>'å·±','â¼±'=>'å·¾','â¼²'=>'å¹²','â¼³'=>'幺','â¼´'=>'广','â¼µ'=>'å»´','â¼¶'=>'廾','â¼·'=>'弋','⼸'=>'弓','â¼¹'=>'å½','⼺'=>'彡','â¼»'=>'å½³','â¼¼'=>'心','â¼½'=>'戈','â¼¾'=>'戶','⼿'=>'手','â½€'=>'支','â½'=>'æ”´','⽂'=>'æ–‡','⽃'=>'æ–—','⽄'=>'æ–¤','â½…'=>'æ–¹','⽆'=>'æ— ','⽇'=>'æ—¥','⽈'=>'æ›°','⽉'=>'月','⽊'=>'木','⽋'=>'æ¬ ','⽌'=>'æ¢','â½'=>'æ¹','⽎'=>'殳','â½'=>'毋','â½'=>'比','⽑'=>'毛','â½’'=>'æ°','⽓'=>'æ°”','â½”'=>'æ°´','⽕'=>'ç«','â½–'=>'爪','â½—'=>'父','⽘'=>'爻','â½™'=>'爿','⽚'=>'片','â½›'=>'牙','⽜'=>'牛','â½'=>'犬','⽞'=>'玄','⽟'=>'玉','â½ '=>'瓜','⽡'=>'瓦','â½¢'=>'甘','â½£'=>'生','⽤'=>'用','â½¥'=>'ç”°','⽦'=>'ç–‹','â½§'=>'ç–’','⽨'=>'ç™¶','⽩'=>'白','⽪'=>'çš®','⽫'=>'çš¿','⽬'=>'ç›®','â½'=>'矛','â½®'=>'矢','⽯'=>'石','â½°'=>'示','â½±'=>'禸','â½²'=>'禾','â½³'=>'ç©´','â½´'=>'ç«‹','â½µ'=>'竹','â½¶'=>'ç±³','â½·'=>'糸','⽸'=>'ç¼¶','â½¹'=>'网','⽺'=>'羊','â½»'=>'ç¾½','â½¼'=>'è€','â½½'=>'而','â½¾'=>'耒','⽿'=>'耳','â¾€'=>'è¿','â¾'=>'肉','⾂'=>'臣','⾃'=>'自','⾄'=>'至','â¾…'=>'臼','⾆'=>'舌','⾇'=>'舛','⾈'=>'舟','⾉'=>'艮','⾊'=>'色','⾋'=>'艸','⾌'=>'è™','â¾'=>'虫','⾎'=>'è¡€','â¾'=>'行','â¾'=>'è¡£','⾑'=>'襾','â¾’'=>'見','⾓'=>'è§’','â¾”'=>'言','⾕'=>'è°·','â¾–'=>'豆','â¾—'=>'豕','⾘'=>'豸','â¾™'=>'è²','⾚'=>'赤','â¾›'=>'èµ°','⾜'=>'è¶³','â¾'=>'身','⾞'=>'車','⾟'=>'è¾›','â¾ '=>'è¾°','⾡'=>'è¾µ','â¾¢'=>'é‚‘','â¾£'=>'é…‰','⾤'=>'釆','â¾¥'=>'里','⾦'=>'金','â¾§'=>'é•·','⾨'=>'é–€','⾩'=>'阜','⾪'=>'éš¶','⾫'=>'éš¹','⾬'=>'雨','â¾'=>'é‘','â¾®'=>'éž','⾯'=>'é¢','â¾°'=>'é©','â¾±'=>'韋','â¾²'=>'éŸ','â¾³'=>'音','â¾´'=>'é ','â¾µ'=>'風','â¾¶'=>'飛','â¾·'=>'食','⾸'=>'首','â¾¹'=>'香','⾺'=>'馬','â¾»'=>'骨','â¾¼'=>'高','â¾½'=>'髟','â¾¾'=>'鬥','⾿'=>'鬯','â¿€'=>'鬲','â¿'=>'鬼','â¿‚'=>'éš','⿃'=>'é³¥','â¿„'=>'é¹µ','â¿…'=>'鹿','⿆'=>'麥','⿇'=>'麻','⿈'=>'黃','⿉'=>'é»','⿊'=>'黑','â¿‹'=>'黹','⿌'=>'黽','â¿'=>'鼎','⿎'=>'鼓','â¿'=>'é¼ ','â¿'=>'é¼»','â¿‘'=>'齊','â¿’'=>'é½’','â¿“'=>'é¾','â¿”'=>'龜','â¿•'=>'é¾ ',' '=>' ','〶'=>'〒','〸'=>'å','〹'=>'å„','〺'=>'å…','ãŒ'=>'ã‹ã‚™','ãŽ'=>'ãã‚™','ã'=>'ãã‚™','ã’'=>'ã‘ã‚™','ã”'=>'ã“ã‚™','ã–'=>'ã•ã‚™','ã˜'=>'ã—ã‚™','ãš'=>'ã™ã‚™','ãœ'=>'ã›ã‚™','ãž'=>'ãã‚™','ã '=>'ãŸã‚™','ã¢'=>'ã¡ã‚™','ã¥'=>'ã¤ã‚™','ã§'=>'ã¦ã‚™','ã©'=>'ã¨ã‚™','ã°'=>'ã¯ã‚™','ã±'=>'ã¯ã‚š','ã³'=>'ã²ã‚™','ã´'=>'ã²ã‚š','ã¶'=>'ãµã‚™','ã·'=>'ãµã‚š','ã¹'=>'ã¸ã‚™','ãº'=>'ã¸ã‚š','ã¼'=>'ã»ã‚™','ã½'=>'ã»ã‚š','ã‚”'=>'ã†ã‚™','ã‚›'=>' ã‚™','゜'=>' ゚','ゞ'=>'ã‚ã‚™','ゟ'=>'より','ガ'=>'ã‚«ã‚™','ã‚®'=>'ã‚ã‚™','ã‚°'=>'グ','ゲ'=>'ゲ','ã‚´'=>'ゴ','ã‚¶'=>'ザ','ジ'=>'ã‚·ã‚™','ズ'=>'ズ','ゼ'=>'ゼ','ゾ'=>'ゾ','ダ'=>'ã‚¿ã‚™','ヂ'=>'ãƒã‚™','ヅ'=>'ヅ','デ'=>'デ','ド'=>'ド','ãƒ'=>'ãƒã‚™','パ'=>'ãƒã‚š','ビ'=>'ビ','ピ'=>'ピ','ブ'=>'ブ','プ'=>'プ','ベ'=>'ベ','ペ'=>'ペ','ボ'=>'ボ','ãƒ'=>'ポ','ヴ'=>'ヴ','ヷ'=>'ヷ','ヸ'=>'ヸ','ヹ'=>'ヹ','ヺ'=>'ヺ','ヾ'=>'ヾ','ヿ'=>'コト','ㄱ'=>'á„€','ㄲ'=>'á„','ㄳ'=>'ᆪ','ã„´'=>'á„‚','ㄵ'=>'ᆬ','ã„¶'=>'á†','ã„·'=>'ᄃ','ㄸ'=>'á„„','ㄹ'=>'á„…','ㄺ'=>'ᆰ','ã„»'=>'ᆱ','ㄼ'=>'ᆲ','ㄽ'=>'ᆳ','ㄾ'=>'ᆴ','ã„¿'=>'ᆵ','ã…€'=>'ᄚ','ã…'=>'ᄆ','ã…‚'=>'ᄇ','ã…ƒ'=>'ᄈ','ã…„'=>'á„¡','ã……'=>'ᄉ','ã…†'=>'ᄊ','ã…‡'=>'á„‹','ã…ˆ'=>'ᄌ','ã…‰'=>'á„','ã…Š'=>'ᄎ','ã…‹'=>'á„','ã…Œ'=>'á„','ã…'=>'á„‘','ã…Ž'=>'á„’','ã…'=>'á…¡','ã…'=>'á…¢','ã…‘'=>'á…£','ã…’'=>'á…¤','ã…“'=>'á…¥','ã…”'=>'á…¦','ã…•'=>'á…§','ã…–'=>'á…¨','ã…—'=>'á…©','ã…˜'=>'á…ª','ã…™'=>'á…«','ã…š'=>'á…¬','ã…›'=>'á…','ã…œ'=>'á…®','ã…'=>'á…¯','ã…ž'=>'á…°','ã…Ÿ'=>'á…±','ã… '=>'á…²','ã…¡'=>'á…³','ã…¢'=>'á…´','ã…£'=>'á…µ','ã…¤'=>'á… ','ã…¥'=>'á„”','ã…¦'=>'á„•','ã…§'=>'ᇇ','ã…¨'=>'ᇈ','ã…©'=>'ᇌ','ã…ª'=>'ᇎ','ã…«'=>'ᇓ','ã…¬'=>'ᇗ','ã…'=>'ᇙ','ã…®'=>'ᄜ','ã…¯'=>'á‡','ã…°'=>'ᇟ','ã…±'=>'á„','ã…²'=>'ᄞ','ã…³'=>'á„ ','ã…´'=>'á„¢','ã…µ'=>'á„£','ã…¶'=>'á„§','ã…·'=>'á„©','ã…¸'=>'á„«','ã…¹'=>'ᄬ','ã…º'=>'á„','ã…»'=>'á„®','ã…¼'=>'ᄯ','ã…½'=>'ᄲ','ã…¾'=>'á„¶','ã…¿'=>'á…€','ㆀ'=>'á…‡','ã†'=>'á…Œ','ㆂ'=>'ᇱ','ㆃ'=>'ᇲ','ㆄ'=>'á…—','ㆅ'=>'á…˜','ㆆ'=>'á…™','ㆇ'=>'ᆄ','ㆈ'=>'ᆅ','ㆉ'=>'ᆈ','ㆊ'=>'ᆑ','ㆋ'=>'ᆒ','ㆌ'=>'ᆔ','ã†'=>'ᆞ','ㆎ'=>'ᆡ','㆒'=>'一','㆓'=>'二','㆔'=>'三','㆕'=>'å››','㆖'=>'上','㆗'=>'ä¸','㆘'=>'下','㆙'=>'甲','㆚'=>'ä¹™','㆛'=>'丙','㆜'=>'ä¸','ã†'=>'天','㆞'=>'地','㆟'=>'人','㈀'=>'(á„€)','ãˆ'=>'(á„‚)','㈂'=>'(ᄃ)','㈃'=>'(á„…)','㈄'=>'(ᄆ)','㈅'=>'(ᄇ)','㈆'=>'(ᄉ)','㈇'=>'(á„‹)','㈈'=>'(ᄌ)','㈉'=>'(ᄎ)','㈊'=>'(á„)','㈋'=>'(á„)','㈌'=>'(á„‘)','ãˆ'=>'(á„’)','㈎'=>'(가)','ãˆ'=>'(á„‚á…¡)','ãˆ'=>'(다)','㈑'=>'(á„…á…¡)','㈒'=>'(마)','㈓'=>'(바)','㈔'=>'(사)','㈕'=>'(á„‹á…¡)','㈖'=>'(자)','㈗'=>'(차)','㈘'=>'(á„á…¡)','㈙'=>'(á„á…¡)','㈚'=>'(á„‘á…¡)','㈛'=>'(á„’á…¡)','㈜'=>'(주)','ãˆ'=>'(오전)','㈞'=>'(á„‹á…©á„’á…®)','㈠'=>'(一)','㈡'=>'(二)','㈢'=>'(三)','㈣'=>'(å››)','㈤'=>'(五)','㈥'=>'(å…)','㈦'=>'(七)','㈧'=>'(å…«)','㈨'=>'(ä¹)','㈩'=>'(å)','㈪'=>'(月)','㈫'=>'(ç«)','㈬'=>'(æ°´)','ãˆ'=>'(木)','㈮'=>'(金)','㈯'=>'(土)','㈰'=>'(æ—¥)','㈱'=>'(æ ª)','㈲'=>'(有)','㈳'=>'(社)','㈴'=>'(å)','㈵'=>'(特)','㈶'=>'(財)','㈷'=>'(ç¥)','㈸'=>'(労)','㈹'=>'(代)','㈺'=>'(呼)','㈻'=>'(å¦)','㈼'=>'(監)','㈽'=>'(ä¼)','㈾'=>'(資)','㈿'=>'(å”)','㉀'=>'(ç¥)','ã‰'=>'(休)','㉂'=>'(自)','㉃'=>'(至)','ã‰'=>'PTE','㉑'=>'21','㉒'=>'22','㉓'=>'23','㉔'=>'24','㉕'=>'25','㉖'=>'26','㉗'=>'27','㉘'=>'28','㉙'=>'29','㉚'=>'30','㉛'=>'31','㉜'=>'32','ã‰'=>'33','㉞'=>'34','㉟'=>'35','㉠'=>'á„€','㉡'=>'á„‚','㉢'=>'ᄃ','㉣'=>'á„…','㉤'=>'ᄆ','㉥'=>'ᄇ','㉦'=>'ᄉ','㉧'=>'á„‹','㉨'=>'ᄌ','㉩'=>'ᄎ','㉪'=>'á„','㉫'=>'á„','㉬'=>'á„‘','ã‰'=>'á„’','㉮'=>'가','㉯'=>'á„‚á…¡','㉰'=>'다','㉱'=>'á„…á…¡','㉲'=>'마','㉳'=>'바','㉴'=>'사','㉵'=>'á„‹á…¡','㉶'=>'자','㉷'=>'차','㉸'=>'á„á…¡','㉹'=>'á„á…¡','㉺'=>'á„‘á…¡','㉻'=>'á„’á…¡','㉼'=>'참고','㉽'=>'주의','㉾'=>'á„‹á…®','㊀'=>'一','ãŠ'=>'二','㊂'=>'三','㊃'=>'å››','㊄'=>'五','㊅'=>'å…','㊆'=>'七','㊇'=>'å…«','㊈'=>'ä¹','㊉'=>'å','㊊'=>'月','㊋'=>'ç«','㊌'=>'æ°´','ãŠ'=>'木','㊎'=>'金','ãŠ'=>'土','ãŠ'=>'æ—¥','㊑'=>'æ ª','㊒'=>'有','㊓'=>'社','㊔'=>'å','㊕'=>'特','㊖'=>'財','㊗'=>'ç¥','㊘'=>'労','㊙'=>'秘','㊚'=>'ç”·','㊛'=>'女','㊜'=>'é©','ãŠ'=>'優','㊞'=>'å°','㊟'=>'注','㊠'=>'é …','㊡'=>'休','㊢'=>'写','㊣'=>'æ£','㊤'=>'上','㊥'=>'ä¸','㊦'=>'下','㊧'=>'å·¦','㊨'=>'å³','㊩'=>'医','㊪'=>'å®—','㊫'=>'å¦','㊬'=>'監','ãŠ'=>'ä¼','㊮'=>'資','㊯'=>'å”','㊰'=>'夜','㊱'=>'36','㊲'=>'37','㊳'=>'38','㊴'=>'39','㊵'=>'40','㊶'=>'41','㊷'=>'42','㊸'=>'43','㊹'=>'44','㊺'=>'45','㊻'=>'46','㊼'=>'47','㊽'=>'48','㊾'=>'49','㊿'=>'50','ã‹€'=>'1月','ã‹'=>'2月','ã‹‚'=>'3月','㋃'=>'4月','ã‹„'=>'5月','ã‹…'=>'6月','㋆'=>'7月','㋇'=>'8月','㋈'=>'9月','㋉'=>'10月','㋊'=>'11月','ã‹‹'=>'12月','㋌'=>'Hg','ã‹'=>'erg','㋎'=>'eV','ã‹'=>'LTD','ã‹'=>'ã‚¢','ã‹‘'=>'イ','ã‹’'=>'ウ','ã‹“'=>'エ','ã‹”'=>'オ','ã‹•'=>'ã‚«','ã‹–'=>'ã‚','ã‹—'=>'ク','㋘'=>'ケ','ã‹™'=>'コ','㋚'=>'サ','ã‹›'=>'ã‚·','㋜'=>'ス','ã‹'=>'ã‚»','㋞'=>'ソ','㋟'=>'ã‚¿','ã‹ '=>'ãƒ','ã‹¡'=>'ツ','ã‹¢'=>'テ','ã‹£'=>'ト','㋤'=>'ナ','ã‹¥'=>'ニ','㋦'=>'ヌ','ã‹§'=>'ãƒ','㋨'=>'ノ','ã‹©'=>'ãƒ','㋪'=>'ヒ','ã‹«'=>'フ','㋬'=>'ヘ','ã‹'=>'ホ','ã‹®'=>'マ','㋯'=>'ミ','ã‹°'=>'ム','㋱'=>'メ','㋲'=>'モ','㋳'=>'ヤ','ã‹´'=>'ユ','㋵'=>'ヨ','ã‹¶'=>'ラ','ã‹·'=>'リ','㋸'=>'ル','㋹'=>'レ','㋺'=>'ãƒ','ã‹»'=>'ワ','㋼'=>'ヰ','㋽'=>'ヱ','㋾'=>'ヲ','㌀'=>'ã‚¢ãƒã‚šãƒ¼ãƒˆ','ãŒ'=>'アルファ','㌂'=>'アンペア','㌃'=>'アール','㌄'=>'イニング','㌅'=>'インãƒ','㌆'=>'ウォン','㌇'=>'エスクード','㌈'=>'エーカー','㌉'=>'オンス','㌊'=>'オーム','㌋'=>'カイリ','㌌'=>'カラット','ãŒ'=>'ã‚«ãƒãƒªãƒ¼','㌎'=>'ã‚«ã‚™ãƒãƒ³','ãŒ'=>'ガンマ','ãŒ'=>'ã‚゙ガ','㌑'=>'ã‚゙ニー','㌒'=>'ã‚ュリー','㌓'=>'ã‚゙ルダー','㌔'=>'ã‚ãƒ','㌕'=>'ã‚ãƒã‚¯ã‚™ãƒ©ãƒ ','㌖'=>'ã‚ãƒãƒ¡ãƒ¼ãƒˆãƒ«','㌗'=>'ã‚ãƒãƒ¯ãƒƒãƒˆ','㌘'=>'グラム','㌙'=>'グラムトン','㌚'=>'クルゼイãƒ','㌛'=>'クãƒãƒ¼ãƒ','㌜'=>'ケース','ãŒ'=>'コルナ','㌞'=>'コーポ','㌟'=>'サイクル','㌠'=>'サンãƒãƒ¼ãƒ ','㌡'=>'シリング','㌢'=>'センãƒ','㌣'=>'セント','㌤'=>'ダース','㌥'=>'デシ','㌦'=>'ドル','㌧'=>'トン','㌨'=>'ナノ','㌩'=>'ノット','㌪'=>'ãƒã‚¤ãƒ„','㌫'=>'ãƒã‚šãƒ¼ã‚»ãƒ³ãƒˆ','㌬'=>'ãƒã‚šãƒ¼ãƒ„','ãŒ'=>'ãƒã‚™ãƒ¼ãƒ¬ãƒ«','㌮'=>'ピアストル','㌯'=>'ピクル','㌰'=>'ピコ','㌱'=>'ビル','㌲'=>'ファラッド','㌳'=>'フィート','㌴'=>'ブッシェル','㌵'=>'フラン','㌶'=>'ヘクタール','㌷'=>'ペソ','㌸'=>'ペニヒ','㌹'=>'ヘルツ','㌺'=>'ペンス','㌻'=>'ページ','㌼'=>'ベータ','㌽'=>'ポイント','㌾'=>'ボルト','㌿'=>'ホン','ã€'=>'ポンド','ã'=>'ホール','ã‚'=>'ホーン','ãƒ'=>'マイクãƒ','ã„'=>'マイル','ã…'=>'マッãƒ','ã†'=>'マルク','ã‡'=>'マンション','ãˆ'=>'ミクãƒãƒ³','ã‰'=>'ミリ','ãŠ'=>'ミリãƒã‚™ãƒ¼ãƒ«','ã‹'=>'メガ','ãŒ'=>'メガトン','ã'=>'メートル','ãŽ'=>'ヤード','ã'=>'ヤール','ã'=>'ユアン','ã‘'=>'リットル','ã’'=>'リラ','ã“'=>'ルピー','ã”'=>'ルーブル','ã•'=>'レム','ã–'=>'レントゲン','ã—'=>'ワット','ã˜'=>'0点','ã™'=>'1点','ãš'=>'2点','ã›'=>'3点','ãœ'=>'4点','ã'=>'5点','ãž'=>'6点','ãŸ'=>'7点','ã '=>'8点','ã¡'=>'9点','ã¢'=>'10点','ã£'=>'11点','ã¤'=>'12点','ã¥'=>'13点','ã¦'=>'14点','ã§'=>'15点','ã¨'=>'16点','ã©'=>'17点','ãª'=>'18点','ã«'=>'19点','ã¬'=>'20点','ã'=>'21点','ã®'=>'22点','ã¯'=>'23点','ã°'=>'24点','ã±'=>'hPa','ã²'=>'da','ã³'=>'AU','ã´'=>'bar','ãµ'=>'oV','ã¶'=>'pc','ã·'=>'dm','ã¸'=>'dm2','ã¹'=>'dm3','ãº'=>'IU','ã»'=>'å¹³æˆ','ã¼'=>'æ˜å’Œ','ã½'=>'大æ£','ã¾'=>'明治','ã¿'=>'æ ªå¼ä¼šç¤¾','㎀'=>'pA','ãŽ'=>'nA','㎂'=>'μA','㎃'=>'mA','㎄'=>'kA','㎅'=>'KB','㎆'=>'MB','㎇'=>'GB','㎈'=>'cal','㎉'=>'kcal','㎊'=>'pF','㎋'=>'nF','㎌'=>'μF','ãŽ'=>'μg','㎎'=>'mg','ãŽ'=>'kg','ãŽ'=>'Hz','㎑'=>'kHz','㎒'=>'MHz','㎓'=>'GHz','㎔'=>'THz','㎕'=>'μl','㎖'=>'ml','㎗'=>'dl','㎘'=>'kl','㎙'=>'fm','㎚'=>'nm','㎛'=>'μm','㎜'=>'mm','ãŽ'=>'cm','㎞'=>'km','㎟'=>'mm2','㎠'=>'cm2','㎡'=>'m2','㎢'=>'km2','㎣'=>'mm3','㎤'=>'cm3','㎥'=>'m3','㎦'=>'km3','㎧'=>'m∕s','㎨'=>'m∕s2','㎩'=>'Pa','㎪'=>'kPa','㎫'=>'MPa','㎬'=>'GPa','ãŽ'=>'rad','㎮'=>'rad∕s','㎯'=>'rad∕s2','㎰'=>'ps','㎱'=>'ns','㎲'=>'μs','㎳'=>'ms','㎴'=>'pV','㎵'=>'nV','㎶'=>'μV','㎷'=>'mV','㎸'=>'kV','㎹'=>'MV','㎺'=>'pW','㎻'=>'nW','㎼'=>'μW','㎽'=>'mW','㎾'=>'kW','㎿'=>'MW','ã€'=>'kΩ','ã'=>'MΩ','ã‚'=>'a.m.','ãƒ'=>'Bq','ã„'=>'cc','ã…'=>'cd','ã†'=>'C∕kg','ã‡'=>'Co.','ãˆ'=>'dB','ã‰'=>'Gy','ãŠ'=>'ha','ã‹'=>'HP','ãŒ'=>'in','ã'=>'KK','ãŽ'=>'KM','ã'=>'kt','ã'=>'lm','ã‘'=>'ln','ã’'=>'log','ã“'=>'lx','ã”'=>'mb','ã•'=>'mil','ã–'=>'mol','ã—'=>'PH','ã˜'=>'p.m.','ã™'=>'PPM','ãš'=>'PR','ã›'=>'sr','ãœ'=>'Sv','ã'=>'Wb','ãž'=>'V∕m','ãŸ'=>'A∕m','ã '=>'1æ—¥','ã¡'=>'2æ—¥','ã¢'=>'3æ—¥','ã£'=>'4æ—¥','ã¤'=>'5æ—¥','ã¥'=>'6æ—¥','ã¦'=>'7æ—¥','ã§'=>'8æ—¥','ã¨'=>'9æ—¥','ã©'=>'10æ—¥','ãª'=>'11æ—¥','ã«'=>'12æ—¥','ã¬'=>'13æ—¥','ã'=>'14æ—¥','ã®'=>'15æ—¥','ã¯'=>'16æ—¥','ã°'=>'17æ—¥','ã±'=>'18æ—¥','ã²'=>'19æ—¥','ã³'=>'20æ—¥','ã´'=>'21æ—¥','ãµ'=>'22æ—¥','ã¶'=>'23æ—¥','ã·'=>'24æ—¥','ã¸'=>'25æ—¥','ã¹'=>'26æ—¥','ãº'=>'27æ—¥','ã»'=>'28æ—¥','ã¼'=>'29æ—¥','ã½'=>'30æ—¥','ã¾'=>'31æ—¥','ã¿'=>'gal','豈'=>'豈','ï¤'=>'æ›´','車'=>'車','賈'=>'賈','滑'=>'滑','串'=>'串','句'=>'å¥','龜'=>'龜','龜'=>'龜','契'=>'契','金'=>'金','喇'=>'å–‡','奈'=>'奈','ï¤'=>'懶','癩'=>'癩','ï¤'=>'ç¾…','ï¤'=>'蘿','螺'=>'螺','裸'=>'裸','邏'=>'é‚','樂'=>'樂','洛'=>'æ´›','烙'=>'烙','珞'=>'çž','落'=>'è½','酪'=>'é…ª','駱'=>'é§±','亂'=>'亂','卵'=>'åµ','ï¤'=>'欄','爛'=>'爛','蘭'=>'è˜','ï¤ '=>'鸞','嵐'=>'åµ','濫'=>'æ¿«','藍'=>'è—','襤'=>'襤','拉'=>'拉','臘'=>'臘','蠟'=>'è Ÿ','廊'=>'廊','朗'=>'朗','浪'=>'浪','狼'=>'狼','郎'=>'郎','ï¤'=>'來','冷'=>'冷','勞'=>'勞','擄'=>'æ“„','櫓'=>'æ«“','爐'=>'çˆ','盧'=>'ç›§','老'=>'è€','蘆'=>'蘆','虜'=>'虜','路'=>'è·¯','露'=>'露','魯'=>'é¯','鷺'=>'é·º','碌'=>'碌','祿'=>'祿','綠'=>'ç¶ ','菉'=>'è‰','錄'=>'錄','鹿'=>'鹿','ï¥'=>'è«–','壟'=>'壟','弄'=>'弄','籠'=>'ç± ','聾'=>'è¾','牢'=>'牢','磊'=>'磊','賂'=>'賂','雷'=>'é›·','壘'=>'壘','屢'=>'å±¢','樓'=>'樓','ï¥'=>'æ·š','漏'=>'æ¼','ï¥'=>'ç´¯','ï¥'=>'縷','陋'=>'陋','勒'=>'å‹’','肋'=>'è‚‹','凜'=>'凜','凌'=>'凌','稜'=>'稜','綾'=>'ç¶¾','菱'=>'è±','陵'=>'陵','讀'=>'讀','拏'=>'æ‹','樂'=>'樂','ï¥'=>'諾','丹'=>'丹','寧'=>'寧','ï¥ '=>'怒','率'=>'率','異'=>'ç•°','北'=>'北','磻'=>'磻','便'=>'便','復'=>'復','不'=>'ä¸','泌'=>'泌','數'=>'數','索'=>'ç´¢','參'=>'åƒ','塞'=>'塞','ï¥'=>'çœ','葉'=>'葉','說'=>'說','殺'=>'殺','辰'=>'è¾°','沈'=>'沈','拾'=>'拾','若'=>'è‹¥','掠'=>'æŽ ','略'=>'ç•¥','亮'=>'亮','兩'=>'å…©','凉'=>'凉','梁'=>'æ¢','糧'=>'ç³§','良'=>'良','諒'=>'è«’','量'=>'é‡','勵'=>'勵','呂'=>'å‘‚','ï¦'=>'女','廬'=>'廬','旅'=>'æ—…','濾'=>'濾','礪'=>'礪','閭'=>'é–','驪'=>'驪','麗'=>'麗','黎'=>'黎','力'=>'力','曆'=>'曆','歷'=>'æ·','ï¦'=>'è½¢','年'=>'å¹´','ï¦'=>'æ†','ï¦'=>'戀','撚'=>'æ’š','漣'=>'æ¼£','煉'=>'ç…‰','璉'=>'ç’‰','秊'=>'ç§Š','練'=>'ç·´','聯'=>'è¯','輦'=>'輦','蓮'=>'è“®','連'=>'連','鍊'=>'éŠ','列'=>'列','ï¦'=>'劣','咽'=>'å’½','烈'=>'烈','ï¦ '=>'裂','說'=>'說','廉'=>'廉','念'=>'念','捻'=>'æ»','殮'=>'æ®®','簾'=>'ç°¾','獵'=>'çµ','令'=>'令','囹'=>'囹','寧'=>'寧','嶺'=>'嶺','怜'=>'怜','ï¦'=>'玲','瑩'=>'ç‘©','羚'=>'羚','聆'=>'è†','鈴'=>'鈴','零'=>'é›¶','靈'=>'éˆ','領'=>'é ˜','例'=>'例','禮'=>'禮','醴'=>'醴','隸'=>'隸','惡'=>'惡','了'=>'了','僚'=>'僚','寮'=>'寮','尿'=>'å°¿','料'=>'æ–™','樂'=>'樂','ï§€'=>'燎','ï§'=>'療','ï§‚'=>'蓼','遼'=>'é¼','ï§„'=>'é¾','ï§…'=>'暈','阮'=>'阮','劉'=>'劉','杻'=>'æ»','柳'=>'柳','ï§Š'=>'æµ','ï§‹'=>'溜','ï§Œ'=>'ç‰','ï§'=>'ç•™','ï§Ž'=>'ç¡«','ï§'=>'ç´','ï§'=>'類','ï§‘'=>'å…','ï§’'=>'戮','ï§“'=>'陸','ï§”'=>'倫','ï§•'=>'å´™','ï§–'=>'æ·ª','ï§—'=>'輪','律'=>'律','ï§™'=>'æ…„','ï§š'=>'æ —','ï§›'=>'率','ï§œ'=>'隆','ï§'=>'利','ï§ž'=>'å','ï§Ÿ'=>'å±¥','ï§ '=>'易','ï§¡'=>'æŽ','ï§¢'=>'梨','ï§£'=>'æ³¥','理'=>'ç†','ï§¥'=>'ç—¢','罹'=>'ç½¹','ï§§'=>'è£','裡'=>'裡','ï§©'=>'里','離'=>'離','ï§«'=>'匿','溺'=>'溺','ï§'=>'å','ï§®'=>'ç‡','璘'=>'ç’˜','ï§°'=>'è—º','ï§±'=>'隣','ï§²'=>'é±—','ï§³'=>'麟','ï§´'=>'æž—','ï§µ'=>'æ·‹','ï§¶'=>'臨','ï§·'=>'ç«‹','笠'=>'ç¬ ','ï§¹'=>'ç²’','狀'=>'ç‹€','ï§»'=>'ç‚™','ï§¼'=>'è˜','ï§½'=>'什','ï§¾'=>'茶','ï§¿'=>'刺','切'=>'切','ï¨'=>'度','拓'=>'æ‹“','糖'=>'ç³–','宅'=>'å®…','洞'=>'æ´ž','暴'=>'æš´','輻'=>'è¼»','行'=>'行','降'=>'é™','見'=>'見','廓'=>'廓','兀'=>'å…€','ï¨'=>'å—€','ï¨'=>'塚','晴'=>'æ™´','凞'=>'凞','猪'=>'猪','益'=>'益','礼'=>'礼','神'=>'神','祥'=>'祥','福'=>'ç¦','靖'=>'é–','ï¨'=>'ç²¾','羽'=>'ç¾½','ï¨ '=>'蘒','諸'=>'諸','逸'=>'逸','都'=>'都','飯'=>'飯','飼'=>'飼','館'=>'館','ï¨'=>'é¶´','侮'=>'ä¾®','僧'=>'僧','免'=>'å…','勉'=>'勉','勤'=>'勤','卑'=>'å‘','喝'=>'å–','嘆'=>'嘆','器'=>'器','塀'=>'å¡€','墨'=>'墨','層'=>'層','屮'=>'å±®','悔'=>'æ‚”','慨'=>'æ…¨','憎'=>'憎','ï©€'=>'懲','ï©'=>'æ•','ï©‚'=>'æ—¢','暑'=>'æš‘','ï©„'=>'梅','ï©…'=>'æµ·','渚'=>'渚','漢'=>'æ¼¢','煮'=>'ç…®','爫'=>'爫','琢'=>'ç¢','ï©‹'=>'碑','社'=>'社','ï©'=>'祉','祈'=>'祈','ï©'=>'ç¥','ï©'=>'祖','ï©‘'=>'ç¥','ï©’'=>'ç¦','ï©“'=>'禎','ï©”'=>'ç©€','ï©•'=>'çª','ï©–'=>'節','ï©—'=>'ç·´','縉'=>'縉','ï©™'=>'ç¹','署'=>'ç½²','ï©›'=>'者','臭'=>'è‡','ï©'=>'艹','艹'=>'艹','著'=>'è‘—','ï© '=>'è¤','ï©¡'=>'視','ï©¢'=>'è¬','ï©£'=>'謹','賓'=>'賓','ï©¥'=>'è´ˆ','辶'=>'è¾¶','ï©§'=>'逸','難'=>'難','ï©©'=>'響','頻'=>'é »','ï©°'=>'並','况'=>'况','全'=>'å…¨','侀'=>'ä¾€','ï©´'=>'å……','冀'=>'冀','ï©¶'=>'勇','ï©·'=>'勺','喝'=>'å–','啕'=>'å••','喙'=>'å–™','ï©»'=>'å—¢','塚'=>'塚','墳'=>'墳','奄'=>'奄','ï©¿'=>'奔','婢'=>'å©¢','ïª'=>'嬨','廒'=>'å»’','廙'=>'å»™','彩'=>'彩','徭'=>'å¾','惘'=>'惘','慎'=>'æ…Ž','愈'=>'愈','憎'=>'憎','慠'=>'æ… ','懲'=>'懲','戴'=>'戴','ïª'=>'æ„','搜'=>'æœ','ïª'=>'æ‘’','ïª'=>'æ•–','晴'=>'æ™´','朗'=>'朗','望'=>'望','杖'=>'æ–','歹'=>'æ¹','殺'=>'殺','流'=>'æµ','滛'=>'æ»›','滋'=>'滋','漢'=>'æ¼¢','瀞'=>'瀞','煮'=>'ç…®','ïª'=>'çž§','爵'=>'爵','犯'=>'犯','ïª '=>'猪','瑱'=>'瑱','甆'=>'甆','画'=>'ç”»','瘝'=>'ç˜','瘟'=>'瘟','益'=>'益','盛'=>'ç››','直'=>'ç›´','睊'=>'çŠ','着'=>'ç€','磌'=>'磌','窱'=>'窱','ïª'=>'節','类'=>'ç±»','絛'=>'çµ›','練'=>'ç·´','缾'=>'ç¼¾','者'=>'者','荒'=>'è’','華'=>'è¯','蝹'=>'è¹','襁'=>'è¥','覆'=>'覆','視'=>'視','調'=>'調','諸'=>'諸','請'=>'è«‹','謁'=>'è¬','諾'=>'諾','諭'=>'è«','謹'=>'謹','ï«€'=>'變','ï«'=>'è´ˆ','ï«‚'=>'輸','遲'=>'é²','ï«„'=>'醙','ï«…'=>'鉶','陼'=>'陼','難'=>'難','靖'=>'é–','韛'=>'韛','響'=>'響','ï«‹'=>'é ‹','頻'=>'é »','ï«'=>'鬒','龜'=>'龜','ï«'=>'𢡊','ï«'=>'𢡄','ï«‘'=>'ð£•','ï«’'=>'ã®','ï«“'=>'䀘','ï«”'=>'䀹','ï«•'=>'𥉉','ï«–'=>'ð¥³','ï«—'=>'𧻓','齃'=>'齃','ï«™'=>'龎','ff'=>'ff','ï¬'=>'fi','fl'=>'fl','ffi'=>'ffi','ffl'=>'ffl','ſt'=>'st','st'=>'st','ﬓ'=>'Õ´Õ¶','ﬔ'=>'Õ´Õ¥','ﬕ'=>'Õ´Õ«','ﬖ'=>'Õ¾Õ¶','ﬗ'=>'Õ´Õ','ï¬'=>'×™Ö´','ײַ'=>'ײַ','ï¬ '=>'×¢','ﬡ'=>'×','ﬢ'=>'ד','ﬣ'=>'×”','ﬤ'=>'×›','ﬥ'=>'ל','ﬦ'=>'×','ﬧ'=>'ר','ﬨ'=>'ת','﬩'=>'+','שׁ'=>'ש×','שׂ'=>'שׂ','שּׁ'=>'שּ×','ï¬'=>'שּׂ','אַ'=>'×Ö·','אָ'=>'×Ö¸','אּ'=>'×Ö¼','בּ'=>'בּ','גּ'=>'×’Ö¼','דּ'=>'דּ','הּ'=>'×”Ö¼','וּ'=>'וּ','זּ'=>'×–Ö¼','טּ'=>'טּ','יּ'=>'×™Ö¼','ךּ'=>'ךּ','כּ'=>'×›Ö¼','לּ'=>'לּ','מּ'=>'מּ','ï€'=>'× Ö¼','ï'=>'סּ','ïƒ'=>'×£Ö¼','ï„'=>'פּ','ï†'=>'צּ','ï‡'=>'×§Ö¼','ïˆ'=>'רּ','ï‰'=>'שּ','ïŠ'=>'תּ','ï‹'=>'וֹ','ïŒ'=>'בֿ','ï'=>'×›Ö¿','ïŽ'=>'פֿ','ï'=>'×ל','ï'=>'Ù±','ï‘'=>'Ù±','ï’'=>'Ù»','ï“'=>'Ù»','ï”'=>'Ù»','ï•'=>'Ù»','ï–'=>'Ù¾','ï—'=>'Ù¾','ï˜'=>'Ù¾','ï™'=>'Ù¾','ïš'=>'Ú€','ï›'=>'Ú€','ïœ'=>'Ú€','ï'=>'Ú€','ïž'=>'Ùº','ïŸ'=>'Ùº','ï '=>'Ùº','ï¡'=>'Ùº','ï¢'=>'Ù¿','ï£'=>'Ù¿','ï¤'=>'Ù¿','ï¥'=>'Ù¿','ï¦'=>'Ù¹','ï§'=>'Ù¹','ï¨'=>'Ù¹','ï©'=>'Ù¹','ïª'=>'Ú¤','ï«'=>'Ú¤','ï¬'=>'Ú¤','ï'=>'Ú¤','ï®'=>'Ú¦','ï¯'=>'Ú¦','ï°'=>'Ú¦','ï±'=>'Ú¦','ï²'=>'Ú„','ï³'=>'Ú„','ï´'=>'Ú„','ïµ'=>'Ú„','ï¶'=>'Úƒ','ï·'=>'Úƒ','ï¸'=>'Úƒ','ï¹'=>'Úƒ','ïº'=>'Ú†','ï»'=>'Ú†','ï¼'=>'Ú†','ï½'=>'Ú†','ï¾'=>'Ú‡','ï¿'=>'Ú‡','ﮀ'=>'Ú‡','ï®'=>'Ú‡','ﮂ'=>'Ú','ﮃ'=>'Ú','ﮄ'=>'ÚŒ','ï®…'=>'ÚŒ','ﮆ'=>'ÚŽ','ﮇ'=>'ÚŽ','ﮈ'=>'Úˆ','ﮉ'=>'Úˆ','ﮊ'=>'Ú˜','ﮋ'=>'Ú˜','ﮌ'=>'Ú‘','ï®'=>'Ú‘','ﮎ'=>'Ú©','ï®'=>'Ú©','ï®'=>'Ú©','ﮑ'=>'Ú©','ï®’'=>'Ú¯','ﮓ'=>'Ú¯','ï®”'=>'Ú¯','ﮕ'=>'Ú¯','ï®–'=>'Ú³','ï®—'=>'Ú³','ﮘ'=>'Ú³','ï®™'=>'Ú³','ﮚ'=>'Ú±','ï®›'=>'Ú±','ﮜ'=>'Ú±','ï®'=>'Ú±','ﮞ'=>'Úº','ﮟ'=>'Úº','ï® '=>'Ú»','ﮡ'=>'Ú»','ﮢ'=>'Ú»','ﮣ'=>'Ú»','ﮤ'=>'Û•Ù”','ﮥ'=>'Û•Ù”','ﮦ'=>'Û','ï®§'=>'Û','ﮨ'=>'Û','ﮩ'=>'Û','ﮪ'=>'Ú¾','ﮫ'=>'Ú¾','ﮬ'=>'Ú¾','ï®'=>'Ú¾','ï®®'=>'Û’','ﮯ'=>'Û’','ï®°'=>'Û’Ù”','ï®±'=>'Û’Ù”','ﯓ'=>'Ú','ﯔ'=>'Ú','ﯕ'=>'Ú','ﯖ'=>'Ú','ﯗ'=>'Û‡','ﯘ'=>'Û‡','ﯙ'=>'Û†','ﯚ'=>'Û†','ﯛ'=>'Ûˆ','ﯜ'=>'Ûˆ','ï¯'=>'Û‡Ù´','ﯞ'=>'Û‹','ﯟ'=>'Û‹','ï¯ '=>'Û…','ﯡ'=>'Û…','ﯢ'=>'Û‰','ﯣ'=>'Û‰','ﯤ'=>'Û','ﯥ'=>'Û','ﯦ'=>'Û','ﯧ'=>'Û','ﯨ'=>'Ù‰','ﯩ'=>'Ù‰','ﯪ'=>'ئا','ﯫ'=>'ئا','ﯬ'=>'ÙŠÙ”Û•','ï¯'=>'ÙŠÙ”Û•','ﯮ'=>'ÙŠÙ”Ùˆ','ﯯ'=>'ÙŠÙ”Ùˆ','ﯰ'=>'ÙŠÙ”Û‡','ﯱ'=>'ÙŠÙ”Û‡','ﯲ'=>'ÙŠÙ”Û†','ﯳ'=>'ÙŠÙ”Û†','ﯴ'=>'ÙŠÙ”Ûˆ','ﯵ'=>'ÙŠÙ”Ûˆ','ﯶ'=>'ÙŠÙ”Û','ﯷ'=>'ÙŠÙ”Û','ﯸ'=>'ÙŠÙ”Û','ﯹ'=>'ÙŠÙ”Ù‰','ﯺ'=>'ÙŠÙ”Ù‰','ﯻ'=>'ÙŠÙ”Ù‰','ﯼ'=>'ÛŒ','ﯽ'=>'ÛŒ','ﯾ'=>'ÛŒ','ﯿ'=>'ÛŒ','ï°€'=>'ئج','ï°'=>'ÙŠÙ”Ø','ï°‚'=>'ÙŠÙ”Ù…','ï°ƒ'=>'ÙŠÙ”Ù‰','ï°„'=>'ÙŠÙ”ÙŠ','ï°…'=>'بج','ï°†'=>'بØ','ï°‡'=>'بخ','ï°ˆ'=>'بم','ï°‰'=>'بى','ï°Š'=>'بي','ï°‹'=>'تج','ï°Œ'=>'تØ','ï°'=>'تخ','ï°Ž'=>'تم','ï°'=>'تى','ï°'=>'تي','ï°‘'=>'ثج','ï°’'=>'ثم','ï°“'=>'ثى','ï°”'=>'ثي','ï°•'=>'جØ','ï°–'=>'جم','ï°—'=>'ØØ¬','ï°˜'=>'ØÙ…','ï°™'=>'خج','ï°š'=>'Ø®Ø','ï°›'=>'خم','ï°œ'=>'سج','ï°'=>'سØ','ï°ž'=>'سخ','ï°Ÿ'=>'سم','ï° '=>'صØ','ï°¡'=>'صم','ï°¢'=>'ضج','ï°£'=>'ضØ','ï°¤'=>'ضخ','ï°¥'=>'ضم','ï°¦'=>'Ø·Ø','ï°§'=>'طم','ï°¨'=>'ظم','ï°©'=>'عج','ï°ª'=>'عم','ï°«'=>'غج','ï°¬'=>'غم','ï°'=>'ÙØ¬','ï°®'=>'ÙØ','ï°¯'=>'ÙØ®','ï°°'=>'ÙÙ…','ï°±'=>'ÙÙ‰','ï°²'=>'ÙÙŠ','ï°³'=>'Ù‚Ø','ï°´'=>'قم','ï°µ'=>'قى','ï°¶'=>'قي','ï°·'=>'كا','ï°¸'=>'كج','ï°¹'=>'ÙƒØ','ï°º'=>'كخ','ï°»'=>'كل','ï°¼'=>'كم','ï°½'=>'كى','ï°¾'=>'كي','ï°¿'=>'لج','ï±€'=>'Ù„Ø','ï±'=>'لخ','ﱂ'=>'لم','ﱃ'=>'لى','ﱄ'=>'لي','ï±…'=>'مج','ﱆ'=>'Ù…Ø','ﱇ'=>'مخ','ﱈ'=>'مم','ﱉ'=>'مى','ﱊ'=>'مي','ﱋ'=>'نج','ﱌ'=>'Ù†Ø','ï±'=>'نخ','ﱎ'=>'نم','ï±'=>'نى','ï±'=>'ني','ﱑ'=>'هج','ï±’'=>'هم','ﱓ'=>'هى','ï±”'=>'هي','ﱕ'=>'يج','ï±–'=>'ÙŠØ','ï±—'=>'يخ','ﱘ'=>'يم','ï±™'=>'يى','ﱚ'=>'يي','ï±›'=>'ذٰ','ﱜ'=>'رٰ','ï±'=>'ىٰ','ﱞ'=>' ٌّ','ﱟ'=>' ÙÙ‘','ï± '=>' ÙŽÙ‘','ﱡ'=>' ÙÙ‘','ï±¢'=>' ÙÙ‘','ï±£'=>' ّٰ','ﱤ'=>'ئر','ï±¥'=>'ئز','ﱦ'=>'ÙŠÙ”Ù…','ï±§'=>'ÙŠÙ”Ù†','ﱨ'=>'ÙŠÙ”Ù‰','ﱩ'=>'ÙŠÙ”ÙŠ','ﱪ'=>'بر','ﱫ'=>'بز','ﱬ'=>'بم','ï±'=>'بن','ï±®'=>'بى','ﱯ'=>'بي','ï±°'=>'تر','ï±±'=>'تز','ï±²'=>'تم','ï±³'=>'تن','ï±´'=>'تى','ï±µ'=>'تي','ï±¶'=>'ثر','ï±·'=>'ثز','ﱸ'=>'ثم','ï±¹'=>'ثن','ﱺ'=>'ثى','ï±»'=>'ثي','ï±¼'=>'ÙÙ‰','ï±½'=>'ÙÙŠ','ï±¾'=>'قى','ﱿ'=>'قي','ï²€'=>'كا','ï²'=>'كل','ﲂ'=>'كم','ﲃ'=>'كى','ﲄ'=>'كي','ï²…'=>'لم','ﲆ'=>'لى','ﲇ'=>'لي','ﲈ'=>'ما','ﲉ'=>'مم','ﲊ'=>'نر','ﲋ'=>'نز','ﲌ'=>'نم','ï²'=>'نن','ﲎ'=>'نى','ï²'=>'ني','ï²'=>'ىٰ','ﲑ'=>'ير','ï²’'=>'يز','ﲓ'=>'يم','ï²”'=>'ين','ﲕ'=>'يى','ï²–'=>'يي','ï²—'=>'ئج','ﲘ'=>'ÙŠÙ”Ø','ï²™'=>'ئخ','ﲚ'=>'ÙŠÙ”Ù…','ï²›'=>'ÙŠÙ”Ù‡','ﲜ'=>'بج','ï²'=>'بØ','ﲞ'=>'بخ','ﲟ'=>'بم','ï² '=>'به','ﲡ'=>'تج','ï²¢'=>'تØ','ï²£'=>'تخ','ﲤ'=>'تم','ï²¥'=>'ته','ﲦ'=>'ثم','ï²§'=>'جØ','ﲨ'=>'جم','ﲩ'=>'ØØ¬','ﲪ'=>'ØÙ…','ﲫ'=>'خج','ﲬ'=>'خم','ï²'=>'سج','ï²®'=>'سØ','ﲯ'=>'سخ','ï²°'=>'سم','ï²±'=>'صØ','ï²²'=>'صخ','ï²³'=>'صم','ï²´'=>'ضج','ï²µ'=>'ضØ','ï²¶'=>'ضخ','ï²·'=>'ضم','ﲸ'=>'Ø·Ø','ï²¹'=>'ظم','ﲺ'=>'عج','ï²»'=>'عم','ï²¼'=>'غج','ï²½'=>'غم','ï²¾'=>'ÙØ¬','ﲿ'=>'ÙØ','ï³€'=>'ÙØ®','ï³'=>'ÙÙ…','ﳂ'=>'Ù‚Ø','ﳃ'=>'قم','ﳄ'=>'كج','ï³…'=>'ÙƒØ','ﳆ'=>'كخ','ﳇ'=>'كل','ﳈ'=>'كم','ﳉ'=>'لج','ﳊ'=>'Ù„Ø','ﳋ'=>'لخ','ﳌ'=>'لم','ï³'=>'له','ﳎ'=>'مج','ï³'=>'Ù…Ø','ï³'=>'مخ','ﳑ'=>'مم','ï³’'=>'نج','ﳓ'=>'Ù†Ø','ï³”'=>'نخ','ﳕ'=>'نم','ï³–'=>'نه','ï³—'=>'هج','ﳘ'=>'هم','ï³™'=>'هٰ','ﳚ'=>'يج','ï³›'=>'ÙŠØ','ﳜ'=>'يخ','ï³'=>'يم','ﳞ'=>'يه','ﳟ'=>'ÙŠÙ”Ù…','ï³ '=>'ÙŠÙ”Ù‡','ﳡ'=>'بم','ï³¢'=>'به','ï³£'=>'تم','ﳤ'=>'ته','ï³¥'=>'ثم','ﳦ'=>'ثه','ï³§'=>'سم','ﳨ'=>'سه','ﳩ'=>'شم','ﳪ'=>'شه','ﳫ'=>'كل','ﳬ'=>'كم','ï³'=>'لم','ï³®'=>'نم','ﳯ'=>'نه','ï³°'=>'يم','ï³±'=>'يه','ï³²'=>'Ù€ÙŽÙ‘','ï³³'=>'Ù€ÙÙ‘','ï³´'=>'Ù€ÙÙ‘','ï³µ'=>'طى','ï³¶'=>'طي','ï³·'=>'عى','ﳸ'=>'عي','ï³¹'=>'غى','ﳺ'=>'غي','ï³»'=>'سى','ï³¼'=>'سي','ï³½'=>'شى','ï³¾'=>'شي','ﳿ'=>'ØÙ‰','ï´€'=>'ØÙŠ','ï´'=>'جى','ï´‚'=>'جي','ï´ƒ'=>'خى','ï´„'=>'خي','ï´…'=>'صى','ï´†'=>'صي','ï´‡'=>'ضى','ï´ˆ'=>'ضي','ï´‰'=>'شج','ï´Š'=>'Ø´Ø','ï´‹'=>'شخ','ï´Œ'=>'شم','ï´'=>'شر','ï´Ž'=>'سر','ï´'=>'صر','ï´'=>'ضر','ï´‘'=>'طى','ï´’'=>'طي','ï´“'=>'عى','ï´”'=>'عي','ï´•'=>'غى','ï´–'=>'غي','ï´—'=>'سى','ï´˜'=>'سي','ï´™'=>'شى','ï´š'=>'شي','ï´›'=>'ØÙ‰','ï´œ'=>'ØÙŠ','ï´'=>'جى','ï´ž'=>'جي','ï´Ÿ'=>'خى','ï´ '=>'خي','ï´¡'=>'صى','ï´¢'=>'صي','ï´£'=>'ضى','ï´¤'=>'ضي','ï´¥'=>'شج','ï´¦'=>'Ø´Ø','ï´§'=>'شخ','ï´¨'=>'شم','ï´©'=>'شر','ï´ª'=>'سر','ï´«'=>'صر','ï´¬'=>'ضر','ï´'=>'شج','ï´®'=>'Ø´Ø','ï´¯'=>'شخ','ï´°'=>'شم','ï´±'=>'سه','ï´²'=>'شه','ï´³'=>'طم','ï´´'=>'سج','ï´µ'=>'سØ','ï´¶'=>'سخ','ï´·'=>'شج','ï´¸'=>'Ø´Ø','ï´¹'=>'شخ','ï´º'=>'طم','ï´»'=>'ظم','ï´¼'=>'اً','ï´½'=>'اً','ïµ'=>'تجم','ﵑ'=>'ØªØØ¬','ïµ’'=>'ØªØØ¬','ﵓ'=>'تØÙ…','ïµ”'=>'تخم','ﵕ'=>'تمج','ïµ–'=>'تمØ','ïµ—'=>'تمخ','ﵘ'=>'جمØ','ïµ™'=>'جمØ','ﵚ'=>'ØÙ…ÙŠ','ïµ›'=>'ØÙ…Ù‰','ﵜ'=>'Ø³ØØ¬','ïµ'=>'سجØ','ﵞ'=>'سجى','ﵟ'=>'سمØ','ïµ '=>'سمØ','ﵡ'=>'سمج','ïµ¢'=>'سمم','ïµ£'=>'سمم','ﵤ'=>'ØµØØ','ïµ¥'=>'ØµØØ','ﵦ'=>'صمم','ïµ§'=>'Ø´ØÙ…','ﵨ'=>'Ø´ØÙ…','ﵩ'=>'شجي','ﵪ'=>'شمخ','ﵫ'=>'شمخ','ﵬ'=>'شمم','ïµ'=>'شمم','ïµ®'=>'ضØÙ‰','ﵯ'=>'ضخم','ïµ°'=>'ضخم','ïµ±'=>'طمØ','ïµ²'=>'طمØ','ïµ³'=>'طمم','ïµ´'=>'طمي','ïµµ'=>'عجم','ïµ¶'=>'عمم','ïµ·'=>'عمم','ﵸ'=>'عمى','ïµ¹'=>'غمم','ﵺ'=>'غمي','ïµ»'=>'غمى','ïµ¼'=>'ÙØ®Ù…','ïµ½'=>'ÙØ®Ù…','ïµ¾'=>'قمØ','ﵿ'=>'قمم','ï¶€'=>'Ù„ØÙ…','ï¶'=>'Ù„ØÙŠ','ï¶‚'=>'Ù„ØÙ‰','ﶃ'=>'لجج','ï¶„'=>'لجج','ï¶…'=>'لخم','ﶆ'=>'لخم','ﶇ'=>'لمØ','ﶈ'=>'لمØ','ﶉ'=>'Ù…ØØ¬','ï¶Š'=>'Ù…ØÙ…','ï¶‹'=>'Ù…ØÙŠ','ï¶Œ'=>'مجØ','ï¶'=>'مجم','ï¶Ž'=>'مخج','ï¶'=>'مخم','ï¶’'=>'مجخ','ï¶“'=>'همج','ï¶”'=>'همم','ï¶•'=>'Ù†ØÙ…','ï¶–'=>'Ù†ØÙ‰','ï¶—'=>'نجم','ﶘ'=>'نجم','ï¶™'=>'نجى','ï¶š'=>'نمي','ï¶›'=>'نمى','ï¶œ'=>'يمم','ï¶'=>'يمم','ï¶ž'=>'بخي','ï¶Ÿ'=>'تجي','ï¶ '=>'تجى','ï¶¡'=>'تخي','ï¶¢'=>'تخى','ï¶£'=>'تمي','ﶤ'=>'تمى','ï¶¥'=>'جمي','ﶦ'=>'جØÙ‰','ï¶§'=>'جمى','ﶨ'=>'سخى','ï¶©'=>'صØÙŠ','ﶪ'=>'Ø´ØÙŠ','ï¶«'=>'ضØÙŠ','ﶬ'=>'لجي','ï¶'=>'لمي','ï¶®'=>'ÙŠØÙŠ','ﶯ'=>'يجي','ï¶°'=>'يمي','ï¶±'=>'ممي','ï¶²'=>'قمي','ï¶³'=>'Ù†ØÙŠ','ï¶´'=>'قمØ','ï¶µ'=>'Ù„ØÙ…','ï¶¶'=>'عمي','ï¶·'=>'كمي','ﶸ'=>'نجØ','ï¶¹'=>'مخي','ﶺ'=>'لجم','ï¶»'=>'كمم','ï¶¼'=>'لجم','ï¶½'=>'نجØ','ï¶¾'=>'جØÙŠ','ï¶¿'=>'ØØ¬ÙŠ','ï·€'=>'مجي','ï·'=>'Ùمي','ï·‚'=>'بØÙŠ','ï·ƒ'=>'كمم','ï·„'=>'عجم','ï·…'=>'صمم','ï·†'=>'سخي','ï·‡'=>'نجي','ï·°'=>'صلے','ï·±'=>'قلے','ï·²'=>'الله','ï·³'=>'اكبر','ï·´'=>'Ù…ØÙ…د','ï·µ'=>'صلعم','ï·¶'=>'رسول','ï··'=>'عليه','ï·¸'=>'وسلم','ï·¹'=>'صلى','ï·º'=>'صلى الله عليه وسلم','ï·»'=>'جل جلاله','ï·¼'=>'ریال','ï¸'=>',','︑'=>'ã€','︒'=>'。','︓'=>':','︔'=>';','︕'=>'!','︖'=>'?','︗'=>'〖','︘'=>'〗','︙'=>'...','︰'=>'..','︱'=>'—','︲'=>'–','︳'=>'_','︴'=>'_','︵'=>'(','︶'=>')','︷'=>'{','︸'=>'}','︹'=>'〔','︺'=>'〕','︻'=>'ã€','︼'=>'】','︽'=>'《','︾'=>'》','︿'=>'〈','ï¹€'=>'〉','ï¹'=>'「','﹂'=>'ã€','﹃'=>'『','﹄'=>'ã€','﹇'=>'[','﹈'=>']','﹉'=>' Ì…','﹊'=>' Ì…','﹋'=>' Ì…','﹌'=>' Ì…','ï¹'=>'_','﹎'=>'_','ï¹'=>'_','ï¹'=>',','﹑'=>'ã€','ï¹’'=>'.','ï¹”'=>';','﹕'=>':','ï¹–'=>'?','ï¹—'=>'!','﹘'=>'—','ï¹™'=>'(','﹚'=>')','ï¹›'=>'{','﹜'=>'}','ï¹'=>'〔','﹞'=>'〕','﹟'=>'#','ï¹ '=>'&','﹡'=>'*','ï¹¢'=>'+','ï¹£'=>'-','﹤'=>'<','ï¹¥'=>'>','﹦'=>'=','﹨'=>'\\','﹩'=>'$','﹪'=>'%','﹫'=>'@','ï¹°'=>' Ù‹','ï¹±'=>'ـً','ï¹²'=>' ÙŒ','ï¹´'=>' Ù','ï¹¶'=>' ÙŽ','ï¹·'=>'Ù€ÙŽ','ﹸ'=>' Ù','ï¹¹'=>'Ù€Ù','ﹺ'=>' Ù','ï¹»'=>'Ù€Ù','ï¹¼'=>' Ù‘','ï¹½'=>'ـّ','ï¹¾'=>' Ù’','ﹿ'=>'ـْ','ﺀ'=>'Ø¡','ïº'=>'آ','ﺂ'=>'آ','ﺃ'=>'أ','ﺄ'=>'أ','ﺅ'=>'ÙˆÙ”','ﺆ'=>'ÙˆÙ”','ﺇ'=>'إ','ﺈ'=>'إ','ﺉ'=>'ÙŠÙ”','ﺊ'=>'ÙŠÙ”','ﺋ'=>'ÙŠÙ”','ﺌ'=>'ÙŠÙ”','ïº'=>'ا','ﺎ'=>'ا','ïº'=>'ب','ïº'=>'ب','ﺑ'=>'ب','ﺒ'=>'ب','ﺓ'=>'Ø©','ﺔ'=>'Ø©','ﺕ'=>'ت','ﺖ'=>'ت','ﺗ'=>'ت','ﺘ'=>'ت','ﺙ'=>'Ø«','ﺚ'=>'Ø«','ﺛ'=>'Ø«','ﺜ'=>'Ø«','ïº'=>'ج','ﺞ'=>'ج','ﺟ'=>'ج','ïº '=>'ج','ﺡ'=>'Ø','ﺢ'=>'Ø','ﺣ'=>'Ø','ﺤ'=>'Ø','ﺥ'=>'Ø®','ﺦ'=>'Ø®','ﺧ'=>'Ø®','ﺨ'=>'Ø®','ﺩ'=>'د','ﺪ'=>'د','ﺫ'=>'ذ','ﺬ'=>'ذ','ïº'=>'ر','ﺮ'=>'ر','ﺯ'=>'ز','ﺰ'=>'ز','ﺱ'=>'س','ﺲ'=>'س','ﺳ'=>'س','ﺴ'=>'س','ﺵ'=>'Ø´','ﺶ'=>'Ø´','ﺷ'=>'Ø´','ﺸ'=>'Ø´','ﺹ'=>'ص','ﺺ'=>'ص','ﺻ'=>'ص','ﺼ'=>'ص','ﺽ'=>'ض','ﺾ'=>'ض','ﺿ'=>'ض','ﻀ'=>'ض','ï»'=>'Ø·','ﻂ'=>'Ø·','ﻃ'=>'Ø·','ﻄ'=>'Ø·','ï»…'=>'ظ','ﻆ'=>'ظ','ﻇ'=>'ظ','ﻈ'=>'ظ','ﻉ'=>'ع','ﻊ'=>'ع','ﻋ'=>'ع','ﻌ'=>'ع','ï»'=>'غ','ﻎ'=>'غ','ï»'=>'غ','ï»'=>'غ','ﻑ'=>'Ù','ï»’'=>'Ù','ﻓ'=>'Ù','ï»”'=>'Ù','ﻕ'=>'Ù‚','ï»–'=>'Ù‚','ï»—'=>'Ù‚','ﻘ'=>'Ù‚','ï»™'=>'Ùƒ','ﻚ'=>'Ùƒ','ï»›'=>'Ùƒ','ﻜ'=>'Ùƒ','ï»'=>'Ù„','ﻞ'=>'Ù„','ﻟ'=>'Ù„','ï» '=>'Ù„','ﻡ'=>'Ù…','ﻢ'=>'Ù…','ﻣ'=>'Ù…','ﻤ'=>'Ù…','ﻥ'=>'Ù†','ﻦ'=>'Ù†','ï»§'=>'Ù†','ﻨ'=>'Ù†','ﻩ'=>'Ù‡','ﻪ'=>'Ù‡','ﻫ'=>'Ù‡','ﻬ'=>'Ù‡','ï»'=>'Ùˆ','ï»®'=>'Ùˆ','ﻯ'=>'Ù‰','ï»°'=>'Ù‰','ï»±'=>'ÙŠ','ﻲ'=>'ÙŠ','ﻳ'=>'ÙŠ','ï»´'=>'ÙŠ','ﻵ'=>'لآ','ï»¶'=>'لآ','ï»·'=>'لأ','ﻸ'=>'لأ','ﻹ'=>'لإ','ﻺ'=>'لإ','ï»»'=>'لا','ﻼ'=>'لا','ï¼'=>'!','"'=>'"','#'=>'#','$'=>'$','ï¼…'=>'%','&'=>'&','''=>'\'','('=>'(',')'=>')','*'=>'*','+'=>'+',','=>',','ï¼'=>'-','.'=>'.','ï¼'=>'/','ï¼'=>'0','1'=>'1','ï¼’'=>'2','3'=>'3','ï¼”'=>'4','5'=>'5','ï¼–'=>'6','ï¼—'=>'7','8'=>'8','ï¼™'=>'9',':'=>':','ï¼›'=>';','<'=>'<','ï¼'=>'=','>'=>'>','?'=>'?','ï¼ '=>'@','A'=>'A','ï¼¢'=>'B','ï¼£'=>'C','D'=>'D','ï¼¥'=>'E','F'=>'F','ï¼§'=>'G','H'=>'H','I'=>'I','J'=>'J','K'=>'K','L'=>'L','ï¼'=>'M','ï¼®'=>'N','O'=>'O','ï¼°'=>'P','ï¼±'=>'Q','ï¼²'=>'R','ï¼³'=>'S','ï¼´'=>'T','ï¼µ'=>'U','ï¼¶'=>'V','ï¼·'=>'W','X'=>'X','ï¼¹'=>'Y','Z'=>'Z','ï¼»'=>'[','ï¼¼'=>'\\','ï¼½'=>']','ï¼¾'=>'^','_'=>'_','ï½€'=>'`','ï½'=>'a','b'=>'b','c'=>'c','d'=>'d','ï½…'=>'e','f'=>'f','g'=>'g','h'=>'h','i'=>'i','j'=>'j','k'=>'k','l'=>'l','ï½'=>'m','n'=>'n','ï½'=>'o','ï½'=>'p','q'=>'q','ï½’'=>'r','s'=>'s','ï½”'=>'t','u'=>'u','ï½–'=>'v','ï½—'=>'w','x'=>'x','ï½™'=>'y','z'=>'z','ï½›'=>'{','|'=>'|','ï½'=>'}','~'=>'~','⦅'=>'⦅','ï½ '=>'⦆','。'=>'。','ï½¢'=>'「','ï½£'=>'ã€','、'=>'ã€','ï½¥'=>'・','ヲ'=>'ヲ','ï½§'=>'ã‚¡','ィ'=>'ã‚£','ゥ'=>'ã‚¥','ェ'=>'ã‚§','ォ'=>'ã‚©','ャ'=>'ャ','ï½'=>'ュ','ï½®'=>'ョ','ッ'=>'ッ','ï½°'=>'ー','ï½±'=>'ã‚¢','ï½²'=>'イ','ï½³'=>'ウ','ï½´'=>'エ','ï½µ'=>'オ','ï½¶'=>'ã‚«','ï½·'=>'ã‚','ク'=>'ク','ï½¹'=>'ケ','コ'=>'コ','ï½»'=>'サ','ï½¼'=>'ã‚·','ï½½'=>'ス','ï½¾'=>'ã‚»','ソ'=>'ソ','ï¾€'=>'ã‚¿','ï¾'=>'ãƒ','ツ'=>'ツ','テ'=>'テ','ト'=>'ト','ï¾…'=>'ナ','ニ'=>'ニ','ヌ'=>'ヌ','ネ'=>'ãƒ','ノ'=>'ノ','ハ'=>'ãƒ','ヒ'=>'ヒ','フ'=>'フ','ï¾'=>'ヘ','ホ'=>'ホ','ï¾'=>'マ','ï¾'=>'ミ','ム'=>'ム','ï¾’'=>'メ','モ'=>'モ','ï¾”'=>'ヤ','ユ'=>'ユ','ï¾–'=>'ヨ','ï¾—'=>'ラ','リ'=>'リ','ï¾™'=>'ル','レ'=>'レ','ï¾›'=>'ãƒ','ワ'=>'ワ','ï¾'=>'ン','゙'=>'ã‚™','゚'=>'゚','ï¾ '=>'á… ','ᄀ'=>'á„€','ï¾¢'=>'á„','ï¾£'=>'ᆪ','ᄂ'=>'á„‚','ï¾¥'=>'ᆬ','ᆭ'=>'á†','ï¾§'=>'ᄃ','ᄄ'=>'á„„','ᄅ'=>'á„…','ᆰ'=>'ᆰ','ᆱ'=>'ᆱ','ᆲ'=>'ᆲ','ï¾'=>'ᆳ','ï¾®'=>'ᆴ','ᆵ'=>'ᆵ','ï¾°'=>'ᄚ','ï¾±'=>'ᄆ','ï¾²'=>'ᄇ','ï¾³'=>'ᄈ','ï¾´'=>'á„¡','ï¾µ'=>'ᄉ','ï¾¶'=>'ᄊ','ï¾·'=>'á„‹','ᄌ'=>'ᄌ','ï¾¹'=>'á„','ᄎ'=>'ᄎ','ï¾»'=>'á„','ï¾¼'=>'á„','ï¾½'=>'á„‘','ï¾¾'=>'á„’','ï¿‚'=>'á…¡','ᅢ'=>'á…¢','ï¿„'=>'á…£','ï¿…'=>'á…¤','ᅥ'=>'á…¥','ᅦ'=>'á…¦','ᅧ'=>'á…§','ï¿‹'=>'á…¨','ᅩ'=>'á…©','ï¿'=>'á…ª','ᅫ'=>'á…«','ï¿'=>'á…¬','ï¿’'=>'á…','ï¿“'=>'á…®','ï¿”'=>'á…¯','ï¿•'=>'á…°','ï¿–'=>'á…±','ï¿—'=>'á…²','ᅳ'=>'á…³','ï¿›'=>'á…´','ᅵ'=>'á…µ','ï¿ '=>'¢','ï¿¡'=>'£','ï¿¢'=>'¬','ï¿£'=>' Ì„','¦'=>'¦','ï¿¥'=>'Â¥','₩'=>'â‚©','│'=>'│','ï¿©'=>'â†','↑'=>'↑','ï¿«'=>'→','↓'=>'↓','ï¿'=>'â– ','ï¿®'=>'â—‹','ð…ž'=>'ð…—ð…¥','ð…Ÿ'=>'ð…˜ð…¥','ð… '=>'ð…˜ð…¥ð…®','ð…¡'=>'ð…˜ð…¥ð…¯','ð…¢'=>'ð…˜ð…¥ð…°','ð…£'=>'ð…˜ð…¥ð…±','ð…¤'=>'ð…˜ð…¥ð…²','ð†»'=>'ð†¹ð…¥','ð†¼'=>'ð†ºð…¥','ð†½'=>'ð†¹ð…¥ð…®','ð†¾'=>'ð†ºð…¥ð…®','ð†¿'=>'ð†¹ð…¥ð…¯','ð‡€'=>'ð†ºð…¥ð…¯','ð€'=>'A','ð'=>'B','ð‚'=>'C','ðƒ'=>'D','ð„'=>'E','ð…'=>'F','ð†'=>'G','ð‡'=>'H','ðˆ'=>'I','ð‰'=>'J','ðŠ'=>'K','ð‹'=>'L','ðŒ'=>'M','ð'=>'N','ðŽ'=>'O','ð'=>'P','ð'=>'Q','ð‘'=>'R','ð’'=>'S','ð“'=>'T','ð”'=>'U','ð•'=>'V','ð–'=>'W','ð—'=>'X','ð˜'=>'Y','ð™'=>'Z','ðš'=>'a','ð›'=>'b','ðœ'=>'c','ð'=>'d','ðž'=>'e','ðŸ'=>'f','ð '=>'g','ð¡'=>'h','ð¢'=>'i','ð£'=>'j','ð¤'=>'k','ð¥'=>'l','ð¦'=>'m','ð§'=>'n','ð¨'=>'o','ð©'=>'p','ðª'=>'q','ð«'=>'r','ð¬'=>'s','ð'=>'t','ð®'=>'u','ð¯'=>'v','ð°'=>'w','ð±'=>'x','ð²'=>'y','ð³'=>'z','ð´'=>'A','ðµ'=>'B','ð¶'=>'C','ð·'=>'D','ð¸'=>'E','ð¹'=>'F','ðº'=>'G','ð»'=>'H','ð¼'=>'I','ð½'=>'J','ð¾'=>'K','ð¿'=>'L','ð‘€'=>'M','ð‘'=>'N','ð‘‚'=>'O','ð‘ƒ'=>'P','ð‘„'=>'Q','ð‘…'=>'R','ð‘†'=>'S','ð‘‡'=>'T','ð‘ˆ'=>'U','ð‘‰'=>'V','ð‘Š'=>'W','ð‘‹'=>'X','ð‘Œ'=>'Y','ð‘'=>'Z','ð‘Ž'=>'a','ð‘'=>'b','ð‘'=>'c','ð‘‘'=>'d','ð‘’'=>'e','ð‘“'=>'f','ð‘”'=>'g','ð‘–'=>'i','ð‘—'=>'j','ð‘˜'=>'k','ð‘™'=>'l','ð‘š'=>'m','ð‘›'=>'n','ð‘œ'=>'o','ð‘'=>'p','ð‘ž'=>'q','ð‘Ÿ'=>'r','ð‘ '=>'s','ð‘¡'=>'t','ð‘¢'=>'u','ð‘£'=>'v','ð‘¤'=>'w','ð‘¥'=>'x','ð‘¦'=>'y','ð‘§'=>'z','ð‘¨'=>'A','ð‘©'=>'B','ð‘ª'=>'C','ð‘«'=>'D','ð‘¬'=>'E','ð‘'=>'F','ð‘®'=>'G','ð‘¯'=>'H','ð‘°'=>'I','ð‘±'=>'J','ð‘²'=>'K','ð‘³'=>'L','ð‘´'=>'M','ð‘µ'=>'N','ð‘¶'=>'O','ð‘·'=>'P','ð‘¸'=>'Q','ð‘¹'=>'R','ð‘º'=>'S','ð‘»'=>'T','ð‘¼'=>'U','ð‘½'=>'V','ð‘¾'=>'W','ð‘¿'=>'X','ð’€'=>'Y','ð’'=>'Z','ð’‚'=>'a','ð’ƒ'=>'b','ð’„'=>'c','ð’…'=>'d','ð’†'=>'e','ð’‡'=>'f','ð’ˆ'=>'g','ð’‰'=>'h','ð’Š'=>'i','ð’‹'=>'j','ð’Œ'=>'k','ð’'=>'l','ð’Ž'=>'m','ð’'=>'n','ð’'=>'o','ð’‘'=>'p','ð’’'=>'q','ð’“'=>'r','ð’”'=>'s','ð’•'=>'t','ð’–'=>'u','ð’—'=>'v','ð’˜'=>'w','ð’™'=>'x','ð’š'=>'y','ð’›'=>'z','ð’œ'=>'A','ð’ž'=>'C','ð’Ÿ'=>'D','ð’¢'=>'G','ð’¥'=>'J','ð’¦'=>'K','ð’©'=>'N','ð’ª'=>'O','ð’«'=>'P','ð’¬'=>'Q','ð’®'=>'S','ð’¯'=>'T','ð’°'=>'U','ð’±'=>'V','ð’²'=>'W','ð’³'=>'X','ð’´'=>'Y','ð’µ'=>'Z','ð’¶'=>'a','ð’·'=>'b','ð’¸'=>'c','ð’¹'=>'d','ð’»'=>'f','ð’½'=>'h','ð’¾'=>'i','ð’¿'=>'j','ð“€'=>'k','ð“'=>'l','ð“‚'=>'m','ð“ƒ'=>'n','ð“…'=>'p','ð“†'=>'q','ð“‡'=>'r','ð“ˆ'=>'s','ð“‰'=>'t','ð“Š'=>'u','ð“‹'=>'v','ð“Œ'=>'w','ð“'=>'x','ð“Ž'=>'y','ð“'=>'z','ð“'=>'A','ð“‘'=>'B','ð“’'=>'C','ð““'=>'D','ð“”'=>'E','ð“•'=>'F','ð“–'=>'G','ð“—'=>'H','ð“˜'=>'I','ð“™'=>'J','ð“š'=>'K','ð“›'=>'L','ð“œ'=>'M','ð“'=>'N','ð“ž'=>'O','ð“Ÿ'=>'P','ð“ '=>'Q','ð“¡'=>'R','ð“¢'=>'S','ð“£'=>'T','ð“¤'=>'U','ð“¥'=>'V','ð“¦'=>'W','ð“§'=>'X','ð“¨'=>'Y','ð“©'=>'Z','ð“ª'=>'a','ð“«'=>'b','ð“¬'=>'c','ð“'=>'d','ð“®'=>'e','ð“¯'=>'f','ð“°'=>'g','ð“±'=>'h','ð“²'=>'i','ð“³'=>'j','ð“´'=>'k','ð“µ'=>'l','ð“¶'=>'m','ð“·'=>'n','ð“¸'=>'o','ð“¹'=>'p','ð“º'=>'q','ð“»'=>'r','ð“¼'=>'s','ð“½'=>'t','ð“¾'=>'u','ð“¿'=>'v','ð”€'=>'w','ð”'=>'x','ð”‚'=>'y','ð”ƒ'=>'z','ð”„'=>'A','ð”…'=>'B','ð”‡'=>'D','ð”ˆ'=>'E','ð”‰'=>'F','ð”Š'=>'G','ð”'=>'J','ð”Ž'=>'K','ð”'=>'L','ð”'=>'M','ð”‘'=>'N','ð”’'=>'O','ð”“'=>'P','ð””'=>'Q','ð”–'=>'S','ð”—'=>'T','ð”˜'=>'U','ð”™'=>'V','ð”š'=>'W','ð”›'=>'X','ð”œ'=>'Y','ð”ž'=>'a','ð”Ÿ'=>'b','ð” '=>'c','ð”¡'=>'d','ð”¢'=>'e','ð”£'=>'f','ð”¤'=>'g','ð”¥'=>'h','ð”¦'=>'i','ð”§'=>'j','ð”¨'=>'k','ð”©'=>'l','ð”ª'=>'m','ð”«'=>'n','ð”¬'=>'o','ð”'=>'p','ð”®'=>'q','ð”¯'=>'r','ð”°'=>'s','ð”±'=>'t','ð”²'=>'u','ð”³'=>'v','ð”´'=>'w','ð”µ'=>'x','ð”¶'=>'y','ð”·'=>'z','ð”¸'=>'A','ð”¹'=>'B','ð”»'=>'D','ð”¼'=>'E','ð”½'=>'F','ð”¾'=>'G','ð•€'=>'I','ð•'=>'J','ð•‚'=>'K','ð•ƒ'=>'L','ð•„'=>'M','ð•†'=>'O','ð•Š'=>'S','ð•‹'=>'T','ð•Œ'=>'U','ð•'=>'V','ð•Ž'=>'W','ð•'=>'X','ð•'=>'Y','ð•’'=>'a','ð•“'=>'b','ð•”'=>'c','ð••'=>'d','ð•–'=>'e','ð•—'=>'f','ð•˜'=>'g','ð•™'=>'h','ð•š'=>'i','ð•›'=>'j','ð•œ'=>'k','ð•'=>'l','ð•ž'=>'m','ð•Ÿ'=>'n','ð• '=>'o','ð•¡'=>'p','ð•¢'=>'q','ð•£'=>'r','ð•¤'=>'s','ð•¥'=>'t','ð•¦'=>'u','ð•§'=>'v','ð•¨'=>'w','ð•©'=>'x','ð•ª'=>'y','ð•«'=>'z','ð•¬'=>'A','ð•'=>'B','ð•®'=>'C','ð•¯'=>'D','ð•°'=>'E','ð•±'=>'F','ð•²'=>'G','ð•³'=>'H','ð•´'=>'I','ð•µ'=>'J','ð•¶'=>'K','ð•·'=>'L','ð•¸'=>'M','ð•¹'=>'N','ð•º'=>'O','ð•»'=>'P','ð•¼'=>'Q','ð•½'=>'R','ð•¾'=>'S','ð•¿'=>'T','ð–€'=>'U','ð–'=>'V','ð–‚'=>'W','ð–ƒ'=>'X','ð–„'=>'Y','ð–…'=>'Z','ð–†'=>'a','ð–‡'=>'b','ð–ˆ'=>'c','ð–‰'=>'d','ð–Š'=>'e','ð–‹'=>'f','ð–Œ'=>'g','ð–'=>'h','ð–Ž'=>'i','ð–'=>'j','ð–'=>'k','ð–‘'=>'l','ð–’'=>'m','ð–“'=>'n','ð–”'=>'o','ð–•'=>'p','ð––'=>'q','ð–—'=>'r','ð–˜'=>'s','ð–™'=>'t','ð–š'=>'u','ð–›'=>'v','ð–œ'=>'w','ð–'=>'x','ð–ž'=>'y','ð–Ÿ'=>'z','ð– '=>'A','ð–¡'=>'B','ð–¢'=>'C','ð–£'=>'D','ð–¤'=>'E','ð–¥'=>'F','ð–¦'=>'G','ð–§'=>'H','ð–¨'=>'I','ð–©'=>'J','ð–ª'=>'K','ð–«'=>'L','ð–¬'=>'M','ð–'=>'N','ð–®'=>'O','ð–¯'=>'P','ð–°'=>'Q','ð–±'=>'R','ð–²'=>'S','ð–³'=>'T','ð–´'=>'U','ð–µ'=>'V','ð–¶'=>'W','ð–·'=>'X','ð–¸'=>'Y','ð–¹'=>'Z','ð–º'=>'a','ð–»'=>'b','ð–¼'=>'c','ð–½'=>'d','ð–¾'=>'e','ð–¿'=>'f','ð—€'=>'g','ð—'=>'h','ð—‚'=>'i','ð—ƒ'=>'j','ð—„'=>'k','ð—…'=>'l','ð—†'=>'m','ð—‡'=>'n','ð—ˆ'=>'o','ð—‰'=>'p','ð—Š'=>'q','ð—‹'=>'r','ð—Œ'=>'s','ð—'=>'t','ð—Ž'=>'u','ð—'=>'v','ð—'=>'w','ð—‘'=>'x','ð—’'=>'y','ð—“'=>'z','ð—”'=>'A','ð—•'=>'B','ð—–'=>'C','ð——'=>'D','ð—˜'=>'E','ð—™'=>'F','ð—š'=>'G','ð—›'=>'H','ð—œ'=>'I','ð—'=>'J','ð—ž'=>'K','ð—Ÿ'=>'L','ð— '=>'M','ð—¡'=>'N','ð—¢'=>'O','ð—£'=>'P','ð—¤'=>'Q','ð—¥'=>'R','ð—¦'=>'S','ð—§'=>'T','ð—¨'=>'U','ð—©'=>'V','ð—ª'=>'W','ð—«'=>'X','ð—¬'=>'Y','ð—'=>'Z','ð—®'=>'a','ð—¯'=>'b','ð—°'=>'c','ð—±'=>'d','ð—²'=>'e','ð—³'=>'f','ð—´'=>'g','ð—µ'=>'h','ð—¶'=>'i','ð—·'=>'j','ð—¸'=>'k','ð—¹'=>'l','ð—º'=>'m','ð—»'=>'n','ð—¼'=>'o','ð—½'=>'p','ð—¾'=>'q','ð—¿'=>'r','ð˜€'=>'s','ð˜'=>'t','ð˜‚'=>'u','ð˜ƒ'=>'v','ð˜„'=>'w','ð˜…'=>'x','ð˜†'=>'y','ð˜‡'=>'z','ð˜ˆ'=>'A','ð˜‰'=>'B','ð˜Š'=>'C','ð˜‹'=>'D','ð˜Œ'=>'E','ð˜'=>'F','ð˜Ž'=>'G','ð˜'=>'H','ð˜'=>'I','ð˜‘'=>'J','ð˜’'=>'K','ð˜“'=>'L','ð˜”'=>'M','ð˜•'=>'N','ð˜–'=>'O','ð˜—'=>'P','ð˜˜'=>'Q','ð˜™'=>'R','ð˜š'=>'S','ð˜›'=>'T','ð˜œ'=>'U','ð˜'=>'V','ð˜ž'=>'W','ð˜Ÿ'=>'X','ð˜ '=>'Y','ð˜¡'=>'Z','ð˜¢'=>'a','ð˜£'=>'b','ð˜¤'=>'c','ð˜¥'=>'d','ð˜¦'=>'e','ð˜§'=>'f','ð˜¨'=>'g','ð˜©'=>'h','ð˜ª'=>'i','ð˜«'=>'j','ð˜¬'=>'k','ð˜'=>'l','ð˜®'=>'m','ð˜¯'=>'n','ð˜°'=>'o','ð˜±'=>'p','ð˜²'=>'q','ð˜³'=>'r','ð˜´'=>'s','ð˜µ'=>'t','ð˜¶'=>'u','ð˜·'=>'v','ð˜¸'=>'w','ð˜¹'=>'x','ð˜º'=>'y','ð˜»'=>'z','ð˜¼'=>'A','ð˜½'=>'B','ð˜¾'=>'C','ð˜¿'=>'D','ð™€'=>'E','ð™'=>'F','ð™‚'=>'G','ð™ƒ'=>'H','ð™„'=>'I','ð™…'=>'J','ð™†'=>'K','ð™‡'=>'L','ð™ˆ'=>'M','ð™‰'=>'N','ð™Š'=>'O','ð™‹'=>'P','ð™Œ'=>'Q','ð™'=>'R','ð™Ž'=>'S','ð™'=>'T','ð™'=>'U','ð™‘'=>'V','ð™’'=>'W','ð™“'=>'X','ð™”'=>'Y','ð™•'=>'Z','ð™–'=>'a','ð™—'=>'b','ð™˜'=>'c','ð™™'=>'d','ð™š'=>'e','ð™›'=>'f','ð™œ'=>'g','ð™'=>'h','ð™ž'=>'i','ð™Ÿ'=>'j','ð™ '=>'k','ð™¡'=>'l','ð™¢'=>'m','ð™£'=>'n','ð™¤'=>'o','ð™¥'=>'p','ð™¦'=>'q','ð™§'=>'r','ð™¨'=>'s','ð™©'=>'t','ð™ª'=>'u','ð™«'=>'v','ð™¬'=>'w','ð™'=>'x','ð™®'=>'y','ð™¯'=>'z','ð™°'=>'A','ð™±'=>'B','ð™²'=>'C','ð™³'=>'D','ð™´'=>'E','ð™µ'=>'F','ð™¶'=>'G','ð™·'=>'H','ð™¸'=>'I','ð™¹'=>'J','ð™º'=>'K','ð™»'=>'L','ð™¼'=>'M','ð™½'=>'N','ð™¾'=>'O','ð™¿'=>'P','ðš€'=>'Q','ðš'=>'R','ðš‚'=>'S','ðšƒ'=>'T','ðš„'=>'U','ðš…'=>'V','ðš†'=>'W','ðš‡'=>'X','ðšˆ'=>'Y','ðš‰'=>'Z','ðšŠ'=>'a','ðš‹'=>'b','ðšŒ'=>'c','ðš'=>'d','ðšŽ'=>'e','ðš'=>'f','ðš'=>'g','ðš‘'=>'h','ðš’'=>'i','ðš“'=>'j','ðš”'=>'k','ðš•'=>'l','ðš–'=>'m','ðš—'=>'n','ðš˜'=>'o','ðš™'=>'p','ðšš'=>'q','ðš›'=>'r','ðšœ'=>'s','ðš'=>'t','ðšž'=>'u','ðšŸ'=>'v','ðš '=>'w','ðš¡'=>'x','ðš¢'=>'y','ðš£'=>'z','ðš¤'=>'ı','ðš¥'=>'È·','ðš¨'=>'Α','ðš©'=>'Î’','ðšª'=>'Γ','ðš«'=>'Δ','ðš¬'=>'Ε','ðš'=>'Ζ','ðš®'=>'Η','ðš¯'=>'Θ','ðš°'=>'Ι','ðš±'=>'Κ','ðš²'=>'Λ','ðš³'=>'Μ','ðš´'=>'Î','ðšµ'=>'Ξ','ðš¶'=>'Ο','ðš·'=>'Î ','ðš¸'=>'Ρ','ðš¹'=>'Θ','ðšº'=>'Σ','ðš»'=>'Τ','ðš¼'=>'Î¥','ðš½'=>'Φ','ðš¾'=>'Χ','ðš¿'=>'Ψ','ð›€'=>'Ω','ð›'=>'∇','ð›‚'=>'α','ð›ƒ'=>'β','ð›„'=>'γ','ð›…'=>'δ','ð›†'=>'ε','ð›‡'=>'ζ','ð›ˆ'=>'η','ð›‰'=>'θ','ð›Š'=>'ι','ð›‹'=>'κ','ð›Œ'=>'λ','ð›'=>'μ','ð›Ž'=>'ν','ð›'=>'ξ','ð›'=>'ο','ð›‘'=>'Ï€','ð›’'=>'Ï','ð›“'=>'Ï‚','ð›”'=>'σ','ð›•'=>'Ï„','ð›–'=>'Ï…','ð›—'=>'φ','ð›˜'=>'χ','ð›™'=>'ψ','ð›š'=>'ω','ð››'=>'∂','ð›œ'=>'ε','ð›'=>'θ','ð›ž'=>'κ','ð›Ÿ'=>'φ','ð› '=>'Ï','ð›¡'=>'Ï€','ð›¢'=>'Α','ð›£'=>'Î’','ð›¤'=>'Γ','ð›¥'=>'Δ','ð›¦'=>'Ε','ð›§'=>'Ζ','ð›¨'=>'Η','ð›©'=>'Θ','ð›ª'=>'Ι','ð›«'=>'Κ','ð›¬'=>'Λ','ð›'=>'Μ','ð›®'=>'Î','ð›¯'=>'Ξ','ð›°'=>'Ο','ð›±'=>'Î ','ð›²'=>'Ρ','ð›³'=>'Θ','ð›´'=>'Σ','ð›µ'=>'Τ','ð›¶'=>'Î¥','ð›·'=>'Φ','ð›¸'=>'Χ','ð›¹'=>'Ψ','ð›º'=>'Ω','ð›»'=>'∇','ð›¼'=>'α','ð›½'=>'β','ð›¾'=>'γ','ð›¿'=>'δ','ðœ€'=>'ε','ðœ'=>'ζ','ðœ‚'=>'η','ðœƒ'=>'θ','ðœ„'=>'ι','ðœ…'=>'κ','ðœ†'=>'λ','ðœ‡'=>'μ','ðœˆ'=>'ν','ðœ‰'=>'ξ','ðœŠ'=>'ο','ðœ‹'=>'Ï€','ðœŒ'=>'Ï','ðœ'=>'Ï‚','ðœŽ'=>'σ','ðœ'=>'Ï„','ðœ'=>'Ï…','ðœ‘'=>'φ','ðœ’'=>'χ','ðœ“'=>'ψ','ðœ”'=>'ω','ðœ•'=>'∂','ðœ–'=>'ε','ðœ—'=>'θ','ðœ˜'=>'κ','ðœ™'=>'φ','ðœš'=>'Ï','ðœ›'=>'Ï€','ðœœ'=>'Α','ðœ'=>'Î’','ðœž'=>'Γ','ðœŸ'=>'Δ','ðœ '=>'Ε','ðœ¡'=>'Ζ','ðœ¢'=>'Η','ðœ£'=>'Θ','ðœ¤'=>'Ι','ðœ¥'=>'Κ','ðœ¦'=>'Λ','ðœ§'=>'Μ','ðœ¨'=>'Î','ðœ©'=>'Ξ','ðœª'=>'Ο','ðœ«'=>'Î ','ðœ¬'=>'Ρ','ðœ'=>'Θ','ðœ®'=>'Σ','ðœ¯'=>'Τ','ðœ°'=>'Î¥','ðœ±'=>'Φ','ðœ²'=>'Χ','ðœ³'=>'Ψ','ðœ´'=>'Ω','ðœµ'=>'∇','ðœ¶'=>'α','ðœ·'=>'β','ðœ¸'=>'γ','ðœ¹'=>'δ','ðœº'=>'ε','ðœ»'=>'ζ','ðœ¼'=>'η','ðœ½'=>'θ','ðœ¾'=>'ι','ðœ¿'=>'κ','ð€'=>'λ','ð'=>'μ','ð‚'=>'ν','ðƒ'=>'ξ','ð„'=>'ο','ð…'=>'Ï€','ð†'=>'Ï','ð‡'=>'Ï‚','ðˆ'=>'σ','ð‰'=>'Ï„','ðŠ'=>'Ï…','ð‹'=>'φ','ðŒ'=>'χ','ð'=>'ψ','ðŽ'=>'ω','ð'=>'∂','ð'=>'ε','ð‘'=>'θ','ð’'=>'κ','ð“'=>'φ','ð”'=>'Ï','ð•'=>'Ï€','ð–'=>'Α','ð—'=>'Î’','ð˜'=>'Γ','ð™'=>'Δ','ðš'=>'Ε','ð›'=>'Ζ','ðœ'=>'Η','ð'=>'Θ','ðž'=>'Ι','ðŸ'=>'Κ','ð '=>'Λ','ð¡'=>'Μ','ð¢'=>'Î','ð£'=>'Ξ','ð¤'=>'Ο','ð¥'=>'Î ','ð¦'=>'Ρ','ð§'=>'Θ','ð¨'=>'Σ','ð©'=>'Τ','ðª'=>'Î¥','ð«'=>'Φ','ð¬'=>'Χ','ð'=>'Ψ','ð®'=>'Ω','ð¯'=>'∇','ð°'=>'α','ð±'=>'β','ð²'=>'γ','ð³'=>'δ','ð´'=>'ε','ðµ'=>'ζ','ð¶'=>'η','ð·'=>'θ','ð¸'=>'ι','ð¹'=>'κ','ðº'=>'λ','ð»'=>'μ','ð¼'=>'ν','ð½'=>'ξ','ð¾'=>'ο','ð¿'=>'Ï€','ðž€'=>'Ï','ðž'=>'Ï‚','ðž‚'=>'σ','ðžƒ'=>'Ï„','ðž„'=>'Ï…','ðž…'=>'φ','ðž†'=>'χ','ðž‡'=>'ψ','ðžˆ'=>'ω','ðž‰'=>'∂','ðžŠ'=>'ε','ðž‹'=>'θ','ðžŒ'=>'κ','ðž'=>'φ','ðžŽ'=>'Ï','ðž'=>'Ï€','ðž'=>'Α','ðž‘'=>'Î’','ðž’'=>'Γ','ðž“'=>'Δ','ðž”'=>'Ε','ðž•'=>'Ζ','ðž–'=>'Η','ðž—'=>'Θ','ðž˜'=>'Ι','ðž™'=>'Κ','ðžš'=>'Λ','ðž›'=>'Μ','ðžœ'=>'Î','ðž'=>'Ξ','ðžž'=>'Ο','ðžŸ'=>'Î ','ðž '=>'Ρ','ðž¡'=>'Θ','ðž¢'=>'Σ','ðž£'=>'Τ','ðž¤'=>'Î¥','ðž¥'=>'Φ','ðž¦'=>'Χ','ðž§'=>'Ψ','ðž¨'=>'Ω','ðž©'=>'∇','ðžª'=>'α','ðž«'=>'β','ðž¬'=>'γ','ðž'=>'δ','ðž®'=>'ε','ðž¯'=>'ζ','ðž°'=>'η','ðž±'=>'θ','ðž²'=>'ι','ðž³'=>'κ','ðž´'=>'λ','ðžµ'=>'μ','ðž¶'=>'ν','ðž·'=>'ξ','ðž¸'=>'ο','ðž¹'=>'Ï€','ðžº'=>'Ï','ðž»'=>'Ï‚','ðž¼'=>'σ','ðž½'=>'Ï„','ðž¾'=>'Ï…','ðž¿'=>'φ','ðŸ€'=>'χ','ðŸ'=>'ψ','ðŸ‚'=>'ω','ðŸƒ'=>'∂','ðŸ„'=>'ε','ðŸ…'=>'θ','ðŸ†'=>'κ','ðŸ‡'=>'φ','ðŸˆ'=>'Ï','ðŸ‰'=>'Ï€','ðŸŠ'=>'Ïœ','ðŸ‹'=>'Ï','ðŸŽ'=>'0','ðŸ'=>'1','ðŸ'=>'2','ðŸ‘'=>'3','ðŸ’'=>'4','ðŸ“'=>'5','ðŸ”'=>'6','ðŸ•'=>'7','ðŸ–'=>'8','ðŸ—'=>'9','ðŸ˜'=>'0','ðŸ™'=>'1','ðŸš'=>'2','ðŸ›'=>'3','ðŸœ'=>'4','ðŸ'=>'5','ðŸž'=>'6','ðŸŸ'=>'7','ðŸ '=>'8','ðŸ¡'=>'9','ðŸ¢'=>'0','ðŸ£'=>'1','ðŸ¤'=>'2','ðŸ¥'=>'3','ðŸ¦'=>'4','ðŸ§'=>'5','ðŸ¨'=>'6','ðŸ©'=>'7','ðŸª'=>'8','ðŸ«'=>'9','ðŸ¬'=>'0','ðŸ'=>'1','ðŸ®'=>'2','ðŸ¯'=>'3','ðŸ°'=>'4','ðŸ±'=>'5','ðŸ²'=>'6','ðŸ³'=>'7','ðŸ´'=>'8','ðŸµ'=>'9','ðŸ¶'=>'0','ðŸ·'=>'1','ðŸ¸'=>'2','ðŸ¹'=>'3','ðŸº'=>'4','ðŸ»'=>'5','ðŸ¼'=>'6','ðŸ½'=>'7','ðŸ¾'=>'8','ðŸ¿'=>'9','丽'=>'丽','ð¯ '=>'丸','乁'=>'ä¹','𠄢'=>'ð „¢','你'=>'ä½ ','侮'=>'ä¾®','侻'=>'ä¾»','倂'=>'倂','偺'=>'åº','備'=>'å‚™','僧'=>'僧','像'=>'åƒ','㒞'=>'ã’ž','ð¯ '=>'𠘺','免'=>'å…','ð¯ '=>'å…”','ð¯ '=>'å…¤','具'=>'å…·','𠔜'=>'𠔜','㒹'=>'ã’¹','內'=>'å…§','再'=>'å†','𠕋'=>'ð •‹','冗'=>'冗','冤'=>'冤','仌'=>'仌','冬'=>'冬','况'=>'况','𩇟'=>'𩇟','ð¯ '=>'凵','刃'=>'刃','㓟'=>'㓟','ð¯ '=>'刻','剆'=>'剆','割'=>'割','剷'=>'剷','㔕'=>'㔕','勇'=>'勇','勉'=>'勉','勤'=>'勤','勺'=>'勺','包'=>'包','匆'=>'匆','北'=>'北','卉'=>'å‰','ð¯ '=>'å‘','博'=>'åš','即'=>'å³','卽'=>'å½','卿'=>'å¿','卿'=>'å¿','卿'=>'å¿','𠨬'=>'𠨬','灰'=>'ç°','及'=>'åŠ','叟'=>'åŸ','𠭣'=>'ð £','叫'=>'å«','叱'=>'å±','吆'=>'å†','咞'=>'å’ž','吸'=>'å¸','呈'=>'呈','周'=>'周','咢'=>'å’¢','ð¯¡'=>'å“¶','唐'=>'å”','啓'=>'å•“','啣'=>'å•£','善'=>'å–„','善'=>'å–„','喙'=>'å–™','喫'=>'å–«','喳'=>'å–³','嗂'=>'å—‚','圖'=>'圖','嘆'=>'嘆','ð¯¡'=>'圗','噑'=>'噑','ð¯¡'=>'å™´','ð¯¡'=>'切','壮'=>'壮','城'=>'城','埴'=>'埴','堍'=>'å ','型'=>'åž‹','堲'=>'å ²','報'=>'å ±','墬'=>'墬','𡓤'=>'𡓤','売'=>'売','壷'=>'壷','夆'=>'夆','ð¯¡'=>'多','夢'=>'夢','奢'=>'奢','𡚨'=>'𡚨','𡛪'=>'𡛪','姬'=>'姬','娛'=>'娛','娧'=>'娧','姘'=>'姘','婦'=>'婦','㛮'=>'ã›®','㛼'=>'㛼','嬈'=>'嬈','嬾'=>'嬾','嬾'=>'嬾','𡧈'=>'𡧈','ð¯¡'=>'寃','寘'=>'寘','寧'=>'寧','寳'=>'寳','𡬘'=>'𡬘','寿'=>'寿','将'=>'å°†','当'=>'当','尢'=>'å°¢','㞁'=>'ãž','屠'=>'å± ','屮'=>'å±®','峀'=>'å³€','岍'=>'å²','𡷤'=>'ð¡·¤','嵃'=>'嵃','𡷦'=>'ð¡·¦','嵮'=>'åµ®','嵫'=>'嵫','嵼'=>'åµ¼','ð¯¢'=>'å·¡','巢'=>'å·¢','㠯'=>'ã ¯','巽'=>'å·½','帨'=>'帨','帽'=>'帽','幩'=>'幩','㡢'=>'ã¡¢','𢆃'=>'𢆃','㡼'=>'㡼','庰'=>'庰','庳'=>'庳','ð¯¢'=>'庶','廊'=>'廊','ð¯¢'=>'𪎒','ð¯¢'=>'廾','𢌱'=>'𢌱','𢌱'=>'𢌱','舁'=>'èˆ','弢'=>'å¼¢','弢'=>'å¼¢','㣇'=>'㣇','𣊸'=>'𣊸','𦇚'=>'𦇚','形'=>'å½¢','彫'=>'彫','㣣'=>'㣣','徚'=>'徚','ð¯¢'=>'å¿','志'=>'å¿—','忹'=>'忹','悁'=>'æ‚','㤺'=>'㤺','㤜'=>'㤜','悔'=>'æ‚”','𢛔'=>'𢛔','惇'=>'惇','慈'=>'æ…ˆ','慌'=>'æ…Œ','慎'=>'æ…Ž','慌'=>'æ…Œ','慺'=>'æ…º','憎'=>'憎','憲'=>'憲','ð¯¢'=>'憤','憯'=>'憯','懞'=>'懞','懲'=>'懲','懶'=>'懶','成'=>'æˆ','戛'=>'戛','扝'=>'æ‰','抱'=>'抱','拔'=>'æ‹”','捐'=>'æ','𢬌'=>'𢬌','挽'=>'挽','拼'=>'拼','捨'=>'æ¨','掃'=>'掃','揤'=>'æ¤','𢯱'=>'𢯱','搢'=>'æ¢','揅'=>'æ…','ð¯£'=>'掩','㨮'=>'㨮','摩'=>'æ‘©','摾'=>'摾','撝'=>'æ’','摷'=>'æ‘·','㩬'=>'㩬','敏'=>'æ•','敬'=>'敬','𣀊'=>'𣀊','旣'=>'æ—£','書'=>'書','ð¯£'=>'晉','㬙'=>'㬙','ð¯£'=>'æš‘','ð¯£'=>'㬈','㫤'=>'㫤','冒'=>'冒','冕'=>'冕','最'=>'最','暜'=>'æšœ','肭'=>'è‚','䏙'=>'ä™','朗'=>'朗','望'=>'望','朡'=>'朡','杞'=>'æž','杓'=>'æ“','ð¯£'=>'ð£ƒ','㭉'=>'ã‰','柺'=>'柺','枅'=>'æž…','桒'=>'æ¡’','梅'=>'梅','𣑭'=>'ð£‘','梎'=>'梎','栟'=>'æ Ÿ','椔'=>'椔','㮝'=>'ã®','楂'=>'楂','榣'=>'榣','槪'=>'槪','檨'=>'檨','𣚣'=>'𣚣','ð¯£'=>'æ«›','㰘'=>'ã°˜','次'=>'次','𣢧'=>'𣢧','歔'=>'æ”','㱎'=>'㱎','歲'=>'æ²','殟'=>'殟','殺'=>'殺','殻'=>'æ®»','𣪍'=>'ð£ª','𡴋'=>'ð¡´‹','𣫺'=>'𣫺','汎'=>'汎','𣲼'=>'𣲼','沿'=>'沿','泍'=>'æ³','汧'=>'æ±§','洖'=>'æ´–','派'=>'æ´¾','ð¯¤'=>'æµ·','流'=>'æµ','浩'=>'浩','浸'=>'浸','涅'=>'æ¶…','𣴞'=>'𣴞','洴'=>'æ´´','港'=>'港','湮'=>'æ¹®','㴳'=>'ã´³','滋'=>'滋','滇'=>'滇','ð¯¤'=>'𣻑','淹'=>'æ·¹','ð¯¤'=>'æ½®','ð¯¤'=>'𣽞','𣾎'=>'𣾎','濆'=>'濆','瀹'=>'瀹','瀞'=>'瀞','瀛'=>'瀛','㶖'=>'ã¶–','灊'=>'çŠ','災'=>'ç½','灷'=>'ç·','炭'=>'ç‚','𠔥'=>'𠔥','煅'=>'ç……','ð¯¤'=>'𤉣','熜'=>'熜','𤎫'=>'𤎫','爨'=>'爨','爵'=>'爵','牐'=>'ç‰','𤘈'=>'𤘈','犀'=>'犀','犕'=>'犕','𤜵'=>'𤜵','𤠔'=>'𤠔','獺'=>'çº','王'=>'王','㺬'=>'㺬','玥'=>'玥','㺸'=>'㺸','ð¯¤'=>'㺸','瑇'=>'瑇','瑜'=>'瑜','瑱'=>'瑱','璅'=>'ç’…','瓊'=>'瓊','㼛'=>'ã¼›','甤'=>'甤','𤰶'=>'𤰶','甾'=>'甾','𤲒'=>'𤲒','異'=>'ç•°','𢆟'=>'𢆟','瘐'=>'ç˜','𤾡'=>'𤾡','𤾸'=>'𤾸','𥁄'=>'ð¥„','㿼'=>'㿼','䀈'=>'䀈','直'=>'ç›´','ð¯¥'=>'𥃳','𥃲'=>'𥃲','𥄙'=>'𥄙','𥄳'=>'𥄳','眞'=>'眞','真'=>'真','真'=>'真','睊'=>'çŠ','䀹'=>'䀹','瞋'=>'çž‹','䁆'=>'ä†','䂖'=>'ä‚–','ð¯¥'=>'ð¥','硎'=>'硎','ð¯¥'=>'碌','ð¯¥'=>'磌','䃣'=>'䃣','𥘦'=>'𥘦','祖'=>'祖','𥚚'=>'𥚚','𥛅'=>'𥛅','福'=>'ç¦','秫'=>'ç§«','䄯'=>'䄯','穀'=>'ç©€','穊'=>'穊','穏'=>'ç©','𥥼'=>'𥥼','ð¯¥'=>'𥪧','𥪧'=>'𥪧','竮'=>'ç«®','䈂'=>'䈂','𥮫'=>'𥮫','篆'=>'篆','築'=>'築','䈧'=>'䈧','𥲀'=>'𥲀','糒'=>'ç³’','䊠'=>'äŠ ','糨'=>'糨','糣'=>'ç³£','紀'=>'ç´€','𥾆'=>'𥾆','絣'=>'çµ£','ð¯¥'=>'äŒ','緇'=>'ç·‡','縂'=>'縂','繅'=>'ç¹…','䌴'=>'䌴','𦈨'=>'𦈨','𦉇'=>'𦉇','䍙'=>'ä™','𦋙'=>'𦋙','罺'=>'罺','𦌾'=>'𦌾','羕'=>'羕','翺'=>'翺','者'=>'者','𦓚'=>'𦓚','𦔣'=>'𦔣','聠'=>'è ','𦖨'=>'𦖨','聰'=>'è°','𣍟'=>'ð£Ÿ','ð¯¦'=>'ä•','育'=>'育','脃'=>'脃','䐋'=>'ä‹','脾'=>'脾','媵'=>'媵','𦞧'=>'𦞧','𦞵'=>'𦞵','𣎓'=>'𣎓','𣎜'=>'𣎜','舁'=>'èˆ','舄'=>'舄','ð¯¦'=>'辞','䑫'=>'ä‘«','ð¯¦'=>'芑','ð¯¦'=>'芋','芝'=>'èŠ','劳'=>'劳','花'=>'花','芳'=>'芳','芽'=>'芽','苦'=>'苦','𦬼'=>'𦬼','若'=>'è‹¥','茝'=>'èŒ','荣'=>'è£','莭'=>'èŽ','茣'=>'茣','ð¯¦'=>'莽','菧'=>'è§','著'=>'è‘—','荓'=>'è“','菊'=>'èŠ','菌'=>'èŒ','菜'=>'èœ','𦰶'=>'𦰶','𦵫'=>'𦵫','𦳕'=>'𦳕','䔫'=>'䔫','蓱'=>'蓱','蓳'=>'蓳','蔖'=>'è”–','𧏊'=>'ð§Š','蕤'=>'蕤','ð¯¦'=>'𦼬','䕝'=>'ä•','䕡'=>'ä•¡','𦾱'=>'𦾱','𧃒'=>'𧃒','䕫'=>'ä•«','虐'=>'è™','虜'=>'虜','虧'=>'è™§','虩'=>'虩','蚩'=>'èš©','蚈'=>'蚈','蜎'=>'蜎','蛢'=>'蛢','蝹'=>'è¹','蜨'=>'蜨','蝫'=>'è«','螆'=>'螆','䗗'=>'ä——','蟡'=>'蟡','ð¯§'=>'è ','䗹'=>'ä—¹','衠'=>'è¡ ','衣'=>'è¡£','𧙧'=>'ð§™§','裗'=>'裗','裞'=>'裞','䘵'=>'䘵','裺'=>'裺','㒻'=>'ã’»','𧢮'=>'ð§¢®','𧥦'=>'𧥦','ð¯§'=>'äš¾','䛇'=>'䛇','ð¯§'=>'èª ','ð¯§'=>'è«','變'=>'變','豕'=>'豕','𧲨'=>'𧲨','貫'=>'貫','賁'=>'è³','贛'=>'è´›','起'=>'èµ·','𧼯'=>'𧼯','𠠄'=>'ð „','跋'=>'è·‹','趼'=>'è¶¼','跰'=>'è·°','ð¯§'=>'𠣞','軔'=>'è»”','輸'=>'輸','𨗒'=>'𨗒','𨗭'=>'ð¨—','邔'=>'é‚”','郱'=>'郱','鄑'=>'é„‘','𨜮'=>'𨜮','鄛'=>'é„›','鈸'=>'鈸','鋗'=>'é‹—','鋘'=>'鋘','鉼'=>'鉼','鏹'=>'é¹','鐕'=>'é•','ð¯§'=>'𨯺','開'=>'é–‹','䦕'=>'䦕','閷'=>'é–·','𨵷'=>'𨵷','䧦'=>'䧦','雃'=>'雃','嶲'=>'å¶²','霣'=>'霣','𩅅'=>'ð©……','𩈚'=>'𩈚','䩮'=>'ä©®','䩶'=>'ä©¶','韠'=>'éŸ ','𩐊'=>'ð©Š','䪲'=>'䪲','𩒖'=>'ð©’–','頋'=>'é ‹','頋'=>'é ‹','頩'=>'é ©','ð¯¨'=>'ð©–¶','飢'=>'飢','䬳'=>'䬳','餩'=>'餩','馧'=>'馧','駂'=>'é§‚','駾'=>'é§¾','䯎'=>'䯎','𩬰'=>'𩬰','鬒'=>'鬒','鱀'=>'é±€','鳽'=>'é³½','ð¯¨'=>'䳎','䳭'=>'ä³','ð¯¨'=>'éµ§','ð¯¨'=>'𪃎','䳸'=>'䳸','𪄅'=>'𪄅','𪈎'=>'𪈎','𪊑'=>'𪊑','麻'=>'麻','䵖'=>'äµ–','黹'=>'黹','黾'=>'黾','鼅'=>'é¼…','鼏'=>'é¼','鼖'=>'é¼–','鼻'=>'é¼»','ð¯¨'=>'𪘀'); diff --git a/phpBB/includes/utf/data/utf_nfc_qc.php b/phpBB/includes/utf/data/utf_nfc_qc.php deleted file mode 100644 index ff56357ea6..0000000000 --- a/phpBB/includes/utf/data/utf_nfc_qc.php +++ /dev/null @@ -1,2 +0,0 @@ -<?php -$GLOBALS['utf_nfc_qc']=array('Í€'=>1,'Í'=>1,'̓'=>1,'Í„'=>1,'Í´'=>1,';'=>1,'·'=>1,'क़'=>1,'ख़'=>1,'ग़'=>1,'ज़'=>1,'ड़'=>1,'à¥'=>1,'फ़'=>1,'य़'=>1,'à§œ'=>1,'à§'=>1,'à§Ÿ'=>1,'ਲ਼'=>1,'ਸ਼'=>1,'à©™'=>1,'ਗ਼'=>1,'à©›'=>1,'ਫ਼'=>1,'àœ'=>1,'à'=>1,'གྷ'=>1,'à½'=>1,'དྷ'=>1,'བྷ'=>1,'ཛྷ'=>1,'ཀྵ'=>1,'ཱི'=>1,'ཱུ'=>1,'ྲྀ'=>1,'ླྀ'=>1,'à¾'=>1,'ྒྷ'=>1,'à¾'=>1,'ྡྷ'=>1,'ྦྷ'=>1,'ྫྷ'=>1,'ྐྵ'=>1,'á½±'=>1,'á½³'=>1,'á½µ'=>1,'á½·'=>1,'á½¹'=>1,'á½»'=>1,'á½½'=>1,'á¾»'=>1,'á¾¾'=>1,'Έ'=>1,'á¿‹'=>1,'á¿“'=>1,'á¿›'=>1,'á¿£'=>1,'á¿«'=>1,'á¿®'=>1,'`'=>1,'Ό'=>1,'á¿»'=>1,'´'=>1,' '=>1,'â€'=>1,'Ω'=>1,'K'=>1,'â„«'=>1,'〈'=>1,'〉'=>1,'⫝̸'=>1,'豈'=>1,'ï¤'=>1,'車'=>1,'賈'=>1,'滑'=>1,'串'=>1,'句'=>1,'龜'=>1,'龜'=>1,'契'=>1,'金'=>1,'喇'=>1,'奈'=>1,'ï¤'=>1,'癩'=>1,'ï¤'=>1,'ï¤'=>1,'螺'=>1,'裸'=>1,'邏'=>1,'樂'=>1,'洛'=>1,'烙'=>1,'珞'=>1,'落'=>1,'酪'=>1,'駱'=>1,'亂'=>1,'卵'=>1,'ï¤'=>1,'爛'=>1,'蘭'=>1,'ï¤ '=>1,'嵐'=>1,'濫'=>1,'藍'=>1,'襤'=>1,'拉'=>1,'臘'=>1,'蠟'=>1,'廊'=>1,'朗'=>1,'浪'=>1,'狼'=>1,'郎'=>1,'ï¤'=>1,'冷'=>1,'勞'=>1,'擄'=>1,'櫓'=>1,'爐'=>1,'盧'=>1,'老'=>1,'蘆'=>1,'虜'=>1,'路'=>1,'露'=>1,'魯'=>1,'鷺'=>1,'碌'=>1,'祿'=>1,'綠'=>1,'菉'=>1,'錄'=>1,'鹿'=>1,'ï¥'=>1,'壟'=>1,'弄'=>1,'籠'=>1,'聾'=>1,'牢'=>1,'磊'=>1,'賂'=>1,'雷'=>1,'壘'=>1,'屢'=>1,'樓'=>1,'ï¥'=>1,'漏'=>1,'ï¥'=>1,'ï¥'=>1,'陋'=>1,'勒'=>1,'肋'=>1,'凜'=>1,'凌'=>1,'稜'=>1,'綾'=>1,'菱'=>1,'陵'=>1,'讀'=>1,'拏'=>1,'樂'=>1,'ï¥'=>1,'丹'=>1,'寧'=>1,'ï¥ '=>1,'率'=>1,'異'=>1,'北'=>1,'磻'=>1,'便'=>1,'復'=>1,'不'=>1,'泌'=>1,'數'=>1,'索'=>1,'參'=>1,'塞'=>1,'ï¥'=>1,'葉'=>1,'說'=>1,'殺'=>1,'辰'=>1,'沈'=>1,'拾'=>1,'若'=>1,'掠'=>1,'略'=>1,'亮'=>1,'兩'=>1,'凉'=>1,'梁'=>1,'糧'=>1,'良'=>1,'諒'=>1,'量'=>1,'勵'=>1,'呂'=>1,'ï¦'=>1,'廬'=>1,'旅'=>1,'濾'=>1,'礪'=>1,'閭'=>1,'驪'=>1,'麗'=>1,'黎'=>1,'力'=>1,'曆'=>1,'歷'=>1,'ï¦'=>1,'年'=>1,'ï¦'=>1,'ï¦'=>1,'撚'=>1,'漣'=>1,'煉'=>1,'璉'=>1,'秊'=>1,'練'=>1,'聯'=>1,'輦'=>1,'蓮'=>1,'連'=>1,'鍊'=>1,'列'=>1,'ï¦'=>1,'咽'=>1,'烈'=>1,'ï¦ '=>1,'說'=>1,'廉'=>1,'念'=>1,'捻'=>1,'殮'=>1,'簾'=>1,'獵'=>1,'令'=>1,'囹'=>1,'寧'=>1,'嶺'=>1,'怜'=>1,'ï¦'=>1,'瑩'=>1,'羚'=>1,'聆'=>1,'鈴'=>1,'零'=>1,'靈'=>1,'領'=>1,'例'=>1,'禮'=>1,'醴'=>1,'隸'=>1,'惡'=>1,'了'=>1,'僚'=>1,'寮'=>1,'尿'=>1,'料'=>1,'樂'=>1,'ï§€'=>1,'ï§'=>1,'ï§‚'=>1,'遼'=>1,'ï§„'=>1,'ï§…'=>1,'阮'=>1,'劉'=>1,'杻'=>1,'柳'=>1,'ï§Š'=>1,'ï§‹'=>1,'ï§Œ'=>1,'ï§'=>1,'ï§Ž'=>1,'ï§'=>1,'ï§'=>1,'ï§‘'=>1,'ï§’'=>1,'ï§“'=>1,'ï§”'=>1,'ï§•'=>1,'ï§–'=>1,'ï§—'=>1,'律'=>1,'ï§™'=>1,'ï§š'=>1,'ï§›'=>1,'ï§œ'=>1,'ï§'=>1,'ï§ž'=>1,'ï§Ÿ'=>1,'ï§ '=>1,'ï§¡'=>1,'ï§¢'=>1,'ï§£'=>1,'理'=>1,'ï§¥'=>1,'罹'=>1,'ï§§'=>1,'裡'=>1,'ï§©'=>1,'離'=>1,'ï§«'=>1,'溺'=>1,'ï§'=>1,'ï§®'=>1,'璘'=>1,'ï§°'=>1,'ï§±'=>1,'ï§²'=>1,'ï§³'=>1,'ï§´'=>1,'ï§µ'=>1,'ï§¶'=>1,'ï§·'=>1,'笠'=>1,'ï§¹'=>1,'狀'=>1,'ï§»'=>1,'ï§¼'=>1,'ï§½'=>1,'ï§¾'=>1,'ï§¿'=>1,'切'=>1,'ï¨'=>1,'拓'=>1,'糖'=>1,'宅'=>1,'洞'=>1,'暴'=>1,'輻'=>1,'行'=>1,'降'=>1,'見'=>1,'廓'=>1,'兀'=>1,'ï¨'=>1,'ï¨'=>1,'晴'=>1,'凞'=>1,'猪'=>1,'益'=>1,'礼'=>1,'神'=>1,'祥'=>1,'福'=>1,'靖'=>1,'ï¨'=>1,'羽'=>1,'ï¨ '=>1,'諸'=>1,'逸'=>1,'都'=>1,'飯'=>1,'飼'=>1,'館'=>1,'ï¨'=>1,'侮'=>1,'僧'=>1,'免'=>1,'勉'=>1,'勤'=>1,'卑'=>1,'喝'=>1,'嘆'=>1,'器'=>1,'塀'=>1,'墨'=>1,'層'=>1,'屮'=>1,'悔'=>1,'慨'=>1,'憎'=>1,'ï©€'=>1,'ï©'=>1,'ï©‚'=>1,'暑'=>1,'ï©„'=>1,'ï©…'=>1,'渚'=>1,'漢'=>1,'煮'=>1,'爫'=>1,'琢'=>1,'ï©‹'=>1,'社'=>1,'ï©'=>1,'祈'=>1,'ï©'=>1,'ï©'=>1,'ï©‘'=>1,'ï©’'=>1,'ï©“'=>1,'ï©”'=>1,'ï©•'=>1,'ï©–'=>1,'ï©—'=>1,'縉'=>1,'ï©™'=>1,'署'=>1,'ï©›'=>1,'臭'=>1,'ï©'=>1,'艹'=>1,'著'=>1,'ï© '=>1,'ï©¡'=>1,'ï©¢'=>1,'ï©£'=>1,'賓'=>1,'ï©¥'=>1,'辶'=>1,'ï©§'=>1,'難'=>1,'ï©©'=>1,'頻'=>1,'ï©°'=>1,'况'=>1,'全'=>1,'侀'=>1,'ï©´'=>1,'冀'=>1,'ï©¶'=>1,'ï©·'=>1,'喝'=>1,'啕'=>1,'喙'=>1,'ï©»'=>1,'塚'=>1,'墳'=>1,'奄'=>1,'ï©¿'=>1,'婢'=>1,'ïª'=>1,'廒'=>1,'廙'=>1,'彩'=>1,'徭'=>1,'惘'=>1,'慎'=>1,'愈'=>1,'憎'=>1,'慠'=>1,'懲'=>1,'戴'=>1,'ïª'=>1,'搜'=>1,'ïª'=>1,'ïª'=>1,'晴'=>1,'朗'=>1,'望'=>1,'杖'=>1,'歹'=>1,'殺'=>1,'流'=>1,'滛'=>1,'滋'=>1,'漢'=>1,'瀞'=>1,'煮'=>1,'ïª'=>1,'爵'=>1,'犯'=>1,'ïª '=>1,'瑱'=>1,'甆'=>1,'画'=>1,'瘝'=>1,'瘟'=>1,'益'=>1,'盛'=>1,'直'=>1,'睊'=>1,'着'=>1,'磌'=>1,'窱'=>1,'ïª'=>1,'类'=>1,'絛'=>1,'練'=>1,'缾'=>1,'者'=>1,'荒'=>1,'華'=>1,'蝹'=>1,'襁'=>1,'覆'=>1,'視'=>1,'調'=>1,'諸'=>1,'請'=>1,'謁'=>1,'諾'=>1,'諭'=>1,'謹'=>1,'ï«€'=>1,'ï«'=>1,'ï«‚'=>1,'遲'=>1,'ï«„'=>1,'ï«…'=>1,'陼'=>1,'難'=>1,'靖'=>1,'韛'=>1,'響'=>1,'ï«‹'=>1,'頻'=>1,'ï«'=>1,'龜'=>1,'ï«'=>1,'ï«'=>1,'ï«‘'=>1,'ï«’'=>1,'ï«“'=>1,'ï«”'=>1,'ï«•'=>1,'ï«–'=>1,'ï«—'=>1,'齃'=>1,'ï«™'=>1,'ï¬'=>1,'ײַ'=>1,'שׁ'=>1,'שׂ'=>1,'שּׁ'=>1,'ï¬'=>1,'אַ'=>1,'אָ'=>1,'אּ'=>1,'בּ'=>1,'גּ'=>1,'דּ'=>1,'הּ'=>1,'וּ'=>1,'זּ'=>1,'טּ'=>1,'יּ'=>1,'ךּ'=>1,'כּ'=>1,'לּ'=>1,'מּ'=>1,'ï€'=>1,'ï'=>1,'ïƒ'=>1,'ï„'=>1,'ï†'=>1,'ï‡'=>1,'ïˆ'=>1,'ï‰'=>1,'ïŠ'=>1,'ï‹'=>1,'ïŒ'=>1,'ï'=>1,'ïŽ'=>1,'ð…ž'=>1,'ð…Ÿ'=>1,'ð… '=>1,'ð…¡'=>1,'ð…¢'=>1,'ð…£'=>1,'ð…¤'=>1,'ð†»'=>1,'ð†¼'=>1,'ð†½'=>1,'ð†¾'=>1,'ð†¿'=>1,'ð‡€'=>1,'丽'=>1,'ð¯ '=>1,'乁'=>1,'𠄢'=>1,'你'=>1,'侮'=>1,'侻'=>1,'倂'=>1,'偺'=>1,'備'=>1,'僧'=>1,'像'=>1,'㒞'=>1,'ð¯ '=>1,'免'=>1,'ð¯ '=>1,'ð¯ '=>1,'具'=>1,'𠔜'=>1,'㒹'=>1,'內'=>1,'再'=>1,'𠕋'=>1,'冗'=>1,'冤'=>1,'仌'=>1,'冬'=>1,'况'=>1,'𩇟'=>1,'ð¯ '=>1,'刃'=>1,'㓟'=>1,'ð¯ '=>1,'剆'=>1,'割'=>1,'剷'=>1,'㔕'=>1,'勇'=>1,'勉'=>1,'勤'=>1,'勺'=>1,'包'=>1,'匆'=>1,'北'=>1,'卉'=>1,'ð¯ '=>1,'博'=>1,'即'=>1,'卽'=>1,'卿'=>1,'卿'=>1,'卿'=>1,'𠨬'=>1,'灰'=>1,'及'=>1,'叟'=>1,'𠭣'=>1,'叫'=>1,'叱'=>1,'吆'=>1,'咞'=>1,'吸'=>1,'呈'=>1,'周'=>1,'咢'=>1,'ð¯¡'=>1,'唐'=>1,'啓'=>1,'啣'=>1,'善'=>1,'善'=>1,'喙'=>1,'喫'=>1,'喳'=>1,'嗂'=>1,'圖'=>1,'嘆'=>1,'ð¯¡'=>1,'噑'=>1,'ð¯¡'=>1,'ð¯¡'=>1,'壮'=>1,'城'=>1,'埴'=>1,'堍'=>1,'型'=>1,'堲'=>1,'報'=>1,'墬'=>1,'𡓤'=>1,'売'=>1,'壷'=>1,'夆'=>1,'ð¯¡'=>1,'夢'=>1,'奢'=>1,'𡚨'=>1,'𡛪'=>1,'姬'=>1,'娛'=>1,'娧'=>1,'姘'=>1,'婦'=>1,'㛮'=>1,'㛼'=>1,'嬈'=>1,'嬾'=>1,'嬾'=>1,'𡧈'=>1,'ð¯¡'=>1,'寘'=>1,'寧'=>1,'寳'=>1,'𡬘'=>1,'寿'=>1,'将'=>1,'当'=>1,'尢'=>1,'㞁'=>1,'屠'=>1,'屮'=>1,'峀'=>1,'岍'=>1,'𡷤'=>1,'嵃'=>1,'𡷦'=>1,'嵮'=>1,'嵫'=>1,'嵼'=>1,'ð¯¢'=>1,'巢'=>1,'㠯'=>1,'巽'=>1,'帨'=>1,'帽'=>1,'幩'=>1,'㡢'=>1,'𢆃'=>1,'㡼'=>1,'庰'=>1,'庳'=>1,'ð¯¢'=>1,'廊'=>1,'ð¯¢'=>1,'ð¯¢'=>1,'𢌱'=>1,'𢌱'=>1,'舁'=>1,'弢'=>1,'弢'=>1,'㣇'=>1,'𣊸'=>1,'𦇚'=>1,'形'=>1,'彫'=>1,'㣣'=>1,'徚'=>1,'ð¯¢'=>1,'志'=>1,'忹'=>1,'悁'=>1,'㤺'=>1,'㤜'=>1,'悔'=>1,'𢛔'=>1,'惇'=>1,'慈'=>1,'慌'=>1,'慎'=>1,'慌'=>1,'慺'=>1,'憎'=>1,'憲'=>1,'ð¯¢'=>1,'憯'=>1,'懞'=>1,'懲'=>1,'懶'=>1,'成'=>1,'戛'=>1,'扝'=>1,'抱'=>1,'拔'=>1,'捐'=>1,'𢬌'=>1,'挽'=>1,'拼'=>1,'捨'=>1,'掃'=>1,'揤'=>1,'𢯱'=>1,'搢'=>1,'揅'=>1,'ð¯£'=>1,'㨮'=>1,'摩'=>1,'摾'=>1,'撝'=>1,'摷'=>1,'㩬'=>1,'敏'=>1,'敬'=>1,'𣀊'=>1,'旣'=>1,'書'=>1,'ð¯£'=>1,'㬙'=>1,'ð¯£'=>1,'ð¯£'=>1,'㫤'=>1,'冒'=>1,'冕'=>1,'最'=>1,'暜'=>1,'肭'=>1,'䏙'=>1,'朗'=>1,'望'=>1,'朡'=>1,'杞'=>1,'杓'=>1,'ð¯£'=>1,'㭉'=>1,'柺'=>1,'枅'=>1,'桒'=>1,'梅'=>1,'𣑭'=>1,'梎'=>1,'栟'=>1,'椔'=>1,'㮝'=>1,'楂'=>1,'榣'=>1,'槪'=>1,'檨'=>1,'𣚣'=>1,'ð¯£'=>1,'㰘'=>1,'次'=>1,'𣢧'=>1,'歔'=>1,'㱎'=>1,'歲'=>1,'殟'=>1,'殺'=>1,'殻'=>1,'𣪍'=>1,'𡴋'=>1,'𣫺'=>1,'汎'=>1,'𣲼'=>1,'沿'=>1,'泍'=>1,'汧'=>1,'洖'=>1,'派'=>1,'ð¯¤'=>1,'流'=>1,'浩'=>1,'浸'=>1,'涅'=>1,'𣴞'=>1,'洴'=>1,'港'=>1,'湮'=>1,'㴳'=>1,'滋'=>1,'滇'=>1,'ð¯¤'=>1,'淹'=>1,'ð¯¤'=>1,'ð¯¤'=>1,'𣾎'=>1,'濆'=>1,'瀹'=>1,'瀞'=>1,'瀛'=>1,'㶖'=>1,'灊'=>1,'災'=>1,'灷'=>1,'炭'=>1,'𠔥'=>1,'煅'=>1,'ð¯¤'=>1,'熜'=>1,'𤎫'=>1,'爨'=>1,'爵'=>1,'牐'=>1,'𤘈'=>1,'犀'=>1,'犕'=>1,'𤜵'=>1,'𤠔'=>1,'獺'=>1,'王'=>1,'㺬'=>1,'玥'=>1,'㺸'=>1,'ð¯¤'=>1,'瑇'=>1,'瑜'=>1,'瑱'=>1,'璅'=>1,'瓊'=>1,'㼛'=>1,'甤'=>1,'𤰶'=>1,'甾'=>1,'𤲒'=>1,'異'=>1,'𢆟'=>1,'瘐'=>1,'𤾡'=>1,'𤾸'=>1,'𥁄'=>1,'㿼'=>1,'䀈'=>1,'直'=>1,'ð¯¥'=>1,'𥃲'=>1,'𥄙'=>1,'𥄳'=>1,'眞'=>1,'真'=>1,'真'=>1,'睊'=>1,'䀹'=>1,'瞋'=>1,'䁆'=>1,'䂖'=>1,'ð¯¥'=>1,'硎'=>1,'ð¯¥'=>1,'ð¯¥'=>1,'䃣'=>1,'𥘦'=>1,'祖'=>1,'𥚚'=>1,'𥛅'=>1,'福'=>1,'秫'=>1,'䄯'=>1,'穀'=>1,'穊'=>1,'穏'=>1,'𥥼'=>1,'ð¯¥'=>1,'𥪧'=>1,'竮'=>1,'䈂'=>1,'𥮫'=>1,'篆'=>1,'築'=>1,'䈧'=>1,'𥲀'=>1,'糒'=>1,'䊠'=>1,'糨'=>1,'糣'=>1,'紀'=>1,'𥾆'=>1,'絣'=>1,'ð¯¥'=>1,'緇'=>1,'縂'=>1,'繅'=>1,'䌴'=>1,'𦈨'=>1,'𦉇'=>1,'䍙'=>1,'𦋙'=>1,'罺'=>1,'𦌾'=>1,'羕'=>1,'翺'=>1,'者'=>1,'𦓚'=>1,'𦔣'=>1,'聠'=>1,'𦖨'=>1,'聰'=>1,'𣍟'=>1,'ð¯¦'=>1,'育'=>1,'脃'=>1,'䐋'=>1,'脾'=>1,'媵'=>1,'𦞧'=>1,'𦞵'=>1,'𣎓'=>1,'𣎜'=>1,'舁'=>1,'舄'=>1,'ð¯¦'=>1,'䑫'=>1,'ð¯¦'=>1,'ð¯¦'=>1,'芝'=>1,'劳'=>1,'花'=>1,'芳'=>1,'芽'=>1,'苦'=>1,'𦬼'=>1,'若'=>1,'茝'=>1,'荣'=>1,'莭'=>1,'茣'=>1,'ð¯¦'=>1,'菧'=>1,'著'=>1,'荓'=>1,'菊'=>1,'菌'=>1,'菜'=>1,'𦰶'=>1,'𦵫'=>1,'𦳕'=>1,'䔫'=>1,'蓱'=>1,'蓳'=>1,'蔖'=>1,'𧏊'=>1,'蕤'=>1,'ð¯¦'=>1,'䕝'=>1,'䕡'=>1,'𦾱'=>1,'𧃒'=>1,'䕫'=>1,'虐'=>1,'虜'=>1,'虧'=>1,'虩'=>1,'蚩'=>1,'蚈'=>1,'蜎'=>1,'蛢'=>1,'蝹'=>1,'蜨'=>1,'蝫'=>1,'螆'=>1,'䗗'=>1,'蟡'=>1,'ð¯§'=>1,'䗹'=>1,'衠'=>1,'衣'=>1,'𧙧'=>1,'裗'=>1,'裞'=>1,'䘵'=>1,'裺'=>1,'㒻'=>1,'𧢮'=>1,'𧥦'=>1,'ð¯§'=>1,'䛇'=>1,'ð¯§'=>1,'ð¯§'=>1,'變'=>1,'豕'=>1,'𧲨'=>1,'貫'=>1,'賁'=>1,'贛'=>1,'起'=>1,'𧼯'=>1,'𠠄'=>1,'跋'=>1,'趼'=>1,'跰'=>1,'ð¯§'=>1,'軔'=>1,'輸'=>1,'𨗒'=>1,'𨗭'=>1,'邔'=>1,'郱'=>1,'鄑'=>1,'𨜮'=>1,'鄛'=>1,'鈸'=>1,'鋗'=>1,'鋘'=>1,'鉼'=>1,'鏹'=>1,'鐕'=>1,'ð¯§'=>1,'開'=>1,'䦕'=>1,'閷'=>1,'𨵷'=>1,'䧦'=>1,'雃'=>1,'嶲'=>1,'霣'=>1,'𩅅'=>1,'𩈚'=>1,'䩮'=>1,'䩶'=>1,'韠'=>1,'𩐊'=>1,'䪲'=>1,'𩒖'=>1,'頋'=>1,'頋'=>1,'頩'=>1,'ð¯¨'=>1,'飢'=>1,'䬳'=>1,'餩'=>1,'馧'=>1,'駂'=>1,'駾'=>1,'䯎'=>1,'𩬰'=>1,'鬒'=>1,'鱀'=>1,'鳽'=>1,'ð¯¨'=>1,'䳭'=>1,'ð¯¨'=>1,'ð¯¨'=>1,'䳸'=>1,'𪄅'=>1,'𪈎'=>1,'𪊑'=>1,'麻'=>1,'䵖'=>1,'黹'=>1,'黾'=>1,'鼅'=>1,'鼏'=>1,'鼖'=>1,'鼻'=>1,'ð¯¨'=>1,'Ì€'=>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,'ൗ'=>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,'ᆼ'=>0,'ᆽ'=>0,'ᆾ'=>0,'ᆿ'=>0,'ᇀ'=>0,'á‡'=>0,'ᇂ'=>0,'ᬵ'=>0,'ã‚™'=>0,'゚'=>0); diff --git a/phpBB/includes/utf/data/utf_nfkc_qc.php b/phpBB/includes/utf/data/utf_nfkc_qc.php deleted file mode 100644 index 181a07b351..0000000000 --- a/phpBB/includes/utf/data/utf_nfkc_qc.php +++ /dev/null @@ -1,2 +0,0 @@ -<?php -$GLOBALS['utf_nfkc_qc']=array(' '=>1,'¨'=>1,'ª'=>1,'¯'=>1,'²'=>1,'³'=>1,'´'=>1,'µ'=>1,'¸'=>1,'¹'=>1,'º'=>1,'¼'=>1,'½'=>1,'¾'=>1,'IJ'=>1,'ij'=>1,'Ä¿'=>1,'Å€'=>1,'ʼn'=>1,'Å¿'=>1,'Ç„'=>1,'Ç…'=>1,'dž'=>1,'LJ'=>1,'Lj'=>1,'lj'=>1,'ÇŠ'=>1,'Ç‹'=>1,'ÇŒ'=>1,'DZ'=>1,'Dz'=>1,'dz'=>1,'ʰ'=>1,'ʱ'=>1,'ʲ'=>1,'ʳ'=>1,'Ê´'=>1,'ʵ'=>1,'ʶ'=>1,'Ê·'=>1,'ʸ'=>1,'˘'=>1,'Ë™'=>1,'Ëš'=>1,'Ë›'=>1,'Ëœ'=>1,'Ë'=>1,'Ë '=>1,'Ë¡'=>1,'Ë¢'=>1,'Ë£'=>1,'ˤ'=>1,'Í€'=>1,'Í'=>1,'̓'=>1,'Í„'=>1,'Í´'=>1,'ͺ'=>1,';'=>1,'΄'=>1,'Î…'=>1,'·'=>1,'Ï'=>1,'Ï‘'=>1,'Ï’'=>1,'Ï“'=>1,'Ï”'=>1,'Ï•'=>1,'Ï–'=>1,'ϰ'=>1,'ϱ'=>1,'ϲ'=>1,'Ï´'=>1,'ϵ'=>1,'Ϲ'=>1,'Ö‡'=>1,'Ùµ'=>1,'Ù¶'=>1,'Ù·'=>1,'Ù¸'=>1,'क़'=>1,'ख़'=>1,'ग़'=>1,'ज़'=>1,'ड़'=>1,'à¥'=>1,'फ़'=>1,'य़'=>1,'à§œ'=>1,'à§'=>1,'à§Ÿ'=>1,'ਲ਼'=>1,'ਸ਼'=>1,'à©™'=>1,'ਗ਼'=>1,'à©›'=>1,'ਫ਼'=>1,'àœ'=>1,'à'=>1,'ำ'=>1,'ຳ'=>1,'ໜ'=>1,'à»'=>1,'༌'=>1,'གྷ'=>1,'à½'=>1,'དྷ'=>1,'བྷ'=>1,'ཛྷ'=>1,'ཀྵ'=>1,'ཱི'=>1,'ཱུ'=>1,'ྲྀ'=>1,'ཷ'=>1,'ླྀ'=>1,'ཹ'=>1,'à¾'=>1,'ྒྷ'=>1,'à¾'=>1,'ྡྷ'=>1,'ྦྷ'=>1,'ྫྷ'=>1,'ྐྵ'=>1,'ჼ'=>1,'á´¬'=>1,'á´'=>1,'á´®'=>1,'á´°'=>1,'á´±'=>1,'á´²'=>1,'á´³'=>1,'á´´'=>1,'á´µ'=>1,'á´¶'=>1,'á´·'=>1,'á´¸'=>1,'á´¹'=>1,'á´º'=>1,'á´¼'=>1,'á´½'=>1,'á´¾'=>1,'á´¿'=>1,'áµ€'=>1,'áµ'=>1,'ᵂ'=>1,'ᵃ'=>1,'ᵄ'=>1,'áµ…'=>1,'ᵆ'=>1,'ᵇ'=>1,'ᵈ'=>1,'ᵉ'=>1,'ᵊ'=>1,'ᵋ'=>1,'ᵌ'=>1,'áµ'=>1,'áµ'=>1,'áµ'=>1,'ᵑ'=>1,'áµ’'=>1,'ᵓ'=>1,'áµ”'=>1,'ᵕ'=>1,'áµ–'=>1,'áµ—'=>1,'ᵘ'=>1,'áµ™'=>1,'ᵚ'=>1,'áµ›'=>1,'ᵜ'=>1,'áµ'=>1,'ᵞ'=>1,'ᵟ'=>1,'áµ '=>1,'ᵡ'=>1,'áµ¢'=>1,'áµ£'=>1,'ᵤ'=>1,'áµ¥'=>1,'ᵦ'=>1,'áµ§'=>1,'ᵨ'=>1,'ᵩ'=>1,'ᵪ'=>1,'ᵸ'=>1,'á¶›'=>1,'á¶œ'=>1,'á¶'=>1,'á¶ž'=>1,'á¶Ÿ'=>1,'á¶ '=>1,'á¶¡'=>1,'á¶¢'=>1,'á¶£'=>1,'ᶤ'=>1,'á¶¥'=>1,'ᶦ'=>1,'á¶§'=>1,'ᶨ'=>1,'á¶©'=>1,'ᶪ'=>1,'á¶«'=>1,'ᶬ'=>1,'á¶'=>1,'á¶®'=>1,'ᶯ'=>1,'á¶°'=>1,'á¶±'=>1,'á¶²'=>1,'á¶³'=>1,'á¶´'=>1,'á¶µ'=>1,'á¶¶'=>1,'á¶·'=>1,'ᶸ'=>1,'á¶¹'=>1,'ᶺ'=>1,'á¶»'=>1,'á¶¼'=>1,'á¶½'=>1,'á¶¾'=>1,'á¶¿'=>1,'ẚ'=>1,'ẛ'=>1,'á½±'=>1,'á½³'=>1,'á½µ'=>1,'á½·'=>1,'á½¹'=>1,'á½»'=>1,'á½½'=>1,'á¾»'=>1,'á¾½'=>1,'á¾¾'=>1,'᾿'=>1,'á¿€'=>1,'á¿'=>1,'Έ'=>1,'á¿‹'=>1,'á¿'=>1,'῎'=>1,'á¿'=>1,'á¿“'=>1,'á¿›'=>1,'á¿'=>1,'῞'=>1,'῟'=>1,'á¿£'=>1,'á¿«'=>1,'á¿'=>1,'á¿®'=>1,'`'=>1,'Ό'=>1,'á¿»'=>1,'´'=>1,'῾'=>1,' '=>1,'â€'=>1,' '=>1,' '=>1,' '=>1,' '=>1,' '=>1,' '=>1,' '=>1,' '=>1,' '=>1,'‑'=>1,'‗'=>1,'․'=>1,'‥'=>1,'…'=>1,' '=>1,'″'=>1,'‴'=>1,'‶'=>1,'‷'=>1,'‼'=>1,'‾'=>1,'â‡'=>1,'âˆ'=>1,'â‰'=>1,'â—'=>1,'âŸ'=>1,'â°'=>1,'â±'=>1,'â´'=>1,'âµ'=>1,'â¶'=>1,'â·'=>1,'â¸'=>1,'â¹'=>1,'âº'=>1,'â»'=>1,'â¼'=>1,'â½'=>1,'â¾'=>1,'â¿'=>1,'â‚€'=>1,'â‚'=>1,'â‚‚'=>1,'₃'=>1,'â‚„'=>1,'â‚…'=>1,'₆'=>1,'₇'=>1,'₈'=>1,'₉'=>1,'₊'=>1,'â‚‹'=>1,'₌'=>1,'â‚'=>1,'₎'=>1,'â‚'=>1,'â‚‘'=>1,'â‚’'=>1,'â‚“'=>1,'â‚”'=>1,'₨'=>1,'â„€'=>1,'â„'=>1,'â„‚'=>1,'℃'=>1,'â„…'=>1,'℆'=>1,'ℇ'=>1,'℉'=>1,'ℊ'=>1,'â„‹'=>1,'ℌ'=>1,'â„'=>1,'ℎ'=>1,'â„'=>1,'â„'=>1,'â„‘'=>1,'â„’'=>1,'â„“'=>1,'â„•'=>1,'â„–'=>1,'â„™'=>1,'ℚ'=>1,'â„›'=>1,'ℜ'=>1,'â„'=>1,'â„ '=>1,'â„¡'=>1,'â„¢'=>1,'ℤ'=>1,'Ω'=>1,'ℨ'=>1,'K'=>1,'â„«'=>1,'ℬ'=>1,'â„'=>1,'ℯ'=>1,'â„°'=>1,'ℱ'=>1,'ℳ'=>1,'â„´'=>1,'ℵ'=>1,'â„¶'=>1,'â„·'=>1,'ℸ'=>1,'ℹ'=>1,'â„»'=>1,'ℼ'=>1,'ℽ'=>1,'ℾ'=>1,'â„¿'=>1,'â…€'=>1,'â……'=>1,'â…†'=>1,'â…‡'=>1,'â…ˆ'=>1,'â…‰'=>1,'â…“'=>1,'â…”'=>1,'â…•'=>1,'â…–'=>1,'â…—'=>1,'â…˜'=>1,'â…™'=>1,'â…š'=>1,'â…›'=>1,'â…œ'=>1,'â…'=>1,'â…ž'=>1,'â…Ÿ'=>1,'â… '=>1,'â…¡'=>1,'â…¢'=>1,'â…£'=>1,'â…¤'=>1,'â…¥'=>1,'â…¦'=>1,'â…§'=>1,'â…¨'=>1,'â…©'=>1,'â…ª'=>1,'â…«'=>1,'â…¬'=>1,'â…'=>1,'â…®'=>1,'â…¯'=>1,'â…°'=>1,'â…±'=>1,'â…²'=>1,'â…³'=>1,'â…´'=>1,'â…µ'=>1,'â…¶'=>1,'â…·'=>1,'â…¸'=>1,'â…¹'=>1,'â…º'=>1,'â…»'=>1,'â…¼'=>1,'â…½'=>1,'â…¾'=>1,'â…¿'=>1,'∬'=>1,'âˆ'=>1,'∯'=>1,'∰'=>1,'〈'=>1,'〉'=>1,'â‘ '=>1,'â‘¡'=>1,'â‘¢'=>1,'â‘£'=>1,'⑤'=>1,'â‘¥'=>1,'⑦'=>1,'â‘§'=>1,'⑨'=>1,'â‘©'=>1,'⑪'=>1,'â‘«'=>1,'⑬'=>1,'â‘'=>1,'â‘®'=>1,'⑯'=>1,'â‘°'=>1,'⑱'=>1,'⑲'=>1,'⑳'=>1,'â‘´'=>1,'⑵'=>1,'â‘¶'=>1,'â‘·'=>1,'⑸'=>1,'⑹'=>1,'⑺'=>1,'â‘»'=>1,'⑼'=>1,'⑽'=>1,'⑾'=>1,'â‘¿'=>1,'â’€'=>1,'â’'=>1,'â’‚'=>1,'â’ƒ'=>1,'â’„'=>1,'â’…'=>1,'â’†'=>1,'â’‡'=>1,'â’ˆ'=>1,'â’‰'=>1,'â’Š'=>1,'â’‹'=>1,'â’Œ'=>1,'â’'=>1,'â’Ž'=>1,'â’'=>1,'â’'=>1,'â’‘'=>1,'â’’'=>1,'â’“'=>1,'â’”'=>1,'â’•'=>1,'â’–'=>1,'â’—'=>1,'â’˜'=>1,'â’™'=>1,'â’š'=>1,'â’›'=>1,'â’œ'=>1,'â’'=>1,'â’ž'=>1,'â’Ÿ'=>1,'â’ '=>1,'â’¡'=>1,'â’¢'=>1,'â’£'=>1,'â’¤'=>1,'â’¥'=>1,'â’¦'=>1,'â’§'=>1,'â’¨'=>1,'â’©'=>1,'â’ª'=>1,'â’«'=>1,'â’¬'=>1,'â’'=>1,'â’®'=>1,'â’¯'=>1,'â’°'=>1,'â’±'=>1,'â’²'=>1,'â’³'=>1,'â’´'=>1,'â’µ'=>1,'â’¶'=>1,'â’·'=>1,'â’¸'=>1,'â’¹'=>1,'â’º'=>1,'â’»'=>1,'â’¼'=>1,'â’½'=>1,'â’¾'=>1,'â’¿'=>1,'â“€'=>1,'â“'=>1,'â“‚'=>1,'Ⓝ'=>1,'â“„'=>1,'â“…'=>1,'Ⓠ'=>1,'Ⓡ'=>1,'Ⓢ'=>1,'Ⓣ'=>1,'Ⓤ'=>1,'â“‹'=>1,'Ⓦ'=>1,'â“'=>1,'Ⓨ'=>1,'â“'=>1,'â“'=>1,'â“‘'=>1,'â“’'=>1,'â““'=>1,'â“”'=>1,'â“•'=>1,'â“–'=>1,'â“—'=>1,'ⓘ'=>1,'â“™'=>1,'ⓚ'=>1,'â“›'=>1,'ⓜ'=>1,'â“'=>1,'ⓞ'=>1,'ⓟ'=>1,'â“ '=>1,'â“¡'=>1,'â“¢'=>1,'â“£'=>1,'ⓤ'=>1,'â“¥'=>1,'ⓦ'=>1,'â“§'=>1,'ⓨ'=>1,'â“©'=>1,'⓪'=>1,'⨌'=>1,'â©´'=>1,'⩵'=>1,'â©¶'=>1,'⫝̸'=>1,'ⵯ'=>1,'⺟'=>1,'⻳'=>1,'â¼€'=>1,'â¼'=>1,'⼂'=>1,'⼃'=>1,'⼄'=>1,'â¼…'=>1,'⼆'=>1,'⼇'=>1,'⼈'=>1,'⼉'=>1,'⼊'=>1,'⼋'=>1,'⼌'=>1,'â¼'=>1,'⼎'=>1,'â¼'=>1,'â¼'=>1,'⼑'=>1,'â¼’'=>1,'⼓'=>1,'â¼”'=>1,'⼕'=>1,'â¼–'=>1,'â¼—'=>1,'⼘'=>1,'â¼™'=>1,'⼚'=>1,'â¼›'=>1,'⼜'=>1,'â¼'=>1,'⼞'=>1,'⼟'=>1,'â¼ '=>1,'⼡'=>1,'â¼¢'=>1,'â¼£'=>1,'⼤'=>1,'â¼¥'=>1,'⼦'=>1,'â¼§'=>1,'⼨'=>1,'⼩'=>1,'⼪'=>1,'⼫'=>1,'⼬'=>1,'â¼'=>1,'â¼®'=>1,'⼯'=>1,'â¼°'=>1,'â¼±'=>1,'â¼²'=>1,'â¼³'=>1,'â¼´'=>1,'â¼µ'=>1,'â¼¶'=>1,'â¼·'=>1,'⼸'=>1,'â¼¹'=>1,'⼺'=>1,'â¼»'=>1,'â¼¼'=>1,'â¼½'=>1,'â¼¾'=>1,'⼿'=>1,'â½€'=>1,'â½'=>1,'⽂'=>1,'⽃'=>1,'⽄'=>1,'â½…'=>1,'⽆'=>1,'⽇'=>1,'⽈'=>1,'⽉'=>1,'⽊'=>1,'⽋'=>1,'⽌'=>1,'â½'=>1,'⽎'=>1,'â½'=>1,'â½'=>1,'⽑'=>1,'â½’'=>1,'⽓'=>1,'â½”'=>1,'⽕'=>1,'â½–'=>1,'â½—'=>1,'⽘'=>1,'â½™'=>1,'⽚'=>1,'â½›'=>1,'⽜'=>1,'â½'=>1,'⽞'=>1,'⽟'=>1,'â½ '=>1,'⽡'=>1,'â½¢'=>1,'â½£'=>1,'⽤'=>1,'â½¥'=>1,'⽦'=>1,'â½§'=>1,'⽨'=>1,'⽩'=>1,'⽪'=>1,'⽫'=>1,'⽬'=>1,'â½'=>1,'â½®'=>1,'⽯'=>1,'â½°'=>1,'â½±'=>1,'â½²'=>1,'â½³'=>1,'â½´'=>1,'â½µ'=>1,'â½¶'=>1,'â½·'=>1,'⽸'=>1,'â½¹'=>1,'⽺'=>1,'â½»'=>1,'â½¼'=>1,'â½½'=>1,'â½¾'=>1,'⽿'=>1,'â¾€'=>1,'â¾'=>1,'⾂'=>1,'⾃'=>1,'⾄'=>1,'â¾…'=>1,'⾆'=>1,'⾇'=>1,'⾈'=>1,'⾉'=>1,'⾊'=>1,'⾋'=>1,'⾌'=>1,'â¾'=>1,'⾎'=>1,'â¾'=>1,'â¾'=>1,'⾑'=>1,'â¾’'=>1,'⾓'=>1,'â¾”'=>1,'⾕'=>1,'â¾–'=>1,'â¾—'=>1,'⾘'=>1,'â¾™'=>1,'⾚'=>1,'â¾›'=>1,'⾜'=>1,'â¾'=>1,'⾞'=>1,'⾟'=>1,'â¾ '=>1,'⾡'=>1,'â¾¢'=>1,'â¾£'=>1,'⾤'=>1,'â¾¥'=>1,'⾦'=>1,'â¾§'=>1,'⾨'=>1,'⾩'=>1,'⾪'=>1,'⾫'=>1,'⾬'=>1,'â¾'=>1,'â¾®'=>1,'⾯'=>1,'â¾°'=>1,'â¾±'=>1,'â¾²'=>1,'â¾³'=>1,'â¾´'=>1,'â¾µ'=>1,'â¾¶'=>1,'â¾·'=>1,'⾸'=>1,'â¾¹'=>1,'⾺'=>1,'â¾»'=>1,'â¾¼'=>1,'â¾½'=>1,'â¾¾'=>1,'⾿'=>1,'â¿€'=>1,'â¿'=>1,'â¿‚'=>1,'⿃'=>1,'â¿„'=>1,'â¿…'=>1,'⿆'=>1,'⿇'=>1,'⿈'=>1,'⿉'=>1,'⿊'=>1,'â¿‹'=>1,'⿌'=>1,'â¿'=>1,'⿎'=>1,'â¿'=>1,'â¿'=>1,'â¿‘'=>1,'â¿’'=>1,'â¿“'=>1,'â¿”'=>1,'â¿•'=>1,' '=>1,'〶'=>1,'〸'=>1,'〹'=>1,'〺'=>1,'ã‚›'=>1,'゜'=>1,'ゟ'=>1,'ヿ'=>1,'ㄱ'=>1,'ㄲ'=>1,'ㄳ'=>1,'ã„´'=>1,'ㄵ'=>1,'ã„¶'=>1,'ã„·'=>1,'ㄸ'=>1,'ㄹ'=>1,'ㄺ'=>1,'ã„»'=>1,'ㄼ'=>1,'ㄽ'=>1,'ㄾ'=>1,'ã„¿'=>1,'ã…€'=>1,'ã…'=>1,'ã…‚'=>1,'ã…ƒ'=>1,'ã…„'=>1,'ã……'=>1,'ã…†'=>1,'ã…‡'=>1,'ã…ˆ'=>1,'ã…‰'=>1,'ã…Š'=>1,'ã…‹'=>1,'ã…Œ'=>1,'ã…'=>1,'ã…Ž'=>1,'ã…'=>1,'ã…'=>1,'ã…‘'=>1,'ã…’'=>1,'ã…“'=>1,'ã…”'=>1,'ã…•'=>1,'ã…–'=>1,'ã…—'=>1,'ã…˜'=>1,'ã…™'=>1,'ã…š'=>1,'ã…›'=>1,'ã…œ'=>1,'ã…'=>1,'ã…ž'=>1,'ã…Ÿ'=>1,'ã… '=>1,'ã…¡'=>1,'ã…¢'=>1,'ã…£'=>1,'ã…¤'=>1,'ã…¥'=>1,'ã…¦'=>1,'ã…§'=>1,'ã…¨'=>1,'ã…©'=>1,'ã…ª'=>1,'ã…«'=>1,'ã…¬'=>1,'ã…'=>1,'ã…®'=>1,'ã…¯'=>1,'ã…°'=>1,'ã…±'=>1,'ã…²'=>1,'ã…³'=>1,'ã…´'=>1,'ã…µ'=>1,'ã…¶'=>1,'ã…·'=>1,'ã…¸'=>1,'ã…¹'=>1,'ã…º'=>1,'ã…»'=>1,'ã…¼'=>1,'ã…½'=>1,'ã…¾'=>1,'ã…¿'=>1,'ㆀ'=>1,'ã†'=>1,'ㆂ'=>1,'ㆃ'=>1,'ㆄ'=>1,'ㆅ'=>1,'ㆆ'=>1,'ㆇ'=>1,'ㆈ'=>1,'ㆉ'=>1,'ㆊ'=>1,'ㆋ'=>1,'ㆌ'=>1,'ã†'=>1,'ㆎ'=>1,'㆒'=>1,'㆓'=>1,'㆔'=>1,'㆕'=>1,'㆖'=>1,'㆗'=>1,'㆘'=>1,'㆙'=>1,'㆚'=>1,'㆛'=>1,'㆜'=>1,'ã†'=>1,'㆞'=>1,'㆟'=>1,'㈀'=>1,'ãˆ'=>1,'㈂'=>1,'㈃'=>1,'㈄'=>1,'㈅'=>1,'㈆'=>1,'㈇'=>1,'㈈'=>1,'㈉'=>1,'㈊'=>1,'㈋'=>1,'㈌'=>1,'ãˆ'=>1,'㈎'=>1,'ãˆ'=>1,'ãˆ'=>1,'㈑'=>1,'㈒'=>1,'㈓'=>1,'㈔'=>1,'㈕'=>1,'㈖'=>1,'㈗'=>1,'㈘'=>1,'㈙'=>1,'㈚'=>1,'㈛'=>1,'㈜'=>1,'ãˆ'=>1,'㈞'=>1,'㈠'=>1,'㈡'=>1,'㈢'=>1,'㈣'=>1,'㈤'=>1,'㈥'=>1,'㈦'=>1,'㈧'=>1,'㈨'=>1,'㈩'=>1,'㈪'=>1,'㈫'=>1,'㈬'=>1,'ãˆ'=>1,'㈮'=>1,'㈯'=>1,'㈰'=>1,'㈱'=>1,'㈲'=>1,'㈳'=>1,'㈴'=>1,'㈵'=>1,'㈶'=>1,'㈷'=>1,'㈸'=>1,'㈹'=>1,'㈺'=>1,'㈻'=>1,'㈼'=>1,'㈽'=>1,'㈾'=>1,'㈿'=>1,'㉀'=>1,'ã‰'=>1,'㉂'=>1,'㉃'=>1,'ã‰'=>1,'㉑'=>1,'㉒'=>1,'㉓'=>1,'㉔'=>1,'㉕'=>1,'㉖'=>1,'㉗'=>1,'㉘'=>1,'㉙'=>1,'㉚'=>1,'㉛'=>1,'㉜'=>1,'ã‰'=>1,'㉞'=>1,'㉟'=>1,'㉠'=>1,'㉡'=>1,'㉢'=>1,'㉣'=>1,'㉤'=>1,'㉥'=>1,'㉦'=>1,'㉧'=>1,'㉨'=>1,'㉩'=>1,'㉪'=>1,'㉫'=>1,'㉬'=>1,'ã‰'=>1,'㉮'=>1,'㉯'=>1,'㉰'=>1,'㉱'=>1,'㉲'=>1,'㉳'=>1,'㉴'=>1,'㉵'=>1,'㉶'=>1,'㉷'=>1,'㉸'=>1,'㉹'=>1,'㉺'=>1,'㉻'=>1,'㉼'=>1,'㉽'=>1,'㉾'=>1,'㊀'=>1,'ãŠ'=>1,'㊂'=>1,'㊃'=>1,'㊄'=>1,'㊅'=>1,'㊆'=>1,'㊇'=>1,'㊈'=>1,'㊉'=>1,'㊊'=>1,'㊋'=>1,'㊌'=>1,'ãŠ'=>1,'㊎'=>1,'ãŠ'=>1,'ãŠ'=>1,'㊑'=>1,'㊒'=>1,'㊓'=>1,'㊔'=>1,'㊕'=>1,'㊖'=>1,'㊗'=>1,'㊘'=>1,'㊙'=>1,'㊚'=>1,'㊛'=>1,'㊜'=>1,'ãŠ'=>1,'㊞'=>1,'㊟'=>1,'㊠'=>1,'㊡'=>1,'㊢'=>1,'㊣'=>1,'㊤'=>1,'㊥'=>1,'㊦'=>1,'㊧'=>1,'㊨'=>1,'㊩'=>1,'㊪'=>1,'㊫'=>1,'㊬'=>1,'ãŠ'=>1,'㊮'=>1,'㊯'=>1,'㊰'=>1,'㊱'=>1,'㊲'=>1,'㊳'=>1,'㊴'=>1,'㊵'=>1,'㊶'=>1,'㊷'=>1,'㊸'=>1,'㊹'=>1,'㊺'=>1,'㊻'=>1,'㊼'=>1,'㊽'=>1,'㊾'=>1,'㊿'=>1,'ã‹€'=>1,'ã‹'=>1,'ã‹‚'=>1,'㋃'=>1,'ã‹„'=>1,'ã‹…'=>1,'㋆'=>1,'㋇'=>1,'㋈'=>1,'㋉'=>1,'㋊'=>1,'ã‹‹'=>1,'㋌'=>1,'ã‹'=>1,'㋎'=>1,'ã‹'=>1,'ã‹'=>1,'ã‹‘'=>1,'ã‹’'=>1,'ã‹“'=>1,'ã‹”'=>1,'ã‹•'=>1,'ã‹–'=>1,'ã‹—'=>1,'㋘'=>1,'ã‹™'=>1,'㋚'=>1,'ã‹›'=>1,'㋜'=>1,'ã‹'=>1,'㋞'=>1,'㋟'=>1,'ã‹ '=>1,'ã‹¡'=>1,'ã‹¢'=>1,'ã‹£'=>1,'㋤'=>1,'ã‹¥'=>1,'㋦'=>1,'ã‹§'=>1,'㋨'=>1,'ã‹©'=>1,'㋪'=>1,'ã‹«'=>1,'㋬'=>1,'ã‹'=>1,'ã‹®'=>1,'㋯'=>1,'ã‹°'=>1,'㋱'=>1,'㋲'=>1,'㋳'=>1,'ã‹´'=>1,'㋵'=>1,'ã‹¶'=>1,'ã‹·'=>1,'㋸'=>1,'㋹'=>1,'㋺'=>1,'ã‹»'=>1,'㋼'=>1,'㋽'=>1,'㋾'=>1,'㌀'=>1,'ãŒ'=>1,'㌂'=>1,'㌃'=>1,'㌄'=>1,'㌅'=>1,'㌆'=>1,'㌇'=>1,'㌈'=>1,'㌉'=>1,'㌊'=>1,'㌋'=>1,'㌌'=>1,'ãŒ'=>1,'㌎'=>1,'ãŒ'=>1,'ãŒ'=>1,'㌑'=>1,'㌒'=>1,'㌓'=>1,'㌔'=>1,'㌕'=>1,'㌖'=>1,'㌗'=>1,'㌘'=>1,'㌙'=>1,'㌚'=>1,'㌛'=>1,'㌜'=>1,'ãŒ'=>1,'㌞'=>1,'㌟'=>1,'㌠'=>1,'㌡'=>1,'㌢'=>1,'㌣'=>1,'㌤'=>1,'㌥'=>1,'㌦'=>1,'㌧'=>1,'㌨'=>1,'㌩'=>1,'㌪'=>1,'㌫'=>1,'㌬'=>1,'ãŒ'=>1,'㌮'=>1,'㌯'=>1,'㌰'=>1,'㌱'=>1,'㌲'=>1,'㌳'=>1,'㌴'=>1,'㌵'=>1,'㌶'=>1,'㌷'=>1,'㌸'=>1,'㌹'=>1,'㌺'=>1,'㌻'=>1,'㌼'=>1,'㌽'=>1,'㌾'=>1,'㌿'=>1,'ã€'=>1,'ã'=>1,'ã‚'=>1,'ãƒ'=>1,'ã„'=>1,'ã…'=>1,'ã†'=>1,'ã‡'=>1,'ãˆ'=>1,'ã‰'=>1,'ãŠ'=>1,'ã‹'=>1,'ãŒ'=>1,'ã'=>1,'ãŽ'=>1,'ã'=>1,'ã'=>1,'ã‘'=>1,'ã’'=>1,'ã“'=>1,'ã”'=>1,'ã•'=>1,'ã–'=>1,'ã—'=>1,'ã˜'=>1,'ã™'=>1,'ãš'=>1,'ã›'=>1,'ãœ'=>1,'ã'=>1,'ãž'=>1,'ãŸ'=>1,'ã '=>1,'ã¡'=>1,'ã¢'=>1,'ã£'=>1,'ã¤'=>1,'ã¥'=>1,'ã¦'=>1,'ã§'=>1,'ã¨'=>1,'ã©'=>1,'ãª'=>1,'ã«'=>1,'ã¬'=>1,'ã'=>1,'ã®'=>1,'ã¯'=>1,'ã°'=>1,'ã±'=>1,'ã²'=>1,'ã³'=>1,'ã´'=>1,'ãµ'=>1,'ã¶'=>1,'ã·'=>1,'ã¸'=>1,'ã¹'=>1,'ãº'=>1,'ã»'=>1,'ã¼'=>1,'ã½'=>1,'ã¾'=>1,'ã¿'=>1,'㎀'=>1,'ãŽ'=>1,'㎂'=>1,'㎃'=>1,'㎄'=>1,'㎅'=>1,'㎆'=>1,'㎇'=>1,'㎈'=>1,'㎉'=>1,'㎊'=>1,'㎋'=>1,'㎌'=>1,'ãŽ'=>1,'㎎'=>1,'ãŽ'=>1,'ãŽ'=>1,'㎑'=>1,'㎒'=>1,'㎓'=>1,'㎔'=>1,'㎕'=>1,'㎖'=>1,'㎗'=>1,'㎘'=>1,'㎙'=>1,'㎚'=>1,'㎛'=>1,'㎜'=>1,'ãŽ'=>1,'㎞'=>1,'㎟'=>1,'㎠'=>1,'㎡'=>1,'㎢'=>1,'㎣'=>1,'㎤'=>1,'㎥'=>1,'㎦'=>1,'㎧'=>1,'㎨'=>1,'㎩'=>1,'㎪'=>1,'㎫'=>1,'㎬'=>1,'ãŽ'=>1,'㎮'=>1,'㎯'=>1,'㎰'=>1,'㎱'=>1,'㎲'=>1,'㎳'=>1,'㎴'=>1,'㎵'=>1,'㎶'=>1,'㎷'=>1,'㎸'=>1,'㎹'=>1,'㎺'=>1,'㎻'=>1,'㎼'=>1,'㎽'=>1,'㎾'=>1,'㎿'=>1,'ã€'=>1,'ã'=>1,'ã‚'=>1,'ãƒ'=>1,'ã„'=>1,'ã…'=>1,'ã†'=>1,'ã‡'=>1,'ãˆ'=>1,'ã‰'=>1,'ãŠ'=>1,'ã‹'=>1,'ãŒ'=>1,'ã'=>1,'ãŽ'=>1,'ã'=>1,'ã'=>1,'ã‘'=>1,'ã’'=>1,'ã“'=>1,'ã”'=>1,'ã•'=>1,'ã–'=>1,'ã—'=>1,'ã˜'=>1,'ã™'=>1,'ãš'=>1,'ã›'=>1,'ãœ'=>1,'ã'=>1,'ãž'=>1,'ãŸ'=>1,'ã '=>1,'ã¡'=>1,'ã¢'=>1,'ã£'=>1,'ã¤'=>1,'ã¥'=>1,'ã¦'=>1,'ã§'=>1,'ã¨'=>1,'ã©'=>1,'ãª'=>1,'ã«'=>1,'ã¬'=>1,'ã'=>1,'ã®'=>1,'ã¯'=>1,'ã°'=>1,'ã±'=>1,'ã²'=>1,'ã³'=>1,'ã´'=>1,'ãµ'=>1,'ã¶'=>1,'ã·'=>1,'ã¸'=>1,'ã¹'=>1,'ãº'=>1,'ã»'=>1,'ã¼'=>1,'ã½'=>1,'ã¾'=>1,'ã¿'=>1,'豈'=>1,'ï¤'=>1,'車'=>1,'賈'=>1,'滑'=>1,'串'=>1,'句'=>1,'龜'=>1,'龜'=>1,'契'=>1,'金'=>1,'喇'=>1,'奈'=>1,'ï¤'=>1,'癩'=>1,'ï¤'=>1,'ï¤'=>1,'螺'=>1,'裸'=>1,'邏'=>1,'樂'=>1,'洛'=>1,'烙'=>1,'珞'=>1,'落'=>1,'酪'=>1,'駱'=>1,'亂'=>1,'卵'=>1,'ï¤'=>1,'爛'=>1,'蘭'=>1,'ï¤ '=>1,'嵐'=>1,'濫'=>1,'藍'=>1,'襤'=>1,'拉'=>1,'臘'=>1,'蠟'=>1,'廊'=>1,'朗'=>1,'浪'=>1,'狼'=>1,'郎'=>1,'ï¤'=>1,'冷'=>1,'勞'=>1,'擄'=>1,'櫓'=>1,'爐'=>1,'盧'=>1,'老'=>1,'蘆'=>1,'虜'=>1,'路'=>1,'露'=>1,'魯'=>1,'鷺'=>1,'碌'=>1,'祿'=>1,'綠'=>1,'菉'=>1,'錄'=>1,'鹿'=>1,'ï¥'=>1,'壟'=>1,'弄'=>1,'籠'=>1,'聾'=>1,'牢'=>1,'磊'=>1,'賂'=>1,'雷'=>1,'壘'=>1,'屢'=>1,'樓'=>1,'ï¥'=>1,'漏'=>1,'ï¥'=>1,'ï¥'=>1,'陋'=>1,'勒'=>1,'肋'=>1,'凜'=>1,'凌'=>1,'稜'=>1,'綾'=>1,'菱'=>1,'陵'=>1,'讀'=>1,'拏'=>1,'樂'=>1,'ï¥'=>1,'丹'=>1,'寧'=>1,'ï¥ '=>1,'率'=>1,'異'=>1,'北'=>1,'磻'=>1,'便'=>1,'復'=>1,'不'=>1,'泌'=>1,'數'=>1,'索'=>1,'參'=>1,'塞'=>1,'ï¥'=>1,'葉'=>1,'說'=>1,'殺'=>1,'辰'=>1,'沈'=>1,'拾'=>1,'若'=>1,'掠'=>1,'略'=>1,'亮'=>1,'兩'=>1,'凉'=>1,'梁'=>1,'糧'=>1,'良'=>1,'諒'=>1,'量'=>1,'勵'=>1,'呂'=>1,'ï¦'=>1,'廬'=>1,'旅'=>1,'濾'=>1,'礪'=>1,'閭'=>1,'驪'=>1,'麗'=>1,'黎'=>1,'力'=>1,'曆'=>1,'歷'=>1,'ï¦'=>1,'年'=>1,'ï¦'=>1,'ï¦'=>1,'撚'=>1,'漣'=>1,'煉'=>1,'璉'=>1,'秊'=>1,'練'=>1,'聯'=>1,'輦'=>1,'蓮'=>1,'連'=>1,'鍊'=>1,'列'=>1,'ï¦'=>1,'咽'=>1,'烈'=>1,'ï¦ '=>1,'說'=>1,'廉'=>1,'念'=>1,'捻'=>1,'殮'=>1,'簾'=>1,'獵'=>1,'令'=>1,'囹'=>1,'寧'=>1,'嶺'=>1,'怜'=>1,'ï¦'=>1,'瑩'=>1,'羚'=>1,'聆'=>1,'鈴'=>1,'零'=>1,'靈'=>1,'領'=>1,'例'=>1,'禮'=>1,'醴'=>1,'隸'=>1,'惡'=>1,'了'=>1,'僚'=>1,'寮'=>1,'尿'=>1,'料'=>1,'樂'=>1,'ï§€'=>1,'ï§'=>1,'ï§‚'=>1,'遼'=>1,'ï§„'=>1,'ï§…'=>1,'阮'=>1,'劉'=>1,'杻'=>1,'柳'=>1,'ï§Š'=>1,'ï§‹'=>1,'ï§Œ'=>1,'ï§'=>1,'ï§Ž'=>1,'ï§'=>1,'ï§'=>1,'ï§‘'=>1,'ï§’'=>1,'ï§“'=>1,'ï§”'=>1,'ï§•'=>1,'ï§–'=>1,'ï§—'=>1,'律'=>1,'ï§™'=>1,'ï§š'=>1,'ï§›'=>1,'ï§œ'=>1,'ï§'=>1,'ï§ž'=>1,'ï§Ÿ'=>1,'ï§ '=>1,'ï§¡'=>1,'ï§¢'=>1,'ï§£'=>1,'理'=>1,'ï§¥'=>1,'罹'=>1,'ï§§'=>1,'裡'=>1,'ï§©'=>1,'離'=>1,'ï§«'=>1,'溺'=>1,'ï§'=>1,'ï§®'=>1,'璘'=>1,'ï§°'=>1,'ï§±'=>1,'ï§²'=>1,'ï§³'=>1,'ï§´'=>1,'ï§µ'=>1,'ï§¶'=>1,'ï§·'=>1,'笠'=>1,'ï§¹'=>1,'狀'=>1,'ï§»'=>1,'ï§¼'=>1,'ï§½'=>1,'ï§¾'=>1,'ï§¿'=>1,'切'=>1,'ï¨'=>1,'拓'=>1,'糖'=>1,'宅'=>1,'洞'=>1,'暴'=>1,'輻'=>1,'行'=>1,'降'=>1,'見'=>1,'廓'=>1,'兀'=>1,'ï¨'=>1,'ï¨'=>1,'晴'=>1,'凞'=>1,'猪'=>1,'益'=>1,'礼'=>1,'神'=>1,'祥'=>1,'福'=>1,'靖'=>1,'ï¨'=>1,'羽'=>1,'ï¨ '=>1,'諸'=>1,'逸'=>1,'都'=>1,'飯'=>1,'飼'=>1,'館'=>1,'ï¨'=>1,'侮'=>1,'僧'=>1,'免'=>1,'勉'=>1,'勤'=>1,'卑'=>1,'喝'=>1,'嘆'=>1,'器'=>1,'塀'=>1,'墨'=>1,'層'=>1,'屮'=>1,'悔'=>1,'慨'=>1,'憎'=>1,'ï©€'=>1,'ï©'=>1,'ï©‚'=>1,'暑'=>1,'ï©„'=>1,'ï©…'=>1,'渚'=>1,'漢'=>1,'煮'=>1,'爫'=>1,'琢'=>1,'ï©‹'=>1,'社'=>1,'ï©'=>1,'祈'=>1,'ï©'=>1,'ï©'=>1,'ï©‘'=>1,'ï©’'=>1,'ï©“'=>1,'ï©”'=>1,'ï©•'=>1,'ï©–'=>1,'ï©—'=>1,'縉'=>1,'ï©™'=>1,'署'=>1,'ï©›'=>1,'臭'=>1,'ï©'=>1,'艹'=>1,'著'=>1,'ï© '=>1,'ï©¡'=>1,'ï©¢'=>1,'ï©£'=>1,'賓'=>1,'ï©¥'=>1,'辶'=>1,'ï©§'=>1,'難'=>1,'ï©©'=>1,'頻'=>1,'ï©°'=>1,'况'=>1,'全'=>1,'侀'=>1,'ï©´'=>1,'冀'=>1,'ï©¶'=>1,'ï©·'=>1,'喝'=>1,'啕'=>1,'喙'=>1,'ï©»'=>1,'塚'=>1,'墳'=>1,'奄'=>1,'ï©¿'=>1,'婢'=>1,'ïª'=>1,'廒'=>1,'廙'=>1,'彩'=>1,'徭'=>1,'惘'=>1,'慎'=>1,'愈'=>1,'憎'=>1,'慠'=>1,'懲'=>1,'戴'=>1,'ïª'=>1,'搜'=>1,'ïª'=>1,'ïª'=>1,'晴'=>1,'朗'=>1,'望'=>1,'杖'=>1,'歹'=>1,'殺'=>1,'流'=>1,'滛'=>1,'滋'=>1,'漢'=>1,'瀞'=>1,'煮'=>1,'ïª'=>1,'爵'=>1,'犯'=>1,'ïª '=>1,'瑱'=>1,'甆'=>1,'画'=>1,'瘝'=>1,'瘟'=>1,'益'=>1,'盛'=>1,'直'=>1,'睊'=>1,'着'=>1,'磌'=>1,'窱'=>1,'ïª'=>1,'类'=>1,'絛'=>1,'練'=>1,'缾'=>1,'者'=>1,'荒'=>1,'華'=>1,'蝹'=>1,'襁'=>1,'覆'=>1,'視'=>1,'調'=>1,'諸'=>1,'請'=>1,'謁'=>1,'諾'=>1,'諭'=>1,'謹'=>1,'ï«€'=>1,'ï«'=>1,'ï«‚'=>1,'遲'=>1,'ï«„'=>1,'ï«…'=>1,'陼'=>1,'難'=>1,'靖'=>1,'韛'=>1,'響'=>1,'ï«‹'=>1,'頻'=>1,'ï«'=>1,'龜'=>1,'ï«'=>1,'ï«'=>1,'ï«‘'=>1,'ï«’'=>1,'ï«“'=>1,'ï«”'=>1,'ï«•'=>1,'ï«–'=>1,'ï«—'=>1,'齃'=>1,'ï«™'=>1,'ff'=>1,'ï¬'=>1,'fl'=>1,'ffi'=>1,'ffl'=>1,'ſt'=>1,'st'=>1,'ﬓ'=>1,'ﬔ'=>1,'ﬕ'=>1,'ﬖ'=>1,'ﬗ'=>1,'ï¬'=>1,'ײַ'=>1,'ï¬ '=>1,'ﬡ'=>1,'ﬢ'=>1,'ﬣ'=>1,'ﬤ'=>1,'ﬥ'=>1,'ﬦ'=>1,'ﬧ'=>1,'ﬨ'=>1,'﬩'=>1,'שׁ'=>1,'שׂ'=>1,'שּׁ'=>1,'ï¬'=>1,'אַ'=>1,'אָ'=>1,'אּ'=>1,'בּ'=>1,'גּ'=>1,'דּ'=>1,'הּ'=>1,'וּ'=>1,'זּ'=>1,'טּ'=>1,'יּ'=>1,'ךּ'=>1,'כּ'=>1,'לּ'=>1,'מּ'=>1,'ï€'=>1,'ï'=>1,'ïƒ'=>1,'ï„'=>1,'ï†'=>1,'ï‡'=>1,'ïˆ'=>1,'ï‰'=>1,'ïŠ'=>1,'ï‹'=>1,'ïŒ'=>1,'ï'=>1,'ïŽ'=>1,'ï'=>1,'ï'=>1,'ï‘'=>1,'ï’'=>1,'ï“'=>1,'ï”'=>1,'ï•'=>1,'ï–'=>1,'ï—'=>1,'ï˜'=>1,'ï™'=>1,'ïš'=>1,'ï›'=>1,'ïœ'=>1,'ï'=>1,'ïž'=>1,'ïŸ'=>1,'ï '=>1,'ï¡'=>1,'ï¢'=>1,'ï£'=>1,'ï¤'=>1,'ï¥'=>1,'ï¦'=>1,'ï§'=>1,'ï¨'=>1,'ï©'=>1,'ïª'=>1,'ï«'=>1,'ï¬'=>1,'ï'=>1,'ï®'=>1,'ï¯'=>1,'ï°'=>1,'ï±'=>1,'ï²'=>1,'ï³'=>1,'ï´'=>1,'ïµ'=>1,'ï¶'=>1,'ï·'=>1,'ï¸'=>1,'ï¹'=>1,'ïº'=>1,'ï»'=>1,'ï¼'=>1,'ï½'=>1,'ï¾'=>1,'ï¿'=>1,'ﮀ'=>1,'ï®'=>1,'ﮂ'=>1,'ﮃ'=>1,'ﮄ'=>1,'ï®…'=>1,'ﮆ'=>1,'ﮇ'=>1,'ﮈ'=>1,'ﮉ'=>1,'ﮊ'=>1,'ﮋ'=>1,'ﮌ'=>1,'ï®'=>1,'ﮎ'=>1,'ï®'=>1,'ï®'=>1,'ﮑ'=>1,'ï®’'=>1,'ﮓ'=>1,'ï®”'=>1,'ﮕ'=>1,'ï®–'=>1,'ï®—'=>1,'ﮘ'=>1,'ï®™'=>1,'ﮚ'=>1,'ï®›'=>1,'ﮜ'=>1,'ï®'=>1,'ﮞ'=>1,'ﮟ'=>1,'ï® '=>1,'ﮡ'=>1,'ﮢ'=>1,'ﮣ'=>1,'ﮤ'=>1,'ﮥ'=>1,'ﮦ'=>1,'ï®§'=>1,'ﮨ'=>1,'ﮩ'=>1,'ﮪ'=>1,'ﮫ'=>1,'ﮬ'=>1,'ï®'=>1,'ï®®'=>1,'ﮯ'=>1,'ï®°'=>1,'ï®±'=>1,'ﯓ'=>1,'ﯔ'=>1,'ﯕ'=>1,'ﯖ'=>1,'ﯗ'=>1,'ﯘ'=>1,'ﯙ'=>1,'ﯚ'=>1,'ﯛ'=>1,'ﯜ'=>1,'ï¯'=>1,'ﯞ'=>1,'ﯟ'=>1,'ï¯ '=>1,'ﯡ'=>1,'ﯢ'=>1,'ﯣ'=>1,'ﯤ'=>1,'ﯥ'=>1,'ﯦ'=>1,'ﯧ'=>1,'ﯨ'=>1,'ﯩ'=>1,'ﯪ'=>1,'ﯫ'=>1,'ﯬ'=>1,'ï¯'=>1,'ﯮ'=>1,'ﯯ'=>1,'ﯰ'=>1,'ﯱ'=>1,'ﯲ'=>1,'ﯳ'=>1,'ﯴ'=>1,'ﯵ'=>1,'ﯶ'=>1,'ﯷ'=>1,'ﯸ'=>1,'ﯹ'=>1,'ﯺ'=>1,'ﯻ'=>1,'ﯼ'=>1,'ﯽ'=>1,'ﯾ'=>1,'ﯿ'=>1,'ï°€'=>1,'ï°'=>1,'ï°‚'=>1,'ï°ƒ'=>1,'ï°„'=>1,'ï°…'=>1,'ï°†'=>1,'ï°‡'=>1,'ï°ˆ'=>1,'ï°‰'=>1,'ï°Š'=>1,'ï°‹'=>1,'ï°Œ'=>1,'ï°'=>1,'ï°Ž'=>1,'ï°'=>1,'ï°'=>1,'ï°‘'=>1,'ï°’'=>1,'ï°“'=>1,'ï°”'=>1,'ï°•'=>1,'ï°–'=>1,'ï°—'=>1,'ï°˜'=>1,'ï°™'=>1,'ï°š'=>1,'ï°›'=>1,'ï°œ'=>1,'ï°'=>1,'ï°ž'=>1,'ï°Ÿ'=>1,'ï° '=>1,'ï°¡'=>1,'ï°¢'=>1,'ï°£'=>1,'ï°¤'=>1,'ï°¥'=>1,'ï°¦'=>1,'ï°§'=>1,'ï°¨'=>1,'ï°©'=>1,'ï°ª'=>1,'ï°«'=>1,'ï°¬'=>1,'ï°'=>1,'ï°®'=>1,'ï°¯'=>1,'ï°°'=>1,'ï°±'=>1,'ï°²'=>1,'ï°³'=>1,'ï°´'=>1,'ï°µ'=>1,'ï°¶'=>1,'ï°·'=>1,'ï°¸'=>1,'ï°¹'=>1,'ï°º'=>1,'ï°»'=>1,'ï°¼'=>1,'ï°½'=>1,'ï°¾'=>1,'ï°¿'=>1,'ï±€'=>1,'ï±'=>1,'ﱂ'=>1,'ﱃ'=>1,'ﱄ'=>1,'ï±…'=>1,'ﱆ'=>1,'ﱇ'=>1,'ﱈ'=>1,'ﱉ'=>1,'ﱊ'=>1,'ﱋ'=>1,'ﱌ'=>1,'ï±'=>1,'ﱎ'=>1,'ï±'=>1,'ï±'=>1,'ﱑ'=>1,'ï±’'=>1,'ﱓ'=>1,'ï±”'=>1,'ﱕ'=>1,'ï±–'=>1,'ï±—'=>1,'ﱘ'=>1,'ï±™'=>1,'ﱚ'=>1,'ï±›'=>1,'ﱜ'=>1,'ï±'=>1,'ﱞ'=>1,'ﱟ'=>1,'ï± '=>1,'ﱡ'=>1,'ï±¢'=>1,'ï±£'=>1,'ﱤ'=>1,'ï±¥'=>1,'ﱦ'=>1,'ï±§'=>1,'ﱨ'=>1,'ﱩ'=>1,'ﱪ'=>1,'ﱫ'=>1,'ﱬ'=>1,'ï±'=>1,'ï±®'=>1,'ﱯ'=>1,'ï±°'=>1,'ï±±'=>1,'ï±²'=>1,'ï±³'=>1,'ï±´'=>1,'ï±µ'=>1,'ï±¶'=>1,'ï±·'=>1,'ﱸ'=>1,'ï±¹'=>1,'ﱺ'=>1,'ï±»'=>1,'ï±¼'=>1,'ï±½'=>1,'ï±¾'=>1,'ﱿ'=>1,'ï²€'=>1,'ï²'=>1,'ﲂ'=>1,'ﲃ'=>1,'ﲄ'=>1,'ï²…'=>1,'ﲆ'=>1,'ﲇ'=>1,'ﲈ'=>1,'ﲉ'=>1,'ﲊ'=>1,'ﲋ'=>1,'ﲌ'=>1,'ï²'=>1,'ﲎ'=>1,'ï²'=>1,'ï²'=>1,'ﲑ'=>1,'ï²’'=>1,'ﲓ'=>1,'ï²”'=>1,'ﲕ'=>1,'ï²–'=>1,'ï²—'=>1,'ﲘ'=>1,'ï²™'=>1,'ﲚ'=>1,'ï²›'=>1,'ﲜ'=>1,'ï²'=>1,'ﲞ'=>1,'ﲟ'=>1,'ï² '=>1,'ﲡ'=>1,'ï²¢'=>1,'ï²£'=>1,'ﲤ'=>1,'ï²¥'=>1,'ﲦ'=>1,'ï²§'=>1,'ﲨ'=>1,'ﲩ'=>1,'ﲪ'=>1,'ﲫ'=>1,'ﲬ'=>1,'ï²'=>1,'ï²®'=>1,'ﲯ'=>1,'ï²°'=>1,'ï²±'=>1,'ï²²'=>1,'ï²³'=>1,'ï²´'=>1,'ï²µ'=>1,'ï²¶'=>1,'ï²·'=>1,'ﲸ'=>1,'ï²¹'=>1,'ﲺ'=>1,'ï²»'=>1,'ï²¼'=>1,'ï²½'=>1,'ï²¾'=>1,'ﲿ'=>1,'ï³€'=>1,'ï³'=>1,'ﳂ'=>1,'ﳃ'=>1,'ﳄ'=>1,'ï³…'=>1,'ﳆ'=>1,'ﳇ'=>1,'ﳈ'=>1,'ﳉ'=>1,'ﳊ'=>1,'ﳋ'=>1,'ﳌ'=>1,'ï³'=>1,'ﳎ'=>1,'ï³'=>1,'ï³'=>1,'ﳑ'=>1,'ï³’'=>1,'ﳓ'=>1,'ï³”'=>1,'ﳕ'=>1,'ï³–'=>1,'ï³—'=>1,'ﳘ'=>1,'ï³™'=>1,'ﳚ'=>1,'ï³›'=>1,'ﳜ'=>1,'ï³'=>1,'ﳞ'=>1,'ﳟ'=>1,'ï³ '=>1,'ﳡ'=>1,'ï³¢'=>1,'ï³£'=>1,'ﳤ'=>1,'ï³¥'=>1,'ﳦ'=>1,'ï³§'=>1,'ﳨ'=>1,'ﳩ'=>1,'ﳪ'=>1,'ﳫ'=>1,'ﳬ'=>1,'ï³'=>1,'ï³®'=>1,'ﳯ'=>1,'ï³°'=>1,'ï³±'=>1,'ï³²'=>1,'ï³³'=>1,'ï³´'=>1,'ï³µ'=>1,'ï³¶'=>1,'ï³·'=>1,'ﳸ'=>1,'ï³¹'=>1,'ﳺ'=>1,'ï³»'=>1,'ï³¼'=>1,'ï³½'=>1,'ï³¾'=>1,'ﳿ'=>1,'ï´€'=>1,'ï´'=>1,'ï´‚'=>1,'ï´ƒ'=>1,'ï´„'=>1,'ï´…'=>1,'ï´†'=>1,'ï´‡'=>1,'ï´ˆ'=>1,'ï´‰'=>1,'ï´Š'=>1,'ï´‹'=>1,'ï´Œ'=>1,'ï´'=>1,'ï´Ž'=>1,'ï´'=>1,'ï´'=>1,'ï´‘'=>1,'ï´’'=>1,'ï´“'=>1,'ï´”'=>1,'ï´•'=>1,'ï´–'=>1,'ï´—'=>1,'ï´˜'=>1,'ï´™'=>1,'ï´š'=>1,'ï´›'=>1,'ï´œ'=>1,'ï´'=>1,'ï´ž'=>1,'ï´Ÿ'=>1,'ï´ '=>1,'ï´¡'=>1,'ï´¢'=>1,'ï´£'=>1,'ï´¤'=>1,'ï´¥'=>1,'ï´¦'=>1,'ï´§'=>1,'ï´¨'=>1,'ï´©'=>1,'ï´ª'=>1,'ï´«'=>1,'ï´¬'=>1,'ï´'=>1,'ï´®'=>1,'ï´¯'=>1,'ï´°'=>1,'ï´±'=>1,'ï´²'=>1,'ï´³'=>1,'ï´´'=>1,'ï´µ'=>1,'ï´¶'=>1,'ï´·'=>1,'ï´¸'=>1,'ï´¹'=>1,'ï´º'=>1,'ï´»'=>1,'ï´¼'=>1,'ï´½'=>1,'ïµ'=>1,'ﵑ'=>1,'ïµ’'=>1,'ﵓ'=>1,'ïµ”'=>1,'ﵕ'=>1,'ïµ–'=>1,'ïµ—'=>1,'ﵘ'=>1,'ïµ™'=>1,'ﵚ'=>1,'ïµ›'=>1,'ﵜ'=>1,'ïµ'=>1,'ﵞ'=>1,'ﵟ'=>1,'ïµ '=>1,'ﵡ'=>1,'ïµ¢'=>1,'ïµ£'=>1,'ﵤ'=>1,'ïµ¥'=>1,'ﵦ'=>1,'ïµ§'=>1,'ﵨ'=>1,'ﵩ'=>1,'ﵪ'=>1,'ﵫ'=>1,'ﵬ'=>1,'ïµ'=>1,'ïµ®'=>1,'ﵯ'=>1,'ïµ°'=>1,'ïµ±'=>1,'ïµ²'=>1,'ïµ³'=>1,'ïµ´'=>1,'ïµµ'=>1,'ïµ¶'=>1,'ïµ·'=>1,'ﵸ'=>1,'ïµ¹'=>1,'ﵺ'=>1,'ïµ»'=>1,'ïµ¼'=>1,'ïµ½'=>1,'ïµ¾'=>1,'ﵿ'=>1,'ï¶€'=>1,'ï¶'=>1,'ï¶‚'=>1,'ﶃ'=>1,'ï¶„'=>1,'ï¶…'=>1,'ﶆ'=>1,'ﶇ'=>1,'ﶈ'=>1,'ﶉ'=>1,'ï¶Š'=>1,'ï¶‹'=>1,'ï¶Œ'=>1,'ï¶'=>1,'ï¶Ž'=>1,'ï¶'=>1,'ï¶’'=>1,'ï¶“'=>1,'ï¶”'=>1,'ï¶•'=>1,'ï¶–'=>1,'ï¶—'=>1,'ﶘ'=>1,'ï¶™'=>1,'ï¶š'=>1,'ï¶›'=>1,'ï¶œ'=>1,'ï¶'=>1,'ï¶ž'=>1,'ï¶Ÿ'=>1,'ï¶ '=>1,'ï¶¡'=>1,'ï¶¢'=>1,'ï¶£'=>1,'ﶤ'=>1,'ï¶¥'=>1,'ﶦ'=>1,'ï¶§'=>1,'ﶨ'=>1,'ï¶©'=>1,'ﶪ'=>1,'ï¶«'=>1,'ﶬ'=>1,'ï¶'=>1,'ï¶®'=>1,'ﶯ'=>1,'ï¶°'=>1,'ï¶±'=>1,'ï¶²'=>1,'ï¶³'=>1,'ï¶´'=>1,'ï¶µ'=>1,'ï¶¶'=>1,'ï¶·'=>1,'ﶸ'=>1,'ï¶¹'=>1,'ﶺ'=>1,'ï¶»'=>1,'ï¶¼'=>1,'ï¶½'=>1,'ï¶¾'=>1,'ï¶¿'=>1,'ï·€'=>1,'ï·'=>1,'ï·‚'=>1,'ï·ƒ'=>1,'ï·„'=>1,'ï·…'=>1,'ï·†'=>1,'ï·‡'=>1,'ï·°'=>1,'ï·±'=>1,'ï·²'=>1,'ï·³'=>1,'ï·´'=>1,'ï·µ'=>1,'ï·¶'=>1,'ï··'=>1,'ï·¸'=>1,'ï·¹'=>1,'ï·º'=>1,'ï·»'=>1,'ï·¼'=>1,'ï¸'=>1,'︑'=>1,'︒'=>1,'︓'=>1,'︔'=>1,'︕'=>1,'︖'=>1,'︗'=>1,'︘'=>1,'︙'=>1,'︰'=>1,'︱'=>1,'︲'=>1,'︳'=>1,'︴'=>1,'︵'=>1,'︶'=>1,'︷'=>1,'︸'=>1,'︹'=>1,'︺'=>1,'︻'=>1,'︼'=>1,'︽'=>1,'︾'=>1,'︿'=>1,'ï¹€'=>1,'ï¹'=>1,'﹂'=>1,'﹃'=>1,'﹄'=>1,'﹇'=>1,'﹈'=>1,'﹉'=>1,'﹊'=>1,'﹋'=>1,'﹌'=>1,'ï¹'=>1,'﹎'=>1,'ï¹'=>1,'ï¹'=>1,'﹑'=>1,'ï¹’'=>1,'ï¹”'=>1,'﹕'=>1,'ï¹–'=>1,'ï¹—'=>1,'﹘'=>1,'ï¹™'=>1,'﹚'=>1,'ï¹›'=>1,'﹜'=>1,'ï¹'=>1,'﹞'=>1,'﹟'=>1,'ï¹ '=>1,'﹡'=>1,'ï¹¢'=>1,'ï¹£'=>1,'﹤'=>1,'ï¹¥'=>1,'﹦'=>1,'﹨'=>1,'﹩'=>1,'﹪'=>1,'﹫'=>1,'ï¹°'=>1,'ï¹±'=>1,'ï¹²'=>1,'ï¹´'=>1,'ï¹¶'=>1,'ï¹·'=>1,'ﹸ'=>1,'ï¹¹'=>1,'ﹺ'=>1,'ï¹»'=>1,'ï¹¼'=>1,'ï¹½'=>1,'ï¹¾'=>1,'ﹿ'=>1,'ﺀ'=>1,'ïº'=>1,'ﺂ'=>1,'ﺃ'=>1,'ﺄ'=>1,'ﺅ'=>1,'ﺆ'=>1,'ﺇ'=>1,'ﺈ'=>1,'ﺉ'=>1,'ﺊ'=>1,'ﺋ'=>1,'ﺌ'=>1,'ïº'=>1,'ﺎ'=>1,'ïº'=>1,'ïº'=>1,'ﺑ'=>1,'ﺒ'=>1,'ﺓ'=>1,'ﺔ'=>1,'ﺕ'=>1,'ﺖ'=>1,'ﺗ'=>1,'ﺘ'=>1,'ﺙ'=>1,'ﺚ'=>1,'ﺛ'=>1,'ﺜ'=>1,'ïº'=>1,'ﺞ'=>1,'ﺟ'=>1,'ïº '=>1,'ﺡ'=>1,'ﺢ'=>1,'ﺣ'=>1,'ﺤ'=>1,'ﺥ'=>1,'ﺦ'=>1,'ﺧ'=>1,'ﺨ'=>1,'ﺩ'=>1,'ﺪ'=>1,'ﺫ'=>1,'ﺬ'=>1,'ïº'=>1,'ﺮ'=>1,'ﺯ'=>1,'ﺰ'=>1,'ﺱ'=>1,'ﺲ'=>1,'ﺳ'=>1,'ﺴ'=>1,'ﺵ'=>1,'ﺶ'=>1,'ﺷ'=>1,'ﺸ'=>1,'ﺹ'=>1,'ﺺ'=>1,'ﺻ'=>1,'ﺼ'=>1,'ﺽ'=>1,'ﺾ'=>1,'ﺿ'=>1,'ﻀ'=>1,'ï»'=>1,'ﻂ'=>1,'ﻃ'=>1,'ﻄ'=>1,'ï»…'=>1,'ﻆ'=>1,'ﻇ'=>1,'ﻈ'=>1,'ﻉ'=>1,'ﻊ'=>1,'ﻋ'=>1,'ﻌ'=>1,'ï»'=>1,'ﻎ'=>1,'ï»'=>1,'ï»'=>1,'ﻑ'=>1,'ï»’'=>1,'ﻓ'=>1,'ï»”'=>1,'ﻕ'=>1,'ï»–'=>1,'ï»—'=>1,'ﻘ'=>1,'ï»™'=>1,'ﻚ'=>1,'ï»›'=>1,'ﻜ'=>1,'ï»'=>1,'ﻞ'=>1,'ﻟ'=>1,'ï» '=>1,'ﻡ'=>1,'ﻢ'=>1,'ﻣ'=>1,'ﻤ'=>1,'ﻥ'=>1,'ﻦ'=>1,'ï»§'=>1,'ﻨ'=>1,'ﻩ'=>1,'ﻪ'=>1,'ﻫ'=>1,'ﻬ'=>1,'ï»'=>1,'ï»®'=>1,'ﻯ'=>1,'ï»°'=>1,'ï»±'=>1,'ﻲ'=>1,'ﻳ'=>1,'ï»´'=>1,'ﻵ'=>1,'ï»¶'=>1,'ï»·'=>1,'ﻸ'=>1,'ﻹ'=>1,'ﻺ'=>1,'ï»»'=>1,'ﻼ'=>1,'ï¼'=>1,'"'=>1,'#'=>1,'$'=>1,'ï¼…'=>1,'&'=>1,'''=>1,'('=>1,')'=>1,'*'=>1,'+'=>1,','=>1,'ï¼'=>1,'.'=>1,'ï¼'=>1,'ï¼'=>1,'1'=>1,'ï¼’'=>1,'3'=>1,'ï¼”'=>1,'5'=>1,'ï¼–'=>1,'ï¼—'=>1,'8'=>1,'ï¼™'=>1,':'=>1,'ï¼›'=>1,'<'=>1,'ï¼'=>1,'>'=>1,'?'=>1,'ï¼ '=>1,'A'=>1,'ï¼¢'=>1,'ï¼£'=>1,'D'=>1,'ï¼¥'=>1,'F'=>1,'ï¼§'=>1,'H'=>1,'I'=>1,'J'=>1,'K'=>1,'L'=>1,'ï¼'=>1,'ï¼®'=>1,'O'=>1,'ï¼°'=>1,'ï¼±'=>1,'ï¼²'=>1,'ï¼³'=>1,'ï¼´'=>1,'ï¼µ'=>1,'ï¼¶'=>1,'ï¼·'=>1,'X'=>1,'ï¼¹'=>1,'Z'=>1,'ï¼»'=>1,'ï¼¼'=>1,'ï¼½'=>1,'ï¼¾'=>1,'_'=>1,'ï½€'=>1,'ï½'=>1,'b'=>1,'c'=>1,'d'=>1,'ï½…'=>1,'f'=>1,'g'=>1,'h'=>1,'i'=>1,'j'=>1,'k'=>1,'l'=>1,'ï½'=>1,'n'=>1,'ï½'=>1,'ï½'=>1,'q'=>1,'ï½’'=>1,'s'=>1,'ï½”'=>1,'u'=>1,'ï½–'=>1,'ï½—'=>1,'x'=>1,'ï½™'=>1,'z'=>1,'ï½›'=>1,'|'=>1,'ï½'=>1,'~'=>1,'⦅'=>1,'ï½ '=>1,'。'=>1,'ï½¢'=>1,'ï½£'=>1,'、'=>1,'ï½¥'=>1,'ヲ'=>1,'ï½§'=>1,'ィ'=>1,'ゥ'=>1,'ェ'=>1,'ォ'=>1,'ャ'=>1,'ï½'=>1,'ï½®'=>1,'ッ'=>1,'ï½°'=>1,'ï½±'=>1,'ï½²'=>1,'ï½³'=>1,'ï½´'=>1,'ï½µ'=>1,'ï½¶'=>1,'ï½·'=>1,'ク'=>1,'ï½¹'=>1,'コ'=>1,'ï½»'=>1,'ï½¼'=>1,'ï½½'=>1,'ï½¾'=>1,'ソ'=>1,'ï¾€'=>1,'ï¾'=>1,'ツ'=>1,'テ'=>1,'ト'=>1,'ï¾…'=>1,'ニ'=>1,'ヌ'=>1,'ネ'=>1,'ノ'=>1,'ハ'=>1,'ヒ'=>1,'フ'=>1,'ï¾'=>1,'ホ'=>1,'ï¾'=>1,'ï¾'=>1,'ム'=>1,'ï¾’'=>1,'モ'=>1,'ï¾”'=>1,'ユ'=>1,'ï¾–'=>1,'ï¾—'=>1,'リ'=>1,'ï¾™'=>1,'レ'=>1,'ï¾›'=>1,'ワ'=>1,'ï¾'=>1,'゙'=>1,'゚'=>1,'ï¾ '=>1,'ᄀ'=>1,'ï¾¢'=>1,'ï¾£'=>1,'ᄂ'=>1,'ï¾¥'=>1,'ᆭ'=>1,'ï¾§'=>1,'ᄄ'=>1,'ᄅ'=>1,'ᆰ'=>1,'ᆱ'=>1,'ᆲ'=>1,'ï¾'=>1,'ï¾®'=>1,'ᆵ'=>1,'ï¾°'=>1,'ï¾±'=>1,'ï¾²'=>1,'ï¾³'=>1,'ï¾´'=>1,'ï¾µ'=>1,'ï¾¶'=>1,'ï¾·'=>1,'ᄌ'=>1,'ï¾¹'=>1,'ᄎ'=>1,'ï¾»'=>1,'ï¾¼'=>1,'ï¾½'=>1,'ï¾¾'=>1,'ï¿‚'=>1,'ᅢ'=>1,'ï¿„'=>1,'ï¿…'=>1,'ᅥ'=>1,'ᅦ'=>1,'ᅧ'=>1,'ï¿‹'=>1,'ᅩ'=>1,'ï¿'=>1,'ᅫ'=>1,'ï¿'=>1,'ï¿’'=>1,'ï¿“'=>1,'ï¿”'=>1,'ï¿•'=>1,'ï¿–'=>1,'ï¿—'=>1,'ᅳ'=>1,'ï¿›'=>1,'ᅵ'=>1,'ï¿ '=>1,'ï¿¡'=>1,'ï¿¢'=>1,'ï¿£'=>1,'¦'=>1,'ï¿¥'=>1,'₩'=>1,'│'=>1,'ï¿©'=>1,'↑'=>1,'ï¿«'=>1,'↓'=>1,'ï¿'=>1,'ï¿®'=>1,'ð…ž'=>1,'ð…Ÿ'=>1,'ð… '=>1,'ð…¡'=>1,'ð…¢'=>1,'ð…£'=>1,'ð…¤'=>1,'ð†»'=>1,'ð†¼'=>1,'ð†½'=>1,'ð†¾'=>1,'ð†¿'=>1,'ð‡€'=>1,'ð€'=>1,'ð'=>1,'ð‚'=>1,'ðƒ'=>1,'ð„'=>1,'ð…'=>1,'ð†'=>1,'ð‡'=>1,'ðˆ'=>1,'ð‰'=>1,'ðŠ'=>1,'ð‹'=>1,'ðŒ'=>1,'ð'=>1,'ðŽ'=>1,'ð'=>1,'ð'=>1,'ð‘'=>1,'ð’'=>1,'ð“'=>1,'ð”'=>1,'ð•'=>1,'ð–'=>1,'ð—'=>1,'ð˜'=>1,'ð™'=>1,'ðš'=>1,'ð›'=>1,'ðœ'=>1,'ð'=>1,'ðž'=>1,'ðŸ'=>1,'ð '=>1,'ð¡'=>1,'ð¢'=>1,'ð£'=>1,'ð¤'=>1,'ð¥'=>1,'ð¦'=>1,'ð§'=>1,'ð¨'=>1,'ð©'=>1,'ðª'=>1,'ð«'=>1,'ð¬'=>1,'ð'=>1,'ð®'=>1,'ð¯'=>1,'ð°'=>1,'ð±'=>1,'ð²'=>1,'ð³'=>1,'ð´'=>1,'ðµ'=>1,'ð¶'=>1,'ð·'=>1,'ð¸'=>1,'ð¹'=>1,'ðº'=>1,'ð»'=>1,'ð¼'=>1,'ð½'=>1,'ð¾'=>1,'ð¿'=>1,'ð‘€'=>1,'ð‘'=>1,'ð‘‚'=>1,'ð‘ƒ'=>1,'ð‘„'=>1,'ð‘…'=>1,'ð‘†'=>1,'ð‘‡'=>1,'ð‘ˆ'=>1,'ð‘‰'=>1,'ð‘Š'=>1,'ð‘‹'=>1,'ð‘Œ'=>1,'ð‘'=>1,'ð‘Ž'=>1,'ð‘'=>1,'ð‘'=>1,'ð‘‘'=>1,'ð‘’'=>1,'ð‘“'=>1,'ð‘”'=>1,'ð‘–'=>1,'ð‘—'=>1,'ð‘˜'=>1,'ð‘™'=>1,'ð‘š'=>1,'ð‘›'=>1,'ð‘œ'=>1,'ð‘'=>1,'ð‘ž'=>1,'ð‘Ÿ'=>1,'ð‘ '=>1,'ð‘¡'=>1,'ð‘¢'=>1,'ð‘£'=>1,'ð‘¤'=>1,'ð‘¥'=>1,'ð‘¦'=>1,'ð‘§'=>1,'ð‘¨'=>1,'ð‘©'=>1,'ð‘ª'=>1,'ð‘«'=>1,'ð‘¬'=>1,'ð‘'=>1,'ð‘®'=>1,'ð‘¯'=>1,'ð‘°'=>1,'ð‘±'=>1,'ð‘²'=>1,'ð‘³'=>1,'ð‘´'=>1,'ð‘µ'=>1,'ð‘¶'=>1,'ð‘·'=>1,'ð‘¸'=>1,'ð‘¹'=>1,'ð‘º'=>1,'ð‘»'=>1,'ð‘¼'=>1,'ð‘½'=>1,'ð‘¾'=>1,'ð‘¿'=>1,'ð’€'=>1,'ð’'=>1,'ð’‚'=>1,'ð’ƒ'=>1,'ð’„'=>1,'ð’…'=>1,'ð’†'=>1,'ð’‡'=>1,'ð’ˆ'=>1,'ð’‰'=>1,'ð’Š'=>1,'ð’‹'=>1,'ð’Œ'=>1,'ð’'=>1,'ð’Ž'=>1,'ð’'=>1,'ð’'=>1,'ð’‘'=>1,'ð’’'=>1,'ð’“'=>1,'ð’”'=>1,'ð’•'=>1,'ð’–'=>1,'ð’—'=>1,'ð’˜'=>1,'ð’™'=>1,'ð’š'=>1,'ð’›'=>1,'ð’œ'=>1,'ð’ž'=>1,'ð’Ÿ'=>1,'ð’¢'=>1,'ð’¥'=>1,'ð’¦'=>1,'ð’©'=>1,'ð’ª'=>1,'ð’«'=>1,'ð’¬'=>1,'ð’®'=>1,'ð’¯'=>1,'ð’°'=>1,'ð’±'=>1,'ð’²'=>1,'ð’³'=>1,'ð’´'=>1,'ð’µ'=>1,'ð’¶'=>1,'ð’·'=>1,'ð’¸'=>1,'ð’¹'=>1,'ð’»'=>1,'ð’½'=>1,'ð’¾'=>1,'ð’¿'=>1,'ð“€'=>1,'ð“'=>1,'ð“‚'=>1,'ð“ƒ'=>1,'ð“…'=>1,'ð“†'=>1,'ð“‡'=>1,'ð“ˆ'=>1,'ð“‰'=>1,'ð“Š'=>1,'ð“‹'=>1,'ð“Œ'=>1,'ð“'=>1,'ð“Ž'=>1,'ð“'=>1,'ð“'=>1,'ð“‘'=>1,'ð“’'=>1,'ð““'=>1,'ð“”'=>1,'ð“•'=>1,'ð“–'=>1,'ð“—'=>1,'ð“˜'=>1,'ð“™'=>1,'ð“š'=>1,'ð“›'=>1,'ð“œ'=>1,'ð“'=>1,'ð“ž'=>1,'ð“Ÿ'=>1,'ð“ '=>1,'ð“¡'=>1,'ð“¢'=>1,'ð“£'=>1,'ð“¤'=>1,'ð“¥'=>1,'ð“¦'=>1,'ð“§'=>1,'ð“¨'=>1,'ð“©'=>1,'ð“ª'=>1,'ð“«'=>1,'ð“¬'=>1,'ð“'=>1,'ð“®'=>1,'ð“¯'=>1,'ð“°'=>1,'ð“±'=>1,'ð“²'=>1,'ð“³'=>1,'ð“´'=>1,'ð“µ'=>1,'ð“¶'=>1,'ð“·'=>1,'ð“¸'=>1,'ð“¹'=>1,'ð“º'=>1,'ð“»'=>1,'ð“¼'=>1,'ð“½'=>1,'ð“¾'=>1,'ð“¿'=>1,'ð”€'=>1,'ð”'=>1,'ð”‚'=>1,'ð”ƒ'=>1,'ð”„'=>1,'ð”…'=>1,'ð”‡'=>1,'ð”ˆ'=>1,'ð”‰'=>1,'ð”Š'=>1,'ð”'=>1,'ð”Ž'=>1,'ð”'=>1,'ð”'=>1,'ð”‘'=>1,'ð”’'=>1,'ð”“'=>1,'ð””'=>1,'ð”–'=>1,'ð”—'=>1,'ð”˜'=>1,'ð”™'=>1,'ð”š'=>1,'ð”›'=>1,'ð”œ'=>1,'ð”ž'=>1,'ð”Ÿ'=>1,'ð” '=>1,'ð”¡'=>1,'ð”¢'=>1,'ð”£'=>1,'ð”¤'=>1,'ð”¥'=>1,'ð”¦'=>1,'ð”§'=>1,'ð”¨'=>1,'ð”©'=>1,'ð”ª'=>1,'ð”«'=>1,'ð”¬'=>1,'ð”'=>1,'ð”®'=>1,'ð”¯'=>1,'ð”°'=>1,'ð”±'=>1,'ð”²'=>1,'ð”³'=>1,'ð”´'=>1,'ð”µ'=>1,'ð”¶'=>1,'ð”·'=>1,'ð”¸'=>1,'ð”¹'=>1,'ð”»'=>1,'ð”¼'=>1,'ð”½'=>1,'ð”¾'=>1,'ð•€'=>1,'ð•'=>1,'ð•‚'=>1,'ð•ƒ'=>1,'ð•„'=>1,'ð•†'=>1,'ð•Š'=>1,'ð•‹'=>1,'ð•Œ'=>1,'ð•'=>1,'ð•Ž'=>1,'ð•'=>1,'ð•'=>1,'ð•’'=>1,'ð•“'=>1,'ð•”'=>1,'ð••'=>1,'ð•–'=>1,'ð•—'=>1,'ð•˜'=>1,'ð•™'=>1,'ð•š'=>1,'ð•›'=>1,'ð•œ'=>1,'ð•'=>1,'ð•ž'=>1,'ð•Ÿ'=>1,'ð• '=>1,'ð•¡'=>1,'ð•¢'=>1,'ð•£'=>1,'ð•¤'=>1,'ð•¥'=>1,'ð•¦'=>1,'ð•§'=>1,'ð•¨'=>1,'ð•©'=>1,'ð•ª'=>1,'ð•«'=>1,'ð•¬'=>1,'ð•'=>1,'ð•®'=>1,'ð•¯'=>1,'ð•°'=>1,'ð•±'=>1,'ð•²'=>1,'ð•³'=>1,'ð•´'=>1,'ð•µ'=>1,'ð•¶'=>1,'ð•·'=>1,'ð•¸'=>1,'ð•¹'=>1,'ð•º'=>1,'ð•»'=>1,'ð•¼'=>1,'ð•½'=>1,'ð•¾'=>1,'ð•¿'=>1,'ð–€'=>1,'ð–'=>1,'ð–‚'=>1,'ð–ƒ'=>1,'ð–„'=>1,'ð–…'=>1,'ð–†'=>1,'ð–‡'=>1,'ð–ˆ'=>1,'ð–‰'=>1,'ð–Š'=>1,'ð–‹'=>1,'ð–Œ'=>1,'ð–'=>1,'ð–Ž'=>1,'ð–'=>1,'ð–'=>1,'ð–‘'=>1,'ð–’'=>1,'ð–“'=>1,'ð–”'=>1,'ð–•'=>1,'ð––'=>1,'ð–—'=>1,'ð–˜'=>1,'ð–™'=>1,'ð–š'=>1,'ð–›'=>1,'ð–œ'=>1,'ð–'=>1,'ð–ž'=>1,'ð–Ÿ'=>1,'ð– '=>1,'ð–¡'=>1,'ð–¢'=>1,'ð–£'=>1,'ð–¤'=>1,'ð–¥'=>1,'ð–¦'=>1,'ð–§'=>1,'ð–¨'=>1,'ð–©'=>1,'ð–ª'=>1,'ð–«'=>1,'ð–¬'=>1,'ð–'=>1,'ð–®'=>1,'ð–¯'=>1,'ð–°'=>1,'ð–±'=>1,'ð–²'=>1,'ð–³'=>1,'ð–´'=>1,'ð–µ'=>1,'ð–¶'=>1,'ð–·'=>1,'ð–¸'=>1,'ð–¹'=>1,'ð–º'=>1,'ð–»'=>1,'ð–¼'=>1,'ð–½'=>1,'ð–¾'=>1,'ð–¿'=>1,'ð—€'=>1,'ð—'=>1,'ð—‚'=>1,'ð—ƒ'=>1,'ð—„'=>1,'ð—…'=>1,'ð—†'=>1,'ð—‡'=>1,'ð—ˆ'=>1,'ð—‰'=>1,'ð—Š'=>1,'ð—‹'=>1,'ð—Œ'=>1,'ð—'=>1,'ð—Ž'=>1,'ð—'=>1,'ð—'=>1,'ð—‘'=>1,'ð—’'=>1,'ð—“'=>1,'ð—”'=>1,'ð—•'=>1,'ð—–'=>1,'ð——'=>1,'ð—˜'=>1,'ð—™'=>1,'ð—š'=>1,'ð—›'=>1,'ð—œ'=>1,'ð—'=>1,'ð—ž'=>1,'ð—Ÿ'=>1,'ð— '=>1,'ð—¡'=>1,'ð—¢'=>1,'ð—£'=>1,'ð—¤'=>1,'ð—¥'=>1,'ð—¦'=>1,'ð—§'=>1,'ð—¨'=>1,'ð—©'=>1,'ð—ª'=>1,'ð—«'=>1,'ð—¬'=>1,'ð—'=>1,'ð—®'=>1,'ð—¯'=>1,'ð—°'=>1,'ð—±'=>1,'ð—²'=>1,'ð—³'=>1,'ð—´'=>1,'ð—µ'=>1,'ð—¶'=>1,'ð—·'=>1,'ð—¸'=>1,'ð—¹'=>1,'ð—º'=>1,'ð—»'=>1,'ð—¼'=>1,'ð—½'=>1,'ð—¾'=>1,'ð—¿'=>1,'ð˜€'=>1,'ð˜'=>1,'ð˜‚'=>1,'ð˜ƒ'=>1,'ð˜„'=>1,'ð˜…'=>1,'ð˜†'=>1,'ð˜‡'=>1,'ð˜ˆ'=>1,'ð˜‰'=>1,'ð˜Š'=>1,'ð˜‹'=>1,'ð˜Œ'=>1,'ð˜'=>1,'ð˜Ž'=>1,'ð˜'=>1,'ð˜'=>1,'ð˜‘'=>1,'ð˜’'=>1,'ð˜“'=>1,'ð˜”'=>1,'ð˜•'=>1,'ð˜–'=>1,'ð˜—'=>1,'ð˜˜'=>1,'ð˜™'=>1,'ð˜š'=>1,'ð˜›'=>1,'ð˜œ'=>1,'ð˜'=>1,'ð˜ž'=>1,'ð˜Ÿ'=>1,'ð˜ '=>1,'ð˜¡'=>1,'ð˜¢'=>1,'ð˜£'=>1,'ð˜¤'=>1,'ð˜¥'=>1,'ð˜¦'=>1,'ð˜§'=>1,'ð˜¨'=>1,'ð˜©'=>1,'ð˜ª'=>1,'ð˜«'=>1,'ð˜¬'=>1,'ð˜'=>1,'ð˜®'=>1,'ð˜¯'=>1,'ð˜°'=>1,'ð˜±'=>1,'ð˜²'=>1,'ð˜³'=>1,'ð˜´'=>1,'ð˜µ'=>1,'ð˜¶'=>1,'ð˜·'=>1,'ð˜¸'=>1,'ð˜¹'=>1,'ð˜º'=>1,'ð˜»'=>1,'ð˜¼'=>1,'ð˜½'=>1,'ð˜¾'=>1,'ð˜¿'=>1,'ð™€'=>1,'ð™'=>1,'ð™‚'=>1,'ð™ƒ'=>1,'ð™„'=>1,'ð™…'=>1,'ð™†'=>1,'ð™‡'=>1,'ð™ˆ'=>1,'ð™‰'=>1,'ð™Š'=>1,'ð™‹'=>1,'ð™Œ'=>1,'ð™'=>1,'ð™Ž'=>1,'ð™'=>1,'ð™'=>1,'ð™‘'=>1,'ð™’'=>1,'ð™“'=>1,'ð™”'=>1,'ð™•'=>1,'ð™–'=>1,'ð™—'=>1,'ð™˜'=>1,'ð™™'=>1,'ð™š'=>1,'ð™›'=>1,'ð™œ'=>1,'ð™'=>1,'ð™ž'=>1,'ð™Ÿ'=>1,'ð™ '=>1,'ð™¡'=>1,'ð™¢'=>1,'ð™£'=>1,'ð™¤'=>1,'ð™¥'=>1,'ð™¦'=>1,'ð™§'=>1,'ð™¨'=>1,'ð™©'=>1,'ð™ª'=>1,'ð™«'=>1,'ð™¬'=>1,'ð™'=>1,'ð™®'=>1,'ð™¯'=>1,'ð™°'=>1,'ð™±'=>1,'ð™²'=>1,'ð™³'=>1,'ð™´'=>1,'ð™µ'=>1,'ð™¶'=>1,'ð™·'=>1,'ð™¸'=>1,'ð™¹'=>1,'ð™º'=>1,'ð™»'=>1,'ð™¼'=>1,'ð™½'=>1,'ð™¾'=>1,'ð™¿'=>1,'ðš€'=>1,'ðš'=>1,'ðš‚'=>1,'ðšƒ'=>1,'ðš„'=>1,'ðš…'=>1,'ðš†'=>1,'ðš‡'=>1,'ðšˆ'=>1,'ðš‰'=>1,'ðšŠ'=>1,'ðš‹'=>1,'ðšŒ'=>1,'ðš'=>1,'ðšŽ'=>1,'ðš'=>1,'ðš'=>1,'ðš‘'=>1,'ðš’'=>1,'ðš“'=>1,'ðš”'=>1,'ðš•'=>1,'ðš–'=>1,'ðš—'=>1,'ðš˜'=>1,'ðš™'=>1,'ðšš'=>1,'ðš›'=>1,'ðšœ'=>1,'ðš'=>1,'ðšž'=>1,'ðšŸ'=>1,'ðš '=>1,'ðš¡'=>1,'ðš¢'=>1,'ðš£'=>1,'ðš¤'=>1,'ðš¥'=>1,'ðš¨'=>1,'ðš©'=>1,'ðšª'=>1,'ðš«'=>1,'ðš¬'=>1,'ðš'=>1,'ðš®'=>1,'ðš¯'=>1,'ðš°'=>1,'ðš±'=>1,'ðš²'=>1,'ðš³'=>1,'ðš´'=>1,'ðšµ'=>1,'ðš¶'=>1,'ðš·'=>1,'ðš¸'=>1,'ðš¹'=>1,'ðšº'=>1,'ðš»'=>1,'ðš¼'=>1,'ðš½'=>1,'ðš¾'=>1,'ðš¿'=>1,'ð›€'=>1,'ð›'=>1,'ð›‚'=>1,'ð›ƒ'=>1,'ð›„'=>1,'ð›…'=>1,'ð›†'=>1,'ð›‡'=>1,'ð›ˆ'=>1,'ð›‰'=>1,'ð›Š'=>1,'ð›‹'=>1,'ð›Œ'=>1,'ð›'=>1,'ð›Ž'=>1,'ð›'=>1,'ð›'=>1,'ð›‘'=>1,'ð›’'=>1,'ð›“'=>1,'ð›”'=>1,'ð›•'=>1,'ð›–'=>1,'ð›—'=>1,'ð›˜'=>1,'ð›™'=>1,'ð›š'=>1,'ð››'=>1,'ð›œ'=>1,'ð›'=>1,'ð›ž'=>1,'ð›Ÿ'=>1,'ð› '=>1,'ð›¡'=>1,'ð›¢'=>1,'ð›£'=>1,'ð›¤'=>1,'ð›¥'=>1,'ð›¦'=>1,'ð›§'=>1,'ð›¨'=>1,'ð›©'=>1,'ð›ª'=>1,'ð›«'=>1,'ð›¬'=>1,'ð›'=>1,'ð›®'=>1,'ð›¯'=>1,'ð›°'=>1,'ð›±'=>1,'ð›²'=>1,'ð›³'=>1,'ð›´'=>1,'ð›µ'=>1,'ð›¶'=>1,'ð›·'=>1,'ð›¸'=>1,'ð›¹'=>1,'ð›º'=>1,'ð›»'=>1,'ð›¼'=>1,'ð›½'=>1,'ð›¾'=>1,'ð›¿'=>1,'ðœ€'=>1,'ðœ'=>1,'ðœ‚'=>1,'ðœƒ'=>1,'ðœ„'=>1,'ðœ…'=>1,'ðœ†'=>1,'ðœ‡'=>1,'ðœˆ'=>1,'ðœ‰'=>1,'ðœŠ'=>1,'ðœ‹'=>1,'ðœŒ'=>1,'ðœ'=>1,'ðœŽ'=>1,'ðœ'=>1,'ðœ'=>1,'ðœ‘'=>1,'ðœ’'=>1,'ðœ“'=>1,'ðœ”'=>1,'ðœ•'=>1,'ðœ–'=>1,'ðœ—'=>1,'ðœ˜'=>1,'ðœ™'=>1,'ðœš'=>1,'ðœ›'=>1,'ðœœ'=>1,'ðœ'=>1,'ðœž'=>1,'ðœŸ'=>1,'ðœ '=>1,'ðœ¡'=>1,'ðœ¢'=>1,'ðœ£'=>1,'ðœ¤'=>1,'ðœ¥'=>1,'ðœ¦'=>1,'ðœ§'=>1,'ðœ¨'=>1,'ðœ©'=>1,'ðœª'=>1,'ðœ«'=>1,'ðœ¬'=>1,'ðœ'=>1,'ðœ®'=>1,'ðœ¯'=>1,'ðœ°'=>1,'ðœ±'=>1,'ðœ²'=>1,'ðœ³'=>1,'ðœ´'=>1,'ðœµ'=>1,'ðœ¶'=>1,'ðœ·'=>1,'ðœ¸'=>1,'ðœ¹'=>1,'ðœº'=>1,'ðœ»'=>1,'ðœ¼'=>1,'ðœ½'=>1,'ðœ¾'=>1,'ðœ¿'=>1,'ð€'=>1,'ð'=>1,'ð‚'=>1,'ðƒ'=>1,'ð„'=>1,'ð…'=>1,'ð†'=>1,'ð‡'=>1,'ðˆ'=>1,'ð‰'=>1,'ðŠ'=>1,'ð‹'=>1,'ðŒ'=>1,'ð'=>1,'ðŽ'=>1,'ð'=>1,'ð'=>1,'ð‘'=>1,'ð’'=>1,'ð“'=>1,'ð”'=>1,'ð•'=>1,'ð–'=>1,'ð—'=>1,'ð˜'=>1,'ð™'=>1,'ðš'=>1,'ð›'=>1,'ðœ'=>1,'ð'=>1,'ðž'=>1,'ðŸ'=>1,'ð '=>1,'ð¡'=>1,'ð¢'=>1,'ð£'=>1,'ð¤'=>1,'ð¥'=>1,'ð¦'=>1,'ð§'=>1,'ð¨'=>1,'ð©'=>1,'ðª'=>1,'ð«'=>1,'ð¬'=>1,'ð'=>1,'ð®'=>1,'ð¯'=>1,'ð°'=>1,'ð±'=>1,'ð²'=>1,'ð³'=>1,'ð´'=>1,'ðµ'=>1,'ð¶'=>1,'ð·'=>1,'ð¸'=>1,'ð¹'=>1,'ðº'=>1,'ð»'=>1,'ð¼'=>1,'ð½'=>1,'ð¾'=>1,'ð¿'=>1,'ðž€'=>1,'ðž'=>1,'ðž‚'=>1,'ðžƒ'=>1,'ðž„'=>1,'ðž…'=>1,'ðž†'=>1,'ðž‡'=>1,'ðžˆ'=>1,'ðž‰'=>1,'ðžŠ'=>1,'ðž‹'=>1,'ðžŒ'=>1,'ðž'=>1,'ðžŽ'=>1,'ðž'=>1,'ðž'=>1,'ðž‘'=>1,'ðž’'=>1,'ðž“'=>1,'ðž”'=>1,'ðž•'=>1,'ðž–'=>1,'ðž—'=>1,'ðž˜'=>1,'ðž™'=>1,'ðžš'=>1,'ðž›'=>1,'ðžœ'=>1,'ðž'=>1,'ðžž'=>1,'ðžŸ'=>1,'ðž '=>1,'ðž¡'=>1,'ðž¢'=>1,'ðž£'=>1,'ðž¤'=>1,'ðž¥'=>1,'ðž¦'=>1,'ðž§'=>1,'ðž¨'=>1,'ðž©'=>1,'ðžª'=>1,'ðž«'=>1,'ðž¬'=>1,'ðž'=>1,'ðž®'=>1,'ðž¯'=>1,'ðž°'=>1,'ðž±'=>1,'ðž²'=>1,'ðž³'=>1,'ðž´'=>1,'ðžµ'=>1,'ðž¶'=>1,'ðž·'=>1,'ðž¸'=>1,'ðž¹'=>1,'ðžº'=>1,'ðž»'=>1,'ðž¼'=>1,'ðž½'=>1,'ðž¾'=>1,'ðž¿'=>1,'ðŸ€'=>1,'ðŸ'=>1,'ðŸ‚'=>1,'ðŸƒ'=>1,'ðŸ„'=>1,'ðŸ…'=>1,'ðŸ†'=>1,'ðŸ‡'=>1,'ðŸˆ'=>1,'ðŸ‰'=>1,'ðŸŠ'=>1,'ðŸ‹'=>1,'ðŸŽ'=>1,'ðŸ'=>1,'ðŸ'=>1,'ðŸ‘'=>1,'ðŸ’'=>1,'ðŸ“'=>1,'ðŸ”'=>1,'ðŸ•'=>1,'ðŸ–'=>1,'ðŸ—'=>1,'ðŸ˜'=>1,'ðŸ™'=>1,'ðŸš'=>1,'ðŸ›'=>1,'ðŸœ'=>1,'ðŸ'=>1,'ðŸž'=>1,'ðŸŸ'=>1,'ðŸ '=>1,'ðŸ¡'=>1,'ðŸ¢'=>1,'ðŸ£'=>1,'ðŸ¤'=>1,'ðŸ¥'=>1,'ðŸ¦'=>1,'ðŸ§'=>1,'ðŸ¨'=>1,'ðŸ©'=>1,'ðŸª'=>1,'ðŸ«'=>1,'ðŸ¬'=>1,'ðŸ'=>1,'ðŸ®'=>1,'ðŸ¯'=>1,'ðŸ°'=>1,'ðŸ±'=>1,'ðŸ²'=>1,'ðŸ³'=>1,'ðŸ´'=>1,'ðŸµ'=>1,'ðŸ¶'=>1,'ðŸ·'=>1,'ðŸ¸'=>1,'ðŸ¹'=>1,'ðŸº'=>1,'ðŸ»'=>1,'ðŸ¼'=>1,'ðŸ½'=>1,'ðŸ¾'=>1,'ðŸ¿'=>1,'丽'=>1,'ð¯ '=>1,'乁'=>1,'𠄢'=>1,'你'=>1,'侮'=>1,'侻'=>1,'倂'=>1,'偺'=>1,'備'=>1,'僧'=>1,'像'=>1,'㒞'=>1,'ð¯ '=>1,'免'=>1,'ð¯ '=>1,'ð¯ '=>1,'具'=>1,'𠔜'=>1,'㒹'=>1,'內'=>1,'再'=>1,'𠕋'=>1,'冗'=>1,'冤'=>1,'仌'=>1,'冬'=>1,'况'=>1,'𩇟'=>1,'ð¯ '=>1,'刃'=>1,'㓟'=>1,'ð¯ '=>1,'剆'=>1,'割'=>1,'剷'=>1,'㔕'=>1,'勇'=>1,'勉'=>1,'勤'=>1,'勺'=>1,'包'=>1,'匆'=>1,'北'=>1,'卉'=>1,'ð¯ '=>1,'博'=>1,'即'=>1,'卽'=>1,'卿'=>1,'卿'=>1,'卿'=>1,'𠨬'=>1,'灰'=>1,'及'=>1,'叟'=>1,'𠭣'=>1,'叫'=>1,'叱'=>1,'吆'=>1,'咞'=>1,'吸'=>1,'呈'=>1,'周'=>1,'咢'=>1,'ð¯¡'=>1,'唐'=>1,'啓'=>1,'啣'=>1,'善'=>1,'善'=>1,'喙'=>1,'喫'=>1,'喳'=>1,'嗂'=>1,'圖'=>1,'嘆'=>1,'ð¯¡'=>1,'噑'=>1,'ð¯¡'=>1,'ð¯¡'=>1,'壮'=>1,'城'=>1,'埴'=>1,'堍'=>1,'型'=>1,'堲'=>1,'報'=>1,'墬'=>1,'𡓤'=>1,'売'=>1,'壷'=>1,'夆'=>1,'ð¯¡'=>1,'夢'=>1,'奢'=>1,'𡚨'=>1,'𡛪'=>1,'姬'=>1,'娛'=>1,'娧'=>1,'姘'=>1,'婦'=>1,'㛮'=>1,'㛼'=>1,'嬈'=>1,'嬾'=>1,'嬾'=>1,'𡧈'=>1,'ð¯¡'=>1,'寘'=>1,'寧'=>1,'寳'=>1,'𡬘'=>1,'寿'=>1,'将'=>1,'当'=>1,'尢'=>1,'㞁'=>1,'屠'=>1,'屮'=>1,'峀'=>1,'岍'=>1,'𡷤'=>1,'嵃'=>1,'𡷦'=>1,'嵮'=>1,'嵫'=>1,'嵼'=>1,'ð¯¢'=>1,'巢'=>1,'㠯'=>1,'巽'=>1,'帨'=>1,'帽'=>1,'幩'=>1,'㡢'=>1,'𢆃'=>1,'㡼'=>1,'庰'=>1,'庳'=>1,'ð¯¢'=>1,'廊'=>1,'ð¯¢'=>1,'ð¯¢'=>1,'𢌱'=>1,'𢌱'=>1,'舁'=>1,'弢'=>1,'弢'=>1,'㣇'=>1,'𣊸'=>1,'𦇚'=>1,'形'=>1,'彫'=>1,'㣣'=>1,'徚'=>1,'ð¯¢'=>1,'志'=>1,'忹'=>1,'悁'=>1,'㤺'=>1,'㤜'=>1,'悔'=>1,'𢛔'=>1,'惇'=>1,'慈'=>1,'慌'=>1,'慎'=>1,'慌'=>1,'慺'=>1,'憎'=>1,'憲'=>1,'ð¯¢'=>1,'憯'=>1,'懞'=>1,'懲'=>1,'懶'=>1,'成'=>1,'戛'=>1,'扝'=>1,'抱'=>1,'拔'=>1,'捐'=>1,'𢬌'=>1,'挽'=>1,'拼'=>1,'捨'=>1,'掃'=>1,'揤'=>1,'𢯱'=>1,'搢'=>1,'揅'=>1,'ð¯£'=>1,'㨮'=>1,'摩'=>1,'摾'=>1,'撝'=>1,'摷'=>1,'㩬'=>1,'敏'=>1,'敬'=>1,'𣀊'=>1,'旣'=>1,'書'=>1,'ð¯£'=>1,'㬙'=>1,'ð¯£'=>1,'ð¯£'=>1,'㫤'=>1,'冒'=>1,'冕'=>1,'最'=>1,'暜'=>1,'肭'=>1,'䏙'=>1,'朗'=>1,'望'=>1,'朡'=>1,'杞'=>1,'杓'=>1,'ð¯£'=>1,'㭉'=>1,'柺'=>1,'枅'=>1,'桒'=>1,'梅'=>1,'𣑭'=>1,'梎'=>1,'栟'=>1,'椔'=>1,'㮝'=>1,'楂'=>1,'榣'=>1,'槪'=>1,'檨'=>1,'𣚣'=>1,'ð¯£'=>1,'㰘'=>1,'次'=>1,'𣢧'=>1,'歔'=>1,'㱎'=>1,'歲'=>1,'殟'=>1,'殺'=>1,'殻'=>1,'𣪍'=>1,'𡴋'=>1,'𣫺'=>1,'汎'=>1,'𣲼'=>1,'沿'=>1,'泍'=>1,'汧'=>1,'洖'=>1,'派'=>1,'ð¯¤'=>1,'流'=>1,'浩'=>1,'浸'=>1,'涅'=>1,'𣴞'=>1,'洴'=>1,'港'=>1,'湮'=>1,'㴳'=>1,'滋'=>1,'滇'=>1,'ð¯¤'=>1,'淹'=>1,'ð¯¤'=>1,'ð¯¤'=>1,'𣾎'=>1,'濆'=>1,'瀹'=>1,'瀞'=>1,'瀛'=>1,'㶖'=>1,'灊'=>1,'災'=>1,'灷'=>1,'炭'=>1,'𠔥'=>1,'煅'=>1,'ð¯¤'=>1,'熜'=>1,'𤎫'=>1,'爨'=>1,'爵'=>1,'牐'=>1,'𤘈'=>1,'犀'=>1,'犕'=>1,'𤜵'=>1,'𤠔'=>1,'獺'=>1,'王'=>1,'㺬'=>1,'玥'=>1,'㺸'=>1,'ð¯¤'=>1,'瑇'=>1,'瑜'=>1,'瑱'=>1,'璅'=>1,'瓊'=>1,'㼛'=>1,'甤'=>1,'𤰶'=>1,'甾'=>1,'𤲒'=>1,'異'=>1,'𢆟'=>1,'瘐'=>1,'𤾡'=>1,'𤾸'=>1,'𥁄'=>1,'㿼'=>1,'䀈'=>1,'直'=>1,'ð¯¥'=>1,'𥃲'=>1,'𥄙'=>1,'𥄳'=>1,'眞'=>1,'真'=>1,'真'=>1,'睊'=>1,'䀹'=>1,'瞋'=>1,'䁆'=>1,'䂖'=>1,'ð¯¥'=>1,'硎'=>1,'ð¯¥'=>1,'ð¯¥'=>1,'䃣'=>1,'𥘦'=>1,'祖'=>1,'𥚚'=>1,'𥛅'=>1,'福'=>1,'秫'=>1,'䄯'=>1,'穀'=>1,'穊'=>1,'穏'=>1,'𥥼'=>1,'ð¯¥'=>1,'𥪧'=>1,'竮'=>1,'䈂'=>1,'𥮫'=>1,'篆'=>1,'築'=>1,'䈧'=>1,'𥲀'=>1,'糒'=>1,'䊠'=>1,'糨'=>1,'糣'=>1,'紀'=>1,'𥾆'=>1,'絣'=>1,'ð¯¥'=>1,'緇'=>1,'縂'=>1,'繅'=>1,'䌴'=>1,'𦈨'=>1,'𦉇'=>1,'䍙'=>1,'𦋙'=>1,'罺'=>1,'𦌾'=>1,'羕'=>1,'翺'=>1,'者'=>1,'𦓚'=>1,'𦔣'=>1,'聠'=>1,'𦖨'=>1,'聰'=>1,'𣍟'=>1,'ð¯¦'=>1,'育'=>1,'脃'=>1,'䐋'=>1,'脾'=>1,'媵'=>1,'𦞧'=>1,'𦞵'=>1,'𣎓'=>1,'𣎜'=>1,'舁'=>1,'舄'=>1,'ð¯¦'=>1,'䑫'=>1,'ð¯¦'=>1,'ð¯¦'=>1,'芝'=>1,'劳'=>1,'花'=>1,'芳'=>1,'芽'=>1,'苦'=>1,'𦬼'=>1,'若'=>1,'茝'=>1,'荣'=>1,'莭'=>1,'茣'=>1,'ð¯¦'=>1,'菧'=>1,'著'=>1,'荓'=>1,'菊'=>1,'菌'=>1,'菜'=>1,'𦰶'=>1,'𦵫'=>1,'𦳕'=>1,'䔫'=>1,'蓱'=>1,'蓳'=>1,'蔖'=>1,'𧏊'=>1,'蕤'=>1,'ð¯¦'=>1,'䕝'=>1,'䕡'=>1,'𦾱'=>1,'𧃒'=>1,'䕫'=>1,'虐'=>1,'虜'=>1,'虧'=>1,'虩'=>1,'蚩'=>1,'蚈'=>1,'蜎'=>1,'蛢'=>1,'蝹'=>1,'蜨'=>1,'蝫'=>1,'螆'=>1,'䗗'=>1,'蟡'=>1,'ð¯§'=>1,'䗹'=>1,'衠'=>1,'衣'=>1,'𧙧'=>1,'裗'=>1,'裞'=>1,'䘵'=>1,'裺'=>1,'㒻'=>1,'𧢮'=>1,'𧥦'=>1,'ð¯§'=>1,'䛇'=>1,'ð¯§'=>1,'ð¯§'=>1,'變'=>1,'豕'=>1,'𧲨'=>1,'貫'=>1,'賁'=>1,'贛'=>1,'起'=>1,'𧼯'=>1,'𠠄'=>1,'跋'=>1,'趼'=>1,'跰'=>1,'ð¯§'=>1,'軔'=>1,'輸'=>1,'𨗒'=>1,'𨗭'=>1,'邔'=>1,'郱'=>1,'鄑'=>1,'𨜮'=>1,'鄛'=>1,'鈸'=>1,'鋗'=>1,'鋘'=>1,'鉼'=>1,'鏹'=>1,'鐕'=>1,'ð¯§'=>1,'開'=>1,'䦕'=>1,'閷'=>1,'𨵷'=>1,'䧦'=>1,'雃'=>1,'嶲'=>1,'霣'=>1,'𩅅'=>1,'𩈚'=>1,'䩮'=>1,'䩶'=>1,'韠'=>1,'𩐊'=>1,'䪲'=>1,'𩒖'=>1,'頋'=>1,'頋'=>1,'頩'=>1,'ð¯¨'=>1,'飢'=>1,'䬳'=>1,'餩'=>1,'馧'=>1,'駂'=>1,'駾'=>1,'䯎'=>1,'𩬰'=>1,'鬒'=>1,'鱀'=>1,'鳽'=>1,'ð¯¨'=>1,'䳭'=>1,'ð¯¨'=>1,'ð¯¨'=>1,'䳸'=>1,'𪄅'=>1,'𪈎'=>1,'𪊑'=>1,'麻'=>1,'䵖'=>1,'黹'=>1,'黾'=>1,'鼅'=>1,'鼏'=>1,'鼖'=>1,'鼻'=>1,'ð¯¨'=>1,'Ì€'=>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,'ൗ'=>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,'ᆼ'=>0,'ᆽ'=>0,'ᆾ'=>0,'ᆿ'=>0,'ᇀ'=>0,'á‡'=>0,'ᇂ'=>0,'ᬵ'=>0,'ã‚™'=>0,'゚'=>0); diff --git a/phpBB/includes/utf/data/utf_normalizer_common.php b/phpBB/includes/utf/data/utf_normalizer_common.php deleted file mode 100644 index 2eb7feac69..0000000000 --- a/phpBB/includes/utf/data/utf_normalizer_common.php +++ /dev/null @@ -1,4 +0,0 @@ -<?php -$GLOBALS['utf_jamo_index']=array('á„€'=>44032,'á„'=>44620,'á„‚'=>45208,'ᄃ'=>45796,'á„„'=>46384,'á„…'=>46972,'ᄆ'=>47560,'ᄇ'=>48148,'ᄈ'=>48736,'ᄉ'=>49324,'ᄊ'=>49912,'á„‹'=>50500,'ᄌ'=>51088,'á„'=>51676,'ᄎ'=>52264,'á„'=>52852,'á„'=>53440,'á„‘'=>54028,'á„’'=>54616,'á…¡'=>0,'á…¢'=>28,'á…£'=>56,'á…¤'=>84,'á…¥'=>112,'á…¦'=>140,'á…§'=>168,'á…¨'=>196,'á…©'=>224,'á…ª'=>252,'á…«'=>280,'á…¬'=>308,'á…'=>336,'á…®'=>364,'á…¯'=>392,'á…°'=>420,'á…±'=>448,'á…²'=>476,'á…³'=>504,'á…´'=>532,'á…µ'=>560,'ᆧ'=>0,'ᆨ'=>1,'ᆩ'=>2,'ᆪ'=>3,'ᆫ'=>4,'ᆬ'=>5,'á†'=>6,'ᆮ'=>7,'ᆯ'=>8,'ᆰ'=>9,'ᆱ'=>10,'ᆲ'=>11,'ᆳ'=>12,'ᆴ'=>13,'ᆵ'=>14,'ᆶ'=>15,'ᆷ'=>16,'ᆸ'=>17,'ᆹ'=>18,'ᆺ'=>19,'ᆻ'=>20,'ᆼ'=>21,'ᆽ'=>22,'ᆾ'=>23,'ᆿ'=>24,'ᇀ'=>25,'á‡'=>26,'ᇂ'=>27); -$GLOBALS['utf_jamo_type']=array('á„€'=>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,'á…µ'=>1,'ᆧ'=>2,'ᆨ'=>2,'ᆩ'=>2,'ᆪ'=>2,'ᆫ'=>2,'ᆬ'=>2,'á†'=>2,'ᆮ'=>2,'ᆯ'=>2,'ᆰ'=>2,'ᆱ'=>2,'ᆲ'=>2,'ᆳ'=>2,'ᆴ'=>2,'ᆵ'=>2,'ᆶ'=>2,'ᆷ'=>2,'ᆸ'=>2,'ᆹ'=>2,'ᆺ'=>2,'ᆻ'=>2,'ᆼ'=>2,'ᆽ'=>2,'ᆾ'=>2,'ᆿ'=>2,'ᇀ'=>2,'á‡'=>2,'ᇂ'=>2); -$GLOBALS['utf_combining_class']=array('Ì€'=>230,'Ì'=>230,'Ì‚'=>230,'̃'=>230,'Ì„'=>230,'Ì…'=>230,'̆'=>230,'̇'=>230,'̈'=>230,'̉'=>230,'ÌŠ'=>230,'Ì‹'=>230,'ÌŒ'=>230,'Ì'=>230,'ÌŽ'=>230,'Ì'=>230,'Ì'=>230,'Ì‘'=>230,'Ì’'=>230,'Ì“'=>230,'Ì”'=>230,'Ì•'=>232,'Ì–'=>220,'Ì—'=>220,'̘'=>220,'Ì™'=>220,'Ìš'=>232,'Ì›'=>216,'Ìœ'=>220,'Ì'=>220,'Ìž'=>220,'ÌŸ'=>220,'Ì '=>220,'Ì¡'=>202,'Ì¢'=>202,'Ì£'=>220,'̤'=>220,'Ì¥'=>220,'̦'=>220,'̧'=>202,'̨'=>202,'Ì©'=>220,'̪'=>220,'Ì«'=>220,'̬'=>220,'Ì'=>220,'Ì®'=>220,'̯'=>220,'̰'=>220,'̱'=>220,'̲'=>220,'̳'=>220,'Ì´'=>1,'̵'=>1,'̶'=>1,'Ì·'=>1,'̸'=>1,'̹'=>220,'̺'=>220,'Ì»'=>220,'̼'=>220,'̽'=>230,'̾'=>230,'Ì¿'=>230,'Í€'=>230,'Í'=>230,'Í‚'=>230,'̓'=>230,'Í„'=>230,'Í…'=>240,'͆'=>230,'͇'=>220,'͈'=>220,'͉'=>220,'ÍŠ'=>230,'Í‹'=>230,'ÍŒ'=>230,'Í'=>220,'ÍŽ'=>220,'Í'=>230,'Í‘'=>230,'Í’'=>230,'Í“'=>220,'Í”'=>220,'Í•'=>220,'Í–'=>220,'Í—'=>230,'͘'=>232,'Í™'=>220,'Íš'=>220,'Í›'=>230,'Íœ'=>233,'Í'=>234,'Íž'=>234,'ÍŸ'=>233,'Í '=>234,'Í¡'=>234,'Í¢'=>233,'Í£'=>230,'ͤ'=>230,'Í¥'=>230,'ͦ'=>230,'ͧ'=>230,'ͨ'=>230,'Í©'=>230,'ͪ'=>230,'Í«'=>230,'ͬ'=>230,'Í'=>230,'Í®'=>230,'ͯ'=>230,'Òƒ'=>230,'Ò„'=>230,'Ò…'=>230,'Ò†'=>230,'Ö‘'=>220,'Ö’'=>230,'Ö“'=>230,'Ö”'=>230,'Ö•'=>230,'Ö–'=>220,'Ö—'=>230,'Ö˜'=>230,'Ö™'=>230,'Öš'=>222,'Ö›'=>220,'Öœ'=>230,'Ö'=>230,'Öž'=>230,'ÖŸ'=>230,'Ö '=>230,'Ö¡'=>230,'Ö¢'=>220,'Ö£'=>220,'Ö¤'=>220,'Ö¥'=>220,'Ö¦'=>220,'Ö§'=>220,'Ö¨'=>230,'Ö©'=>230,'Öª'=>220,'Ö«'=>230,'Ö¬'=>230,'Ö'=>222,'Ö®'=>228,'Ö¯'=>230,'Ö°'=>10,'Ö±'=>11,'Ö²'=>12,'Ö³'=>13,'Ö´'=>14,'Öµ'=>15,'Ö¶'=>16,'Ö·'=>17,'Ö¸'=>18,'Ö¹'=>19,'Öº'=>19,'Ö»'=>20,'Ö¼'=>21,'Ö½'=>22,'Ö¿'=>23,'×'=>24,'ׂ'=>25,'ׄ'=>230,'×…'=>220,'ׇ'=>18,'Ø'=>230,'Ø‘'=>230,'Ø’'=>230,'Ø“'=>230,'Ø”'=>230,'Ø•'=>230,'Ù‹'=>27,'ÙŒ'=>28,'Ù'=>29,'ÙŽ'=>30,'Ù'=>31,'Ù'=>32,'Ù‘'=>33,'Ù’'=>34,'Ù“'=>230,'Ù”'=>230,'Ù•'=>220,'Ù–'=>220,'Ù—'=>230,'Ù˜'=>230,'Ù™'=>230,'Ùš'=>230,'Ù›'=>230,'Ùœ'=>220,'Ù'=>230,'Ùž'=>230,'Ù°'=>35,'Û–'=>230,'Û—'=>230,'Û˜'=>230,'Û™'=>230,'Ûš'=>230,'Û›'=>230,'Ûœ'=>230,'ÛŸ'=>230,'Û '=>230,'Û¡'=>230,'Û¢'=>230,'Û£'=>220,'Û¤'=>230,'Û§'=>230,'Û¨'=>230,'Ûª'=>220,'Û«'=>230,'Û¬'=>230,'Û'=>220,'Ü‘'=>36,'ܰ'=>230,'ܱ'=>220,'ܲ'=>230,'ܳ'=>230,'Ü´'=>220,'ܵ'=>230,'ܶ'=>230,'Ü·'=>220,'ܸ'=>220,'ܹ'=>220,'ܺ'=>230,'Ü»'=>220,'ܼ'=>220,'ܽ'=>230,'ܾ'=>220,'Ü¿'=>230,'Ý€'=>230,'Ý'=>230,'Ý‚'=>220,'݃'=>230,'Ý„'=>220,'Ý…'=>230,'݆'=>220,'݇'=>230,'݈'=>220,'݉'=>230,'ÝŠ'=>230,'ß«'=>230,'߬'=>230,'ß'=>230,'ß®'=>230,'߯'=>230,'ß°'=>230,'ß±'=>230,'ß²'=>220,'ß³'=>230,'़'=>7,'à¥'=>9,'॑'=>230,'॒'=>220,'॓'=>230,'॔'=>230,'়'=>7,'à§'=>9,'਼'=>7,'à©'=>9,'઼'=>7,'à«'=>9,'଼'=>7,'à'=>9,'à¯'=>9,'à±'=>9,'ౕ'=>84,'à±–'=>91,'಼'=>7,'à³'=>9,'àµ'=>9,'à·Š'=>9,'ุ'=>103,'ู'=>103,'ฺ'=>9,'่'=>107,'้'=>107,'๊'=>107,'๋'=>107,'ຸ'=>118,'ູ'=>118,'່'=>122,'້'=>122,'໊'=>122,'໋'=>122,'༘'=>220,'༙'=>220,'༵'=>220,'༷'=>220,'༹'=>216,'ཱ'=>129,'ི'=>130,'ུ'=>132,'ེ'=>130,'ཻ'=>130,'ོ'=>130,'ཽ'=>130,'ྀ'=>130,'ྂ'=>230,'ྃ'=>230,'྄'=>9,'྆'=>230,'྇'=>230,'࿆'=>220,'့'=>7,'္'=>9,'áŸ'=>230,'᜔'=>9,'᜴'=>9,'្'=>9,'áŸ'=>230,'ᢩ'=>228,'᤹'=>222,'᤺'=>230,'᤻'=>220,'ᨗ'=>230,'ᨘ'=>220,'᬴'=>7,'á„'=>9,'á«'=>230,'á¬'=>220,'á'=>230,'á®'=>230,'á¯'=>230,'á°'=>230,'á±'=>230,'á²'=>230,'á³'=>230,'á·€'=>230,'á·'=>230,'á·‚'=>220,'á·ƒ'=>230,'á·„'=>230,'á·…'=>230,'á·†'=>230,'á·‡'=>230,'á·ˆ'=>230,'á·‰'=>230,'á·Š'=>220,'á·¾'=>230,'á·¿'=>220,'âƒ'=>230,'⃑'=>230,'⃒'=>1,'⃓'=>1,'⃔'=>230,'⃕'=>230,'⃖'=>230,'⃗'=>230,'⃘'=>1,'⃙'=>1,'⃚'=>1,'⃛'=>230,'⃜'=>230,'⃡'=>230,'⃥'=>1,'⃦'=>1,'⃧'=>230,'⃨'=>220,'⃩'=>230,'⃪'=>1,'⃫'=>1,'⃬'=>220,'âƒ'=>220,'⃮'=>220,'⃯'=>220,'〪'=>218,'〫'=>228,'〬'=>232,'ã€'=>222,'〮'=>224,'〯'=>224,'ã‚™'=>8,'゚'=>8,'ê †'=>9,'ﬞ'=>26,'ï¸ '=>230,'︡'=>230,'︢'=>230,'︣'=>230,'ð¨'=>220,'ð¨'=>230,'ð¨¸'=>230,'ð¨¹'=>1,'ð¨º'=>220,'ð¨¿'=>9,'ð…¥'=>216,'ð…¦'=>216,'ð…§'=>1,'ð…¨'=>1,'ð…©'=>1,'ð…'=>226,'ð…®'=>216,'ð…¯'=>216,'ð…°'=>216,'ð…±'=>216,'ð…²'=>216,'ð…»'=>220,'ð…¼'=>220,'ð…½'=>220,'ð…¾'=>220,'ð…¿'=>220,'ð†€'=>220,'ð†'=>220,'ð†‚'=>220,'ð†…'=>230,'ð††'=>230,'ð†‡'=>230,'ð†ˆ'=>230,'ð†‰'=>230,'ð†Š'=>220,'ð†‹'=>220,'ð†ª'=>230,'ð†«'=>230,'ð†¬'=>230,'ð†'=>230,'ð‰‚'=>230,'ð‰ƒ'=>230,'ð‰„'=>230); diff --git a/phpBB/includes/utf/utf_normalizer.php b/phpBB/includes/utf/utf_normalizer.php deleted file mode 100644 index a208552d53..0000000000 --- a/phpBB/includes/utf/utf_normalizer.php +++ /dev/null @@ -1,1513 +0,0 @@ -<?php -/** -* -* @package utf -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 -* -*/ - -/** -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Some Unicode characters encoded in UTF-8 -* -* Preserved for compatibility -*/ -define('UTF8_REPLACEMENT', "\xEF\xBF\xBD"); -define('UTF8_MAX', "\xF4\x8F\xBF\xBF"); -define('UTF8_FFFE', "\xEF\xBF\xBE"); -define('UTF8_FFFF', "\xEF\xBF\xBF"); -define('UTF8_SURROGATE_FIRST', "\xED\xA0\x80"); -define('UTF8_SURROGATE_LAST', "\xED\xBF\xBF"); -define('UTF8_HANGUL_FIRST', "\xEA\xB0\x80"); -define('UTF8_HANGUL_LAST', "\xED\x9E\xA3"); - -define('UTF8_CJK_FIRST', "\xE4\xB8\x80"); -define('UTF8_CJK_LAST', "\xE9\xBE\xBB"); -define('UTF8_CJK_B_FIRST', "\xF0\xA0\x80\x80"); -define('UTF8_CJK_B_LAST', "\xF0\xAA\x9B\x96"); - -// Unset global variables -unset($GLOBALS['utf_jamo_index'], $GLOBALS['utf_jamo_type'], $GLOBALS['utf_nfc_qc'], $GLOBALS['utf_combining_class'], $GLOBALS['utf_canonical_comp'], $GLOBALS['utf_canonical_decomp'], $GLOBALS['utf_nfkc_qc'], $GLOBALS['utf_compatibility_decomp']); - -// NFC_QC and NFKC_QC values -define('UNICODE_QC_MAYBE', 0); -define('UNICODE_QC_NO', 1); - -// Contains all the ASCII characters appearing in UTF-8, sorted by frequency -define('UTF8_ASCII_RANGE', "\x20\x65\x69\x61\x73\x6E\x74\x72\x6F\x6C\x75\x64\x5D\x5B\x63\x6D\x70\x27\x0A\x67\x7C\x68\x76\x2E\x66\x62\x2C\x3A\x3D\x2D\x71\x31\x30\x43\x32\x2A\x79\x78\x29\x28\x4C\x39\x41\x53\x2F\x50\x22\x45\x6A\x4D\x49\x6B\x33\x3E\x35\x54\x3C\x44\x34\x7D\x42\x7B\x38\x46\x77\x52\x36\x37\x55\x47\x4E\x3B\x4A\x7A\x56\x23\x48\x4F\x57\x5F\x26\x21\x4B\x3F\x58\x51\x25\x59\x5C\x09\x5A\x2B\x7E\x5E\x24\x40\x60\x7F\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"); - -// Contains all the tail bytes that can appear in the composition of a UTF-8 char -define('UTF8_TRAILING_BYTES', "\xA9\xA0\xA8\x80\xAA\x99\xA7\xBB\xAB\x89\x94\x82\xB4\xA2\xAE\x83\xB0\xB9\xB8\x93\xAF\xBC\xB3\x81\xA4\xB2\x9C\xA1\xB5\xBE\xBD\xBA\x98\xAD\xB1\x84\x95\xA6\xB6\x88\x8D\x90\xB7\xBF\x92\x85\xA5\x97\x8C\x86\xA3\x8E\x9F\x8F\x87\x91\x9D\xAC\x9E\x8B\x96\x9B\x8A\x9A"); - -// Constants used by the Hangul [de]composition algorithms -define('UNICODE_HANGUL_SBASE', 0xAC00); -define('UNICODE_HANGUL_LBASE', 0x1100); -define('UNICODE_HANGUL_VBASE', 0x1161); -define('UNICODE_HANGUL_TBASE', 0x11A7); -define('UNICODE_HANGUL_SCOUNT', 11172); -define('UNICODE_HANGUL_LCOUNT', 19); -define('UNICODE_HANGUL_VCOUNT', 21); -define('UNICODE_HANGUL_TCOUNT', 28); -define('UNICODE_HANGUL_NCOUNT', 588); -define('UNICODE_JAMO_L', 0); -define('UNICODE_JAMO_V', 1); -define('UNICODE_JAMO_T', 2); - -/** -* Unicode normalization routines -* -* @package utf -*/ -class utf_normalizer -{ - /** - * Validate, cleanup and normalize a string - * - * The ultimate convenience function! Clean up invalid UTF-8 sequences, - * and convert to Normal Form C, canonical composition. - * - * @param string &$str The dirty string - * @return string The same string, all shiny and cleaned-up - */ - static function cleanup(&$str) - { - // The string below is the list of all autorized characters, sorted by frequency in latin text - $pos = strspn($str, "\x20\x65\x69\x61\x73\x6E\x74\x72\x6F\x6C\x75\x64\x5D\x5B\x63\x6D\x70\x27\x0A\x67\x7C\x68\x76\x2E\x66\x62\x2C\x3A\x3D\x2D\x71\x31\x30\x43\x32\x2A\x79\x78\x29\x28\x4C\x39\x41\x53\x2F\x50\x22\x45\x6A\x4D\x49\x6B\x33\x3E\x35\x54\x3C\x44\x34\x7D\x42\x7B\x38\x46\x77\x52\x36\x37\x55\x47\x4E\x3B\x4A\x7A\x56\x23\x48\x4F\x57\x5F\x26\x21\x4B\x3F\x58\x51\x25\x59\x5C\x09\x5A\x2B\x7E\x5E\x24\x40\x60\x7F\x0D"); - $len = strlen($str); - - if ($pos == $len) - { - // ASCII strings with no special chars return immediately - return; - } - - // Note: we do not check for $GLOBALS['utf_canonical_decomp']. It is assumed they are always loaded together - if (!isset($GLOBALS['utf_nfc_qc'])) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/utf/data/utf_nfc_qc.' . $phpEx); - } - - if (!isset($GLOBALS['utf_canonical_decomp'])) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/utf/data/utf_canonical_decomp.' . $phpEx); - } - - // Replace any byte in the range 0x00..0x1F, except for \r, \n and \t - // We replace those characters with a 0xFF byte, which is illegal in UTF-8 and will in turn be replaced with a UTF replacement char - $str = strtr( - $str, - "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F", - "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" - ); - - $str = utf_normalizer::recompose($str, $pos, $len, $GLOBALS['utf_nfc_qc'], $GLOBALS['utf_canonical_decomp']); - } - - /** - * Validate and normalize a UTF string to NFC - * - * @param string &$str Unchecked UTF string - * @return string The string, validated and in normal form - */ - static function nfc(&$str) - { - $pos = strspn($str, UTF8_ASCII_RANGE); - $len = strlen($str); - - if ($pos == $len) - { - // ASCII strings return immediately - return; - } - - if (!isset($GLOBALS['utf_nfc_qc'])) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/utf/data/utf_nfc_qc.' . $phpEx); - } - - if (!isset($GLOBALS['utf_canonical_decomp'])) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/utf/data/utf_canonical_decomp.' . $phpEx); - } - - $str = utf_normalizer::recompose($str, $pos, $len, $GLOBALS['utf_nfc_qc'], $GLOBALS['utf_canonical_decomp']); - } - - /** - * Validate and normalize a UTF string to NFKC - * - * @param string &$str Unchecked UTF string - * @return string The string, validated and in normal form - */ - static function nfkc(&$str) - { - $pos = strspn($str, UTF8_ASCII_RANGE); - $len = strlen($str); - - if ($pos == $len) - { - // ASCII strings return immediately - return; - } - - if (!isset($GLOBALS['utf_nfkc_qc'])) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/utf/data/utf_nfkc_qc.' . $phpEx); - } - - if (!isset($GLOBALS['utf_compatibility_decomp'])) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/utf/data/utf_compatibility_decomp.' . $phpEx); - } - - $str = utf_normalizer::recompose($str, $pos, $len, $GLOBALS['utf_nfkc_qc'], $GLOBALS['utf_compatibility_decomp']); - } - - /** - * Validate and normalize a UTF string to NFD - * - * @param string &$str Unchecked UTF string - * @return string The string, validated and in normal form - */ - static function nfd(&$str) - { - $pos = strspn($str, UTF8_ASCII_RANGE); - $len = strlen($str); - - if ($pos == $len) - { - // ASCII strings return immediately - return; - } - - if (!isset($GLOBALS['utf_canonical_decomp'])) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/utf/data/utf_canonical_decomp.' . $phpEx); - } - - $str = utf_normalizer::decompose($str, $pos, $len, $GLOBALS['utf_canonical_decomp']); - } - - /** - * Validate and normalize a UTF string to NFKD - * - * @param string &$str Unchecked UTF string - * @return string The string, validated and in normal form - */ - static function nfkd(&$str) - { - $pos = strspn($str, UTF8_ASCII_RANGE); - $len = strlen($str); - - if ($pos == $len) - { - // ASCII strings return immediately - return; - } - - if (!isset($GLOBALS['utf_compatibility_decomp'])) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/utf/data/utf_compatibility_decomp.' . $phpEx); - } - - $str = utf_normalizer::decompose($str, $pos, $len, $GLOBALS['utf_compatibility_decomp']); - } - - - /** - * Recompose a UTF string - * - * @param string $str Unchecked UTF string - * @param integer $pos Position of the first UTF char (in bytes) - * @param integer $len Length of the string (in bytes) - * @param array &$qc Quick-check array, passed by reference but never modified - * @param array &$decomp_map Decomposition mapping, passed by reference but never modified - * @return string The string, validated and recomposed - * - * @access private - */ - static function recompose($str, $pos, $len, &$qc, &$decomp_map) - { - global $utf_combining_class, $utf_canonical_comp, $utf_jamo_type, $utf_jamo_index; - - // Load some commonly-used tables - if (!isset($utf_jamo_index, $utf_jamo_type, $utf_combining_class)) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/utf/data/utf_normalizer_common.' . $phpEx); - } - - // Load the canonical composition table - if (!isset($utf_canonical_comp)) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/utf/data/utf_canonical_comp.' . $phpEx); - } - - // Buffer the last ASCII char before the UTF-8 stuff if applicable - $tmp = ''; - $i = $tmp_pos = $last_cc = 0; - - $buffer = ($pos) ? array(++$i => $str[$pos - 1]) : array(); - - // UTF char length array - // This array is used to determine the length of a UTF character. - // Be $c the result of ($str[$pos] & "\xF0") --where $str is the string we're operating on and $pos - // the position of the cursor--, if $utf_len_mask[$c] does not exist, the byte is an ASCII char. - // Otherwise, if $utf_len_mask[$c] is greater than 0, we have a the leading byte of a multibyte character - // whose length is $utf_len_mask[$c] and if it is equal to 0, the byte is a trailing byte. - $utf_len_mask = array( - // Leading bytes masks - "\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4, - // Trailing bytes masks - "\x80" => 0, "\x90" => 0, "\xA0" => 0, "\xB0" => 0 - ); - - $extra_check = array( - "\xED" => 1, "\xEF" => 1, "\xC0" => 1, "\xC1" => 1, "\xE0" => 1, "\xF0" => 1, - "\xF4" => 1, "\xF5" => 1, "\xF6" => 1, "\xF7" => 1, "\xF8" => 1, "\xF9" => 1, - "\xFA" => 1, "\xFB" => 1, "\xFC" => 1, "\xFD" => 1, "\xFE" => 1, "\xFF" => 1 - ); - - $utf_validation_mask = array( - 2 => "\xE0\xC0", - 3 => "\xF0\xC0\xC0", - 4 => "\xF8\xC0\xC0\xC0" - ); - - $utf_validation_check = array( - 2 => "\xC0\x80", - 3 => "\xE0\x80\x80", - 4 => "\xF0\x80\x80\x80" - ); - - // Main loop - do - { - // STEP 0: Capture the current char and buffer it - $c = $str[$pos]; - $c_mask = $c & "\xF0"; - - if (isset($utf_len_mask[$c_mask])) - { - // Byte at $pos is either a leading byte or a missplaced trailing byte - if ($utf_len = $utf_len_mask[$c_mask]) - { - // Capture the char - $buffer[++$i & 7] = $utf_char = substr($str, $pos, $utf_len); - - // Let's find out if a thorough check is needed - if (isset($qc[$utf_char])) - { - // If the UTF char is in the qc array then it may not be in normal form. We do nothing here, the actual processing is below this "if" block - } - else if (isset($utf_combining_class[$utf_char])) - { - if ($utf_combining_class[$utf_char] < $last_cc) - { - // A combining character that is NOT canonically ordered - } - else - { - // A combining character that IS canonically ordered, skip to the next char - $last_cc = $utf_combining_class[$utf_char]; - - $pos += $utf_len; - continue; - } - } - else - { - // At this point, $utf_char holds a UTF char that we know is not a NF[K]C_QC and is not a combining character. - // It can be a singleton, a canonical composite, a replacement char or an even an ill-formed bunch of bytes. Let's find out - $last_cc = 0; - - // Check that we have the correct number of trailing bytes - if (($utf_char & $utf_validation_mask[$utf_len]) != $utf_validation_check[$utf_len]) - { - // Current char isn't well-formed or legal: either one or several trailing bytes are missing, or the Unicode char - // has been encoded in a five- or six- byte sequence - if ($utf_char[0] >= "\xF8") - { - if ($utf_char[0] < "\xFC") - { - $trailing_bytes = 4; - } - else if ($utf_char[0] > "\xFD") - { - $trailing_bytes = 0; - } - else - { - $trailing_bytes = 5; - } - } - else - { - $trailing_bytes = $utf_len - 1; - } - - $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . UTF8_REPLACEMENT; - $pos += strspn($str, UTF8_TRAILING_BYTES, ++$pos, $trailing_bytes); - $tmp_pos = $pos; - - continue; - } - - if (isset($extra_check[$c])) - { - switch ($c) - { - // Note: 0xED is quite common in Korean - case "\xED": - if ($utf_char >= "\xED\xA0\x80") - { - // Surrogates (U+D800..U+DFFF) are not allowed in UTF-8 (UTF sequence 0xEDA080..0xEDBFBF) - $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . UTF8_REPLACEMENT; - $pos += $utf_len; - $tmp_pos = $pos; - continue 2; - } - break; - - // Note: 0xEF is quite common in Japanese - case "\xEF": - if ($utf_char == "\xEF\xBF\xBE" || $utf_char == "\xEF\xBF\xBF") - { - // U+FFFE and U+FFFF are explicitly disallowed (UTF sequence 0xEFBFBE..0xEFBFBF) - $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . UTF8_REPLACEMENT; - $pos += $utf_len; - $tmp_pos = $pos; - continue 2; - } - break; - - case "\xC0": - case "\xC1": - if ($utf_char <= "\xC1\xBF") - { - // Overlong sequence: Unicode char U+0000..U+007F encoded as a double-byte UTF char - $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . UTF8_REPLACEMENT; - $pos += $utf_len; - $tmp_pos = $pos; - continue 2; - } - break; - - case "\xE0": - if ($utf_char <= "\xE0\x9F\xBF") - { - // Unicode char U+0000..U+07FF encoded in 3 bytes - $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . UTF8_REPLACEMENT; - $pos += $utf_len; - $tmp_pos = $pos; - continue 2; - } - break; - - case "\xF0": - if ($utf_char <= "\xF0\x8F\xBF\xBF") - { - // Unicode char U+0000..U+FFFF encoded in 4 bytes - $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . UTF8_REPLACEMENT; - $pos += $utf_len; - $tmp_pos = $pos; - continue 2; - } - break; - - default: - // Five- and six- byte sequences do not need being checked for here anymore - if ($utf_char > UTF8_MAX) - { - // Out of the Unicode range - if ($utf_char[0] < "\xF8") - { - $trailing_bytes = 3; - } - else if ($utf_char[0] < "\xFC") - { - $trailing_bytes = 4; - } - else if ($utf_char[0] > "\xFD") - { - $trailing_bytes = 0; - } - else - { - $trailing_bytes = 5; - } - - $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . UTF8_REPLACEMENT; - $pos += strspn($str, UTF8_TRAILING_BYTES, ++$pos, $trailing_bytes); - $tmp_pos = $pos; - continue 2; - } - break; - } - } - - // The char is a valid starter, move the cursor and go on - $pos += $utf_len; - continue; - } - } - else - { - // A trailing byte came out of nowhere, we will advance the cursor and treat the this byte and all following trailing bytes as if - // each of them was a Unicode replacement char - $spn = strspn($str, UTF8_TRAILING_BYTES, $pos); - $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . str_repeat(UTF8_REPLACEMENT, $spn); - - $pos += $spn; - $tmp_pos = $pos; - continue; - } - - - // STEP 1: Decompose current char - - // We have found a character that is either: - // - in the NFC_QC/NFKC_QC list - // - a non-starter char that is not canonically ordered - // - // We are going to capture the shortest UTF sequence that satisfies these two conditions: - // - // 1 - If the sequence does not start at the begginning of the string, it must begin with a starter, - // and that starter must not have the NF[K]C_QC property equal to "MAYBE" - // - // 2 - If the sequence does not end at the end of the string, it must end with a non-starter and be - // immediately followed by a starter that is not on the QC list - // - $utf_seq = array(); - $last_cc = 0; - $lpos = $pos; - $pos += $utf_len; - - if (isset($decomp_map[$utf_char])) - { - $_pos = 0; - $_len = strlen($decomp_map[$utf_char]); - - do - { - $_utf_len =& $utf_len_mask[$decomp_map[$utf_char][$_pos] & "\xF0"]; - - if (isset($_utf_len)) - { - $utf_seq[] = substr($decomp_map[$utf_char], $_pos, $_utf_len); - $_pos += $_utf_len; - } - else - { - $utf_seq[] = $decomp_map[$utf_char][$_pos]; - ++$_pos; - } - } - while ($_pos < $_len); - } - else - { - // The char is not decomposable - $utf_seq = array($utf_char); - } - - - // STEP 2: Capture the starter - - // Check out the combining class of the first character of the UTF sequence - $k = 0; - if (isset($utf_combining_class[$utf_seq[0]]) || $qc[$utf_char] == UNICODE_QC_MAYBE) - { - // Not a starter, inspect previous characters - // The last 8 characters are kept in a buffer so that we don't have to capture them everytime. - // This is enough for all real-life strings but even if it wasn't, we can capture characters in backward mode, - // although it is slower than this method. - // - // In the following loop, $j starts at the previous buffered character ($i - 1, because current character is - // at offset $i) and process them in backward mode until we find a starter. - // - // $k is the index on each UTF character inside of our UTF sequence. At this time, $utf_seq contains one or more - // characters numbered 0 to n. $k starts at 0 and for each char we prepend we pre-decrement it and for numbering - $starter_found = 0; - $j_min = max(1, $i - 7); - - for ($j = $i - 1; $j >= $j_min && $lpos > $tmp_pos; --$j) - { - $utf_char = $buffer[$j & 7]; - $lpos -= strlen($utf_char); - - if (isset($decomp_map[$utf_char])) - { - // The char is a composite, decompose for storage - $decomp_seq = array(); - $_pos = 0; - $_len = strlen($decomp_map[$utf_char]); - - do - { - $c = $decomp_map[$utf_char][$_pos]; - $_utf_len =& $utf_len_mask[$c & "\xF0"]; - - if (isset($_utf_len)) - { - $decomp_seq[] = substr($decomp_map[$utf_char], $_pos, $_utf_len); - $_pos += $_utf_len; - } - else - { - $decomp_seq[] = $c; - ++$_pos; - } - } - while ($_pos < $_len); - - // Prepend the UTF sequence with our decomposed sequence - if (isset($decomp_seq[1])) - { - // The char expanded into several chars - $decomp_cnt = sizeof($decomp_seq); - - foreach ($decomp_seq as $decomp_i => $decomp_char) - { - $utf_seq[$k + $decomp_i - $decomp_cnt] = $decomp_char; - } - $k -= $decomp_cnt; - } - else - { - // Decomposed to a single char, easier to prepend - $utf_seq[--$k] = $decomp_seq[0]; - } - } - else - { - $utf_seq[--$k] = $utf_char; - } - - if (!isset($utf_combining_class[$utf_seq[$k]])) - { - // We have found our starter - $starter_found = 1; - break; - } - } - - if (!$starter_found && $lpos > $tmp_pos) - { - // The starter was not found in the buffer, let's rewind some more - do - { - // $utf_len_mask contains the masks of both leading bytes and trailing bytes. If $utf_en > 0 then it's a leading byte, otherwise it's a trailing byte. - $c = $str[--$lpos]; - $c_mask = $c & "\xF0"; - - if (isset($utf_len_mask[$c_mask])) - { - // UTF byte - if ($utf_len = $utf_len_mask[$c_mask]) - { - // UTF *leading* byte - $utf_char = substr($str, $lpos, $utf_len); - - if (isset($decomp_map[$utf_char])) - { - // Decompose the character - $decomp_seq = array(); - $_pos = 0; - $_len = strlen($decomp_map[$utf_char]); - - do - { - $c = $decomp_map[$utf_char][$_pos]; - $_utf_len =& $utf_len_mask[$c & "\xF0"]; - - if (isset($_utf_len)) - { - $decomp_seq[] = substr($decomp_map[$utf_char], $_pos, $_utf_len); - $_pos += $_utf_len; - } - else - { - $decomp_seq[] = $c; - ++$_pos; - } - } - while ($_pos < $_len); - - // Prepend the UTF sequence with our decomposed sequence - if (isset($decomp_seq[1])) - { - // The char expanded into several chars - $decomp_cnt = sizeof($decomp_seq); - foreach ($decomp_seq as $decomp_i => $utf_char) - { - $utf_seq[$k + $decomp_i - $decomp_cnt] = $utf_char; - } - $k -= $decomp_cnt; - } - else - { - // Decomposed to a single char, easier to prepend - $utf_seq[--$k] = $decomp_seq[0]; - } - } - else - { - $utf_seq[--$k] = $utf_char; - } - } - } - else - { - // ASCII char - $utf_seq[--$k] = $c; - } - } - while ($lpos > $tmp_pos); - } - } - - - // STEP 3: Capture following combining modifiers - - while ($pos < $len) - { - $c_mask = $str[$pos] & "\xF0"; - - if (isset($utf_len_mask[$c_mask])) - { - if ($utf_len = $utf_len_mask[$c_mask]) - { - $utf_char = substr($str, $pos, $utf_len); - } - else - { - // A trailing byte came out of nowhere - // Trailing bytes are replaced with Unicode replacement chars, we will just ignore it for now, break out of the loop - // as if it was a starter (replacement chars ARE starters) and let the next loop replace it - break; - } - - if (isset($utf_combining_class[$utf_char]) || isset($qc[$utf_char])) - { - // Combining character, add it to the sequence and move the cursor - if (isset($decomp_map[$utf_char])) - { - // Decompose the character - $_pos = 0; - $_len = strlen($decomp_map[$utf_char]); - - do - { - $c = $decomp_map[$utf_char][$_pos]; - $_utf_len =& $utf_len_mask[$c & "\xF0"]; - - if (isset($_utf_len)) - { - $utf_seq[] = substr($decomp_map[$utf_char], $_pos, $_utf_len); - $_pos += $_utf_len; - } - else - { - $utf_seq[] = $c; - ++$_pos; - } - } - while ($_pos < $_len); - } - else - { - $utf_seq[] = $utf_char; - } - - $pos += $utf_len; - } - else - { - // Combining class 0 and no QC, break out of the loop - // Note: we do not know if that character is valid. If it's not, the next iteration will replace it - break; - } - } - else - { - // ASCII chars are starters - break; - } - } - - - // STEP 4: Sort and combine - - // Here we sort... - $k_max = $k + sizeof($utf_seq); - - if (!$k && $k_max == 1) - { - // There is only one char in the UTF sequence, add it then jump to the next iteration of main loop - // Note: the two commented lines below can be enabled under PHP5 for a very small performance gain in most cases -// if (substr_compare($str, $utf_seq[0], $lpos, $pos - $lpos)) -// { - $tmp .= substr($str, $tmp_pos, $lpos - $tmp_pos) . $utf_seq[0]; - $tmp_pos = $pos; -// } - - continue; - } - - // ...there we combine - if (isset($utf_combining_class[$utf_seq[$k]])) - { - $starter = $nf_seq = ''; - } - else - { - $starter = $utf_seq[$k++]; - $nf_seq = ''; - } - $utf_sort = array(); - - // We add an empty char at the end of the UTF char sequence. It will act as a starter and trigger the sort/combine routine - // at the end of the string without altering it - $utf_seq[] = ''; - - do - { - $utf_char = $utf_seq[$k++]; - - if (isset($utf_combining_class[$utf_char])) - { - $utf_sort[$utf_combining_class[$utf_char]][] = $utf_char; - } - else - { - if (empty($utf_sort)) - { - // No combining characters... check for a composite of the two starters - if (isset($utf_canonical_comp[$starter . $utf_char])) - { - // Good ol' composite character - $starter = $utf_canonical_comp[$starter . $utf_char]; - } - else if (isset($utf_jamo_type[$utf_char])) - { - // Current char is a composable jamo - if (isset($utf_jamo_type[$starter]) && $utf_jamo_type[$starter] == UNICODE_JAMO_L && $utf_jamo_type[$utf_char] == UNICODE_JAMO_V) - { - // We have a L jamo followed by a V jamo, we are going to prefetch the next char to see if it's a T jamo - if (isset($utf_jamo_type[$utf_seq[$k]]) && $utf_jamo_type[$utf_seq[$k]] == UNICODE_JAMO_T) - { - // L+V+T jamos, combine to a LVT Hangul syllable ($k is incremented) - $cp = $utf_jamo_index[$starter] + $utf_jamo_index[$utf_char] + $utf_jamo_index[$utf_seq[$k]]; - ++$k; - } - else - { - // L+V jamos, combine to a LV Hangul syllable - $cp = $utf_jamo_index[$starter] + $utf_jamo_index[$utf_char]; - } - - $starter = chr(0xE0 | ($cp >> 12)) . chr(0x80 | (($cp >> 6) & 0x3F)) . chr(0x80 | ($cp & 0x3F)); - } - else - { - // Non-composable jamo, just add it to the sequence - $nf_seq .= $starter; - $starter = $utf_char; - } - } - else - { - // No composite, just add the first starter to the sequence then continue with the other one - $nf_seq .= $starter; - $starter = $utf_char; - } - } - else - { - ksort($utf_sort); - - // For each class of combining characters - foreach ($utf_sort as $cc => $utf_chars) - { - $j = 0; - - do - { - // Look for a composite - if (isset($utf_canonical_comp[$starter . $utf_chars[$j]])) - { - // Found a composite, replace the starter - $starter = $utf_canonical_comp[$starter . $utf_chars[$j]]; - unset($utf_sort[$cc][$j]); - } - else - { - // No composite, all following characters in that class are blocked - break; - } - } - while (isset($utf_sort[$cc][++$j])); - } - - // Add the starter to the normalized sequence, followed by non-starters in canonical order - $nf_seq .= $starter; - - foreach ($utf_sort as $utf_chars) - { - if (!empty($utf_chars)) - { - $nf_seq .= implode('', $utf_chars); - } - } - - // Reset the array and go on - $utf_sort = array(); - $starter = $utf_char; - } - } - } - while ($k <= $k_max); - - $tmp .= substr($str, $tmp_pos, $lpos - $tmp_pos) . $nf_seq; - $tmp_pos = $pos; - } - else - { - // Only a ASCII char can make the program get here - // - // First we skip the current byte with ++$pos, then we quickly skip following ASCII chars with strspn(). - // - // The first two "if"'s here can be removed, with the consequences of being faster on latin text (lots of ASCII) and slower on - // multi-byte text (where the only ASCII chars are spaces and punctuation) - if (++$pos != $len) - { - if ($str[$pos] < "\x80") - { - $pos += strspn($str, UTF8_ASCII_RANGE, ++$pos); - $buffer[++$i & 7] = $str[$pos - 1]; - } - else - { - $buffer[++$i & 7] = $c; - } - } - } - } - while ($pos < $len); - - // Now is time to return the string - if ($tmp_pos) - { - // If the $tmp_pos cursor is not at the beggining of the string then at least one character was not in normal form. Replace $str with the fixed version - if ($tmp_pos == $len) - { - // The $tmp_pos cursor is at the end of $str, therefore $tmp holds the whole $str - return $tmp; - } - else - { - // The rightmost chunk of $str has not been appended to $tmp yet - return $tmp . substr($str, $tmp_pos); - } - } - - // The string was already in normal form - return $str; - } - - /** - * Decompose a UTF string - * - * @param string $str UTF string - * @param integer $pos Position of the first UTF char (in bytes) - * @param integer $len Length of the string (in bytes) - * @param array &$decomp_map Decomposition mapping, passed by reference but never modified - * @return string The string, decomposed and sorted canonically - * - * @access private - */ - static function decompose($str, $pos, $len, &$decomp_map) - { - global $utf_combining_class; - - // Load some commonly-used tables - if (!isset($utf_combining_class)) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/utf/data/utf_normalizer_common.' . $phpEx); - } - - // UTF char length array - $utf_len_mask = array( - // Leading bytes masks - "\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4, - // Trailing bytes masks - "\x80" => 0, "\x90" => 0, "\xA0" => 0, "\xB0" => 0 - ); - - // Some extra checks are triggered on the first byte of a UTF sequence - $extra_check = array( - "\xED" => 1, "\xEF" => 1, "\xC0" => 1, "\xC1" => 1, "\xE0" => 1, "\xF0" => 1, - "\xF4" => 1, "\xF5" => 1, "\xF6" => 1, "\xF7" => 1, "\xF8" => 1, "\xF9" => 1, - "\xFA" => 1, "\xFB" => 1, "\xFC" => 1, "\xFD" => 1, "\xFE" => 1, "\xFF" => 1 - ); - - // These masks are used to check if a UTF sequence is well formed. Here are the only 3 lengths we acknowledge: - // - 2-byte: 110? ???? 10?? ???? - // - 3-byte: 1110 ???? 10?? ???? 10?? ???? - // - 4-byte: 1111 0??? 10?? ???? 10?? ???? 10?? ???? - // Note that 5- and 6- byte sequences are automatically discarded - $utf_validation_mask = array( - 2 => "\xE0\xC0", - 3 => "\xF0\xC0\xC0", - 4 => "\xF8\xC0\xC0\xC0" - ); - - $utf_validation_check = array( - 2 => "\xC0\x80", - 3 => "\xE0\x80\x80", - 4 => "\xF0\x80\x80\x80" - ); - - $tmp = ''; - $starter_pos = $pos; - $tmp_pos = $last_cc = $sort = $dump = 0; - $utf_sort = array(); - - - // Main loop - do - { - // STEP 0: Capture the current char - - $cur_mask = $str[$pos] & "\xF0"; - if (isset($utf_len_mask[$cur_mask])) - { - if ($utf_len = $utf_len_mask[$cur_mask]) - { - // Multibyte char - $utf_char = substr($str, $pos, $utf_len); - $pos += $utf_len; - } - else - { - // A trailing byte came out of nowhere, we will treat it and all following trailing bytes as if each of them was a Unicode - // replacement char and we will advance the cursor - $spn = strspn($str, UTF8_TRAILING_BYTES, $pos); - - if ($dump) - { - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - // Dump combiners - if (!empty($utf_sort)) - { - if ($sort) - { - ksort($utf_sort); - } - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - } - - $tmp .= str_repeat(UTF8_REPLACEMENT, $spn); - $dump = $sort = 0; - } - else - { - $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . str_repeat(UTF8_REPLACEMENT, $spn); - } - - $pos += $spn; - $tmp_pos = $starter_pos = $pos; - - $utf_sort = array(); - $last_cc = 0; - - continue; - } - - - // STEP 1: Decide what to do with current char - - // Now, in that order: - // - check if that character is decomposable - // - check if that character is a non-starter - // - check if that character requires extra checks to be performed - if (isset($decomp_map[$utf_char])) - { - // Decompose the char - $_pos = 0; - $_len = strlen($decomp_map[$utf_char]); - - do - { - $c = $decomp_map[$utf_char][$_pos]; - $_utf_len =& $utf_len_mask[$c & "\xF0"]; - - if (isset($_utf_len)) - { - $_utf_char = substr($decomp_map[$utf_char], $_pos, $_utf_len); - $_pos += $_utf_len; - - if (isset($utf_combining_class[$_utf_char])) - { - // The character decomposed to a non-starter, buffer it for sorting - $utf_sort[$utf_combining_class[$_utf_char]][] = $_utf_char; - - if ($utf_combining_class[$_utf_char] < $last_cc) - { - // Not canonically ordered, will require sorting - $sort = $dump = 1; - } - else - { - $dump = 1; - $last_cc = $utf_combining_class[$_utf_char]; - } - } - else - { - // This character decomposition contains a starter, dump the buffer and continue - if ($dump) - { - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - // Dump combiners - if (!empty($utf_sort)) - { - if ($sort) - { - ksort($utf_sort); - } - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - } - - $tmp .= $_utf_char; - $dump = $sort = 0; - } - else - { - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos) . $_utf_char; - } - - $tmp_pos = $starter_pos = $pos; - $utf_sort = array(); - $last_cc = 0; - } - } - else - { - // This character decomposition contains an ASCII char, which is a starter. Dump the buffer and continue - ++$_pos; - - if ($dump) - { - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - // Dump combiners - if (!empty($utf_sort)) - { - if ($sort) - { - ksort($utf_sort); - } - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - } - - $tmp .= $c; - $dump = $sort = 0; - } - else - { - $tmp .= substr($str, $tmp_pos, $pos - $utf_len - $tmp_pos) . $c; - } - - $tmp_pos = $starter_pos = $pos; - $utf_sort = array(); - $last_cc = 0; - } - } - while ($_pos < $_len); - } - else if (isset($utf_combining_class[$utf_char])) - { - // Combining character - if ($utf_combining_class[$utf_char] < $last_cc) - { - // Not in canonical order - $sort = $dump = 1; - } - else - { - $last_cc = $utf_combining_class[$utf_char]; - } - - $utf_sort[$utf_combining_class[$utf_char]][] = $utf_char; - } - else - { - // Non-decomposable starter, check out if it's a Hangul syllable - if ($utf_char < UTF8_HANGUL_FIRST || $utf_char > UTF8_HANGUL_LAST) - { - // Nope, regular UTF char, check that we have the correct number of trailing bytes - if (($utf_char & $utf_validation_mask[$utf_len]) != $utf_validation_check[$utf_len]) - { - // Current char isn't well-formed or legal: either one or several trailing bytes are missing, or the Unicode char - // has been encoded in a five- or six- byte sequence. - // Move the cursor back to its original position then advance it to the position it should really be at - $pos -= $utf_len; - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - if (!empty($utf_sort)) - { - ksort($utf_sort); - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - $utf_sort = array(); - } - - // Add a replacement char then another replacement char for every trailing byte. - // - // @todo I'm not entirely sure that's how we're supposed to mark invalidated byte sequences, check this - $spn = strspn($str, UTF8_TRAILING_BYTES, ++$pos); - $tmp .= str_repeat(UTF8_REPLACEMENT, $spn + 1); - - $dump = $sort = 0; - - $pos += $spn; - $tmp_pos = $pos; - continue; - } - - if (isset($extra_check[$utf_char[0]])) - { - switch ($utf_char[0]) - { - // Note: 0xED is quite common in Korean - case "\xED": - if ($utf_char >= "\xED\xA0\x80") - { - // Surrogates (U+D800..U+DFFF) are not allowed in UTF-8 (UTF sequence 0xEDA080..0xEDBFBF) - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - if (!empty($utf_sort)) - { - ksort($utf_sort); - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - $utf_sort = array(); - } - - $tmp .= UTF8_REPLACEMENT; - $dump = $sort = 0; - - $tmp_pos = $starter_pos = $pos; - continue 2; - } - break; - - // Note: 0xEF is quite common in Japanese - case "\xEF": - if ($utf_char == "\xEF\xBF\xBE" || $utf_char == "\xEF\xBF\xBF") - { - // U+FFFE and U+FFFF are explicitly disallowed (UTF sequence 0xEFBFBE..0xEFBFBF) - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - if (!empty($utf_sort)) - { - ksort($utf_sort); - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - $utf_sort = array(); - } - - $tmp .= UTF8_REPLACEMENT; - $dump = $sort = 0; - - $tmp_pos = $starter_pos = $pos; - continue 2; - } - break; - - case "\xC0": - case "\xC1": - if ($utf_char <= "\xC1\xBF") - { - // Overlong sequence: Unicode char U+0000..U+007F encoded as a double-byte UTF char - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - if (!empty($utf_sort)) - { - ksort($utf_sort); - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - $utf_sort = array(); - } - - $tmp .= UTF8_REPLACEMENT; - $dump = $sort = 0; - - $tmp_pos = $starter_pos = $pos; - continue 2; - } - break; - - case "\xE0": - if ($utf_char <= "\xE0\x9F\xBF") - { - // Unicode char U+0000..U+07FF encoded in 3 bytes - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - if (!empty($utf_sort)) - { - ksort($utf_sort); - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - $utf_sort = array(); - } - - $tmp .= UTF8_REPLACEMENT; - $dump = $sort = 0; - - $tmp_pos = $starter_pos = $pos; - continue 2; - } - break; - - case "\xF0": - if ($utf_char <= "\xF0\x8F\xBF\xBF") - { - // Unicode char U+0000..U+FFFF encoded in 4 bytes - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - if (!empty($utf_sort)) - { - ksort($utf_sort); - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - $utf_sort = array(); - } - - $tmp .= UTF8_REPLACEMENT; - $dump = $sort = 0; - - $tmp_pos = $starter_pos = $pos; - continue 2; - } - break; - - default: - if ($utf_char > UTF8_MAX) - { - // Out of the Unicode range - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - if (!empty($utf_sort)) - { - ksort($utf_sort); - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - $utf_sort = array(); - } - - $tmp .= UTF8_REPLACEMENT; - $dump = $sort = 0; - - $tmp_pos = $starter_pos = $pos; - continue 2; - } - break; - } - } - } - else - { - // Hangul syllable - $idx = (((ord($utf_char[0]) & 0x0F) << 12) | ((ord($utf_char[1]) & 0x3F) << 6) | (ord($utf_char[2]) & 0x3F)) - UNICODE_HANGUL_SBASE; - - // LIndex can only range from 0 to 18, therefore it cannot influence the first two bytes of the L Jamo, which allows us to hardcode them (based on LBase). - // - // The same goes for VIndex, but for TIndex there's a catch: the value of the third byte could exceed 0xBF and we would have to increment the second byte - if ($t_index = $idx % UNICODE_HANGUL_TCOUNT) - { - if ($t_index < 25) - { - $utf_char = "\xE1\x84\x00\xE1\x85\x00\xE1\x86\x00"; - $utf_char[8] = chr(0xA7 + $t_index); - } - else - { - $utf_char = "\xE1\x84\x00\xE1\x85\x00\xE1\x87\x00"; - $utf_char[8] = chr(0x67 + $t_index); - } - } - else - { - $utf_char = "\xE1\x84\x00\xE1\x85\x00"; - } - - $utf_char[2] = chr(0x80 + (int) ($idx / UNICODE_HANGUL_NCOUNT)); - $utf_char[5] = chr(0xA1 + (int) (($idx % UNICODE_HANGUL_NCOUNT) / UNICODE_HANGUL_TCOUNT)); - - // Just like other decompositions, the resulting Jamos must be dumped to the tmp string - $dump = 1; - } - - // Do we need to dump stuff to the tmp string? - if ($dump) - { - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - // Dump combiners - if (!empty($utf_sort)) - { - if ($sort) - { - ksort($utf_sort); - } - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - } - - $tmp .= $utf_char; - $dump = $sort = 0; - $tmp_pos = $pos; - } - - $last_cc = 0; - $utf_sort = array(); - $starter_pos = $pos; - } - } - else - { - // ASCII char, which happens to be a starter (as any other ASCII char) - if ($dump) - { - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - // Dump combiners - if (!empty($utf_sort)) - { - if ($sort) - { - ksort($utf_sort); - } - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - } - - $tmp .= $str[$pos]; - $dump = $sort = 0; - $tmp_pos = ++$pos; - - $pos += strspn($str, UTF8_ASCII_RANGE, $pos); - } - else - { - $pos += strspn($str, UTF8_ASCII_RANGE, ++$pos); - } - - $last_cc = 0; - $utf_sort = array(); - $starter_pos = $pos; - } - } - while ($pos < $len); - - // Now is time to return the string - if ($dump) - { - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - // Dump combiners - if (!empty($utf_sort)) - { - if ($sort) - { - ksort($utf_sort); - } - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - } - - return $tmp; - } - else if ($tmp_pos) - { - // If the $tmp_pos cursor was moved then at least one character was not in normal form. Replace $str with the fixed version - if ($tmp_pos == $len) - { - // The $tmp_pos cursor is at the end of $str, therefore $tmp holds the whole $str - return $tmp; - } - else - { - // The rightmost chunk of $str has not been appended to $tmp yet - return $tmp . substr($str, $tmp_pos); - } - } - - // The string was already in normal form - return $str; - } -} diff --git a/phpBB/includes/utf/utf_tools.php b/phpBB/includes/utf/utf_tools.php index c402e15032..01caf47349 100644 --- a/phpBB/includes/utf/utf_tools.php +++ b/phpBB/includes/utf/utf_tools.php @@ -1,9 +1,13 @@ <?php /** * -* @package utf -* @copyright (c) 2006 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* 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. * */ @@ -18,552 +22,99 @@ if (!defined('IN_PHPBB')) setlocale(LC_CTYPE, 'C'); /** +* Setup the UTF-8 portability layer +*/ +Patchwork\Utf8\Bootup::initUtf8Encode(); +Patchwork\Utf8\Bootup::initMbstring(); +Patchwork\Utf8\Bootup::initIntl(); + +/** * UTF-8 tools * * Whenever possible, these functions will try to use PHP's built-in functions or * extensions, otherwise they will default to custom routines. * -* @package utf */ -if (!extension_loaded('xml')) -{ - /** - * Implementation of PHP's native utf8_encode for people without XML support - * This function exploits some nice things that ISO-8859-1 and UTF-8 have in common - * - * @param string $str ISO-8859-1 encoded data - * @return string UTF-8 encoded data - */ - function utf8_encode($str) - { - $out = ''; - for ($i = 0, $len = strlen($str); $i < $len; $i++) - { - $letter = $str[$i]; - $num = ord($letter); - if ($num < 0x80) - { - $out .= $letter; - } - else if ($num < 0xC0) - { - $out .= "\xC2" . $letter; - } - else - { - $out .= "\xC3" . chr($num - 64); - } - } - return $out; - } - - /** - * Implementation of PHP's native utf8_decode for people without XML support - * - * @param string $str UTF-8 encoded data - * @return string ISO-8859-1 encoded data - */ - function utf8_decode($str) - { - $pos = 0; - $len = strlen($str); - $ret = ''; - - while ($pos < $len) - { - $ord = ord($str[$pos]) & 0xF0; - if ($ord === 0xC0 || $ord === 0xD0) - { - $charval = ((ord($str[$pos]) & 0x1F) << 6) | (ord($str[$pos + 1]) & 0x3F); - $pos += 2; - $ret .= (($charval < 256) ? chr($charval) : '?'); - } - else if ($ord === 0xE0) - { - $ret .= '?'; - $pos += 3; - } - else if ($ord === 0xF0) - { - $ret .= '?'; - $pos += 4; - } - else - { - $ret .= $str[$pos]; - ++$pos; - } - } - return $ret; - } -} - -// mbstring is old and has it's functions around for older versions of PHP. -// if mbstring is not loaded, we go into native mode. -if (extension_loaded('mbstring')) +/** +* UTF-8 aware alternative to strrpos +* @ignore +*/ +function utf8_strrpos($str, $needle, $offset = null) { - mb_internal_encoding('UTF-8'); - - /** - * UTF-8 aware alternative to strrpos - * Find position of last occurrence of a char in a string - */ - /** - * UTF-8 aware alternative to strrpos - * @ignore - */ - function utf8_strrpos($str, $needle, $offset = null) - { - // Emulate behaviour of strrpos rather than raising warning - if (empty($str)) - { - return false; - } - - if (is_null($offset)) - { - return mb_strrpos($str, $needle); - } - else - { - return mb_strrpos($str, $needle, $offset); - } - } - - /** - * UTF-8 aware alternative to strpos - * @ignore - */ - function utf8_strpos($str, $needle, $offset = null) + // Emulate behaviour of strrpos rather than raising warning + if (empty($str)) { - if (is_null($offset)) - { - return mb_strpos($str, $needle); - } - else - { - return mb_strpos($str, $needle, $offset); - } + return false; } - /** - * UTF-8 aware alternative to strtolower - * @ignore - */ - function utf8_strtolower($str) + if (is_null($offset)) { - return mb_strtolower($str); + return mb_strrpos($str, $needle); } - - /** - * UTF-8 aware alternative to strtoupper - * @ignore - */ - function utf8_strtoupper($str) + else { - return mb_strtoupper($str); + return mb_strrpos($str, $needle, $offset); } +} - /** - * UTF-8 aware alternative to substr - * @ignore - */ - function utf8_substr($str, $offset, $length = null) +/** +* UTF-8 aware alternative to strpos +* @ignore +*/ +function utf8_strpos($str, $needle, $offset = null) +{ + if (is_null($offset)) { - if (is_null($length)) - { - return mb_substr($str, $offset); - } - else - { - return mb_substr($str, $offset, $length); - } + return mb_strpos($str, $needle); } - - /** - * Return the length (in characters) of a UTF-8 string - * @ignore - */ - function utf8_strlen($text) + else { - return mb_strlen($text, 'utf-8'); + return mb_strpos($str, $needle, $offset); } } -else -{ - /** - * UTF-8 aware alternative to strrpos - * Find position of last occurrence of a char in a string - * - * @author Harry Fuecks - * @param string $str haystack - * @param string $needle needle - * @param integer $offset (optional) offset (from left) - * @return mixed integer position or FALSE on failure - */ - function utf8_strrpos($str, $needle, $offset = null) - { - if (is_null($offset)) - { - $ar = explode($needle, $str); - - if (sizeof($ar) > 1) - { - // Pop off the end of the string where the last match was made - array_pop($ar); - $str = join($needle, $ar); - - return utf8_strlen($str); - } - return false; - } - else - { - if (!is_int($offset)) - { - trigger_error('utf8_strrpos expects parameter 3 to be long', E_USER_ERROR); - return false; - } - - $str = utf8_substr($str, $offset); - - if (false !== ($pos = utf8_strrpos($str, $needle))) - { - return $pos + $offset; - } - - return false; - } - } - - /** - * UTF-8 aware alternative to strpos - * Find position of first occurrence of a string - * - * @author Harry Fuecks - * @param string $str haystack - * @param string $needle needle - * @param integer $offset offset in characters (from left) - * @return mixed integer position or FALSE on failure - */ - function utf8_strpos($str, $needle, $offset = null) - { - if (is_null($offset)) - { - $ar = explode($needle, $str); - if (sizeof($ar) > 1) - { - return utf8_strlen($ar[0]); - } - return false; - } - else - { - if (!is_int($offset)) - { - trigger_error('utf8_strpos: Offset must be an integer', E_USER_ERROR); - return false; - } - - $str = utf8_substr($str, $offset); - if (false !== ($pos = utf8_strpos($str, $needle))) - { - return $pos + $offset; - } +/** +* UTF-8 aware alternative to strtolower +* @ignore +*/ +function utf8_strtolower($str) +{ + return mb_strtolower($str); +} - return false; - } - } +/** +* UTF-8 aware alternative to strtoupper +* @ignore +*/ +function utf8_strtoupper($str) +{ + return mb_strtoupper($str); +} - /** - * UTF-8 aware alternative to strtolower - * Make a string lowercase - * Note: The concept of a characters "case" only exists is some alphabets - * such as Latin, Greek, Cyrillic, Armenian and archaic Georgian - it does - * not exist in the Chinese alphabet, for example. See Unicode Standard - * Annex #21: Case Mappings - * - * @param string - * @return string string in lowercase - */ - function utf8_strtolower($string) +/** +* UTF-8 aware alternative to substr +* @ignore +*/ +function utf8_substr($str, $offset, $length = null) +{ + if (is_null($length)) { - static $utf8_upper_to_lower = array( - "\xC3\x80" => "\xC3\xA0", "\xC3\x81" => "\xC3\xA1", - "\xC3\x82" => "\xC3\xA2", "\xC3\x83" => "\xC3\xA3", "\xC3\x84" => "\xC3\xA4", "\xC3\x85" => "\xC3\xA5", - "\xC3\x86" => "\xC3\xA6", "\xC3\x87" => "\xC3\xA7", "\xC3\x88" => "\xC3\xA8", "\xC3\x89" => "\xC3\xA9", - "\xC3\x8A" => "\xC3\xAA", "\xC3\x8B" => "\xC3\xAB", "\xC3\x8C" => "\xC3\xAC", "\xC3\x8D" => "\xC3\xAD", - "\xC3\x8E" => "\xC3\xAE", "\xC3\x8F" => "\xC3\xAF", "\xC3\x90" => "\xC3\xB0", "\xC3\x91" => "\xC3\xB1", - "\xC3\x92" => "\xC3\xB2", "\xC3\x93" => "\xC3\xB3", "\xC3\x94" => "\xC3\xB4", "\xC3\x95" => "\xC3\xB5", - "\xC3\x96" => "\xC3\xB6", "\xC3\x98" => "\xC3\xB8", "\xC3\x99" => "\xC3\xB9", "\xC3\x9A" => "\xC3\xBA", - "\xC3\x9B" => "\xC3\xBB", "\xC3\x9C" => "\xC3\xBC", "\xC3\x9D" => "\xC3\xBD", "\xC3\x9E" => "\xC3\xBE", - "\xC4\x80" => "\xC4\x81", "\xC4\x82" => "\xC4\x83", "\xC4\x84" => "\xC4\x85", "\xC4\x86" => "\xC4\x87", - "\xC4\x88" => "\xC4\x89", "\xC4\x8A" => "\xC4\x8B", "\xC4\x8C" => "\xC4\x8D", "\xC4\x8E" => "\xC4\x8F", - "\xC4\x90" => "\xC4\x91", "\xC4\x92" => "\xC4\x93", "\xC4\x96" => "\xC4\x97", "\xC4\x98" => "\xC4\x99", - "\xC4\x9A" => "\xC4\x9B", "\xC4\x9C" => "\xC4\x9D", "\xC4\x9E" => "\xC4\x9F", "\xC4\xA0" => "\xC4\xA1", - "\xC4\xA2" => "\xC4\xA3", "\xC4\xA4" => "\xC4\xA5", "\xC4\xA6" => "\xC4\xA7", "\xC4\xA8" => "\xC4\xA9", - "\xC4\xAA" => "\xC4\xAB", "\xC4\xAE" => "\xC4\xAF", "\xC4\xB4" => "\xC4\xB5", "\xC4\xB6" => "\xC4\xB7", - "\xC4\xB9" => "\xC4\xBA", "\xC4\xBB" => "\xC4\xBC", "\xC4\xBD" => "\xC4\xBE", "\xC5\x81" => "\xC5\x82", - "\xC5\x83" => "\xC5\x84", "\xC5\x85" => "\xC5\x86", "\xC5\x87" => "\xC5\x88", "\xC5\x8A" => "\xC5\x8B", - "\xC5\x8C" => "\xC5\x8D", "\xC5\x90" => "\xC5\x91", "\xC5\x94" => "\xC5\x95", "\xC5\x96" => "\xC5\x97", - "\xC5\x98" => "\xC5\x99", "\xC5\x9A" => "\xC5\x9B", "\xC5\x9C" => "\xC5\x9D", "\xC5\x9E" => "\xC5\x9F", - "\xC5\xA0" => "\xC5\xA1", "\xC5\xA2" => "\xC5\xA3", "\xC5\xA4" => "\xC5\xA5", "\xC5\xA6" => "\xC5\xA7", - "\xC5\xA8" => "\xC5\xA9", "\xC5\xAA" => "\xC5\xAB", "\xC5\xAC" => "\xC5\xAD", "\xC5\xAE" => "\xC5\xAF", - "\xC5\xB0" => "\xC5\xB1", "\xC5\xB2" => "\xC5\xB3", "\xC5\xB4" => "\xC5\xB5", "\xC5\xB6" => "\xC5\xB7", - "\xC5\xB8" => "\xC3\xBF", "\xC5\xB9" => "\xC5\xBA", "\xC5\xBB" => "\xC5\xBC", "\xC5\xBD" => "\xC5\xBE", - "\xC6\xA0" => "\xC6\xA1", "\xC6\xAF" => "\xC6\xB0", "\xC8\x98" => "\xC8\x99", "\xC8\x9A" => "\xC8\x9B", - "\xCE\x86" => "\xCE\xAC", "\xCE\x88" => "\xCE\xAD", "\xCE\x89" => "\xCE\xAE", "\xCE\x8A" => "\xCE\xAF", - "\xCE\x8C" => "\xCF\x8C", "\xCE\x8E" => "\xCF\x8D", "\xCE\x8F" => "\xCF\x8E", "\xCE\x91" => "\xCE\xB1", - "\xCE\x92" => "\xCE\xB2", "\xCE\x93" => "\xCE\xB3", "\xCE\x94" => "\xCE\xB4", "\xCE\x95" => "\xCE\xB5", - "\xCE\x96" => "\xCE\xB6", "\xCE\x97" => "\xCE\xB7", "\xCE\x98" => "\xCE\xB8", "\xCE\x99" => "\xCE\xB9", - "\xCE\x9A" => "\xCE\xBA", "\xCE\x9B" => "\xCE\xBB", "\xCE\x9C" => "\xCE\xBC", "\xCE\x9D" => "\xCE\xBD", - "\xCE\x9E" => "\xCE\xBE", "\xCE\x9F" => "\xCE\xBF", "\xCE\xA0" => "\xCF\x80", "\xCE\xA1" => "\xCF\x81", - "\xCE\xA3" => "\xCF\x83", "\xCE\xA4" => "\xCF\x84", "\xCE\xA5" => "\xCF\x85", "\xCE\xA6" => "\xCF\x86", - "\xCE\xA7" => "\xCF\x87", "\xCE\xA8" => "\xCF\x88", "\xCE\xA9" => "\xCF\x89", "\xCE\xAA" => "\xCF\x8A", - "\xCE\xAB" => "\xCF\x8B", "\xD0\x81" => "\xD1\x91", "\xD0\x82" => "\xD1\x92", "\xD0\x83" => "\xD1\x93", - "\xD0\x84" => "\xD1\x94", "\xD0\x85" => "\xD1\x95", "\xD0\x86" => "\xD1\x96", "\xD0\x87" => "\xD1\x97", - "\xD0\x88" => "\xD1\x98", "\xD0\x89" => "\xD1\x99", "\xD0\x8A" => "\xD1\x9A", "\xD0\x8B" => "\xD1\x9B", - "\xD0\x8C" => "\xD1\x9C", "\xD0\x8E" => "\xD1\x9E", "\xD0\x8F" => "\xD1\x9F", "\xD0\x90" => "\xD0\xB0", - "\xD0\x91" => "\xD0\xB1", "\xD0\x92" => "\xD0\xB2", "\xD0\x93" => "\xD0\xB3", "\xD0\x94" => "\xD0\xB4", - "\xD0\x95" => "\xD0\xB5", "\xD0\x96" => "\xD0\xB6", "\xD0\x97" => "\xD0\xB7", "\xD0\x98" => "\xD0\xB8", - "\xD0\x99" => "\xD0\xB9", "\xD0\x9A" => "\xD0\xBA", "\xD0\x9B" => "\xD0\xBB", "\xD0\x9C" => "\xD0\xBC", - "\xD0\x9D" => "\xD0\xBD", "\xD0\x9E" => "\xD0\xBE", "\xD0\x9F" => "\xD0\xBF", "\xD0\xA0" => "\xD1\x80", - "\xD0\xA1" => "\xD1\x81", "\xD0\xA2" => "\xD1\x82", "\xD0\xA3" => "\xD1\x83", "\xD0\xA4" => "\xD1\x84", - "\xD0\xA5" => "\xD1\x85", "\xD0\xA6" => "\xD1\x86", "\xD0\xA7" => "\xD1\x87", "\xD0\xA8" => "\xD1\x88", - "\xD0\xA9" => "\xD1\x89", "\xD0\xAA" => "\xD1\x8A", "\xD0\xAB" => "\xD1\x8B", "\xD0\xAC" => "\xD1\x8C", - "\xD0\xAD" => "\xD1\x8D", "\xD0\xAE" => "\xD1\x8E", "\xD0\xAF" => "\xD1\x8F", "\xD2\x90" => "\xD2\x91", - "\xE1\xB8\x82" => "\xE1\xB8\x83", "\xE1\xB8\x8A" => "\xE1\xB8\x8B", "\xE1\xB8\x9E" => "\xE1\xB8\x9F", "\xE1\xB9\x80" => "\xE1\xB9\x81", - "\xE1\xB9\x96" => "\xE1\xB9\x97", "\xE1\xB9\xA0" => "\xE1\xB9\xA1", "\xE1\xB9\xAA" => "\xE1\xB9\xAB", "\xE1\xBA\x80" => "\xE1\xBA\x81", - "\xE1\xBA\x82" => "\xE1\xBA\x83", "\xE1\xBA\x84" => "\xE1\xBA\x85", "\xE1\xBB\xB2" => "\xE1\xBB\xB3" - ); - - return strtr(strtolower($string), $utf8_upper_to_lower); + return mb_substr($str, $offset); } - - /** - * UTF-8 aware alternative to strtoupper - * Make a string uppercase - * Note: The concept of a characters "case" only exists is some alphabets - * such as Latin, Greek, Cyrillic, Armenian and archaic Georgian - it does - * not exist in the Chinese alphabet, for example. See Unicode Standard - * Annex #21: Case Mappings - * - * @param string - * @return string string in uppercase - */ - function utf8_strtoupper($string) + else { - static $utf8_lower_to_upper = array( - "\xC3\xA0" => "\xC3\x80", "\xC3\xA1" => "\xC3\x81", - "\xC3\xA2" => "\xC3\x82", "\xC3\xA3" => "\xC3\x83", "\xC3\xA4" => "\xC3\x84", "\xC3\xA5" => "\xC3\x85", - "\xC3\xA6" => "\xC3\x86", "\xC3\xA7" => "\xC3\x87", "\xC3\xA8" => "\xC3\x88", "\xC3\xA9" => "\xC3\x89", - "\xC3\xAA" => "\xC3\x8A", "\xC3\xAB" => "\xC3\x8B", "\xC3\xAC" => "\xC3\x8C", "\xC3\xAD" => "\xC3\x8D", - "\xC3\xAE" => "\xC3\x8E", "\xC3\xAF" => "\xC3\x8F", "\xC3\xB0" => "\xC3\x90", "\xC3\xB1" => "\xC3\x91", - "\xC3\xB2" => "\xC3\x92", "\xC3\xB3" => "\xC3\x93", "\xC3\xB4" => "\xC3\x94", "\xC3\xB5" => "\xC3\x95", - "\xC3\xB6" => "\xC3\x96", "\xC3\xB8" => "\xC3\x98", "\xC3\xB9" => "\xC3\x99", "\xC3\xBA" => "\xC3\x9A", - "\xC3\xBB" => "\xC3\x9B", "\xC3\xBC" => "\xC3\x9C", "\xC3\xBD" => "\xC3\x9D", "\xC3\xBE" => "\xC3\x9E", - "\xC3\xBF" => "\xC5\xB8", "\xC4\x81" => "\xC4\x80", "\xC4\x83" => "\xC4\x82", "\xC4\x85" => "\xC4\x84", - "\xC4\x87" => "\xC4\x86", "\xC4\x89" => "\xC4\x88", "\xC4\x8B" => "\xC4\x8A", "\xC4\x8D" => "\xC4\x8C", - "\xC4\x8F" => "\xC4\x8E", "\xC4\x91" => "\xC4\x90", "\xC4\x93" => "\xC4\x92", "\xC4\x97" => "\xC4\x96", - "\xC4\x99" => "\xC4\x98", "\xC4\x9B" => "\xC4\x9A", "\xC4\x9D" => "\xC4\x9C", "\xC4\x9F" => "\xC4\x9E", - "\xC4\xA1" => "\xC4\xA0", "\xC4\xA3" => "\xC4\xA2", "\xC4\xA5" => "\xC4\xA4", "\xC4\xA7" => "\xC4\xA6", - "\xC4\xA9" => "\xC4\xA8", "\xC4\xAB" => "\xC4\xAA", "\xC4\xAF" => "\xC4\xAE", "\xC4\xB5" => "\xC4\xB4", - "\xC4\xB7" => "\xC4\xB6", "\xC4\xBA" => "\xC4\xB9", "\xC4\xBC" => "\xC4\xBB", "\xC4\xBE" => "\xC4\xBD", - "\xC5\x82" => "\xC5\x81", "\xC5\x84" => "\xC5\x83", "\xC5\x86" => "\xC5\x85", "\xC5\x88" => "\xC5\x87", - "\xC5\x8B" => "\xC5\x8A", "\xC5\x8D" => "\xC5\x8C", "\xC5\x91" => "\xC5\x90", "\xC5\x95" => "\xC5\x94", - "\xC5\x97" => "\xC5\x96", "\xC5\x99" => "\xC5\x98", "\xC5\x9B" => "\xC5\x9A", "\xC5\x9D" => "\xC5\x9C", - "\xC5\x9F" => "\xC5\x9E", "\xC5\xA1" => "\xC5\xA0", "\xC5\xA3" => "\xC5\xA2", "\xC5\xA5" => "\xC5\xA4", - "\xC5\xA7" => "\xC5\xA6", "\xC5\xA9" => "\xC5\xA8", "\xC5\xAB" => "\xC5\xAA", "\xC5\xAD" => "\xC5\xAC", - "\xC5\xAF" => "\xC5\xAE", "\xC5\xB1" => "\xC5\xB0", "\xC5\xB3" => "\xC5\xB2", "\xC5\xB5" => "\xC5\xB4", - "\xC5\xB7" => "\xC5\xB6", "\xC5\xBA" => "\xC5\xB9", "\xC5\xBC" => "\xC5\xBB", "\xC5\xBE" => "\xC5\xBD", - "\xC6\xA1" => "\xC6\xA0", "\xC6\xB0" => "\xC6\xAF", "\xC8\x99" => "\xC8\x98", "\xC8\x9B" => "\xC8\x9A", - "\xCE\xAC" => "\xCE\x86", "\xCE\xAD" => "\xCE\x88", "\xCE\xAE" => "\xCE\x89", "\xCE\xAF" => "\xCE\x8A", - "\xCE\xB1" => "\xCE\x91", "\xCE\xB2" => "\xCE\x92", "\xCE\xB3" => "\xCE\x93", "\xCE\xB4" => "\xCE\x94", - "\xCE\xB5" => "\xCE\x95", "\xCE\xB6" => "\xCE\x96", "\xCE\xB7" => "\xCE\x97", "\xCE\xB8" => "\xCE\x98", - "\xCE\xB9" => "\xCE\x99", "\xCE\xBA" => "\xCE\x9A", "\xCE\xBB" => "\xCE\x9B", "\xCE\xBC" => "\xCE\x9C", - "\xCE\xBD" => "\xCE\x9D", "\xCE\xBE" => "\xCE\x9E", "\xCE\xBF" => "\xCE\x9F", "\xCF\x80" => "\xCE\xA0", - "\xCF\x81" => "\xCE\xA1", "\xCF\x83" => "\xCE\xA3", "\xCF\x84" => "\xCE\xA4", "\xCF\x85" => "\xCE\xA5", - "\xCF\x86" => "\xCE\xA6", "\xCF\x87" => "\xCE\xA7", "\xCF\x88" => "\xCE\xA8", "\xCF\x89" => "\xCE\xA9", - "\xCF\x8A" => "\xCE\xAA", "\xCF\x8B" => "\xCE\xAB", "\xCF\x8C" => "\xCE\x8C", "\xCF\x8D" => "\xCE\x8E", - "\xCF\x8E" => "\xCE\x8F", "\xD0\xB0" => "\xD0\x90", "\xD0\xB1" => "\xD0\x91", "\xD0\xB2" => "\xD0\x92", - "\xD0\xB3" => "\xD0\x93", "\xD0\xB4" => "\xD0\x94", "\xD0\xB5" => "\xD0\x95", "\xD0\xB6" => "\xD0\x96", - "\xD0\xB7" => "\xD0\x97", "\xD0\xB8" => "\xD0\x98", "\xD0\xB9" => "\xD0\x99", "\xD0\xBA" => "\xD0\x9A", - "\xD0\xBB" => "\xD0\x9B", "\xD0\xBC" => "\xD0\x9C", "\xD0\xBD" => "\xD0\x9D", "\xD0\xBE" => "\xD0\x9E", - "\xD0\xBF" => "\xD0\x9F", "\xD1\x80" => "\xD0\xA0", "\xD1\x81" => "\xD0\xA1", "\xD1\x82" => "\xD0\xA2", - "\xD1\x83" => "\xD0\xA3", "\xD1\x84" => "\xD0\xA4", "\xD1\x85" => "\xD0\xA5", "\xD1\x86" => "\xD0\xA6", - "\xD1\x87" => "\xD0\xA7", "\xD1\x88" => "\xD0\xA8", "\xD1\x89" => "\xD0\xA9", "\xD1\x8A" => "\xD0\xAA", - "\xD1\x8B" => "\xD0\xAB", "\xD1\x8C" => "\xD0\xAC", "\xD1\x8D" => "\xD0\xAD", "\xD1\x8E" => "\xD0\xAE", - "\xD1\x8F" => "\xD0\xAF", "\xD1\x91" => "\xD0\x81", "\xD1\x92" => "\xD0\x82", "\xD1\x93" => "\xD0\x83", - "\xD1\x94" => "\xD0\x84", "\xD1\x95" => "\xD0\x85", "\xD1\x96" => "\xD0\x86", "\xD1\x97" => "\xD0\x87", - "\xD1\x98" => "\xD0\x88", "\xD1\x99" => "\xD0\x89", "\xD1\x9A" => "\xD0\x8A", "\xD1\x9B" => "\xD0\x8B", - "\xD1\x9C" => "\xD0\x8C", "\xD1\x9E" => "\xD0\x8E", "\xD1\x9F" => "\xD0\x8F", "\xD2\x91" => "\xD2\x90", - "\xE1\xB8\x83" => "\xE1\xB8\x82", "\xE1\xB8\x8B" => "\xE1\xB8\x8A", "\xE1\xB8\x9F" => "\xE1\xB8\x9E", "\xE1\xB9\x81" => "\xE1\xB9\x80", - "\xE1\xB9\x97" => "\xE1\xB9\x96", "\xE1\xB9\xA1" => "\xE1\xB9\xA0", "\xE1\xB9\xAB" => "\xE1\xB9\xAA", "\xE1\xBA\x81" => "\xE1\xBA\x80", - "\xE1\xBA\x83" => "\xE1\xBA\x82", "\xE1\xBA\x85" => "\xE1\xBA\x84", "\xE1\xBB\xB3" => "\xE1\xBB\xB2" - ); - - return strtr(strtoupper($string), $utf8_lower_to_upper); - } - - /** - * UTF-8 aware alternative to substr - * Return part of a string given character offset (and optionally length) - * - * Note arguments: comparied to substr - if offset or length are - * not integers, this version will not complain but rather massages them - * into an integer. - * - * Note on returned values: substr documentation states false can be - * returned in some cases (e.g. offset > string length) - * mb_substr never returns false, it will return an empty string instead. - * This adopts the mb_substr approach - * - * Note on implementation: PCRE only supports repetitions of less than - * 65536, in order to accept up to MAXINT values for offset and length, - * we'll repeat a group of 65535 characters when needed. - * - * Note on implementation: calculating the number of characters in the - * string is a relatively expensive operation, so we only carry it out when - * necessary. It isn't necessary for +ve offsets and no specified length - * - * @author Chris Smith<chris@jalakai.co.uk> - * @param string $str - * @param integer $offset number of UTF-8 characters offset (from left) - * @param integer $length (optional) length in UTF-8 characters from offset - * @return mixed string or FALSE if failure - */ - function utf8_substr($str, $offset, $length = NULL) - { - // generates E_NOTICE - // for PHP4 objects, but not PHP5 objects - $str = (string) $str; - $offset = (int) $offset; - if (!is_null($length)) - { - $length = (int) $length; - } - - // handle trivial cases - if ($length === 0 || ($offset < 0 && $length < 0 && $length < $offset)) - { - return ''; - } - - // normalise negative offsets (we could use a tail - // anchored pattern, but they are horribly slow!) - if ($offset < 0) - { - // see notes - $strlen = utf8_strlen($str); - $offset = $strlen + $offset; - if ($offset < 0) - { - $offset = 0; - } - } - - $op = ''; - $lp = ''; - - // establish a pattern for offset, a - // non-captured group equal in length to offset - if ($offset > 0) - { - $ox = (int) ($offset / 65535); - $oy = $offset % 65535; - - if ($ox) - { - $op = '(?:.{65535}){' . $ox . '}'; - } - - $op = '^(?:' . $op . '.{' . $oy . '})'; - } - else - { - // offset == 0; just anchor the pattern - $op = '^'; - } - - // establish a pattern for length - if (is_null($length)) - { - // the rest of the string - $lp = '(.*)$'; - } - else - { - if (!isset($strlen)) - { - // see notes - $strlen = utf8_strlen($str); - } - - // another trivial case - if ($offset > $strlen) - { - return ''; - } - - if ($length > 0) - { - // reduce any length that would - // go passed the end of the string - $length = min($strlen - $offset, $length); - - $lx = (int) ($length / 65535); - $ly = $length % 65535; - - // negative length requires a captured group - // of length characters - if ($lx) - { - $lp = '(?:.{65535}){' . $lx . '}'; - } - $lp = '(' . $lp . '.{'. $ly . '})'; - } - else if ($length < 0) - { - if ($length < ($offset - $strlen)) - { - return ''; - } - - $lx = (int)((-$length) / 65535); - $ly = (-$length) % 65535; - - // negative length requires ... capture everything - // except a group of -length characters - // anchored at the tail-end of the string - if ($lx) - { - $lp = '(?:.{65535}){' . $lx . '}'; - } - $lp = '(.*)(?:' . $lp . '.{' . $ly . '})$'; - } - } - - if (!preg_match('#' . $op . $lp . '#us', $str, $match)) - { - return ''; - } - - return $match[1]; + return mb_substr($str, $offset, $length); } +} - /** - * Return the length (in characters) of a UTF-8 string - * - * @param string $text UTF-8 string - * @return integer Length (in chars) of given string - */ - function utf8_strlen($text) - { - // Since utf8_decode is replacing multibyte characters to ? strlen works fine - return strlen(utf8_decode($text)); - } +/** +* Return the length (in characters) of a UTF-8 string +* @ignore +*/ +function utf8_strlen($text) +{ + return mb_strlen($text, 'utf-8'); } /** @@ -864,7 +415,6 @@ function utf8_recode($string, $encoding) // Trigger an error?! Fow now just give bad data :-( trigger_error('Unknown encoding: ' . $encoding, E_USER_ERROR); - //return $string; // use utf_normalizer::cleanup() ? } /** @@ -1603,19 +1153,12 @@ function utf8_case_fold_nfkc($text, $option = 'full') "\xF0\x9D\x9E\xBB" => "\xCF\x83", "\xF0\x9D\x9F\x8A" => "\xCF\x9D", ); - global $phpbb_root_path, $phpEx; // do the case fold $text = utf8_case_fold($text, $option); - if (!class_exists('utf_normalizer')) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/utf/utf_normalizer.' . $phpEx); - } - // convert to NFKC - utf_normalizer::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); @@ -1700,7 +1243,6 @@ function utf8_case_fold_nfc($text, $option = 'full') "\xE1\xBF\xB7" => "\xE1\xBF\xB6\xCD\x85", "\xE1\xBF\xBC" => "\xCE\xA9\xCD\x85", ); - global $phpbb_root_path, $phpEx; // perform a small trick, avoid further normalization on composed points that contain U+0345 in their decomposition $text = strtr($text, $ypogegrammeni); @@ -1711,106 +1253,56 @@ function utf8_case_fold_nfc($text, $option = 'full') return $text; } -if (extension_loaded('intl')) +/** +* wrapper around PHP's native normalizer from intl +* previously a PECL extension, included in the core since PHP 5.3.0 +* http://php.net/manual/en/normalizer.normalize.php +* +* @param mixed $strings a string or an array of strings to normalize +* @return mixed the normalized content, preserving array keys if array given. +*/ +function utf8_normalize_nfc($strings) { - /** - * wrapper around PHP's native normalizer from intl - * previously a PECL extension, included in the core since PHP 5.3.0 - * http://php.net/manual/en/normalizer.normalize.php - * - * @param mixed $strings a string or an array of strings to normalize - * @return mixed the normalized content, preserving array keys if array given. - */ - function utf8_normalize_nfc($strings) + if (empty($strings)) { - if (empty($strings)) - { - return $strings; - } - - if (!is_array($strings)) - { - if (Normalizer::isNormalized($strings)) - { - return $strings; - } - return (string) Normalizer::normalize($strings); - } - else - { - foreach ($strings as $key => $string) - { - if (is_array($string)) - { - foreach ($string as $_key => $_string) - { - if (Normalizer::isNormalized($strings[$key][$_key])) - { - continue; - } - $strings[$key][$_key] = (string) Normalizer::normalize($strings[$key][$_key]); - } - } - else - { - if (Normalizer::isNormalized($strings[$key])) - { - continue; - } - $strings[$key] = (string) Normalizer::normalize($strings[$key]); - } - } - } - return $strings; } -} -else -{ - /** - * A wrapper function for the normalizer which takes care of including the class if - * required and modifies the passed strings to be in NFC (Normalization Form Composition). - * - * @param mixed $strings a string or an array of strings to normalize - * @return mixed the normalized content, preserving array keys if array given. - */ - function utf8_normalize_nfc($strings) + + if (!is_array($strings)) { - if (empty($strings)) + if (Normalizer::isNormalized($strings)) { return $strings; } - - if (!class_exists('utf_normalizer')) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/utf/utf_normalizer.' . $phpEx); - } - - if (!is_array($strings)) - { - utf_normalizer::nfc($strings); - } - else if (is_array($strings)) + return (string) Normalizer::normalize($strings); + } + else + { + foreach ($strings as $key => $string) { - foreach ($strings as $key => $string) + if (is_array($string)) { - if (is_array($string)) + foreach ($string as $_key => $_string) { - foreach ($string as $_key => $_string) + if (Normalizer::isNormalized($strings[$key][$_key])) { - utf_normalizer::nfc($strings[$key][$_key]); + continue; } + $strings[$key][$_key] = (string) Normalizer::normalize($strings[$key][$_key]); } - else + } + else + { + if (Normalizer::isNormalized($strings[$key])) { - utf_normalizer::nfc($strings[$key]); + continue; } + $strings[$key] = (string) Normalizer::normalize($strings[$key]); } } - - return $strings; } + + return $strings; } /** @@ -1956,50 +1448,3 @@ function utf8_basename($filename) return $filename; } - -/** -* UTF8-safe str_replace() function -* -* @param string $search The value to search for -* @param string $replace The replacement string -* @param string $subject The target string -* @return string The resultant string -*/ -function utf8_str_replace($search, $replace, $subject) -{ - if (!is_array($search)) - { - $search = array($search); - if (is_array($replace)) - { - $replace = (string) $replace; - trigger_error('Array to string conversion', E_USER_NOTICE); - } - } - - $length = sizeof($search); - - if (!is_array($replace)) - { - $replace = array_fill(0, $length, $replace); - } - else - { - $replace = array_pad($replace, $length, ''); - } - - for ($i = 0; $i < $length; $i++) - { - $search_length = utf8_strlen($search[$i]); - $replace_length = utf8_strlen($replace[$i]); - - $offset = 0; - while (($start = utf8_strpos($subject, $search[$i], $offset)) !== false) - { - $subject = utf8_substr($subject, 0, $start) . $replace[$i] . utf8_substr($subject, $start + $search_length); - $offset = $start + $replace_length; - } - } - - return $subject; -} |