diff --git a/phpBB/adm/style/acp_ban.html b/phpBB/adm/style/acp_ban.html
index ffea40027e..147eae106b 100644
--- a/phpBB/adm/style/acp_ban.html
+++ b/phpBB/adm/style/acp_ban.html
@@ -11,11 +11,11 @@
@@ -60,11 +73,6 @@
{S_BAN_END_OPTIONS}
{L_YEAR_MONTH_DAY}
-
- {L_BAN_EXCLUDE}{L_COLON} {L_BAN_EXCLUDE_EXPLAIN}
- {L_YES}
- {L_NO}
-
{L_BAN_REASON}{L_COLON}
@@ -90,44 +98,41 @@
{L_UNBAN_EXPLAIN}
-
diff --git a/phpBB/adm/style/admin.css b/phpBB/adm/style/admin.css
index 6924f6d890..f6598331eb 100644
--- a/phpBB/adm/style/admin.css
+++ b/phpBB/adm/style/admin.css
@@ -288,6 +288,10 @@ li {
padding-right: 10px;
}
+.w-50 {
+ width: 50%;
+}
+
@media only screen and (max-width: 700px), only screen and (max-device-width: 700px) {
#wrap,
#page-body,
diff --git a/phpBB/config/default/container/services.yml b/phpBB/config/default/container/services.yml
index 59d52073f9..9b01005852 100644
--- a/phpBB/config/default/container/services.yml
+++ b/phpBB/config/default/container/services.yml
@@ -2,6 +2,7 @@ imports:
- { resource: services_attachment.yml }
- { resource: services_auth.yml }
- { resource: services_avatar.yml }
+ - { resource: services_ban.yml }
- { resource: services_captcha.yml }
- { resource: services_console.yml }
- { resource: services_content.yml }
diff --git a/phpBB/config/default/container/services_ban.yml b/phpBB/config/default/container/services_ban.yml
new file mode 100644
index 0000000000..c9e7c6ddb0
--- /dev/null
+++ b/phpBB/config/default/container/services_ban.yml
@@ -0,0 +1,54 @@
+services:
+# ----- Ban management -----
+ ban.manager:
+ class: \phpbb\ban\manager
+ arguments:
+ - '@ban.type_collection'
+ - '@cache.driver'
+ - '@dbal.conn'
+ - '@language'
+ - '@log'
+ - '@user'
+ - '%tables.bans%'
+ - '%tables.users%'
+
+# ----- Ban types -----
+ ban.type_collection:
+ class: \phpbb\di\service_collection
+ arguments:
+ - '@service_container'
+ tags:
+ - { name: service_collection, tag: ban.type }
+
+ ban.type.email:
+ class: \phpbb\ban\type\email
+ arguments:
+ - '@dbal.conn'
+ - '%tables.bans%'
+ - '%tables.users%'
+ - '%tables.sessions%'
+ - '%tables.sessions_keys%'
+ tags:
+ - { name: ban.type }
+
+ ban.type.ip:
+ class: \phpbb\ban\type\ip
+ arguments:
+ - '@dbal.conn'
+ - '%tables.bans%'
+ - '%tables.users%'
+ - '%tables.sessions%'
+ - '%tables.sessions_keys%'
+ tags:
+ - { name: ban.type }
+
+ ban.type.user:
+ class: \phpbb\ban\type\user
+ arguments:
+ - '@dbal.conn'
+ - '%tables.bans%'
+ - '%tables.users%'
+ - '%tables.sessions%'
+ - '%tables.sessions_keys%'
+ tags:
+ - { name: ban.type }
diff --git a/phpBB/config/default/container/tables.yml b/phpBB/config/default/container/tables.yml
index 2117794b43..005f3ba927 100644
--- a/phpBB/config/default/container/tables.yml
+++ b/phpBB/config/default/container/tables.yml
@@ -9,7 +9,7 @@ parameters:
tables.auth_provider_oauth_states: '%core.table_prefix%oauth_states'
tables.auth_provider_oauth_account_assoc: '%core.table_prefix%oauth_accounts'
tables.backups: '%core.table_prefix%backups'
- tables.banlist: '%core.table_prefix%banlist'
+ tables.bans: '%core.table_prefix%bans'
tables.bbcodes: '%core.table_prefix%bbcodes'
tables.bookmarks: '%core.table_prefix%bookmarks'
tables.bots: '%core.table_prefix%bots'
diff --git a/phpBB/includes/acp/acp_ban.php b/phpBB/includes/acp/acp_ban.php
index 22ae9d4e7b..61f3096b74 100644
--- a/phpBB/includes/acp/acp_ban.php
+++ b/phpBB/includes/acp/acp_ban.php
@@ -14,6 +14,11 @@
/**
* @ignore
*/
+
+use phpbb\ban\exception\type_not_found_exception;
+use phpbb\ban\manager;
+use phpbb\language\language;
+
if (!defined('IN_PHPBB'))
{
exit;
@@ -25,9 +30,12 @@ class acp_ban
function main($id, $mode)
{
- global $user, $template, $request, $phpbb_dispatcher;
+ global $language, $template, $request, $phpbb_dispatcher, $phpbb_container;
global $phpbb_root_path, $phpEx;
+ /** @var manager $ban_manager */
+ $ban_manager = $phpbb_container->get('ban.manager');
+
if (!function_exists('user_ban'))
{
include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
@@ -36,14 +44,15 @@ class acp_ban
$bansubmit = $request->is_set_post('bansubmit');
$unbansubmit = $request->is_set_post('unbansubmit');
- $user->add_lang(array('acp/ban', 'acp/users'));
+ /** @var language $language */
+ $language->add_lang(['acp/ban', 'acp/users']);
$this->tpl_name = 'acp_ban';
$form_key = 'acp_ban';
add_form_key($form_key);
if (($bansubmit || $unbansubmit) && !check_form_key($form_key))
{
- trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
+ trigger_error($language->lang('FORM_INVALID') . adm_back_link($this->u_action), E_USER_WARNING);
}
// Ban submitted?
@@ -53,7 +62,6 @@ class acp_ban
$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);
@@ -68,7 +76,6 @@ class acp_ban
* @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.
@@ -80,7 +87,6 @@ class acp_ban
'ban',
'ban_length',
'ban_length_other',
- 'ban_exclude',
'ban_reason',
'ban_give_reason',
'abort_ban',
@@ -91,7 +97,20 @@ class acp_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);
+
+ $ban_start = new \DateTime();
+ $ban_start->setTimestamp(time());
+ $ban_end = $ban_manager->get_ban_end($ban_start, $ban_length, $ban_length_other);
+
+ $ban = explode("\n", $ban);
+ try
+ {
+ $ban_manager->ban($mode, $ban, $ban_start, $ban_end, $ban_reason, $ban_give_reason);
+ }
+ catch (\phpbb\exception\exception_interface $exception)
+ {
+ trigger_error($language->lang_array($exception->getMessage(), $exception->get_parameters()), E_USER_WARNING);
+ }
/**
* Use this event to perform actions after the ban has been performed
@@ -101,7 +120,6 @@ class acp_ban
* @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
@@ -111,49 +129,50 @@ class acp_ban
'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));
+ trigger_error($language->lang('BAN_UPDATE_SUCCESSFUL') . adm_back_link($this->u_action));
}
}
else if ($unbansubmit)
{
- $ban = $request->variable('unban', array(''));
+ $ban = $request->variable('unban', ['']);
if ($ban)
{
- user_unban($mode, $ban);
+ $ban_manager->unban($mode, $ban);
- trigger_error($user->lang['BAN_UPDATE_SUCCESSFUL'] . adm_back_link($this->u_action));
+ trigger_error($language->lang('BAN_UPDATE_SUCCESSFUL') . adm_back_link($this->u_action));
}
}
// Define language vars
- $this->page_title = $user->lang[strtoupper($mode) . '_BAN'];
+ $this->page_title = $language->lang(strtoupper($mode) . '_BAN');
- $l_ban_explain = $user->lang[strtoupper($mode) . '_BAN_EXPLAIN'];
- $l_ban_exclude_explain = $user->lang[strtoupper($mode) . '_BAN_EXCLUDE_EXPLAIN'];
- $l_unban_title = $user->lang[strtoupper($mode) . '_UNBAN'];
- $l_unban_explain = $user->lang[strtoupper($mode) . '_UNBAN_EXPLAIN'];
- $l_no_ban_cell = $user->lang[strtoupper($mode) . '_NO_BANNED'];
+ $l_ban_explain = $language->lang(strtoupper($mode) . '_BAN_EXPLAIN');
+ $l_unban_title = $language->lang(strtoupper($mode) . '_UNBAN');
+ $l_unban_explain = $language->lang(strtoupper($mode) . '_UNBAN_EXPLAIN');
+ $l_no_ban_cell = $language->lang(strtoupper($mode) . '_NO_BANNED');
switch ($mode)
{
case 'user':
- $l_ban_cell = $user->lang['USERNAME'];
+ $l_ban_cell = $language->lang('USERNAME');
break;
case 'ip':
- $l_ban_cell = $user->lang['IP_HOSTNAME'];
+ $l_ban_cell = $language->lang('IP_HOSTNAME');
break;
case 'email':
- $l_ban_cell = $user->lang['EMAIL_ADDRESS'];
+ $l_ban_cell = $language->lang('EMAIL_ADDRESS');
break;
+
+ default:
+ throw new type_not_found_exception();
}
display_ban_end_options();
@@ -165,10 +184,9 @@ class acp_ban
'L_UNBAN_TITLE' => $l_unban_title,
'L_UNBAN_EXPLAIN' => $l_unban_explain,
'L_BAN_CELL' => $l_ban_cell,
- 'L_BAN_EXCLUDE_EXPLAIN' => $l_ban_exclude_explain,
'L_NO_BAN_CELL' => $l_no_ban_cell,
- 'S_USERNAME_BAN' => ($mode == 'user') ? true : false,
+ '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'),
diff --git a/phpBB/includes/acp/acp_email.php b/phpBB/includes/acp/acp_email.php
index 3fba4917ec..cddf7b3324 100644
--- a/phpBB/includes/acp/acp_email.php
+++ b/phpBB/includes/acp/acp_email.php
@@ -26,7 +26,7 @@ class acp_email
function main($id, $mode)
{
global $config, $db, $user, $template, $phpbb_log, $request;
- global $phpbb_root_path, $phpbb_admin_path, $phpEx, $phpbb_dispatcher;
+ global $phpbb_root_path, $phpbb_admin_path, $phpEx, $phpbb_dispatcher, $phpbb_container;
$user->add_lang('acp/email');
$this->tpl_name = 'acp_email';
@@ -74,7 +74,7 @@ class acp_email
{
// If giving usernames the admin is able to email inactive users too...
$sql_ary = array(
- 'SELECT' => 'username, user_email, user_jabber, user_notify_type, user_lang',
+ 'SELECT' => 'user_id, username, user_email, user_jabber, user_notify_type, user_lang',
'FROM' => array(
USERS_TABLE => '',
),
@@ -88,7 +88,7 @@ class acp_email
if ($group_id)
{
$sql_ary = array(
- 'SELECT' => 'u.user_email, u.username, u.username_clean, u.user_lang, u.user_jabber, u.user_notify_type',
+ 'SELECT' => 'u.user_id, u.user_email, u.username, u.username_clean, u.user_lang, u.user_jabber, u.user_notify_type',
'FROM' => array(
USERS_TABLE => 'u',
USER_GROUP_TABLE => 'ug',
@@ -104,7 +104,7 @@ class acp_email
else
{
$sql_ary = array(
- 'SELECT' => 'u.username, u.username_clean, u.user_email, u.user_jabber, u.user_lang, u.user_notify_type',
+ 'SELECT' => 'u.user_id, u.username, u.username_clean, u.user_email, u.user_jabber, u.user_lang, u.user_notify_type',
'FROM' => array(
USERS_TABLE => 'u',
),
@@ -113,21 +113,6 @@ class acp_email
'ORDER_BY' => 'u.user_lang, u.user_notify_type',
);
}
-
- // Mail banned or not
- if (!isset($_REQUEST['mail_banned_flag']))
- {
- $sql_ary['WHERE'] .= ' AND (b.ban_id IS NULL
- OR b.ban_exclude = 1)';
- $sql_ary['LEFT_JOIN'] = array(
- array(
- 'FROM' => array(
- BANLIST_TABLE => 'b',
- ),
- 'ON' => 'u.user_id = b.ban_userid',
- ),
- );
- }
}
/**
* Modify sql query to change the list of users the email is sent to
@@ -141,11 +126,22 @@ class acp_email
$sql = $db->sql_build_query('SELECT', $sql_ary);
$result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
+ $rows = $db->sql_fetchrowset($result);
+ $db->sql_freeresult($result);
- if (!$row)
+ if (!empty($rows) && !$request->is_set('mail_banned_flag'))
+ {
+ /** @var \phpbb\ban\manager $ban_manager */
+ $ban_manager = $phpbb_container->get('ban.manager');
+ $banned_users = $ban_manager->get_banned_users();
+
+ $rows = array_filter($rows, function ($row) use ($banned_users) {
+ return !isset($banned_users[(int) $row['user_id']]);
+ });
+ }
+
+ if (empty($rows))
{
- $db->sql_freeresult($result);
trigger_error($user->lang['NO_USER'] . adm_back_link($this->u_action), E_USER_WARNING);
}
@@ -155,10 +151,10 @@ class acp_email
// Maximum number of bcc recipients
$max_chunk_size = (int) $config['email_max_chunk_size'];
$email_list = array();
- $old_lang = $row['user_lang'];
- $old_notify_type = $row['user_notify_type'];
+ $old_lang = $rows[0]['user_lang'];
+ $old_notify_type = $rows[0]['user_notify_type'];
- do
+ foreach ($rows as $row)
{
if (($row['user_notify_type'] == NOTIFY_EMAIL && $row['user_email']) ||
($row['user_notify_type'] == NOTIFY_IM && $row['user_jabber']) ||
@@ -185,8 +181,6 @@ class acp_email
$i++;
}
}
- while ($row = $db->sql_fetchrow($result));
- $db->sql_freeresult($result);
// Send the messages
if (!class_exists('messenger'))
diff --git a/phpBB/includes/constants.php b/phpBB/includes/constants.php
index a56a583307..f560dbfbcb 100644
--- a/phpBB/includes/constants.php
+++ b/phpBB/includes/constants.php
@@ -239,7 +239,7 @@ define('ACL_ROLES_TABLE', $table_prefix . 'acl_roles');
define('ACL_USERS_TABLE', $table_prefix . 'acl_users');
define('ATTACHMENTS_TABLE', $table_prefix . 'attachments');
define('BACKUPS_TABLE', $table_prefix . 'backups');
-define('BANLIST_TABLE', $table_prefix . 'banlist');
+define('BANS_TABLE', $table_prefix . 'bans');
define('BBCODES_TABLE', $table_prefix . 'bbcodes');
define('BOOKMARKS_TABLE', $table_prefix . 'bookmarks');
define('BOTS_TABLE', $table_prefix . 'bots');
diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php
index 11a672a2ed..ea9ddbaf3c 100644
--- a/phpBB/includes/functions_admin.php
+++ b/phpBB/includes/functions_admin.php
@@ -3156,109 +3156,68 @@ function display_ban_end_options()
*/
function display_ban_options($mode)
{
- global $user, $db, $template;
+ global $language, $user, $template, $phpbb_container;
- switch ($mode)
+ /** @var \phpbb\ban\manager $ban_manager */
+ $ban_manager = $phpbb_container->get('ban.manager');
+ $ban_rows = $ban_manager->get_bans($mode);
+
+ $banned_options = [];
+
+ foreach ($ban_rows as $ban_row)
{
- case 'user':
+ $banned_options[] = [
+ 'value' => $ban_row['ban_id'],
+ 'label' => $ban_row['label'] ?? $ban_row['ban_item'],
+ ];
- $field = 'username';
-
- $sql = 'SELECT b.*, u.user_id, u.username, u.username_clean
- FROM ' . BANLIST_TABLE . ' b, ' . USERS_TABLE . ' u
- WHERE (b.ban_end >= ' . time() . '
- OR b.ban_end = 0)
- AND u.user_id = b.ban_userid
- ORDER BY u.username_clean ASC';
- break;
-
- case 'ip':
-
- $field = 'ban_ip';
-
- $sql = 'SELECT *
- FROM ' . BANLIST_TABLE . '
- WHERE (ban_end >= ' . time() . "
- OR ban_end = 0)
- AND ban_ip <> ''
- ORDER BY ban_ip";
- break;
-
- case 'email':
-
- $field = 'ban_email';
-
- $sql = 'SELECT *
- FROM ' . BANLIST_TABLE . '
- WHERE (ban_end >= ' . time() . "
- OR ban_end = 0)
- AND ban_email <> ''
- ORDER BY ban_email";
- break;
- }
- $result = $db->sql_query($sql);
-
- $banned_options = $excluded_options = array();
- while ($row = $db->sql_fetchrow($result))
- {
- $option = '' . $row[$field] . ' ';
-
- if ($row['ban_exclude'])
- {
- $excluded_options[] = $option;
- }
- else
- {
- $banned_options[] = $option;
- }
-
- $time_length = ($row['ban_end']) ? ($row['ban_end'] - $row['ban_start']) / 60 : 0;
+ $time_length = ($ban_row['ban_end']) ? ($ban_row['ban_end'] - $ban_row['ban_start']) / 60 : 0;
if ($time_length == 0)
{
// Banned permanently
- $ban_length = $user->lang['PERMANENT'];
+ $ban_length = $language->lang('PERMANENT');
}
else if (isset($ban_end_text[$time_length]))
{
// Banned for a given duration
- $ban_length = $user->lang('BANNED_UNTIL_DURATION', $ban_end_text[$time_length], $user->format_date($row['ban_end'], false, true));
+ $ban_length = $language->lang('BANNED_UNTIL_DURATION', $ban_end_text[$time_length], $user->format_date($ban_row['ban_end'], false, true));
}
else
{
// Banned until given date
- $ban_length = $user->lang('BANNED_UNTIL_DATE', $user->format_date($row['ban_end'], false, true));
+ $ban_length = $language->lang('BANNED_UNTIL_DATE', $user->format_date($ban_row['ban_end'], false, true));
}
$template->assign_block_vars('bans', array(
- 'BAN_ID' => (int) $row['ban_id'],
+ 'BAN_ID' => (int) $ban_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']),
+ 'REASON' => $ban_row['ban_reason'],
+ 'A_REASON' => addslashes($ban_row['ban_reason']),
+ 'GIVE_REASON' => $ban_row['ban_reason_display'],
+ 'A_GIVE_REASON' => addslashes($ban_row['ban_reason_display']),
));
}
- $db->sql_freeresult($result);
- $options = '';
- if ($excluded_options)
+ if (count($banned_options))
{
- $options .= '';
- $options .= implode('', $excluded_options);
- $options .= ' ';
- }
+ $banned_select = [
+ 'tag' => 'select',
+ 'name' => 'unban[]',
+ 'id' => 'unban',
+ 'class' => 'w-50',
+ 'multiple' => true,
+ 'size' => 10,
+ 'data' => [
+ 'onchange' => 'display_details',
+ ],
+ 'options' => [[
+ 'label' => $language->lang('OPTIONS_BANNED'),
+ 'options' => $banned_options,
+ ]],
+ ];
- if ($banned_options)
- {
- $options .= '';
- $options .= implode('', $banned_options);
- $options .= ' ';
+ $template->assign_vars(['BANNED_SELECT' => $banned_select]);
}
-
- $template->assign_vars(array(
- 'S_BANNED_OPTIONS' => ($banned_options || $excluded_options) ? true : false,
- 'BANNED_OPTIONS' => $options,
- ));
}
diff --git a/phpBB/includes/functions_display.php b/phpBB/includes/functions_display.php
index e274ae8476..7e49ed3ede 100644
--- a/phpBB/includes/functions_display.php
+++ b/phpBB/includes/functions_display.php
@@ -1632,6 +1632,10 @@ function phpbb_show_profile($data, $user_notes_enabled = false, $warn_user_enabl
include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
}
+ /** @var \phpbb\ban\manager $ban_manager */
+ $ban_manager = $phpbb_container->get('ban.manager');
+ $user_banned = $ban_manager->check($data);
+
// Can this user receive a Private Message?
$can_receive_pm = $check_can_receive_pm && (
// They must be a "normal" user
@@ -1644,7 +1648,7 @@ function phpbb_show_profile($data, $user_notes_enabled = false, $warn_user_enabl
count($auth->acl_get_list($user_id, 'u_readpm')) &&
// They must not be permanently banned
- !count(phpbb_get_banned_user_ids($user_id, false)) &&
+ (empty($user_banned) || $user_banned['end'] > 0) &&
// They must allow users to contact via PM
(($auth->acl_gets('a_', 'm_') || $auth->acl_getf_global('m_')) || $data['user_allow_pm'])
diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php
index 9cdeb7c619..340f03c0c0 100644
--- a/phpBB/includes/functions_user.php
+++ b/phpBB/includes/functions_user.php
@@ -749,8 +749,9 @@ function user_delete($mode, $user_ids, $retain_username = true)
$db->sql_query($sql);
// Delete the user_id from the banlist
- $sql = 'DELETE FROM ' . BANLIST_TABLE . '
- WHERE ' . $db->sql_in_set('ban_userid', $user_ids);
+ $sql = 'DELETE FROM ' . BANS_TABLE . "
+ WHERE ban_mode = 'user'
+ AND " . $db->sql_in_set('ban_userid', $user_ids);
$db->sql_query($sql);
// Delete the user_id from the session table
@@ -915,30 +916,26 @@ function user_active_flip($mode, $user_id_ary, $reason = INACTIVE_MANUAL)
/**
* Add a ban or ban exclusion to the banlist. Bans either a user, an IP or an email address
*
+* @deprecated 4.0.0-a1 (To be removed: 4.1.0)
+*
* @param string $mode Type of ban. One of the following: user, ip, email
* @param mixed $ban Banned entity. Either string or array with usernames, ips or email addresses
* @param int $ban_len Ban length in minutes
* @param string $ban_len_other Ban length as a date (YYYY-MM-DD)
-* @param boolean $ban_exclude Exclude these entities from banning?
* @param string $ban_reason String describing the reason for this ban
* @param string $ban_give_reason
* @return boolean
*/
-function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reason, $ban_give_reason = '')
+function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_reason, $ban_give_reason = '')
{
- global $db, $user, $cache, $phpbb_log;
+ global $phpbb_container, $user;
- // Delete stale bans
- $sql = 'DELETE FROM ' . BANLIST_TABLE . '
- WHERE ban_end < ' . time() . '
- AND ban_end <> 0';
- $db->sql_query($sql);
+ /** @var \phpbb\ban\manager $ban_manager */
+ $ban_manager = $phpbb_container->get('ban.manager');
- $ban_list = (!is_array($ban)) ? array_unique(explode("\n", $ban)) : $ban;
- $ban_list_log = implode(', ', $ban_list);
+ $items = is_array($ban) ? $ban : [$ban];
$current_time = time();
-
// Set $ban_end to the unix time when the ban should end. 0 is a permanent ban.
if ($ban_len)
{
@@ -953,9 +950,9 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas
(strlen($ban_other[0]) == 4) && (strlen($ban_other[1]) == 2) && (strlen($ban_other[2]) == 2))
{
$ban_end = max($current_time, $user->create_datetime()
- ->setDate((int) $ban_other[0], (int) $ban_other[1], (int) $ban_other[2])
- ->setTime(0, 0, 0)
- ->getTimestamp() + $user->timezone->getOffset(new DateTime('UTC')));
+ ->setDate((int) $ban_other[0], (int) $ban_other[1], (int) $ban_other[2])
+ ->setTime(0, 0, 0)
+ ->getTimestamp() + $user->timezone->getOffset(new DateTime('UTC')));
}
else
{
@@ -968,482 +965,28 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas
$ban_end = 0;
}
- $founder = $founder_names = array();
+ $start = new \DateTime();
+ $start->setTimestamp($current_time);
+ $end = new \DateTime();
+ $end->setTimestamp($ban_end);
- if (!$ban_exclude)
- {
- // Create a list of founder...
- $sql = 'SELECT user_id, user_email, username_clean
- FROM ' . USERS_TABLE . '
- WHERE user_type = ' . USER_FOUNDER;
- $result = $db->sql_query($sql);
-
- while ($row = $db->sql_fetchrow($result))
- {
- $founder[$row['user_id']] = $row['user_email'];
- $founder_names[$row['user_id']] = $row['username_clean'];
- }
- $db->sql_freeresult($result);
- }
-
- $banlist_ary = array();
-
- switch ($mode)
- {
- case 'user':
- $type = 'ban_userid';
-
- // At the moment we do not support wildcard username banning
-
- // Select the relevant user_ids.
- $sql_usernames = array();
-
- foreach ($ban_list as $username)
- {
- $username = trim($username);
- if ($username != '')
- {
- $clean_name = utf8_clean_string($username);
- if ($clean_name == $user->data['username_clean'])
- {
- trigger_error('CANNOT_BAN_YOURSELF', E_USER_WARNING);
- }
- if (in_array($clean_name, $founder_names))
- {
- trigger_error('CANNOT_BAN_FOUNDER', E_USER_WARNING);
- }
- $sql_usernames[] = $clean_name;
- }
- }
-
- // Make sure we have been given someone to ban
- if (!count($sql_usernames))
- {
- trigger_error('NO_USER_SPECIFIED', E_USER_WARNING);
- }
-
- $sql = 'SELECT user_id
- FROM ' . USERS_TABLE . '
- WHERE ' . $db->sql_in_set('username_clean', $sql_usernames);
-
- // Do not allow banning yourself, the guest account, or founders.
- $non_bannable = array($user->data['user_id'], ANONYMOUS);
- if (count($founder))
- {
- $sql .= ' AND ' . $db->sql_in_set('user_id', array_merge(array_keys($founder), $non_bannable), true);
- }
- else
- {
- $sql .= ' AND ' . $db->sql_in_set('user_id', $non_bannable, true);
- }
-
- $result = $db->sql_query($sql);
-
- if ($row = $db->sql_fetchrow($result))
- {
- do
- {
- $banlist_ary[] = (int) $row['user_id'];
- }
- while ($row = $db->sql_fetchrow($result));
-
- $db->sql_freeresult($result);
- }
- else
- {
- $db->sql_freeresult($result);
-
- trigger_error('NO_USERS', E_USER_WARNING);
- }
- break;
-
- case 'ip':
- $type = 'ban_ip';
-
- foreach ($ban_list as $ban_item)
- {
- if (preg_match('#^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})[ ]*\-[ ]*([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$#', trim($ban_item), $ip_range_explode))
- {
- // This is an IP range
- // Don't ask about all this, just don't ask ... !
- $ip_1_counter = $ip_range_explode[1];
- $ip_1_end = $ip_range_explode[5];
-
- while ($ip_1_counter <= $ip_1_end)
- {
- $ip_2_counter = ($ip_1_counter == $ip_range_explode[1]) ? $ip_range_explode[2] : 0;
- $ip_2_end = ($ip_1_counter < $ip_1_end) ? 254 : $ip_range_explode[6];
-
- if ($ip_2_counter == 0 && $ip_2_end == 254)
- {
- $ip_2_counter = 256;
-
- $banlist_ary[] = "$ip_1_counter.*";
- }
-
- while ($ip_2_counter <= $ip_2_end)
- {
- $ip_3_counter = ($ip_2_counter == $ip_range_explode[2] && $ip_1_counter == $ip_range_explode[1]) ? $ip_range_explode[3] : 0;
- $ip_3_end = ($ip_2_counter < $ip_2_end || $ip_1_counter < $ip_1_end) ? 254 : $ip_range_explode[7];
-
- if ($ip_3_counter == 0 && $ip_3_end == 254)
- {
- $ip_3_counter = 256;
-
- $banlist_ary[] = "$ip_1_counter.$ip_2_counter.*";
- }
-
- while ($ip_3_counter <= $ip_3_end)
- {
- $ip_4_counter = ($ip_3_counter == $ip_range_explode[3] && $ip_2_counter == $ip_range_explode[2] && $ip_1_counter == $ip_range_explode[1]) ? $ip_range_explode[4] : 0;
- $ip_4_end = ($ip_3_counter < $ip_3_end || $ip_2_counter < $ip_2_end) ? 254 : $ip_range_explode[8];
-
- if ($ip_4_counter == 0 && $ip_4_end == 254)
- {
- $ip_4_counter = 256;
-
- $banlist_ary[] = "$ip_1_counter.$ip_2_counter.$ip_3_counter.*";
- }
-
- while ($ip_4_counter <= $ip_4_end)
- {
- $banlist_ary[] = "$ip_1_counter.$ip_2_counter.$ip_3_counter.$ip_4_counter";
- $ip_4_counter++;
- }
- $ip_3_counter++;
- }
- $ip_2_counter++;
- }
- $ip_1_counter++;
- }
- }
- else if (preg_match('#^([0-9]{1,3})\.([0-9\*]{1,3})\.([0-9\*]{1,3})\.([0-9\*]{1,3})$#', trim($ban_item)) || preg_match('#^[a-f0-9:]+\*?$#i', trim($ban_item)))
- {
- // Normal IP address
- $banlist_ary[] = trim($ban_item);
- }
- else if (preg_match('#^\*$#', trim($ban_item)))
- {
- // Ban all IPs
- $banlist_ary[] = '*';
- }
- else if (preg_match('#^([\w\-_]\.?){2,}$#is', trim($ban_item)))
- {
- // hostname
- $ip_ary = gethostbynamel(trim($ban_item));
-
- if (!empty($ip_ary))
- {
- foreach ($ip_ary as $ip)
- {
- if ($ip)
- {
- if (strlen($ip) > 40)
- {
- continue;
- }
-
- $banlist_ary[] = $ip;
- }
- }
- }
- }
-
- if (empty($banlist_ary))
- {
- trigger_error('NO_IPS_DEFINED', E_USER_WARNING);
- }
- }
- break;
-
- case 'email':
- $type = 'ban_email';
-
- foreach ($ban_list as $ban_item)
- {
- $ban_item = trim($ban_item);
-
- if (preg_match('#^.*?@*|(([a-z0-9\-]+\.)+([a-z]{2,3}))$#i', $ban_item))
- {
- if (strlen($ban_item) > 100)
- {
- continue;
- }
-
- if (!count($founder) || !in_array($ban_item, $founder))
- {
- $banlist_ary[] = $ban_item;
- }
- }
- }
-
- if (count($ban_list) == 0)
- {
- trigger_error('NO_EMAILS_DEFINED', E_USER_WARNING);
- }
- break;
-
- default:
- trigger_error('NO_MODE', E_USER_WARNING);
- break;
- }
-
- // Fetch currently set bans of the specified type and exclude state. Prevent duplicate bans.
- $sql_where = ($type == 'ban_userid') ? 'ban_userid <> 0' : "$type <> ''";
-
- $sql = "SELECT $type
- FROM " . BANLIST_TABLE . "
- WHERE $sql_where
- AND ban_exclude = " . (int) $ban_exclude;
- $result = $db->sql_query($sql);
-
- // Reset $sql_where, because we use it later...
- $sql_where = '';
-
- if ($row = $db->sql_fetchrow($result))
- {
- $banlist_ary_tmp = array();
- do
- {
- switch ($mode)
- {
- case 'user':
- $banlist_ary_tmp[] = $row['ban_userid'];
- break;
-
- case 'ip':
- $banlist_ary_tmp[] = $row['ban_ip'];
- break;
-
- case 'email':
- $banlist_ary_tmp[] = $row['ban_email'];
- break;
- }
- }
- while ($row = $db->sql_fetchrow($result));
-
- $banlist_ary_tmp = array_intersect($banlist_ary, $banlist_ary_tmp);
-
- if (count($banlist_ary_tmp))
- {
- // One or more entities are already banned/excluded, delete the existing bans, so they can be re-inserted with the given new length
- $sql = 'DELETE FROM ' . BANLIST_TABLE . '
- WHERE ' . $db->sql_in_set($type, $banlist_ary_tmp) . '
- AND ban_exclude = ' . (int) $ban_exclude;
- $db->sql_query($sql);
- }
-
- unset($banlist_ary_tmp);
- }
- $db->sql_freeresult($result);
-
- // We have some entities to ban
- if (count($banlist_ary))
- {
- $sql_ary = array();
-
- foreach ($banlist_ary as $ban_entry)
- {
- $sql_ary[] = array(
- $type => $ban_entry,
- 'ban_start' => (int) $current_time,
- 'ban_end' => (int) $ban_end,
- 'ban_exclude' => (int) $ban_exclude,
- 'ban_reason' => (string) $ban_reason,
- 'ban_give_reason' => (string) $ban_give_reason,
- );
- }
-
- $db->sql_multi_insert(BANLIST_TABLE, $sql_ary);
-
- // If we are banning we want to logout anyone matching the ban
- if (!$ban_exclude)
- {
- switch ($mode)
- {
- case 'user':
- $sql_where = 'WHERE ' . $db->sql_in_set('session_user_id', $banlist_ary);
- break;
-
- case 'ip':
- $sql_where = 'WHERE ' . $db->sql_in_set('session_ip', $banlist_ary);
- break;
-
- case 'email':
- $banlist_ary_sql = array();
-
- foreach ($banlist_ary as $ban_entry)
- {
- $banlist_ary_sql[] = (string) str_replace('*', '%', $ban_entry);
- }
-
- $sql = 'SELECT user_id
- FROM ' . USERS_TABLE . '
- WHERE ' . $db->sql_in_set('user_email', $banlist_ary_sql);
- $result = $db->sql_query($sql);
-
- $sql_in = array();
-
- if ($row = $db->sql_fetchrow($result))
- {
- do
- {
- $sql_in[] = $row['user_id'];
- }
- while ($row = $db->sql_fetchrow($result));
-
- $sql_where = 'WHERE ' . $db->sql_in_set('session_user_id', $sql_in);
- }
- $db->sql_freeresult($result);
- break;
- }
-
- if (isset($sql_where) && $sql_where)
- {
- $sql = 'DELETE FROM ' . SESSIONS_TABLE . "
- $sql_where";
- $db->sql_query($sql);
-
- if ($mode == 'user')
- {
- $sql = 'DELETE FROM ' . SESSIONS_KEYS_TABLE . ' ' . ((in_array('*', $banlist_ary)) ? '' : 'WHERE ' . $db->sql_in_set('user_id', $banlist_ary));
- $db->sql_query($sql);
- }
- }
- }
-
- // Update log
- $log_entry = ($ban_exclude) ? 'LOG_BAN_EXCLUDE_' : 'LOG_BAN_';
-
- // 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)
- {
- $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
- ));
- }
- }
-
- $cache->destroy('sql', BANLIST_TABLE);
-
- return true;
- }
-
- // There was nothing to ban/exclude. But destroying the cache because of the removal of stale bans.
- $cache->destroy('sql', BANLIST_TABLE);
-
- return false;
+ return $ban_manager->ban($mode, $items, $start, $end, $ban_reason, $ban_give_reason);
}
/**
* Unban User
+*
+* @deprecated 4.0.0-a1 (To be removed: 4.1.0)
*/
function user_unban($mode, $ban)
{
- global $db, $user, $cache, $phpbb_log, $phpbb_dispatcher;
+ global $phpbb_container;
- // Delete stale bans
- $sql = 'DELETE FROM ' . BANLIST_TABLE . '
- WHERE ban_end < ' . time() . '
- AND ban_end <> 0';
- $db->sql_query($sql);
+ $items = is_array($ban) ? $ban : [$ban];
- if (!is_array($ban))
- {
- $ban = array($ban);
- }
-
- $unban_sql = array_map('intval', $ban);
-
- if (count($unban_sql))
- {
- // Grab details of bans for logging information later
- switch ($mode)
- {
- case 'user':
- $sql = 'SELECT u.username AS unban_info, u.user_id
- FROM ' . USERS_TABLE . ' u, ' . BANLIST_TABLE . ' b
- WHERE ' . $db->sql_in_set('b.ban_id', $unban_sql) . '
- AND u.user_id = b.ban_userid';
- break;
-
- case 'email':
- $sql = 'SELECT ban_email AS unban_info
- FROM ' . BANLIST_TABLE . '
- WHERE ' . $db->sql_in_set('ban_id', $unban_sql);
- break;
-
- case 'ip':
- $sql = 'SELECT ban_ip AS unban_info
- FROM ' . BANLIST_TABLE . '
- WHERE ' . $db->sql_in_set('ban_id', $unban_sql);
- break;
- }
- $result = $db->sql_query($sql);
-
- $l_unban_list = '';
- $user_ids_ary = array();
- while ($row = $db->sql_fetchrow($result))
- {
- $l_unban_list .= (($l_unban_list != '') ? ', ' : '') . $row['unban_info'];
- if ($mode == 'user')
- {
- $user_ids_ary[] = $row['user_id'];
- }
- }
- $db->sql_freeresult($result);
-
- $sql = 'DELETE FROM ' . BANLIST_TABLE . '
- WHERE ' . $db->sql_in_set('ban_id', $unban_sql);
- $db->sql_query($sql);
-
- // Add to moderator log, admin log and user notes
- $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)
- {
- $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_UNBAN_' . strtoupper($mode), false, array(
- 'reportee_id' => $user_id,
- $l_unban_list
- ));
- }
- }
-
- /**
- * Use this event to perform actions after the unban has been performed
- *
- * @event core.user_unban
- * @var string mode One of the following: user, ip, email
- * @var array user_ids_ary Array with user_ids
- * @since 3.1.11-RC1
- */
- $vars = array(
- 'mode',
- 'user_ids_ary',
- );
- extract($phpbb_dispatcher->trigger_event('core.user_unban', compact($vars)));
- }
-
- $cache->destroy('sql', BANLIST_TABLE);
-
- return false;
+ /** @var \phpbb\ban\manager $ban_manager */
+ $ban_manager = $phpbb_container->get('ban.manager');
+ $ban_manager->unban($mode, $items);
}
/**
@@ -1948,7 +1491,7 @@ function validate_user_email($email, $allowed_email = false)
$ban = $user->check_ban(false, false, $email, true);
if (!empty($ban))
{
- return !empty($ban['ban_give_reason']) ? $ban['ban_give_reason'] : 'EMAIL_BANNED';
+ return !empty($ban['reason']) ? $ban['reason'] : 'EMAIL_BANNED';
}
if (!$config['allow_emailreuse'])
@@ -3719,45 +3262,43 @@ function remove_newly_registered($user_id, $user_data = false)
*/
function phpbb_get_banned_user_ids($user_ids = array(), $ban_end = true)
{
- global $db;
+ global $phpbb_container;
- $sql_user_ids = (!empty($user_ids)) ? $db->sql_in_set('ban_userid', $user_ids) : 'ban_userid <> 0';
+ /** @var \phpbb\ban\manager $ban_manager */
+ $ban_manager = $phpbb_container->get('ban.manager');
+ $banned_users = $ban_manager->get_banned_users();
- // Get banned User ID's
- // Ignore stale bans which were not wiped yet
- $banned_ids_list = array();
- $sql = 'SELECT ban_userid
- FROM ' . BANLIST_TABLE . "
- WHERE $sql_user_ids
- AND ban_exclude <> 1";
-
- if ($ban_end === true)
+ if ($ban_end === false)
{
- // Banned currently
- $sql .= " AND (ban_end > " . time() . '
- OR ban_end = 0)';
+ $banned_users = array_filter($banned_users, function ($end) {
+ return $end <= 0;
+ });
}
- else if ($ban_end === false)
+ else if ($ban_end !== true)
{
- // Permanently banned
- $sql .= " AND ban_end = 0";
+ $banned_users = array_filter($banned_users, function ($end) use ($ban_end) {
+ return $end <= 0 || $end > (int) $ban_end;
+ });
}
else
{
- // Banned until a specified time
- $sql .= " AND (ban_end > " . (int) $ban_end . '
- OR ban_end = 0)';
+ $banned_users = array_filter($banned_users, function ($end) {
+ return $end <= 0 || $end > time();
+ });
}
- $result = $db->sql_query($sql);
- while ($row = $db->sql_fetchrow($result))
+ $result_array = [];
+ foreach ($banned_users as $user_id => $_)
{
- $user_id = (int) $row['ban_userid'];
- $banned_ids_list[$user_id] = $user_id;
- }
- $db->sql_freeresult($result);
+ if (count($user_ids) && !in_array($user_id, $user_ids))
+ {
+ continue;
+ }
- return $banned_ids_list;
+ $result_array[$user_id] = $user_id;
+ }
+
+ return $result_array;
}
/**
diff --git a/phpBB/includes/mcp/mcp_ban.php b/phpBB/includes/mcp/mcp_ban.php
index c358680e00..2398d76371 100644
--- a/phpBB/includes/mcp/mcp_ban.php
+++ b/phpBB/includes/mcp/mcp_ban.php
@@ -68,7 +68,6 @@ class mcp_ban
$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);
@@ -85,7 +84,6 @@ class mcp_ban
* @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.
@@ -97,7 +95,6 @@ class mcp_ban
'ban',
'ban_length',
'ban_length_other',
- 'ban_exclude',
'ban_reason',
'ban_give_reason',
'abort_ban',
@@ -108,7 +105,7 @@ class mcp_ban
{
trigger_error($abort_ban);
}
- user_ban($mode, $ban, $ban_length, $ban_length_other, $ban_exclude, $ban_reason, $ban_give_reason);
+ user_ban($mode, $ban, $ban_length, $ban_length_other, $ban_reason, $ban_give_reason);
/**
* Use this event to perform actions after the ban has been performed
@@ -118,7 +115,6 @@ class mcp_ban
* @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
@@ -128,7 +124,6 @@ class mcp_ban
'ban',
'ban_length',
'ban_length_other',
- 'ban_exclude',
'ban_reason',
'ban_give_reason',
);
@@ -144,7 +139,6 @@ class mcp_ban
'bansubmit' => true,
'banlength' => $ban_length,
'banlengthother' => $ban_length_other,
- 'banexclude' => $ban_exclude,
'banreason' => $ban_reason,
'bangivereason' => $ban_give_reason,
);
@@ -189,7 +183,6 @@ class mcp_ban
$this->page_title = $user->lang[strtoupper($mode) . '_BAN'];
$l_ban_explain = $user->lang[strtoupper($mode) . '_BAN_EXPLAIN'];
- $l_ban_exclude_explain = $user->lang[strtoupper($mode) . '_BAN_EXCLUDE_EXPLAIN'];
$l_unban_title = $user->lang[strtoupper($mode) . '_UNBAN'];
$l_unban_explain = $user->lang[strtoupper($mode) . '_UNBAN_EXPLAIN'];
$l_no_ban_cell = $user->lang[strtoupper($mode) . '_NO_BANNED'];
@@ -218,7 +211,6 @@ class mcp_ban
'L_UNBAN_TITLE' => $l_unban_title,
'L_UNBAN_EXPLAIN' => $l_unban_explain,
'L_BAN_CELL' => $l_ban_cell,
- 'L_BAN_EXCLUDE_EXPLAIN' => $l_ban_exclude_explain,
'L_NO_BAN_CELL' => $l_no_ban_cell,
'S_USERNAME_BAN' => ($mode == 'user') ? true : false,
diff --git a/phpBB/index.php b/phpBB/index.php
index 6275c92458..bc7c1a4707 100644
--- a/phpBB/index.php
+++ b/phpBB/index.php
@@ -114,13 +114,13 @@ if ($show_birthdays)
),
'LEFT_JOIN' => array(
array(
- 'FROM' => array(BANLIST_TABLE => 'b'),
+ 'FROM' => array(BANS_TABLE => 'b'),
'ON' => 'u.user_id = b.ban_userid',
),
),
- 'WHERE' => "(b.ban_id IS NULL OR b.ban_exclude = 1)
- AND (u.user_birthday LIKE '" . $db->sql_escape(sprintf('%2d-%2d-', $now['mday'], $now['mon'])) . "%' $leap_year_birthdays)
- AND u.user_type IN (" . USER_NORMAL . ', ' . USER_FOUNDER . ')',
+ 'WHERE' => 'b.ban_id IS NULL
+ AND u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ")
+ AND (u.user_birthday LIKE '" . $db->sql_escape(sprintf('%2d-%2d-', $now['mday'], $now['mon'])) . "%' $leap_year_birthdays)",
);
/**
diff --git a/phpBB/install/convert/convertor.php b/phpBB/install/convert/convertor.php
index b52a0b03bc..a90b7337dc 100644
--- a/phpBB/install/convert/convertor.php
+++ b/phpBB/install/convert/convertor.php
@@ -755,7 +755,7 @@ class convertor
{
if (!$db->sql_query($insert_query . $waiting_sql))
{
- $this->db_error($user->lang['DB_ERR_INSERT'], htmlspecialchars($insert_query . $waiting_sql, ENT_COMPAT) . ' ' . htmlspecialchars(print_r($db->_sql_error(), true), ENT_COMPAT), __LINE__, __FILE__, true);
+ $this->db_error($user->lang['DB_ERR_INSERT'], htmlspecialchars($insert_query . $waiting_sql, ENT_COMPAT) . ' ' . htmlspecialchars(print_r($db->sql_error(), true), ENT_COMPAT), __LINE__, __FILE__, true);
}
}
@@ -774,7 +774,7 @@ class convertor
if (!$db->sql_query($insert_sql))
{
- $this->db_error($user->lang['DB_ERR_INSERT'], htmlspecialchars($insert_sql, ENT_COMPAT) . ' ' . htmlspecialchars(print_r($db->_sql_error(), true), ENT_COMPAT), __LINE__, __FILE__, true);
+ $this->db_error($user->lang['DB_ERR_INSERT'], htmlspecialchars($insert_sql, ENT_COMPAT) . ' ' . htmlspecialchars(print_r($db->sql_error(), true), ENT_COMPAT), __LINE__, __FILE__, true);
}
$db->sql_return_on_error(false);
@@ -809,7 +809,7 @@ class convertor
foreach ($waiting_rows as $waiting_sql)
{
$db->sql_query($insert_query . $waiting_sql);
- $this->db_error($user->lang['DB_ERR_INSERT'], htmlspecialchars($insert_query . $waiting_sql, ENT_COMPAT) . ' ' . htmlspecialchars(print_r($db->_sql_error(), true), ENT_COMPAT), __LINE__, __FILE__, true);
+ $this->db_error($user->lang['DB_ERR_INSERT'], htmlspecialchars($insert_query . $waiting_sql, ENT_COMPAT) . ' ' . htmlspecialchars(print_r($db->sql_error(), true), ENT_COMPAT), __LINE__, __FILE__, true);
}
$db->sql_return_on_error(false);
diff --git a/phpBB/install/convertors/convert_phpbb20.php b/phpBB/install/convertors/convert_phpbb20.php
index 62294bf449..afea6a92da 100644
--- a/phpBB/install/convertors/convert_phpbb20.php
+++ b/phpBB/install/convertors/convert_phpbb20.php
@@ -445,29 +445,42 @@ if (!$get_info)
),
array(
- 'target' => BANLIST_TABLE,
- 'execute_first' => 'phpbb_check_username_collisions();',
- 'query_first' => array('target', $convert->truncate_statement . BANLIST_TABLE),
+ 'target' => BANS_TABLE,
+ 'execute_first' => 'phpbb_check_username_collisions();',
+ 'query_first' => array('target', $convert->truncate_statement . BANS_TABLE),
- array('ban_ip', 'banlist.ban_ip', 'decode_ban_ip'),
- array('ban_userid', 'banlist.ban_userid', 'phpbb_user_id'),
- array('ban_email', 'banlist.ban_email', ''),
- array('ban_reason', '', ''),
- array('ban_give_reason', '', ''),
+ array('ban_mode', 'user', ''),
+ array('ban_item', 'banlist.ban_userid', 'phpbb_user_id'),
+ array('ban_userid', 'banlist.ban_userid', 'phpbb_user_id'),
+ array('ban_reason', '', ''),
+ array('ban_reason_display', '', ''),
- 'where' => "banlist.ban_ip NOT LIKE '%.%'",
+ 'where' => "banlist.ban_ip NOT LIKE '%.%'
+ AND banlist.ban_userid <> 0",
),
array(
- 'target' => BANLIST_TABLE,
+ 'target' => BANS_TABLE,
- array('ban_ip', 'banlist.ban_ip', ''),
- array('ban_userid', 0, ''),
- array('ban_email', '', ''),
- array('ban_reason', '', ''),
- array('ban_give_reason', '', ''),
+ array('ban_mode', 'email', ''),
+ array('ban_item', 'banlist.ban_email', ''),
+ array('ban_reason', '', ''),
+ array('ban_reason_display', '', ''),
- 'where' => "banlist.ban_ip LIKE '%.%'",
+ 'where' => "banlist.ban_ip NOT LIKE '%.%'
+ AND banlist.ban_email <> ''",
+ ),
+
+ array(
+ 'target' => BANS_TABLE,
+
+ array('ban_mode', 'ip', ''),
+ array('ban_item', 'banlist.ban_ip', 'decode_ban_ip'),
+ array('ban_reason', '', ''),
+ array('ban_reason_display', '', ''),
+
+ 'where' => "banlist.ban_userid = 0
+ AND banlist.ban_ip <> ''",
),
array(
diff --git a/phpBB/language/en/acp/ban.php b/phpBB/language/en/acp/ban.php
index 93d5cf9a8b..6f15932c1e 100644
--- a/phpBB/language/en/acp/ban.php
+++ b/phpBB/language/en/acp/ban.php
@@ -44,7 +44,6 @@ $lang = array_merge($lang, array(
'ACP_BAN_EXPLAIN' => 'Here you can control the banning of users by name, IP or email address. These methods prevent a user reaching any part of the board. You can give a short (maximum 3000 characters) reason for the ban if you wish. This will be displayed in the admin log. The duration of a ban can also be specified. If you want the ban to end on a specific date rather than after a set time period select Until -> for the ban length and enter a date in YYYY-MM-DD format.',
- 'BAN_EXCLUDE' => 'Exclude from banning',
'BAN_LENGTH' => 'Length of ban',
'BAN_REASON' => 'Reason for ban',
'BAN_GIVE_REASON' => 'Reason shown to the banned',
@@ -53,32 +52,28 @@ $lang = array_merge($lang, array(
'BANNED_UNTIL_DURATION' => '%1$s (until %2$s)', // Example: "7 days (until Tue 14.Jul.2009, 14:44)"
'EMAIL_BAN' => 'Ban one or more email addresses',
- 'EMAIL_BAN_EXCLUDE_EXPLAIN' => 'Enable this to exclude the entered email address from all current bans.',
'EMAIL_BAN_EXPLAIN' => 'To specify more than one email address enter each on a new line. To match partial addresses use * as the wildcard, e.g. *@hotmail.com , *@*.domain.tld , etc.',
'EMAIL_NO_BANNED' => 'No banned email addresses',
- 'EMAIL_UNBAN' => 'Un-ban or un-exclude emails',
- 'EMAIL_UNBAN_EXPLAIN' => 'You can unban (or un-exclude) multiple email addresses in one go using the appropriate combination of mouse and keyboard for your computer and browser. Excluded email addresses are emphasised.',
+ 'EMAIL_UNBAN' => 'Un-ban emails',
+ 'EMAIL_UNBAN_EXPLAIN' => 'You can unban multiple email addresses in one go using the appropriate combination of mouse and keyboard for your computer and browser.',
'IP_BAN' => 'Ban one or more IPs',
- 'IP_BAN_EXCLUDE_EXPLAIN' => 'Enable this to exclude the entered IP from all current bans.',
'IP_BAN_EXPLAIN' => 'To specify several different IPs or hostnames enter each on a new line. To specify a range of IP addresses separate the start and end with a hyphen (-), to specify a wildcard use “*”.',
'IP_HOSTNAME' => 'IP addresses or hostnames',
'IP_NO_BANNED' => 'No banned IP addresses',
- 'IP_UNBAN' => 'Un-ban or un-exclude IPs',
- 'IP_UNBAN_EXPLAIN' => 'You can unban (or un-exclude) multiple IP addresses in one go using the appropriate combination of mouse and keyboard for your computer and browser. Excluded IPs are emphasised.',
+ 'IP_UNBAN' => 'Un-ban IPs',
+ 'IP_UNBAN_EXPLAIN' => 'You can unban multiple IP addresses in one go using the appropriate combination of mouse and keyboard for your computer and browser.',
'LENGTH_BAN_INVALID' => 'The date has to be formatted YYYY-MM-DD .',
'OPTIONS_BANNED' => 'Banned',
- 'OPTIONS_EXCLUDED' => 'Excluded',
'PERMANENT' => 'Permanent',
'UNTIL' => 'Until',
'USER_BAN' => 'Ban one or more users by username',
- 'USER_BAN_EXCLUDE_EXPLAIN' => 'Enable this to exclude the entered users from all current bans.',
'USER_BAN_EXPLAIN' => 'You can ban multiple users in one go by entering each name on a new line. Use the Find a member facility to look up and add one or more users automatically.',
'USER_NO_BANNED' => 'No banned usernames',
- 'USER_UNBAN' => 'Un-ban or un-exclude users by username',
- 'USER_UNBAN_EXPLAIN' => 'You can unban (or un-exclude) multiple users in one go using the appropriate combination of mouse and keyboard for your computer and browser. Excluded users are emphasised.',
+ 'USER_UNBAN' => 'Un-ban users by username',
+ 'USER_UNBAN_EXPLAIN' => 'You can unban multiple users in one go using the appropriate combination of mouse and keyboard for your computer and browser.',
));
diff --git a/phpBB/language/en/acp/common.php b/phpBB/language/en/acp/common.php
index e53937c8a3..aeab0af262 100644
--- a/phpBB/language/en/acp/common.php
+++ b/phpBB/language/en/acp/common.php
@@ -553,9 +553,6 @@ $lang = array_merge($lang, array(
'LOG_ATTACH_FILEUPLOAD' => 'Orphan File uploaded to Post » ID %1$d - %2$s',
'LOG_ATTACH_ORPHAN_DEL' => 'Orphan Files deleted » %s',
- 'LOG_BAN_EXCLUDE_USER' => 'Excluded user from ban for reason “%1$s ” » %2$s',
- 'LOG_BAN_EXCLUDE_IP' => 'Excluded IP from ban for reason “%1$s ” » %2$s',
- 'LOG_BAN_EXCLUDE_EMAIL' => 'Excluded email from ban for reason “%1$s ” » %2$s',
'LOG_BAN_USER' => 'Banned user for reason “%1$s ” » %2$s',
'LOG_BAN_IP' => 'Banned IP for reason “%1$s ” » %2$s',
'LOG_BAN_EMAIL' => 'Banned email for reason “%1$s ” » %2$s',
diff --git a/phpBB/language/en/common.php b/phpBB/language/en/common.php
index 18de2a0d2c..5799137f5f 100644
--- a/phpBB/language/en/common.php
+++ b/phpBB/language/en/common.php
@@ -120,9 +120,9 @@ $lang = array_merge($lang, array(
'BBCODE_GUIDE' => 'BBCode guide',
'BCC' => 'BCC',
'BIRTHDAYS' => 'Birthdays',
- 'BOARD_BAN_PERM' => 'You have been permanently banned from this board. Please contact the %2$sBoard Administrator%3$s for more information.',
+ 'BOARD_BAN_PERM' => 'You have been permanently banned from this board. Please contact the %2$sBoard Administrator%3$s for more information.',
'BOARD_BAN_REASON' => 'Reason given for ban: %s ',
- 'BOARD_BAN_TIME' => 'You have been banned from this board until %1$s . Please contact the %2$sBoard Administrator%3$s for more information.',
+ 'BOARD_BAN_TIME' => 'You have been banned from this board until %1$s . Please contact the %2$sBoard Administrator%3$s for more information.',
'BOARD_DISABLE' => 'Sorry but this board is currently unavailable.',
'BOARD_DISABLED' => 'This board is currently disabled.',
'BOARD_UNAVAILABLE' => 'Sorry but the board is temporarily unavailable, please try again in a few minutes.',
diff --git a/phpBB/phpbb/ban/exception/invalid_length_exception.php b/phpBB/phpbb/ban/exception/invalid_length_exception.php
new file mode 100644
index 0000000000..dbbf09f0ac
--- /dev/null
+++ b/phpBB/phpbb/ban/exception/invalid_length_exception.php
@@ -0,0 +1,20 @@
+
+ * @license GNU General Public License, version 2 (GPL-2.0)
+ *
+ * For full copyright and license information, please see
+ * the docs/CREDITS.txt file.
+ *
+ */
+
+namespace phpbb\ban\exception;
+
+use phpbb\exception\runtime_exception;
+
+class invalid_length_exception extends runtime_exception
+{
+}
diff --git a/phpBB/phpbb/ban/exception/no_valid_emails_exception.php b/phpBB/phpbb/ban/exception/no_valid_emails_exception.php
new file mode 100644
index 0000000000..74079ccc2f
--- /dev/null
+++ b/phpBB/phpbb/ban/exception/no_valid_emails_exception.php
@@ -0,0 +1,20 @@
+
+ * @license GNU General Public License, version 2 (GPL-2.0)
+ *
+ * For full copyright and license information, please see
+ * the docs/CREDITS.txt file.
+ *
+ */
+
+namespace phpbb\ban\exception;
+
+use phpbb\exception\runtime_exception;
+
+class no_valid_emails_exception extends runtime_exception
+{
+}
diff --git a/phpBB/phpbb/ban/exception/no_valid_ips_exception.php b/phpBB/phpbb/ban/exception/no_valid_ips_exception.php
new file mode 100644
index 0000000000..e5725d27c9
--- /dev/null
+++ b/phpBB/phpbb/ban/exception/no_valid_ips_exception.php
@@ -0,0 +1,20 @@
+
+ * @license GNU General Public License, version 2 (GPL-2.0)
+ *
+ * For full copyright and license information, please see
+ * the docs/CREDITS.txt file.
+ *
+ */
+
+namespace phpbb\ban\exception;
+
+use phpbb\exception\runtime_exception;
+
+class no_valid_ips_exception extends runtime_exception
+{
+}
diff --git a/phpBB/phpbb/ban/exception/no_valid_users_exception.php b/phpBB/phpbb/ban/exception/no_valid_users_exception.php
new file mode 100644
index 0000000000..72e231c27e
--- /dev/null
+++ b/phpBB/phpbb/ban/exception/no_valid_users_exception.php
@@ -0,0 +1,20 @@
+
+ * @license GNU General Public License, version 2 (GPL-2.0)
+ *
+ * For full copyright and license information, please see
+ * the docs/CREDITS.txt file.
+ *
+ */
+
+namespace phpbb\ban\exception;
+
+use phpbb\exception\runtime_exception;
+
+class no_valid_users_exception extends runtime_exception
+{
+}
diff --git a/phpBB/phpbb/ban/exception/type_not_found_exception.php b/phpBB/phpbb/ban/exception/type_not_found_exception.php
new file mode 100644
index 0000000000..a4d7e8d19f
--- /dev/null
+++ b/phpBB/phpbb/ban/exception/type_not_found_exception.php
@@ -0,0 +1,20 @@
+
+ * @license GNU General Public License, version 2 (GPL-2.0)
+ *
+ * For full copyright and license information, please see
+ * the docs/CREDITS.txt file.
+ *
+ */
+
+namespace phpbb\ban\exception;
+
+use phpbb\exception\runtime_exception;
+
+class type_not_found_exception extends runtime_exception
+{
+}
diff --git a/phpBB/phpbb/ban/manager.php b/phpBB/phpbb/ban/manager.php
new file mode 100644
index 0000000000..e48e734617
--- /dev/null
+++ b/phpBB/phpbb/ban/manager.php
@@ -0,0 +1,573 @@
+
+ * @license GNU General Public License, version 2 (GPL-2.0)
+ *
+ * For full copyright and license information, please see
+ * the docs/CREDITS.txt file.
+ *
+ */
+
+namespace phpbb\ban;
+
+use phpbb\ban\exception\invalid_length_exception;
+use phpbb\ban\exception\type_not_found_exception;
+use phpbb\ban\type\type_interface;
+use phpbb\cache\driver\driver_interface as cache_driver;
+use phpbb\db\driver\driver_interface;
+use phpbb\di\service_collection;
+use phpbb\language\language;
+use phpbb\log\log_interface;
+use phpbb\user;
+
+class manager
+{
+ const CACHE_KEY_INFO = '_ban_info';
+ const CACHE_KEY_USERS = '_banned_users';
+ const CACHE_TTL = 3600;
+
+ /** @var string */
+ protected $bans_table;
+
+ /** @var cache_driver */
+ protected $cache;
+
+ /** @var driver_interface */
+ protected $db;
+
+ /** @var service_collection */
+ protected $types;
+
+ /** @var language */
+ protected $language;
+
+ /** @var log_interface */
+ protected $log;
+
+ /** @var user */
+ protected $user;
+
+ /** @var string */
+ protected $users_table;
+
+ /**
+ * Creates a service which manages all bans. Developers can
+ * create their own ban types which will be handled in this.
+ *
+ * @param service_collection $types A service collection containing all ban types
+ * @param cache_driver $cache A cache object
+ * @param driver_interface $db A phpBB DBAL object
+ * @param language $language Language object
+ * @param log_interface $log Log object
+ * @param user $user User object
+ * @param string $bans_table The bans table
+ * @param string $users_table The users table
+ */
+ public function __construct(service_collection $types, cache_driver $cache, driver_interface $db, language $language,
+ log_interface $log, user $user, string $bans_table, string $users_table = '')
+ {
+ $this->bans_table = $bans_table;
+ $this->cache = $cache;
+ $this->db = $db;
+ $this->types = $types;
+ $this->language = $language;
+ $this->log = $log;
+ $this->user = $user;
+ $this->users_table = $users_table;
+ }
+
+ /**
+ * Creates ban entries for the given $items. Returns true if successful
+ * and false if no entries were added to the database
+ *
+ * @param string $mode A string which identifies a ban type
+ * @param array $items An array of items which should be banned
+ * @param \DateTimeInterface $start A DateTimeInterface object which is the start of the ban
+ * @param \DateTimeInterface $end A DateTimeInterface object which is the end of the ban (or 0 if permanent)
+ * @param string $reason An (internal) reason for the ban
+ * @param string $display_reason An optional reason which should be displayed to the banned
+ *
+ * @return bool
+ */
+ public function ban(string $mode, array $items, \DateTimeInterface $start, \DateTimeInterface $end, string $reason, string $display_reason = ''): bool
+ {
+ if ($start > $end && $end->getTimestamp() !== 0)
+ {
+ throw new invalid_length_exception('LENGTH_BAN_INVALID');
+ }
+
+ /** @var type_interface $ban_mode */
+ $ban_mode = $this->find_type($mode);
+ if ($ban_mode === false)
+ {
+ throw new type_not_found_exception();
+ }
+
+ if (!empty($this->user))
+ {
+ $ban_mode->set_user($this->user);
+ }
+ $this->tidy();
+
+ $ban_items = $ban_mode->prepare_for_storage($items);
+
+ // Prevent duplicate bans
+ $sql = 'DELETE FROM ' . $this->bans_table . "
+ WHERE ban_mode = '" . $this->db->sql_escape($mode) . "'
+ AND " . $this->db->sql_in_set('ban_item', $ban_items, false, true);
+ $this->db->sql_query($sql);
+
+ $insert_array = [];
+ foreach ($ban_items as $ban_item)
+ {
+ $insert_array[] = [
+ 'ban_mode' => $mode,
+ 'ban_item' => $ban_item,
+ 'ban_userid' => $mode === 'user' ? $ban_item : 0,
+ 'ban_start' => $start->getTimestamp(),
+ 'ban_end' => $end->getTimestamp(),
+ 'ban_reason' => $reason,
+ 'ban_reason_display' => $display_reason,
+ ];
+ }
+
+ if (empty($insert_array))
+ {
+ return false;
+ }
+
+ $this->db->sql_multi_insert($this->bans_table, $insert_array);
+
+ $ban_data = [
+ 'items' => $ban_items,
+ 'start' => $start,
+ 'end' => $end,
+ 'reason' => $reason,
+ 'display_reason' => $display_reason,
+ ];
+
+ // Add to admin log, moderator log and user notes
+ $ban_list_log = implode(', ', $items);
+
+ $log_operation = 'LOG_BAN_' . strtoupper($mode);
+ $this->log->add('admin', $this->user->data['user_id'], $this->user->ip, $log_operation, false, [$reason, $ban_list_log]);
+ $this->log->add('mod', $this->user->data['user_id'], $this->user->ip, $log_operation, false, [
+ 'forum_id' => 0,
+ 'topic_id' => 0,
+ $reason,
+ $ban_list_log
+ ]);
+
+ if ($banlist_ary = $ban_mode->after_ban($ban_data))
+ {
+ foreach ($banlist_ary as $user_id)
+ {
+ $this->log->add('user', $this->user->data['user_id'], $this->user->ip, $log_operation, false, [
+ 'reportee_id' => $user_id,
+ $reason,
+ $ban_list_log
+ ]);
+ }
+ }
+
+ $this->cache->destroy(self::CACHE_KEY_INFO);
+ $this->cache->destroy(self::CACHE_KEY_USERS);
+
+ return true;
+ }
+
+ /**
+ * Removes ban entries from the database with the given IDs
+ *
+ * @param string $mode The ban type in which the ban IDs were created
+ * @param array $items An array of ban IDs which should be removed
+ */
+ public function unban(string $mode, array $items)
+ {
+ /** @var type_interface $ban_mode */
+ $ban_mode = $this->find_type($mode);
+ if ($ban_mode === false)
+ {
+ throw new type_not_found_exception();
+ }
+ $this->tidy();
+
+ $sql_ids = array_map('intval', $items);
+
+ if (count($sql_ids))
+ {
+ $sql = 'SELECT ban_item
+ FROM ' . $this->bans_table . '
+ WHERE ' . $this->db->sql_in_set('ban_id', $sql_ids);
+ $result = $this->db->sql_query($sql);
+
+ $unbanned_items = [];
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $unbanned_items[] = $row['ban_item'];
+ }
+ $this->db->sql_freeresult($result);
+
+ $sql = 'DELETE FROM ' . $this->bans_table . '
+ WHERE ' . $this->db->sql_in_set('ban_id', $sql_ids);
+ $this->db->sql_query($sql);
+
+ $unban_data = [
+ 'items' => $unbanned_items,
+ ];
+ $unbanned_users = $ban_mode->after_unban($unban_data);
+
+ // Add to moderator log, admin log and user notes
+ $log_operation = 'LOG_UNBAN_' . strtoupper($mode);
+ $this->log->add('admin', $this->user->data['user_id'], $this->user->ip, $log_operation, false, [$unbanned_users]);
+ $this->log->add('mod', $this->user->data['user_id'], $this->user->ip, $log_operation, false, [
+ 'forum_id' => 0,
+ 'topic_id' => 0,
+ $unbanned_users
+ ]);
+ if (count($unbanned_users))
+ {
+ foreach ($unbanned_users as $user_id)
+ {
+ $this->log->add('user', $this->user->data['user_id'], $this->user->ip, $log_operation, false, array(
+ 'reportee_id' => $user_id,
+ $unbanned_users
+ ));
+ }
+ }
+ }
+
+ $this->cache->destroy(self::CACHE_KEY_INFO);
+ $this->cache->destroy(self::CACHE_KEY_USERS);
+ }
+
+ /**
+ * Checks for the given user data whether the user is banned.
+ * Returns false if nothing was found and an array containing
+ * 'mode', 'end', 'reason' and 'item' otherwise.
+ *
+ * @param array $user_data The array containing the user data
+ *
+ * @return array|bool
+ */
+ public function check(array $user_data = [])
+ {
+ if (empty($user_data))
+ {
+ $user_data = $this->user->data;
+ }
+
+ $ban_info = $this->get_info_cache();
+
+ foreach ($ban_info as $mode => $ban_rows)
+ {
+ /** @var type_interface $ban_mode */
+ $ban_mode = $this->find_type($mode);
+ if ($ban_mode === false)
+ {
+ continue;
+ }
+
+ if ($ban_mode->get_user_column() === null)
+ {
+ $ban_result = $ban_mode->check($ban_rows, $user_data);
+ if ($ban_result !== false)
+ {
+ return $ban_result + ['mode' => $mode];
+ }
+ }
+ else
+ {
+ $user_column = $ban_mode->get_user_column();
+ if (!isset($user_data[$user_column]))
+ {
+ continue;
+ }
+
+ foreach ($ban_rows as $ban_row)
+ {
+ if (!$ban_row['end'] || $ban_row['end'] > time())
+ {
+ if (stripos($ban_row['item'], '*') === false)
+ {
+ if ($ban_row['item'] == $user_data[$user_column])
+ {
+ return $ban_row + ['mode' => $mode];
+ }
+ }
+ else
+ {
+ $regex = '#^' . str_replace('\*', '.*?', preg_quote($ban_row['item'], '#')) . '$#i';
+ if (preg_match($regex, $user_data[$user_column]))
+ {
+ return $ban_row + ['mode' => $mode];
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns all bans for a given ban type. False, if none were found
+ *
+ * @param string $mode The ban type for which the entries should be retrieved
+ *
+ * @return array|bool
+ */
+ public function get_bans(string $mode)
+ {
+ /** @var type_interface $ban_type */
+ $ban_type = $this->find_type($mode);
+ if ($ban_type === false)
+ {
+ throw new type_not_found_exception();
+ }
+ $this->tidy();
+
+ return $ban_type->get_ban_options();
+ }
+
+ /**
+ * Returns an array of banned users with 'id' => 'end' values.
+ * The result is cached for performance reasons and is not as
+ * accurate as the check() method. (Wildcards aren't considered e.g.)
+ *
+ * @return array
+ */
+ public function get_banned_users(): array
+ {
+ $banned_users = $this->cache->get(self::CACHE_KEY_USERS);
+ if ($banned_users === false)
+ {
+ $manual_modes = [];
+ $where_array = [];
+
+ /** @var type_interface $ban_mode */
+ foreach ($this->types as $ban_mode)
+ {
+ $user_column = $ban_mode->get_user_column();
+ if (empty($user_column))
+ {
+ $manual_modes[] = $ban_mode;
+ continue;
+ }
+
+ $where_column = $user_column == 'user_id' ? 'b.ban_userid' : 'b.ban_item';
+
+ $where_array[] = ['AND',
+ [
+ [$where_column, '=', 'u.' . $user_column],
+ ['b.ban_mode', '=', "'{$ban_mode->get_type()}'"],
+ ],
+ ];
+ }
+
+ $sql_array = [
+ 'SELECT' => 'u.user_id, b.ban_end',
+ 'FROM' => [
+ $this->bans_table => 'b',
+ $this->users_table => 'u',
+ ],
+ 'WHERE' => ['AND',
+ [
+ ['OR',
+ $where_array,
+ ],
+ ['u.user_type', '<>', USER_FOUNDER],
+ ],
+ ],
+ ];
+ $sql = $this->db->sql_build_query('SELECT', $sql_array);
+ $result = $this->db->sql_query($sql);
+
+ $banned_users = [];
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $user_id = (int) $row['user_id'];
+ $end = (int) $row['ban_end'];
+ if (!isset($banned_users[$user_id]) || ($banned_users[$user_id] > 0 && $banned_users[$user_id] < $end))
+ {
+ $banned_users[$user_id] = $end;
+ }
+ }
+ $this->db->sql_freeresult($result);
+
+ /** @var type_interface $manual_mode */
+ foreach ($manual_modes as $manual_mode)
+ {
+ $mode_banned_users = $manual_mode->get_banned_users();
+ foreach ($mode_banned_users as $user_id => $end)
+ {
+ $user_id = (int) $user_id;
+ $end = (int) $end;
+ if (!isset($banned_users[$user_id]) || ($banned_users[$user_id] > 0 && $banned_users[$user_id] < $end))
+ {
+ $banned_users[$user_id] = $end;
+ }
+ }
+ }
+
+ $this->cache->put(self::CACHE_KEY_USERS, $banned_users, self::CACHE_TTL);
+ }
+
+ return $banned_users;
+ }
+
+ /**
+ * Get ban end
+ *
+ * @param \DateTimeInterface $ban_start Ban start time
+ * @param int $length Ban length in minutes
+ * @param string $end_date Ban end date as YYYY-MM-DD string
+ * @return \DateTimeInterface Ban end as DateTimeInterface instance
+ */
+ public function get_ban_end(\DateTimeInterface $ban_start, int $length, string $end_date): \DateTimeInterface
+ {
+ $current_time = $ban_start->getTimestamp();
+ $end_time = 0;
+
+ if ($length)
+ {
+ if ($length != -1 || !$end_date)
+ {
+ $end_time = max($current_time, $current_time + ($length) * 60);
+ }
+ else
+ {
+ if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $end_date))
+ {
+ $end_time = max(
+ $current_time,
+ \DateTime::createFromFormat('Y-m-d', $end_date, $this->user->timezone)->getTimestamp()
+ );
+ }
+ else
+ {
+ throw new invalid_length_exception('LENGTH_BAN_INVALID');
+ }
+ }
+ }
+
+ $ban_end = new \DateTime();
+ $ban_end->setTimestamp($end_time);
+
+ return $ban_end;
+ }
+
+ /**
+ * Cleans up the database of e.g. stale bans
+ */
+ public function tidy()
+ {
+ // Delete stale bans
+ $sql = 'DELETE FROM ' . $this->bans_table . '
+ WHERE ban_end > 0
+ AND ban_end < ' . (int) time();
+ $this->db->sql_query($sql);
+
+ /** @var type_interface $type */
+ foreach ($this->types as $type)
+ {
+ $type->tidy();
+ }
+ }
+
+ /**
+ * Finds the ban type for the given mode string.
+ * Returns false if none was found
+ *
+ * @param string $mode The mode string
+ *
+ * @return bool|type\type_interface
+ */
+ protected function find_type(string $mode)
+ {
+ /** @var type_interface $type */
+ foreach ($this->types as $type)
+ {
+ if ($type->get_type() === $mode)
+ {
+ return $type;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns the ban_info from the cache.
+ * If they're not in the cache, bans are retrieved from the database
+ * and then put into the cache.
+ * The array contains an array for each mode with respectively
+ * three values for 'item', 'end' and 'reason' only.
+ *
+ * @return array
+ */
+ protected function get_info_cache(): array
+ {
+ $ban_info = $this->cache->get(self::CACHE_KEY_INFO);
+ if ($ban_info === false)
+ {
+ $sql = 'SELECT ban_mode, ban_item, ban_end, ban_reason_display
+ FROM ' . $this->bans_table;
+ $result = $this->db->sql_query($sql);
+
+ $ban_info = [];
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if (!isset($ban_info[$row['ban_mode']]))
+ {
+ $ban_info[$row['ban_mode']] = [];
+ }
+
+ $ban_info[$row['ban_mode']][] = [
+ 'item' => $row['ban_item'],
+ 'end' => $row['ban_end'],
+ 'reason' => $row['ban_reason_display'],
+ ];
+ }
+ $this->db->sql_freeresult($result);
+
+ $this->cache->put(self::CACHE_KEY_INFO, $ban_info, self::CACHE_TTL);
+ }
+
+ return $ban_info;
+ }
+
+ /**
+ * Get ban info message
+ *
+ * @param array $ban_row Ban data row from database
+ * @param string $ban_triggered_by Ban triggered by; allowed 'user', 'ip', 'email
+ * @param string $contact_link Contact link URL
+ *
+ * @return string Ban message
+ */
+ public function get_ban_message(array $ban_row, string $ban_triggered_by, string $contact_link): string
+ {
+ if ($ban_row['end'] > 0)
+ {
+ $till_date = $this->user->format_date($ban_row['end']);
+ $ban_type = 'BOARD_BAN_TIME';
+ }
+ else
+ {
+ $till_date = '';
+ $ban_type = 'BOARD_BAN_PERM';
+ }
+
+ $message = $this->language->lang($ban_type, $till_date, '', ' ');
+ $message .= !empty($ban_row['reason']) ? ' ' . $this->language->lang('BOARD_BAN_REASON', $ban_row['reason']) : '';
+ $message .= '' . $this->language->lang('BAN_TRIGGERED_BY_' . strtoupper($ban_triggered_by)) . ' ';
+
+ return $message;
+ }
+}
diff --git a/phpBB/phpbb/ban/type/base.php b/phpBB/phpbb/ban/type/base.php
new file mode 100644
index 0000000000..1ae7080991
--- /dev/null
+++ b/phpBB/phpbb/ban/type/base.php
@@ -0,0 +1,240 @@
+
+ * @license GNU General Public License, version 2 (GPL-2.0)
+ *
+ * For full copyright and license information, please see
+ * the docs/CREDITS.txt file.
+ *
+ */
+
+namespace phpbb\ban\type;
+
+use phpbb\db\driver\driver_interface;
+
+abstract class base implements type_interface
+{
+ /** @var driver_interface */
+ protected $db;
+
+ /** @var array */
+ protected $excluded;
+
+ /** @var string */
+ protected $bans_table;
+
+ /** @var string */
+ protected $sessions_keys_table;
+
+ /** @var string */
+ protected $sessions_table;
+
+ /** @var \phpbb\user */
+ protected $user;
+
+ /** @var string */
+ protected $users_table;
+
+ /**
+ * Creates a ban type.
+ *
+ * @param driver_interface $db A phpBB DBAL object
+ * @param string $bans_table The bans table
+ * @param string $users_table The users table
+ * @param string $sessions_table The sessions table
+ * @param string $sessions_keys_table The sessions keys table
+ */
+ public function __construct(driver_interface $db, string $bans_table, string $users_table, string $sessions_table, string $sessions_keys_table)
+ {
+ $this->db = $db;
+ $this->bans_table = $bans_table;
+ $this->users_table = $users_table;
+ $this->sessions_table = $sessions_table;
+ $this->sessions_keys_table = $sessions_keys_table;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function set_user(\phpbb\user $user): void
+ {
+ $this->user = $user;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function after_ban(array $data): array
+ {
+ return $this->logout_affected_users($data['items']);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function after_unban(array $data): array
+ {
+ return [];
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function check(array $ban_rows, array $user_data)
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function tidy(): void
+ {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_banned_users(): array
+ {
+ return [];
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_ban_options(): array
+ {
+ $sql = 'SELECT *
+ FROM ' . $this->bans_table . '
+ WHERE (ban_end >= ' . time() . "
+ OR ban_end = 0)
+ AND ban_mode = '{$this->db->sql_escape($this->get_type())}'
+ ORDER BY ban_item";
+ $result = $this->db->sql_query($sql);
+ $rowset = $this->db->sql_fetchrowset($result);
+ $this->db->sql_freeresult($result);
+
+ return $rowset;
+ }
+
+ /**
+ * Queries users that are excluded from banning (like founders)
+ * from the database and saves them in $this->excluded array.
+ * Returns true on success and false on failure
+ *
+ * @return bool
+ */
+ protected function get_excluded(): bool
+ {
+ $user_column = $this->get_user_column();
+ if (empty($user_column))
+ {
+ return false;
+ }
+
+ $this->excluded = [];
+
+ if (!empty($this->user))
+ {
+ $this->excluded[$this->user->id()] = $this->user->data[$user_column];
+ }
+
+ $sql = "SELECT user_id, {$this->db->sql_escape($user_column)}
+ FROM {$this->users_table}
+ WHERE user_type = " . USER_FOUNDER;
+ $result = $this->db->sql_query($sql);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $this->excluded[(int) $row['user_id']] = $row[$user_column];
+ }
+ $this->db->sql_freeresult($result);
+
+ return true;
+ }
+
+ /**
+ * Logs out all affected users in the given array. The values
+ * have to match the values of the column returned by get_user_column().
+ * Returns all banned users.
+ *
+ * @param array $ban_items
+ *
+ * @return array Logged out users
+ */
+ protected function logout_affected_users(array $ban_items): array
+ {
+ $user_column = $this->get_user_column();
+
+ if (empty($user_column))
+ {
+ return [];
+ }
+
+ if ($user_column !== 'user_id')
+ {
+ $ban_items_sql = [];
+ $ban_like_items = [];
+ foreach ($ban_items as $ban_item)
+ {
+ if (stripos($ban_item, '*') === false)
+ {
+ $ban_items_sql[] = $ban_item;
+ }
+ else
+ {
+ $ban_like_items[] = [$user_column, 'LIKE', str_replace('*', $this->db->get_any_char(), $ban_item)];
+ }
+ }
+
+ $sql_array = [
+ 'SELECT' => 'user_id',
+ 'FROM' => [
+ $this->users_table => '',
+ ],
+ 'WHERE' => ['AND',
+ [
+ ['OR',
+ array_merge([
+ [$user_column, 'IN', $ban_items_sql]
+ ], $ban_like_items),
+ ],
+ ['user_id', 'NOT_IN', array_map('intval', array_keys($this->excluded))],
+ ],
+ ],
+ ];
+ $sql = $this->db->sql_build_query('SELECT', $sql_array);
+ $result = $this->db->sql_query($sql);
+
+ $user_ids = [];
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $user_ids[] = (int) $row['user_id'];
+ }
+ $this->db->sql_freeresult($result);
+ }
+ else
+ {
+ $user_ids = array_map('intval', $ban_items);
+ }
+
+ if (!empty($user_ids) && !empty($this->sessions_table))
+ {
+ $sql = 'DELETE FROM ' . $this->sessions_table . '
+ WHERE ' . $this->db->sql_in_set('session_user_id', $user_ids);
+ $this->db->sql_query($sql);
+ }
+ if (!empty($user_ids) && !empty($this->sessions_keys_table))
+ {
+ $sql = 'DELETE FROM ' . $this->sessions_keys_table . '
+ WHERE ' . $this->db->sql_in_set('user_id', $user_ids);
+ $this->db->sql_query($sql);
+ }
+
+ return $user_ids;
+ }
+}
diff --git a/phpBB/phpbb/ban/type/email.php b/phpBB/phpbb/ban/type/email.php
new file mode 100644
index 0000000000..213084fc24
--- /dev/null
+++ b/phpBB/phpbb/ban/type/email.php
@@ -0,0 +1,63 @@
+
+ * @license GNU General Public License, version 2 (GPL-2.0)
+ *
+ * For full copyright and license information, please see
+ * the docs/CREDITS.txt file.
+ *
+ */
+
+namespace phpbb\ban\type;
+
+use phpbb\ban\exception\no_valid_emails_exception;
+
+class email extends base
+{
+ /**
+ * {@inheritDoc}
+ */
+ public function get_type(): string
+ {
+ return 'email';
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_user_column(): ?string
+ {
+ return 'user_email';
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function prepare_for_storage(array $items): array
+ {
+ $this->get_excluded();
+
+ $regex = '#^.*?@.*|(([a-z0-9\-]+\.)+([a-z]{2,3}))$#i';
+
+ $ban_items = [];
+ foreach ($items as $item)
+ {
+ $item = trim($item);
+ if (strlen($item) > 100 || !preg_match($regex, $item) || in_array($item, $this->excluded))
+ {
+ continue;
+ }
+ $ban_items[] = $item;
+ }
+
+ if (empty($ban_items))
+ {
+ throw new no_valid_emails_exception('NO_EMAILS_DEFINED');
+ }
+
+ return $ban_items;
+ }
+}
diff --git a/phpBB/phpbb/ban/type/ip.php b/phpBB/phpbb/ban/type/ip.php
new file mode 100644
index 0000000000..7f8c6ee81d
--- /dev/null
+++ b/phpBB/phpbb/ban/type/ip.php
@@ -0,0 +1,93 @@
+
+ * @license GNU General Public License, version 2 (GPL-2.0)
+ *
+ * For full copyright and license information, please see
+ * the docs/CREDITS.txt file.
+ *
+ */
+
+namespace phpbb\ban\type;
+
+use phpbb\ban\exception\no_valid_ips_exception;
+use Symfony\Component\HttpFoundation\IpUtils;
+
+class ip extends base
+{
+ private const USER_IP = 'user_ip';
+
+ /**
+ * @inheritDoc
+ */
+ public function get_type(): string
+ {
+ return 'ip';
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function get_user_column(): ?string
+ {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function check(array $ban_rows, array $user_data)
+ {
+ if (!isset($user_data[self::USER_IP]))
+ {
+ return false;
+ }
+
+ foreach ($ban_rows as $ip_ban)
+ {
+ if (IpUtils::checkIp($user_data[self::USER_IP], $ip_ban['item']))
+ {
+ return $ip_ban;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function prepare_for_storage(array $items): array
+ {
+ $ban_items = [];
+ foreach ($items as $ip)
+ {
+ try
+ {
+ // Misuse checkIp for checking validity of IP. Should return true if defined IP is valid.
+ if (!IpUtils::checkIp($ip, $ip))
+ {
+ continue;
+ }
+
+ $ban_items[] = $ip;
+ }
+ // @codeCoverageIgnoreStart
+ catch (\RuntimeException $exception)
+ {
+ // IPv6 not supported, therefore IPv6 address will not be added
+ }
+ // @codeCoverageIgnoreEnd
+ }
+
+ if (empty($ban_items))
+ {
+ throw new no_valid_ips_exception('NO_IPS_DEFINED');
+ }
+
+ return $ban_items;
+ }
+}
diff --git a/phpBB/phpbb/ban/type/type_interface.php b/phpBB/phpbb/ban/type/type_interface.php
new file mode 100644
index 0000000000..db86fc8ae7
--- /dev/null
+++ b/phpBB/phpbb/ban/type/type_interface.php
@@ -0,0 +1,126 @@
+
+ * @license GNU General Public License, version 2 (GPL-2.0)
+ *
+ * For full copyright and license information, please see
+ * the docs/CREDITS.txt file.
+ *
+ */
+
+namespace phpbb\ban\type;
+
+/**
+ * Interface implemented by all ban types
+ */
+interface type_interface
+{
+ /**
+ * Returns the type identifier for this ban type
+ *
+ * @return string
+ */
+ public function get_type(): string;
+
+ /**
+ * Returns the column in the users table which contains
+ * the values that should be looked for when checking a ban.
+ * If it returns null, the check method will be called when
+ * checking for bans.
+ *
+ * @return string|null
+ */
+ public function get_user_column(): ?string;
+
+ /**
+ * Sets a user object to the ban type to have it excluded
+ * from banning.
+ *
+ * @param \phpbb\user $user An user object
+ *
+ * @return void
+ */
+ public function set_user(\phpbb\user $user): void;
+
+ /**
+ * Gives the possibility to do some clean up after banning.
+ * The return value of this method will be passed through
+ * to the caller.
+ *
+ * @param array $data An array containing information about
+ * the bans, like the reason or the start
+ * and end of the ban
+ *
+ * @return array List of banned users
+ */
+ public function after_ban(array $data): array;
+
+ /**
+ * Gives the possibility to do some clean up after unbanning.
+ * The return value of this method will be passed through
+ * to the caller.
+ *
+ * @param array $data An array containing information about
+ * the unbans, e.g. the unbanned items.
+ *
+ * @return array List of unbanned users
+ */
+ public function after_unban(array $data): array;
+
+ /**
+ * In the case that get_user_column() returns null, this method
+ * is called when checking the ban status.
+ * Please note, that this method is basically called on every page,
+ * so the check should perform rather fast.
+ *
+ * Returns an array with information about the ban, like the end or
+ * the reason. False if the user is not banned.
+ *
+ * @param array $ban_rows An array containing the ban rows retrieved
+ * from the database for this specific mode.
+ * They contain the item, reason and end of the ban.
+ * @param array $user_data The user data
+ *
+ * @return array|bool
+ */
+ public function check(array $ban_rows, array $user_data);
+
+ /**
+ * In case get_user_column() returns no string, this method will be called
+ * when a list of banned users is retrieved.
+ * Returns a list of banned users.
+ * The result is cached and is not used for ban checking, so the accuracy
+ * of the results is not as important as when *really* checking in check()
+ *
+ * @return array An array of banned users, where the user ids are the keys
+ * and the value is the end of the ban (or 0 if permanent)
+ */
+ public function get_banned_users(): array;
+
+ /**
+ * Get ban options mapping ban ID to an option to display to admins
+ *
+ * @return array
+ */
+ public function get_ban_options(): array;
+
+ /**
+ * Prepares the given ban items before saving them in the database
+ *
+ * @param array $items
+ *
+ * @return array
+ */
+ public function prepare_for_storage(array $items): array;
+
+ /**
+ * Does some cleanup work for the banning mode.
+ * Is called before banning and unbanning and as cron job.
+ *
+ * @return void
+ */
+ public function tidy(): void;
+}
diff --git a/phpBB/phpbb/ban/type/user.php b/phpBB/phpbb/ban/type/user.php
new file mode 100644
index 0000000000..bfd28e323c
--- /dev/null
+++ b/phpBB/phpbb/ban/type/user.php
@@ -0,0 +1,156 @@
+
+ * @license GNU General Public License, version 2 (GPL-2.0)
+ *
+ * For full copyright and license information, please see
+ * the docs/CREDITS.txt file.
+ *
+ */
+
+namespace phpbb\ban\type;
+
+use phpbb\ban\exception\no_valid_users_exception;
+
+class user extends base
+{
+ /** @var array */
+ private $banned_users;
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_type(): string
+ {
+ return 'user';
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_user_column(): string
+ {
+ return 'user_id';
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function after_ban(array $data): array
+ {
+ $this->logout_affected_users($data['items']);
+ return $this->banned_users;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function after_unban(array $data): array
+ {
+ $user_ids = array_map('intval', $data['items']);
+
+ $sql = 'SELECT user_id, username
+ FROM ' . $this->users_table . '
+ WHERE ' . $this->db->sql_in_set('user_id', $user_ids);
+ $result = $this->db->sql_query($sql);
+
+ $unbanned_users = [];
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $unbanned_users[(int) $row['user_id']] = $row['username'];
+ }
+ $this->db->sql_freeresult($result);
+
+ return $unbanned_users;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get_ban_options(): array
+ {
+ $ban_options = [];
+
+ $sql = 'SELECT b.*, u.user_id, u.username, u.username_clean
+ FROM ' . $this->bans_table . ' b, ' . $this->users_table . ' u
+ WHERE (b.ban_end >= ' . time() . "
+ OR b.ban_end = 0)
+ AND b.ban_userid = u.user_id
+ AND b.ban_mode = '{$this->db->sql_escape($this->get_type())}'
+ ORDER BY u.username_clean ASC";
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $row['label'] = $row['username'];
+ $ban_options[] = $row;
+ }
+ $this->db->sql_freeresult($result);
+
+ return $ban_options;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function prepare_for_storage(array $items): array
+ {
+ // Fill excluded user list
+ $this->get_excluded();
+
+ // Prevent banning of anonymous
+ $this->excluded[ANONYMOUS] = ANONYMOUS;
+
+ $sql_usernames = [];
+ $sql_or_like = [];
+ foreach ($items as $item)
+ {
+ $cleaned_username = utf8_clean_string($item);
+ if (stripos($cleaned_username, '*') === false)
+ {
+ $sql_usernames[] = $cleaned_username;
+ }
+ else
+ {
+ $sql_or_like[] = ['username_clean', 'LIKE', str_replace('*', $this->db->get_any_char(), $cleaned_username)];
+ }
+ }
+
+ $sql_array = [
+ 'SELECT' => 'user_id, username',
+ 'FROM' => [
+ $this->users_table => '',
+ ],
+ 'WHERE' => ['AND',
+ [
+ ['OR',
+ array_merge([
+ ['username_clean', 'IN', $sql_usernames]
+ ], $sql_or_like),
+ ],
+ ['user_id', 'NOT_IN', array_map('intval', $this->excluded)],
+ ],
+ ],
+ ];
+ $sql = $this->db->sql_build_query('SELECT', $sql_array);
+ $result = $this->db->sql_query($sql);
+
+ $ban_items = [];
+ $this->banned_users = [];
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $ban_items[] = (string) $row['user_id'];
+ $this->banned_users[(int) $row['user_id']] = $row['username'];
+ }
+ $this->db->sql_freeresult($result);
+
+ if (empty($ban_items))
+ {
+ throw new no_valid_users_exception('NO_USER_SPECIFIED');
+ }
+
+ return $ban_items;
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v400/ban_table_p1.php b/phpBB/phpbb/db/migration/data/v400/ban_table_p1.php
new file mode 100644
index 0000000000..f58dff52e3
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v400/ban_table_p1.php
@@ -0,0 +1,179 @@
+
+ * @license GNU General Public License, version 2 (GPL-2.0)
+ *
+ * For full copyright and license information, please see
+ * the docs/CREDITS.txt file.
+ *
+ */
+
+namespace phpbb\db\migration\data\v400;
+
+use phpbb\db\migration\migration;
+
+class ban_table_p1 extends migration
+{
+ public static function depends_on(): array
+ {
+ return ['\phpbb\db\migration\data\v320\default_data_type_ids'];
+ }
+
+ public function update_schema(): array
+ {
+ return [
+ 'add_tables' => [
+ $this->table_prefix . 'bans' => [
+ 'COLUMNS' => [
+ 'ban_id' => ['ULINT', null, 'auto_increment'],
+ 'ban_userid' => ['ULINT', 0],
+ 'ban_mode' => ['VCHAR', ''],
+ 'ban_item' => ['STEXT_UNI', ''],
+ 'ban_start' => ['TIMESTAMP', 0],
+ 'ban_end' => ['TIMESTAMP', 0],
+ 'ban_reason' => ['VCHAR_UNI', ''],
+ 'ban_reason_display' => ['VCHAR_UNI', ''],
+ ],
+ 'PRIMARY_KEY' => 'ban_id',
+ 'KEYS' => [
+ 'ban_userid' => ['INDEX', 'ban_userid'],
+ 'ban_end' => ['INDEX', 'ban_end'],
+ ],
+ ],
+ ],
+ ];
+ }
+
+ public function revert_schema(): array
+ {
+ return [
+ 'drop_tables' => [
+ $this->table_prefix . 'bans',
+ ],
+ ];
+ }
+
+ public function update_data(): array
+ {
+ return [
+ ['custom', [[$this, 'old_to_new']]],
+ ];
+ }
+
+ public function revert_data(): array
+ {
+ return [
+ ['custom', [[$this, 'new_to_old']]],
+ ];
+ }
+
+ public function old_to_new($start)
+ {
+ $start = (int) $start;
+ $limit = 500;
+ $processed_rows = 0;
+
+ $sql = 'SELECT *
+ FROM ' . $this->table_prefix . 'banlist';
+ $result = $this->db->sql_query_limit($sql, $limit, $start);
+
+ $bans = [];
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $processed_rows++;
+
+ if ($row['ban_exclude'])
+ {
+ continue;
+ }
+
+ $row['ban_userid'] = (int) $row['ban_userid'];
+ $item = $mode = '';
+ if ($row['ban_ip'] !== '')
+ {
+ $mode = 'ip';
+ $item = $row['ban_ip'];
+ }
+ else if ($row['ban_email'] !== '')
+ {
+ $mode = 'email';
+ $item = $row['ban_email'];
+ }
+ else if ($row['ban_userid'] !== 0)
+ {
+ $mode = 'user';
+ $item = $row['ban_userid'];
+ }
+
+ if ($mode === '' || $item === '')
+ {
+ continue;
+ }
+
+ $bans[] = [
+ 'ban_mode' => $mode,
+ 'ban_userid' => $row['ban_userid'],
+ 'ban_item' => $item,
+ 'ban_start' => $row['ban_start'],
+ 'ban_end' => $row['ban_end'],
+ 'ban_reason' => $row['ban_reason'],
+ 'ban_reason_display' => $row['ban_give_reason'],
+ ];
+ }
+ $this->db->sql_freeresult($result);
+
+ if ($processed_rows > 0)
+ {
+ $this->db->sql_multi_insert($this->table_prefix . 'bans', $bans);
+ }
+ else if ($processed_rows < $limit)
+ {
+ return;
+ }
+
+ return $limit + $start;
+ }
+
+ public function new_to_old($start)
+ {
+ $start = (int) $start;
+ $limit = 500;
+ $processed_rows = 0;
+
+ $sql = 'SELECT *
+ FROM ' . $this->table_prefix . 'bans';
+ $result = $this->db->sql_query_limit($sql, $limit, $start);
+
+ $bans = [];
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $processed_rows++;
+
+ $bans[] = [
+ 'ban_userid' => (int) $row['ban_userid'],
+ 'ban_ip' => ($row['ban_mode'] === 'ip') ? $row['ban_item'] : '',
+ 'ban_email' => ($row['ban_mode'] === 'email') ? $row['ban_item'] : '',
+ 'ban_start' => $row['ban_start'],
+ 'ban_end' => $row['ban_end'],
+ 'ban_exclude' => false,
+ 'ban_reason' => $row['ban_reason'],
+ 'ban_give_reason' => $row['ban_reason_display'],
+ ];
+ }
+ $this->db->sql_freeresult($result);
+
+ if ($processed_rows > 0)
+ {
+ $this->db->sql_multi_insert($this->table_prefix . 'banlist', $bans);
+ }
+ else if ($processed_rows < $limit)
+ {
+ return;
+ }
+
+ return $limit + $start;
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v400/ban_table_p2.php b/phpBB/phpbb/db/migration/data/v400/ban_table_p2.php
new file mode 100644
index 0000000000..1f31c1ec57
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v400/ban_table_p2.php
@@ -0,0 +1,59 @@
+
+ * @license GNU General Public License, version 2 (GPL-2.0)
+ *
+ * For full copyright and license information, please see
+ * the docs/CREDITS.txt file.
+ *
+ */
+
+namespace phpbb\db\migration\data\v400;
+
+class ban_table_p2 extends \phpbb\db\migration\migration
+{
+ public static function depends_on(): array
+ {
+ return ['\phpbb\db\migration\data\v400\ban_table_p1'];
+ }
+
+ public function update_schema(): array
+ {
+ return [
+ 'drop_tables' => [
+ $this->table_prefix . 'banlist',
+ ],
+ ];
+ }
+
+ public function revert_schema(): array
+ {
+ return [
+ 'add_tables' => [
+ $this->table_prefix . 'banlist' => [
+ 'COLUMNS' => [
+ 'ban_id' => ['ULINT', null, 'auto_increment'],
+ 'ban_userid' => ['ULINT', 0],
+ 'ban_ip' => ['VCHAR:40', ''],
+ 'ban_email' => ['VCHAR_UNI:100', ''],
+ 'ban_start' => ['TIMESTAMP', 0],
+ 'ban_end' => ['TIMESTAMP', 0],
+ 'ban_exclude' => ['BOOL', 0],
+ 'ban_reason' => ['VCHAR_UNI', ''],
+ 'ban_give_reason' => ['VCHAR_UNI', ''],
+ ],
+ 'PRIMARY_KEY' => 'ban_id',
+ 'KEYS' => [
+ 'ban_end' => ['INDEX', 'ban_end'],
+ 'ban_user' => ['INDEX', ['ban_userid', 'ban_exclude']],
+ 'ban_email' => ['INDEX', ['ban_email', 'ban_exclude']],
+ 'ban_ip' => ['INDEX', ['ban_ip', 'ban_exclude']],
+ ],
+ ],
+ ],
+ ];
+ }
+}
diff --git a/phpBB/phpbb/session.php b/phpBB/phpbb/session.php
index 9d3f85b9be..4c2471ab92 100644
--- a/phpBB/phpbb/session.php
+++ b/phpBB/phpbb/session.php
@@ -1136,119 +1136,23 @@ class session
*/
function check_ban($user_id = false, $user_ips = false, $user_email = false, $return = false)
{
- global $db, $phpbb_dispatcher;
+ global $phpbb_container, $phpbb_dispatcher;
if (defined('IN_CHECK_BAN') || defined('SKIP_CHECK_BAN'))
{
return false;
}
- $banned = false;
- $cache_ttl = 3600;
- $where_sql = array();
-
- $sql = 'SELECT ban_ip, ban_userid, ban_email, ban_exclude, ban_give_reason, ban_end
- FROM ' . BANLIST_TABLE . '
- WHERE ';
-
- // Determine which entries to check, only return those
- if ($user_email === false)
+ /** @var \phpbb\ban\manager $ban_manager */
+ $ban_manager = $phpbb_container->get('ban.manager');
+ $ban_row = $ban_manager->check(['user_id' => $user_id, 'user_email' => $user_email]);
+ if (empty($ban_row))
{
- $where_sql[] = "ban_email = ''";
+ return false;
}
- if ($user_ips === false)
- {
- $where_sql[] = "(ban_ip = '' OR ban_exclude = 1)";
- }
-
- if ($user_id === false)
- {
- $where_sql[] = '(ban_userid = 0 OR ban_exclude = 1)';
- }
- else
- {
- $cache_ttl = ($user_id == ANONYMOUS) ? 3600 : 0;
- $_sql = '(ban_userid = ' . $user_id;
-
- if ($user_email !== false)
- {
- $_sql .= " OR ban_email <> ''";
- }
-
- if ($user_ips !== false)
- {
- $_sql .= " OR ban_ip <> ''";
- }
-
- $_sql .= ')';
-
- $where_sql[] = $_sql;
- }
-
- $sql .= (count($where_sql)) ? implode(' AND ', $where_sql) : '';
- $result = $db->sql_query($sql, $cache_ttl);
-
- $ban_triggered_by = 'user';
- while ($row = $db->sql_fetchrow($result))
- {
- if ($row['ban_end'] && $row['ban_end'] < time())
- {
- continue;
- }
-
- $ip_banned = false;
- if (!empty($row['ban_ip']))
- {
- if (!is_array($user_ips))
- {
- $ip_banned = preg_match('#^' . str_replace('\*', '.*?', preg_quote($row['ban_ip'], '#')) . '$#i', $user_ips);
- }
- else
- {
- foreach ($user_ips as $user_ip)
- {
- if (preg_match('#^' . str_replace('\*', '.*?', preg_quote($row['ban_ip'], '#')) . '$#i', $user_ip))
- {
- $ip_banned = true;
- break;
- }
- }
- }
- }
-
- if ((!empty($row['ban_userid']) && intval($row['ban_userid']) == $user_id) ||
- $ip_banned ||
- (!empty($row['ban_email']) && preg_match('#^' . str_replace('\*', '.*?', preg_quote($row['ban_email'], '#')) . '$#i', $user_email)))
- {
- if (!empty($row['ban_exclude']))
- {
- $banned = false;
- break;
- }
- else
- {
- $banned = true;
- $ban_row = $row;
-
- if (!empty($row['ban_userid']) && intval($row['ban_userid']) == $user_id)
- {
- $ban_triggered_by = 'user';
- }
- else if ($ip_banned)
- {
- $ban_triggered_by = 'ip';
- }
- else
- {
- $ban_triggered_by = 'email';
- }
-
- // Don't break. Check if there is an exclude rule for this user
- }
- }
- }
- $db->sql_freeresult($result);
+ $banned = true;
+ $ban_triggered_by = $ban_row['mode'];
/**
* Event to set custom ban type
@@ -1266,7 +1170,7 @@ class session
if ($banned && !$return)
{
- global $phpEx;
+ global $config, $phpbb_root_path, $phpEx;
// Initiate environment ... since it won't be set at this stage
$this->setup();
@@ -1300,7 +1204,8 @@ class session
}
// Determine which message to output
- $message = $this->get_ban_message($ban_row, $ban_triggered_by);
+ $contact_link = phpbb_get_board_contact_link($config, $phpbb_root_path, $phpEx);
+ $message = $ban_manager->get_ban_message($ban_row, $ban_triggered_by, $contact_link);
// A very special case... we are within the cron script which is not supposed to print out the ban message... show blank page
if (defined('IN_CRON'))
@@ -1344,19 +1249,6 @@ class session
}
}
- /**
- * Get ban info message
- *
- * @param array $ban_row Ban data row from database
- * @param string $ban_triggered_by Ban triggered by; allowed 'user', 'ip', 'email'
- *
- * @return string
- */
- protected function get_ban_message(array $ban_row, string $ban_triggered_by): string
- {
- return ($ban_row['ban_end']) ? 'BOARD_BAN_TIME' : 'BOARD_BAN_PERM';
- }
-
/**
* Check if ip is blacklisted by Spamhaus SBL
*
diff --git a/phpBB/phpbb/user.php b/phpBB/phpbb/user.php
index 52427d2915..bf4f10c15a 100644
--- a/phpBB/phpbb/user.php
+++ b/phpBB/phpbb/user.php
@@ -879,12 +879,12 @@ class user extends \phpbb\session
{
global $config, $phpbb_root_path, $phpEx;
- $till_date = ($ban_row['ban_end']) ? $this->format_date($ban_row['ban_end']) : '';
- $message = ($ban_row['ban_end']) ? 'BOARD_BAN_TIME' : 'BOARD_BAN_PERM';
+ $till_date = ($ban_row['end']) ? $this->format_date($ban_row['end']) : '';
+ $message = ($ban_row['end']) ? 'BOARD_BAN_TIME' : 'BOARD_BAN_PERM';
$contact_link = phpbb_get_board_contact_link($config, $phpbb_root_path, $phpEx);
$message = $this->language->lang($message, $till_date, '', ' ');
- $message .= ($ban_row['ban_give_reason']) ? ' ' . $this->language->lang('BOARD_BAN_REASON', $ban_row['ban_give_reason']) : '';
+ $message .= ($ban_row['reason']) ? ' ' . $this->language->lang('BOARD_BAN_REASON', $ban_row['reason']) : '';
$message .= '' . $this->language->lang('BAN_TRIGGERED_BY_' . strtoupper($ban_triggered_by)) . ' ';
return $message;
diff --git a/phpBB/styles/prosilver/template/mcp_ban.html b/phpBB/styles/prosilver/template/mcp_ban.html
index ed85e294c2..379c992921 100644
--- a/phpBB/styles/prosilver/template/mcp_ban.html
+++ b/phpBB/styles/prosilver/template/mcp_ban.html
@@ -67,13 +67,6 @@
-
- {L_BAN_EXCLUDE}{L_COLON} {L_BAN_EXCLUDE_EXPLAIN}
-
- {L_YES}
- {L_NO}
-
-
diff --git a/tests/ban/ban_manager_test.php b/tests/ban/ban_manager_test.php
new file mode 100644
index 0000000000..2eb49686d6
--- /dev/null
+++ b/tests/ban/ban_manager_test.php
@@ -0,0 +1,766 @@
+createXMLDataSet(__DIR__ . '/fixtures/sessions_banlist.xml');
+ }
+
+ public function setUp(): void
+ {
+ parent::setUp();
+
+ global $config, $phpbb_dispatcher, $phpbb_root_path, $phpEx;
+
+ $language = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx));
+ $user = new \phpbb\user($language, '\phpbb\datetime');
+ $user->data['user_id'] = 2;
+ $user->data['user_email'] = 'foo@bar.com';
+ $user->data['user_timezone'] = 0;
+ $config = new \phpbb\config\config([]);
+ $phpbb_dispatcher = new \phpbb_mock_event_dispatcher();
+
+ $phpbb_container = new \phpbb_mock_container_builder();
+ $ban_type_email = new \phpbb\ban\type\email($this->db, 'phpbb_bans', 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys');
+ $ban_type_user = new \phpbb\ban\type\user($this->db, 'phpbb_bans', 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys');
+ $ban_type_ip = new \phpbb\ban\type\ip($this->db, 'phpbb_bans', 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys');
+ $phpbb_container->set('ban.type.email', $ban_type_email);
+ $phpbb_container->set('ban.type.user', $ban_type_user);
+ $phpbb_container->set('ban.type.ip', $ban_type_ip);
+ $collection = new \phpbb\di\service_collection($phpbb_container);
+ $collection->add('ban.type.email');
+ $collection->add('ban.type.user');
+ $collection->add('ban.type.ip');
+ $phpbb_log = new \phpbb\log\dummy();
+
+ $this->ban_manager = new \phpbb\ban\manager($collection, new \phpbb\cache\driver\dummy(), $this->db, $language, $phpbb_log, $user, 'phpbb_bans', 'phpbb_users');
+ $phpbb_container->set('ban.manager', $this->ban_manager);
+ $this->phpbb_container = $phpbb_container;
+ }
+
+ public function data_check_ban(): array
+ {
+ return [
+ [
+ [],
+ false
+ ],
+ [
+ ['user_ip' => '127.0.0.1'],
+ [
+ 'item' => '127.0.0.1',
+ 'end' => '0',
+ 'reason' => '1',
+ 'mode' => 'ip',
+ ],
+ ],
+ [
+ ['user_ip' => '10.0.0.1'], // first IP for 10.0.0.1/28 range
+ [
+ 'item' => '10.0.0.1/28',
+ 'end' => '0',
+ 'reason' => '1',
+ 'mode' => 'ip',
+ ],
+ ],
+ [
+ ['user_ip' => '10.0.0.14'], // last IP for 10.0.0.1/28 range
+ [
+ 'item' => '10.0.0.1/28',
+ 'end' => '0',
+ 'reason' => '1',
+ 'mode' => 'ip',
+ ],
+ ],
+ [
+ ['user_ip' => '10.0.0.15'], // first IP outside 10.0.0.1/28 range
+ [
+ 'item' => '10.0.0.1/28',
+ 'end' => '0',
+ 'reason' => '1',
+ 'mode' => 'ip',
+ ],
+ ],
+ [
+ ['user_ip' => '2001:4860:4860::8888'], // first IP in 2001:4860:4860::8888/12 range
+ [
+ 'item' => '2001:4860:4860::8888/12',
+ 'end' => '0',
+ 'reason' => '1',
+ 'mode' => 'ip',
+ ],
+ ],
+ [
+ ['user_ip' => '200F:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF'], // last IP in 2001:4860:4860::8888/12 range
+ [
+ 'item' => '2001:4860:4860::8888/12',
+ 'end' => '0',
+ 'reason' => '1',
+ 'mode' => 'ip',
+ ],
+ ],
+ [
+ ['user_ip' => '2010:4860:4860::1'], // IP outside the 2001:4860:4860::8888/12 range
+ false,
+ ],
+ [
+ ['user_id' => 2],
+ false,
+ ],
+ [
+ ['user_id' => 5], // there is only an expired ban
+ false,
+ ],
+ [
+ ['user_id' => 4],
+ [
+ 'item' => '4',
+ 'end' => '0',
+ 'reason' => '1',
+ 'mode' => 'user',
+ ],
+ ],
+ [
+ ['user_email' => 'test@phpbb.com'],
+ false,
+ ],
+ [
+ ['user_email' => 'bar@example.org'],
+ [
+ 'item' => 'bar@example.org',
+ 'end' => '0',
+ 'reason' => '1',
+ 'mode' => 'email',
+ ],
+ ],
+ [
+ ['user_email' => 'test@foo.bar'],
+ [
+ 'item' => '*@foo.bar',
+ 'end' => '0',
+ 'reason' => '1',
+ 'mode' => 'email',
+ ],
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider data_check_ban
+ */
+ public function test_check_ban($user_data, $expected)
+ {
+ $this->assertEquals($expected, $this->ban_manager->check($user_data));
+ }
+
+ public function data_get_bans(): array
+ {
+ return [
+ [
+ 'foo',
+ '',
+ type_not_found_exception::class
+ ],
+ [
+ 'ip',
+ [
+ [
+ 'ban_id' => '6',
+ 'ban_userid' => 0,
+ 'ban_item' => '10.0.0.1/28',
+ 'ban_start' => '1111',
+ 'ban_end' => '0',
+ 'ban_reason' => 'HAHAHA',
+ 'ban_reason_display' => '1',
+ 'ban_mode' => 'ip',
+ ],
+ [
+ 'ban_id' => '2',
+ 'ban_userid' => 0,
+ 'ban_item' => '127.0.0.1',
+ 'ban_start' => '1111',
+ 'ban_end' => '0',
+ 'ban_reason' => 'HAHAHA',
+ 'ban_reason_display' => '1',
+ 'ban_mode' => 'ip',
+ ],
+ [
+ 'ban_id' => '3',
+ 'ban_userid' => 0,
+ 'ban_item' => '127.1.1.1',
+ 'ban_start' => '1111',
+ 'ban_end' => '0',
+ 'ban_reason' => 'HAHAHA',
+ 'ban_reason_display' => '1',
+ 'ban_mode' => 'ip',
+ ],
+ [
+ 'ban_id' => '7',
+ 'ban_userid' => 0,
+ 'ban_item' => '2001:4860:4860::8888/12',
+ 'ban_start' => '1111',
+ 'ban_end' => '0',
+ 'ban_reason' => 'HAHAHA',
+ 'ban_reason_display' => '1',
+ 'ban_mode' => 'ip',
+ ],
+ ],
+ ],
+ [
+ 'email',
+ [
+ [
+ 'ban_id' => '9',
+ 'ban_userid' => 0,
+ 'ban_item' => '*@foo.bar',
+ 'ban_start' => '1111',
+ 'ban_end' => '0',
+ 'ban_reason' => 'HAHAHA',
+ 'ban_reason_display' => '1',
+ 'ban_mode' => 'email',
+ ],
+ [
+ 'ban_id' => '5',
+ 'ban_userid' => 0,
+ 'ban_item' => 'bar@example.org',
+ 'ban_start' => '1111',
+ 'ban_end' => '0',
+ 'ban_reason' => 'HAHAHA',
+ 'ban_reason_display' => '1',
+ 'ban_mode' => 'email',
+ ],
+ ],
+ ],
+ [
+ 'user',
+ [
+ [
+ 'ban_id' => '4',
+ 'ban_item' => '4',
+ 'ban_start' => '1111',
+ 'ban_end' => '0',
+ 'ban_reason' => 'HAHAHA',
+ 'ban_reason_display' => '1',
+ 'ban_mode' => 'user',
+ 'ban_userid' => 4,
+ 'user_id' => '4',
+ 'username' => 'ipv6_user',
+ 'username_clean' => 'ipv6_user',
+ 'label' => 'ipv6_user',
+ ],
+ ],
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider data_get_bans
+ */
+ public function test_get_bans($ban_type, $expected, $expected_exception = false)
+ {
+ if ($expected_exception !== false)
+ {
+ $this->expectException($expected_exception);
+ }
+
+ $actual = $this->ban_manager->get_bans($ban_type);
+ // Sort both arrays by ban_item to be synced
+ if (is_array($expected) && !empty($actual))
+ {
+ usort($expected, function($a, $b)
+ {
+ return strcmp($a['ban_item'], $b['ban_item']) <=> 0;
+ }
+ );
+ usort($actual, function($a, $b)
+ {
+ return strcmp($a['ban_item'], $b['ban_item']) <=> 0;
+ }
+ );
+ }
+ $this->assertEquals($expected, $actual);
+ }
+
+ public function data_get_ban_end(): array
+ {
+ return [
+ [
+ 0,
+ 20,
+ 0,
+ ],
+ [
+ 80, // 1 minute plus 20 seconds
+ 20,
+ 1,
+ ],
+ [
+ 20,
+ 20,
+ -1,
+ ],
+ [
+ 2 * 86400, // Ban end should be before this time
+ 20,
+ -1,
+ '1970-01-02',
+ ],
+ [
+ 0,
+ 20,
+ -1,
+ '1970-01-02-15:30', // wrong format
+ invalid_length_exception::class,
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider data_get_ban_end
+ */
+ public function test_get_ban_end($expected, $ban_start, $length, $end_date = '', $expected_exception = false)
+ {
+ if ($expected_exception)
+ {
+ $this->expectException($expected_exception);
+ }
+
+ $start_time = new \DateTime();
+ $start_time->setTimestamp($ban_start);
+
+ $expected_end = new \DateTime();
+ $expected_end->setTimestamp($expected);
+
+ $ban_end = $this->ban_manager->get_ban_end($start_time, $length, $end_date);
+
+ if ($length >= 0 || !$end_date)
+ {
+ $this->assertEquals($expected_end, $ban_end);
+ }
+ else
+ {
+ $this->assertLessThan($expected_end, $ban_end);
+ $this->assertGreaterThan($start_time, $ban_end);
+ }
+ }
+
+ public function test_get_banned_users()
+ {
+ $banned_users = $this->ban_manager->get_banned_users();
+ $this->assertEquals(
+ [
+ 4 => 0,
+ 5 => 0
+ ],
+ $banned_users
+ );
+ }
+
+ public function test_get_banned_users_own_method()
+ {
+ global $phpbb_root_path, $phpEx;
+
+ $phpbb_container = new \phpbb_mock_container_builder();
+ $ban_type_email = new \phpbb\ban\type\email($this->db, 'phpbb_bans', 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys');
+ $ban_type_user = new \phpbb\ban\type\user($this->db, 'phpbb_bans', 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys');
+ $ban_type_ip = $this->getMockBuilder(\phpbb\ban\type\ip::class)
+ ->setConstructorArgs([$this->db, 'phpbb_bans', 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys'])
+ ->getMock();
+ $ban_type_ip->method('get_banned_users')
+ ->willReturn([19 => 1234, 20 => 0]);
+ $phpbb_container->set('ban.type.email', $ban_type_email);
+ $phpbb_container->set('ban.type.user', $ban_type_user);
+ $phpbb_container->set('ban.type.ip', $ban_type_ip);
+ $collection = new \phpbb\di\service_collection($phpbb_container);
+ $collection->add('ban.type.email');
+ $collection->add('ban.type.user');
+ $collection->add('ban.type.ip');
+
+ $language = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx));
+ $user = new \phpbb\user($language, '\phpbb\datetime');
+ $phpbb_log = new \phpbb\log\dummy();
+
+ $ban_manager = new \phpbb\ban\manager($collection, new \phpbb\cache\driver\dummy(), $this->db, $language, $phpbb_log, $user, 'phpbb_bans', 'phpbb_users');
+
+ $this->assertEquals(
+ [
+ 4 => 0,
+ 5 => 0,
+ 19 => 1234,
+ 20 => 0,
+ ],
+ $ban_manager->get_banned_users()
+ );
+
+ $ban_type_ip_reflection = new \ReflectionClass($ban_type_ip);
+ $get_excluded_reflection = $ban_type_ip_reflection->getMethod('get_excluded');
+ $get_excluded_reflection->setAccessible(true);
+ $this->assertFalse($get_excluded_reflection->invoke($ban_type_ip));
+ }
+
+ public function test_ban_empty_ban_items()
+ {
+ global $phpbb_root_path, $phpEx;
+
+ $phpbb_container = new \phpbb_mock_container_builder();
+ $ban_type_email = new \phpbb\ban\type\email($this->db, 'phpbb_bans', 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys');
+ $ban_type_user = new \phpbb\ban\type\user($this->db, 'phpbb_bans', 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys');
+ $ban_type_ip = $this->getMockBuilder(\phpbb\ban\type\ip::class)
+ ->setConstructorArgs([$this->db, 'phpbb_bans', 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys'])
+ ->getMock();
+ $ban_type_ip->method('prepare_for_storage')
+ ->willReturn([]);
+ $ban_type_ip->method('get_type')
+ ->willReturn('ip');
+ $phpbb_container->set('ban.type.email', $ban_type_email);
+ $phpbb_container->set('ban.type.user', $ban_type_user);
+ $phpbb_container->set('ban.type.ip', $ban_type_ip);
+ $collection = new \phpbb\di\service_collection($phpbb_container);
+ $collection->add('ban.type.email');
+ $collection->add('ban.type.user');
+ $collection->add('ban.type.ip');
+
+ $language = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx));
+ $user = new \phpbb\user($language, '\phpbb\datetime');
+ $phpbb_log = new \phpbb\log\dummy();
+
+ $ban_manager = new \phpbb\ban\manager($collection, new \phpbb\cache\driver\dummy(), $this->db, $language, $phpbb_log, $user, 'phpbb_bans', 'phpbb_users');
+
+ $start_time = new \DateTime();
+ $start_time->setTimestamp(1000);
+ $end_time = new \DateTime();
+ $end_time->setTimestamp(0);
+
+ $this->assertFalse($ban_manager->ban(
+ 'ip',
+ ['192.168.1.1'],
+ $start_time,
+ $end_time,
+ ''
+ ));
+ }
+
+ public function data_test_ban(): array
+ {
+ return [
+ [
+ 'user',
+ ['normal_user'],
+ 1000,
+ 500, // end before start
+ '',
+ '',
+ false,
+ invalid_length_exception::class,
+ ],
+ [
+ 'foo', // invalid ban type
+ ['normal_user'],
+ 1000,
+ 0, // end before start
+ '',
+ '',
+ false,
+ type_not_found_exception::class,
+ ],
+ [
+ 'user',
+ [], // empty user list
+ 1000,
+ 0,
+ '',
+ '',
+ false,
+ no_valid_users_exception::class,
+ ],
+ [
+ 'user',
+ ['founder'], // user same as current user
+ 1000,
+ 0,
+ '',
+ '',
+ false,
+ no_valid_users_exception::class,
+ ],
+ [
+ 'user',
+ ['normal_user'],
+ 1000,
+ 0,
+ '',
+ '',
+ true,
+ ],
+ [
+ 'user',
+ ['normal_u*'],
+ 1000,
+ 0,
+ '',
+ '',
+ true,
+ ],
+ [
+ 'ip',
+ [],
+ 1000,
+ 0,
+ '',
+ '',
+ false,
+ no_valid_ips_exception::class,
+ ],
+ [
+ 'ip',
+ ['192.168.I.1'], // invalid IP
+ 1000,
+ 0,
+ '',
+ '',
+ false,
+ no_valid_ips_exception::class,
+ ],
+ [
+ 'ip',
+ ['192.168.1.1'],
+ 1000,
+ 0,
+ '',
+ '',
+ true,
+ ],
+ [
+ 'email',
+ ['this_is_not_an_email'],
+ 1000,
+ 0,
+ '',
+ '',
+ false,
+ no_valid_emails_exception::class
+ ],
+ [
+ 'email',
+ ['test@example.com'],
+ 1000,
+ 0,
+ '',
+ '',
+ true,
+ ],
+ [
+ 'email',
+ ['*@foo.bar'],
+ 1000,
+ 0,
+ '',
+ '',
+ true,
+ ],
+ [
+ 'email',
+ ['test@example.com', str_repeat('a', 100) . '@example.com'], // one email too long, shouldn't cause any issues though
+ 1000,
+ 0,
+ '',
+ '',
+ true,
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider data_test_ban
+ */
+ public function test_ban($mode, $items, $start, $end, $reason, $display_reason, $expected, $expected_exception = '')
+ {
+ if ($expected_exception)
+ {
+ $this->expectException($expected_exception);
+ }
+
+ $start_time = new \DateTime();
+ $start_time->setTimestamp($start);
+ $end_time = new \DateTime();
+ $end_time->setTimestamp($end);
+
+ $ban_return = $this->ban_manager->ban($mode, $items, $start_time, $end_time, $reason, $display_reason);
+
+ $this->assertEquals($expected, $ban_return);
+ }
+
+ public function test_ban_actual()
+ {
+ $start_time = new \DateTime();
+ $start_time->setTimestamp(1000);
+ $end_time = new \DateTime();
+ $end_time->setTimestamp(0);
+
+ $ban_return = $this->ban_manager->ban('ip', ['121.122.123.124'], $start_time, $end_time, '', 'because');
+
+ $this->assertTrue($ban_return);
+
+ $this->assertEquals(
+ [
+ 'item' => '121.122.123.124',
+ 'end' => 0,
+ 'reason' => 'because',
+ 'mode' => 'ip'
+ ],
+ $this->ban_manager->check(['user_ip' => '121.122.123.124'])
+ );
+ }
+
+ public function data_test_unban(): array
+ {
+ return [
+ [
+ 'does_not_exist',
+ [10],
+ [],
+ type_not_found_exception::class
+ ],
+ [
+ 'user',
+ [4],
+ [
+ [
+ 'ban_id' => '4',
+ 'ban_userid' => '4',
+ 'ban_item' => '4',
+ 'ban_start' => '1111',
+ 'ban_end' => '0',
+ 'ban_reason' => 'HAHAHA',
+ 'ban_reason_display' => '1',
+ 'ban_mode' => 'user',
+ 'user_id' => '4',
+ 'username' => 'ipv6_user',
+ 'username_clean' => 'ipv6_user',
+ 'label' => 'ipv6_user',
+ ],
+ ],
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider data_test_unban
+ */
+ public function test_unban($mode, $items, $expected, $expected_exception = '')
+ {
+ if ($expected_exception)
+ {
+ $this->expectException($expected_exception);
+ }
+
+ $before_bans = $this->ban_manager->get_bans($mode);
+
+ $this->ban_manager->unban($mode, $items);
+
+ $after_bans = $this->ban_manager->get_bans($mode);
+
+ $ban_diff = array_diff_assoc($before_bans, count($after_bans) ? $after_bans : []);
+
+ $this->assertEquals($expected, $ban_diff);
+ }
+
+ public function test_unban_invalid_type()
+ {
+ $this->expectException(type_not_found_exception::class);
+
+ $this->ban_manager->unban('does_not_exist', []);
+ }
+
+ public function test_base_type_methods()
+ {
+ $ban_type_ip = $this->phpbb_container->get('ban.type.ip');
+ $base_type_reflection = new \ReflectionClass(\phpbb\ban\type\base::class);
+ $after_unban = $base_type_reflection->getMethod('after_unban');
+ $this->assertEquals([], $after_unban->invoke($ban_type_ip, ['items' => ['foo']]));
+
+ $check = $base_type_reflection->getMethod('check');
+ $this->assertFalse($check->invoke($ban_type_ip, [], []));
+ }
+
+ public function data_get_ban_message(): array
+ {
+ return [
+ [
+ [
+ 'end' => 0,
+ ],
+ 'foobar',
+ 'http://foo.bar',
+ 'You have been permanently banned from this board. Please contact the Board Administrator for more information.BAN_TRIGGERED_BY_FOOBAR ',
+ ],
+ [
+ [
+ 'end' => 1,
+ ],
+ 'foobar',
+ 'http://foo.bar',
+ 'You have been banned from this board until . Please contact the Board Administrator for more information.BAN_TRIGGERED_BY_FOOBAR ',
+ ],
+ [
+ [
+ 'end' => 1,
+ 'reason' => 'just because',
+ ],
+ 'foobar',
+ 'http://foo.bar',
+ 'You have been banned from this board until . Please contact the Board Administrator for more information. Reason given for ban: just because BAN_TRIGGERED_BY_FOOBAR ',
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider data_get_ban_message
+ */
+ public function test_get_ban_message($ban_row, $ban_triggered_by, $contact_link, $expected)
+ {
+ $this->assertEquals($expected, $this->ban_manager->get_ban_message($ban_row, $ban_triggered_by, $contact_link));
+ }
+
+ public function test_get_ban_options_user()
+ {
+ $foo = $this->ban_manager->get_bans('user');
+
+ $this->assertEquals(
+ [
+ [
+ 'ban_id' => 4,
+ 'ban_userid' => '4',
+ 'ban_mode' => 'user',
+ 'ban_item' => '4',
+ 'ban_start' => '1111',
+ 'ban_end' => '0',
+ 'ban_reason' => 'HAHAHA',
+ 'ban_reason_display' => '1',
+ 'user_id' => '4',
+ 'username' => 'ipv6_user',
+ 'username_clean' => 'ipv6_user',
+ 'label' => 'ipv6_user',
+ ],
+ ],
+ $foo
+ );
+ }
+}
diff --git a/tests/ban/fixtures/sessions_banlist.xml b/tests/ban/fixtures/sessions_banlist.xml
new file mode 100644
index 0000000000..c6c882fcf9
--- /dev/null
+++ b/tests/ban/fixtures/sessions_banlist.xml
@@ -0,0 +1,177 @@
+
+
+
+ user_id
+ username
+ username_clean
+ user_permissions
+ user_sig
+ user_email
+ user_ip
+ user_type
+
+ 1
+ anonymous
+ anonymous
+
+
+
+ 127.0.0.1
+ 2
+
+
+ 2
+ founder
+ founder
+
+
+ admin@foo.bar
+ 21.22.23.24
+ 3
+
+
+ 3
+ normal_user
+ normal_user
+
+
+ normal_user@foo.bar
+ 21.22.23.25
+ 0
+
+
+ 4
+ ipv6_user
+ ipv6_user
+
+
+ normal_user@foo.bar
+ 2345:0425:2CA1:0000:0000:0567:5673:23b5
+ 0
+
+
+ 5
+ another_user
+ another_user
+
+
+ bar@example.org
+ 123.124.125.126
+ 0
+
+
+
+ session_id
+ session_user_id
+ session_ip
+ session_browser
+ session_admin
+
+ bar_session000000000000000000000
+ 4
+ 127.0.0.1
+ user agent
+ 1
+
+
+
+ ban_id
+ ban_userid
+ ban_mode
+ ban_item
+ ban_start
+ ban_end
+ ban_reason
+ ban_reason_display
+
+ 2
+ 0
+ ip
+ 127.0.0.1
+ 1111
+ 0
+ HAHAHA
+ 1
+
+
+ 3
+ 0
+ ip
+ 127.1.1.1
+ 1111
+ 0
+ HAHAHA
+ 1
+
+
+ 4
+ 4
+ user
+ 4
+ 1111
+ 0
+ HAHAHA
+ 1
+
+
+ 5
+ 0
+ email
+ bar@example.org
+ 1111
+ 0
+ HAHAHA
+ 1
+
+
+ 6
+ 0
+ ip
+ 10.0.0.1/28
+ 1111
+ 0
+ HAHAHA
+ 1
+
+
+ 7
+ 0
+ ip
+ 2001:4860:4860::8888/12
+ 1111
+ 0
+ HAHAHA
+ 1
+
+
+ 8
+ 0
+ invalid_mode
+ foo
+ 1111
+ 0
+ HAHAHA
+ 1
+
+
+ 9
+ 0
+ email
+ *@foo.bar
+ 1111
+ 0
+ HAHAHA
+ 1
+
+
+ 10
+ 10
+ user
+ 3
+ 1111
+ 1234
+ expired
+ 1
+
+
+
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
index 2aa9c6c986..7556dd8c90 100644
--- a/tests/bootstrap.php
+++ b/tests/bootstrap.php
@@ -34,6 +34,8 @@ $phpbb_class_loader_ext = new \phpbb\class_loader('\\', $phpbb_root_path . 'ext/
$phpbb_class_loader_ext->register();
$phpbb_class_loader = new \phpbb\class_loader('phpbb\\', $phpbb_root_path . 'phpbb/', "php");
$phpbb_class_loader->register();
+$phpbb_class_loader_tests = new \phpbb\class_loader('phpbb\\tests\\', $phpbb_root_path . '../tests/', 'php');
+$phpbb_class_loader_tests->register();
require_once 'test_framework/phpbb_test_case_helpers.php';
require_once 'test_framework/phpbb_test_case.php';
diff --git a/tests/dbal/boolean_processor_test.php b/tests/dbal/boolean_processor_test.php
index 517c1dcaf8..3352b99c82 100644
--- a/tests/dbal/boolean_processor_test.php
+++ b/tests/dbal/boolean_processor_test.php
@@ -153,9 +153,9 @@ class phpbb_boolean_processor_test extends phpbb_database_test_case
'LEFT_JOIN' => array(
array(
'FROM' => array(
- 'phpbb_banlist' => 'b',
+ 'phpbb_bans' => 'b',
),
- 'ON' => 'u.user_id = b.ban_userid',
+ 'ON' => 'b.ban_item = ' . $db->cast_expr_to_string('u.user_id'),
),
),
'WHERE' => array('AND',
@@ -172,6 +172,7 @@ class phpbb_boolean_processor_test extends phpbb_database_test_case
array(
array('ug.group_id', '=', 1),
array('b.ban_id', 'IS_NOT', NULL),
+ array('b.ban_mode', '=', "'user'"),
),
),
),
@@ -290,9 +291,9 @@ class phpbb_boolean_processor_test extends phpbb_database_test_case
'LEFT_JOIN' => array(
array(
'FROM' => array(
- 'phpbb_banlist' => 'b',
+ 'phpbb_bans' => 'b',
),
- 'ON' => 'u.user_id = b.ban_userid',
+ 'ON' => 'b.ban_item = ' . $db->cast_expr_to_string('u.user_id'),
),
),
'WHERE' => array('AND',
diff --git a/tests/dbal/cross_join_test.php b/tests/dbal/cross_join_test.php
index 95bcc0be53..83c4b03a60 100644
--- a/tests/dbal/cross_join_test.php
+++ b/tests/dbal/cross_join_test.php
@@ -36,9 +36,9 @@ class phpbb_dbal_cross_join_test extends phpbb_database_test_case
'LEFT_JOIN' => array(
array(
'FROM' => array(
- 'phpbb_banlist' => 'b',
+ 'phpbb_bans' => 'b',
),
- 'ON' => 'u.user_id = b.ban_userid',
+ 'ON' => 'b.ban_item = ' . $db->cast_expr_to_string('u.user_id'),
),
),
'WHERE' => 'ug.group_id = 1
diff --git a/tests/dbal/fixtures/boolean_processor.xml b/tests/dbal/fixtures/boolean_processor.xml
index d31d679f45..9bab747fcf 100644
--- a/tests/dbal/fixtures/boolean_processor.xml
+++ b/tests/dbal/fixtures/boolean_processor.xml
@@ -1,10 +1,12 @@
-
+
ban_id
- ban_userid
+ ban_mode
+ ban_item
1
+ user
2
diff --git a/tests/dbal/fixtures/massmail_crossjoin.xml b/tests/dbal/fixtures/massmail_crossjoin.xml
index 1050ba067e..d453d5e9fd 100644
--- a/tests/dbal/fixtures/massmail_crossjoin.xml
+++ b/tests/dbal/fixtures/massmail_crossjoin.xml
@@ -1,10 +1,12 @@
-
+
ban_id
- ban_userid
+ ban_mode
+ ban_item
1
+ user
2
diff --git a/tests/functions/fixtures/banned_users.xml b/tests/functions/fixtures/banned_users.xml
index cec3f4e51f..082f210ca3 100644
--- a/tests/functions/fixtures/banned_users.xml
+++ b/tests/functions/fixtures/banned_users.xml
@@ -1,38 +1,69 @@
-
+
ban_userid
- ban_exclude
+ ban_mode
ban_end
-
- 1
- 1
- 0
-
2
- 0
+ user
0
3
- 0
+ user
0
4
- 0
+ user
2
5
- 0
- 999999999999999999999
+ user
+ 2147485547
6
- 0
+ user
3
+
+ user_id
+ username_clean
+ user_permissions
+ user_sig
+
+ 2
+ admin
+
+
+
+
+ 3
+ user3
+
+
+
+
+ 4
+ user4
+
+
+
+
+ 5
+ user5
+
+
+
+
+ 6
+ user6
+
+
+
+
diff --git a/tests/functions/fixtures/validate_email.xml b/tests/functions/fixtures/validate_email.xml
index 985050cedc..4fa9bd03d0 100644
--- a/tests/functions/fixtures/validate_email.xml
+++ b/tests/functions/fixtures/validate_email.xml
@@ -1,26 +1,29 @@
-
+
ban_id
- ban_userid
- ban_exclude
+ ban_mode
+ ban_item
+ ban_start
ban_end
- ban_email
- ban_give_reason
+ ban_reason
+ ban_reason_display
1
- 0
- 0
- 0
+ email
banned@example.com
+ 0
+ 0
+
2
- 0
- 0
- 0
+ email
banned2@example.com
+ 0
+ 0
+ just because
just because
diff --git a/tests/functions/phpbb_get_banned_user_ids.php b/tests/functions/phpbb_get_banned_user_ids.php
index 0877a3526e..6aaa5f8641 100644
--- a/tests/functions/phpbb_get_banned_user_ids.php
+++ b/tests/functions/phpbb_get_banned_user_ids.php
@@ -20,6 +20,47 @@ class phpbb_get_banned_user_ids_test extends phpbb_database_test_case
return $this->createXMLDataSet(__DIR__ . '/fixtures/banned_users.xml');
}
+ protected function setUp(): void
+ {
+ global $db, $phpbb_container, $phpbb_root_path, $phpEx;
+
+ $db = $this->new_dbal();
+
+ parent::setUp();
+
+ $phpbb_container = new phpbb_mock_container_builder();
+ $config = new \phpbb\config\config([]);
+ $phpbb_dispatcher = new phpbb_mock_event_dispatcher();
+ $language = new phpbb\language\language(new phpbb\language\language_file_loader($phpbb_root_path, $phpEx));
+ $user = new phpbb\user($language, '\phpbb\datetime');
+ $user->data['user_email'] = '';
+
+ $cache = new \phpbb\cache\service(
+ new \phpbb\cache\driver\dummy(),
+ $config,
+ $db,
+ $phpbb_dispatcher,
+ $phpbb_root_path,
+ $phpEx
+ );
+ $cache->get_driver()->purge();
+
+ $ban_type_email = new \phpbb\ban\type\email($db, 'phpbb_bans', 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys');
+ $ban_type_user = new \phpbb\ban\type\user($db, 'phpbb_bans', 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys');
+ $ban_type_ip = new \phpbb\ban\type\ip($db, 'phpbb_bans', 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys');
+ $phpbb_container->set('ban.type.email', $ban_type_email);
+ $phpbb_container->set('ban.type.user', $ban_type_user);
+ $phpbb_container->set('ban.type.ip', $ban_type_ip);
+ $collection = new \phpbb\di\service_collection($phpbb_container);
+ $collection->add('ban.type.email');
+ $collection->add('ban.type.user');
+ $collection->add('ban.type.ip');
+ $phpbb_log = new \phpbb\log\dummy();
+
+ $ban_manager = new \phpbb\ban\manager($collection, $cache->get_driver(), $db, $language, $phpbb_log, $user, 'phpbb_bans', 'phpbb_users');
+ $phpbb_container->set('ban.manager', $ban_manager);
+ }
+
public function phpbb_get_banned_user_ids_data()
{
return array(
@@ -35,6 +76,11 @@ class phpbb_get_banned_user_ids_test extends phpbb_database_test_case
array(array(1, 2, 4, 5, 6), false),
array(2 => 2),
),
+ array(
+ // True to get users currently banned, but should only return passed user IDs
+ array(array(5, 6, 7), true),
+ array(5 => 5),
+ ),
array(
// Unix timestamp to get users banned until that time
array(array(1, 2, 4, 5, 6), 2),
@@ -43,15 +89,6 @@ class phpbb_get_banned_user_ids_test extends phpbb_database_test_case
);
}
- protected function setUp(): void
- {
- global $db;
-
- $db = $this->new_dbal();
-
- parent::setUp();
- }
-
/**
* @dataProvider phpbb_get_banned_user_ids_data
*/
diff --git a/tests/functions/validate_user_email_test.php b/tests/functions/validate_user_email_test.php
index fb70c3014a..a43244bd50 100644
--- a/tests/functions/validate_user_email_test.php
+++ b/tests/functions/validate_user_email_test.php
@@ -28,18 +28,43 @@ class phpbb_functions_validate_user_email_test extends phpbb_database_test_case
protected function setUp(): void
{
- global $cache, $phpbb_dispatcher, $phpbb_root_path, $phpEx;
+ global $cache, $phpbb_container, $phpbb_dispatcher, $phpbb_root_path, $phpEx;
parent::setUp();
- $cache = new \phpbb\cache\driver\file();
- $cache->purge();
+ $phpbb_container = new phpbb_mock_container_builder();
+ $config = new \phpbb\config\config([]);
$this->db = $this->new_dbal();
$phpbb_dispatcher = new phpbb_mock_event_dispatcher();
$language = new phpbb\language\language(new phpbb\language\language_file_loader($phpbb_root_path, $phpEx));
$this->user = new phpbb\user($language, '\phpbb\datetime');
$this->user->data['user_email'] = '';
$this->helper = new phpbb_functions_validate_data_helper($this);
+
+ $cache = new \phpbb\cache\service(
+ new \phpbb\cache\driver\dummy(),
+ $config,
+ $this->db,
+ $phpbb_dispatcher,
+ $phpbb_root_path,
+ $phpEx
+ );
+ $cache->get_driver()->purge();
+
+ $ban_type_email = new \phpbb\ban\type\email($this->db, 'phpbb_bans', 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys');
+ $ban_type_user = new \phpbb\ban\type\user($this->db, 'phpbb_bans', 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys');
+ $ban_type_ip = new \phpbb\ban\type\ip($this->db, 'phpbb_bans', 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys');
+ $phpbb_container->set('ban.type.email', $ban_type_email);
+ $phpbb_container->set('ban.type.user', $ban_type_user);
+ $phpbb_container->set('ban.type.ip', $ban_type_ip);
+ $collection = new \phpbb\di\service_collection($phpbb_container);
+ $collection->add('ban.type.email');
+ $collection->add('ban.type.user');
+ $collection->add('ban.type.ip');
+ $phpbb_log = new \phpbb\log\dummy();
+
+ $ban_manager = new \phpbb\ban\manager($collection, $cache->get_driver(), $this->db, $language, $phpbb_log, $this->user, 'phpbb_bans', 'phpbb_users');
+ $phpbb_container->set('ban.manager', $ban_manager);
}
/**
diff --git a/tests/functions_user/delete_user_test.php b/tests/functions_user/delete_user_test.php
index 76a0aa50ce..9f4f69d0c2 100644
--- a/tests/functions_user/delete_user_test.php
+++ b/tests/functions_user/delete_user_test.php
@@ -369,7 +369,7 @@ class phpbb_functions_user_delete_user_test extends phpbb_database_test_case
$this->db->sql_freeresult($result);
$sql = 'SELECT ban_id
- FROM ' . BANLIST_TABLE . '
+ FROM ' . BANS_TABLE . '
ORDER BY ban_id ASC';
$result = $this->db->sql_query($sql);
$this->assertEquals($expected_ban, $this->db->sql_fetchrowset($result), 'Ban table content is mismatching after deleting a user.');
diff --git a/tests/functions_user/fixtures/delete_user.xml b/tests/functions_user/fixtures/delete_user.xml
index 8de2659722..c149a42429 100644
--- a/tests/functions_user/fixtures/delete_user.xml
+++ b/tests/functions_user/fixtures/delete_user.xml
@@ -36,30 +36,42 @@
-
+
ban_id
ban_userid
- ban_email
+ ban_mode
+ ban_item
+ ban_start
+ ban_end
ban_reason
- ban_give_reason
+ ban_reason_display
1
2
-
+ user
+ 2
+ 0
+ 0
2
3
-
+ user
+ 3
+ 0
+ 0
3
0
-
+ user
+ 0
+ 0
+ 0
diff --git a/tests/session/check_ban_test.php b/tests/session/check_ban_test.php
index 7b0aac060c..44a4012d3b 100644
--- a/tests/session/check_ban_test.php
+++ b/tests/session/check_ban_test.php
@@ -33,8 +33,6 @@ class phpbb_session_check_ban_test extends phpbb_session_test_case
false, false, false, false, /* should be banned? -> */ false),
array('Matching values in the database, should be banned',
4, '127.0.0.1', 'bar@example.org', true, /* should be banned? -> */ true),
- array('IP Banned, should be banned',
- false, '127.1.1.1', false, false, /* should be banned? -> */ true),
);
}
@@ -53,7 +51,10 @@ class phpbb_session_check_ban_test extends phpbb_session_test_case
'BAN_TRIGGERED_BY_USER' => 'BAN_TRIGGERED_BY_USER',
];
- global $cache, $config, $phpbb_root_path, $phpEx, $phpbb_filesystem;
+ global $cache, $config, $phpbb_root_path, $phpEx, $phpbb_filesystem, $phpbb_container, $user;
+
+ $language = new phpbb\language\language(new phpbb\language\language_file_loader($phpbb_root_path, $phpEx));
+ $user = new \phpbb\user($language, '\phpbb\datetime');
$phpbb_filesystem = new \phpbb\filesystem\filesystem();
@@ -73,6 +74,22 @@ class phpbb_session_check_ban_test extends phpbb_session_test_case
$phpbb_root_path,
$phpEx
);
+
+ $phpbb_container = new phpbb_mock_container_builder();
+ $ban_type_email = new \phpbb\ban\type\email($this->db, 'phpbb_bans', 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys');
+ $ban_type_user = new \phpbb\ban\type\user($this->db, 'phpbb_bans', 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys');
+ $ban_type_ip = new \phpbb\ban\type\ip($this->db, 'phpbb_bans', 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys');
+ $phpbb_container->set('ban.type.email', $ban_type_email);
+ $phpbb_container->set('ban.type.user', $ban_type_user);
+ $phpbb_container->set('ban.type.ip', $ban_type_ip);
+ $collection = new \phpbb\di\service_collection($phpbb_container);
+ $collection->add('ban.type.email');
+ $collection->add('ban.type.user');
+ $collection->add('ban.type.ip');
+ $phpbb_log = new \phpbb\log\dummy();
+
+ $ban_manager = new \phpbb\ban\manager($collection, $cache->get_driver(), $this->db, $language, $phpbb_log, $user, 'phpbb_bans', 'phpbb_users');
+ $phpbb_container->set('ban.manager', $ban_manager);
}
protected function tearDown(): void
diff --git a/tests/session/fixtures/sessions_banlist.xml b/tests/session/fixtures/sessions_banlist.xml
index e720e35f0a..b6c123e119 100644
--- a/tests/session/fixtures/sessions_banlist.xml
+++ b/tests/session/fixtures/sessions_banlist.xml
@@ -26,34 +26,46 @@
1
-
+
ban_id
- ban_userid
- ban_ip
- ban_email
+ ban_mode
+ ban_item
ban_start
ban_end
- ban_exclude
ban_reason
- ban_give_reason
+ ban_reason_display
2
- 4
+ ip
127.0.0.1
- bar@example.org
1111
0
- 0
HAHAHA
1
3
- 0
+ ip
127.1.1.1
-
1111
0
+ HAHAHA
+ 1
+
+
+ 4
+ user
+ 4
+ 1111
+ 0
+ HAHAHA
+ 1
+
+
+ 5
+ email
+ bar@example.org
+ 1111
0
HAHAHA
1
diff --git a/tests/session/fixtures/sessions_empty.xml b/tests/session/fixtures/sessions_empty.xml
index 068951dc4c..4df982ab7f 100644
--- a/tests/session/fixtures/sessions_empty.xml
+++ b/tests/session/fixtures/sessions_empty.xml
@@ -30,11 +30,13 @@
session_ip
session_browser
-
+
ban_id
- ban_userid
- ban_email
+ ban_mode
+ ban_item
+ ban_start
+ ban_end
ban_reason
- ban_give_reason
+ ban_reason_display
diff --git a/tests/session/testable_factory.php b/tests/session/testable_factory.php
index bd25fa02f0..36e9fe6d3f 100644
--- a/tests/session/testable_factory.php
+++ b/tests/session/testable_factory.php
@@ -38,7 +38,7 @@ class phpbb_session_testable_factory
public function __construct()
{
// default configuration values
- $this->config_data = array(
+ $this->config_data = [
'allow_autologin' => false,
'auth_method' => 'db',
'forwarded_for_check' => true,
@@ -53,13 +53,14 @@ class phpbb_session_testable_factory
'limit_search_load' => 0,
'ip_check' => 3,
'browser_check' => 1,
- );
+ ];
- $this->cache_data = array(
- '_bots' => array(),
- );
+ $this->cache_data = [
+ '_bots' => [],
+ '_ban_info' => [],
+ ];
- $this->cookies = array();
+ $this->cookies = [];
$this->server_data = $_SERVER;
}
@@ -73,7 +74,8 @@ class phpbb_session_testable_factory
public function get_session(\phpbb\db\driver\driver_interface $dbal)
{
// set up all the global variables used by session
- global $SID, $_SID, $db, $config, $cache, $request, $phpbb_container, $phpbb_root_path;
+ global $SID, $_SID, $db, $config, $cache, $request, $phpbb_container, $phpbb_dispatcher;
+ global $user, $phpbb_root_path, $phpEx;
$request = $this->request = new phpbb_mock_request(
array(),
@@ -88,6 +90,8 @@ class phpbb_session_testable_factory
$cache = $this->cache = new phpbb_mock_cache($this->get_cache_data());
$SID = $_SID = null;
+ $language = new phpbb\language\language(new phpbb\language\language_file_loader($phpbb_root_path, $phpEx));
+ $user = new \phpbb\user($language, '\phpbb\datetime');
$phpbb_container = $this->container = new phpbb_mock_container_builder();
$phpbb_container->set(
@@ -103,6 +107,24 @@ class phpbb_session_testable_factory
$provider_collection
);
+ $phpbb_dispatcher = new phpbb_mock_event_dispatcher();
+
+ $ban_type_email = new \phpbb\ban\type\email($db, 'phpbb_bans', 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys');
+ $ban_type_user = new \phpbb\ban\type\user($db, 'phpbb_bans', 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys');
+ $ban_type_ip = new \phpbb\ban\type\ip($db, 'phpbb_bans', 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys');
+ $phpbb_container->set('ban.type.email', $ban_type_email);
+ $phpbb_container->set('ban.type.user', $ban_type_user);
+ $phpbb_container->set('ban.type.ip', $ban_type_ip);
+
+ $collection = new \phpbb\di\service_collection($phpbb_container);
+ $collection->add('ban.type.email');
+ $collection->add('ban.type.user');
+ $collection->add('ban.type.ip');
+ $phpbb_log = new \phpbb\log\dummy();
+
+ $ban_manager = new \phpbb\ban\manager($collection, $cache, $db, $language, $phpbb_log, $user,'phpbb_bans', 'phpbb_users');
+ $phpbb_container->set('ban.manager', $ban_manager);
+
$session = new phpbb_mock_session_testable;
return $session;
}
diff --git a/tests/test_framework/phpbb_session_test_case.php b/tests/test_framework/phpbb_session_test_case.php
index e3904f1746..79ac2d9c48 100644
--- a/tests/test_framework/phpbb_session_test_case.php
+++ b/tests/test_framework/phpbb_session_test_case.php
@@ -29,7 +29,7 @@ abstract class phpbb_session_test_case extends phpbb_database_test_case
{
parent::setUp();
- global $symfony_request, $phpbb_path_helper, $request, $phpbb_root_path, $phpEx;
+ global $symfony_request, $phpbb_path_helper, $phpbb_root_path, $phpEx;
$symfony_request = new \phpbb\symfony_request(
new phpbb_mock_request()
);