1
0
mirror of https://github.com/phpbb/phpbb.git synced 2025-05-06 23:55:26 +02:00

[ticket/9687] Finish documentation and integrate the new code

PHPBB3-9687
This commit is contained in:
Oliver Schramm 2018-09-29 19:25:26 +02:00 committed by Marc Alexander
parent 9373fa3edb
commit 7267df431f
No known key found for this signature in database
GPG Key ID: 50E0D2423696F995
14 changed files with 272 additions and 774 deletions

View File

@ -25,9 +25,12 @@ class acp_ban
function main($id, $mode)
{
global $user, $template, $request, $phpbb_dispatcher;
global $user, $template, $request, $phpbb_dispatcher, $phpbb_container;
global $phpbb_root_path, $phpEx;
/** @var \phpbb\ban\manager $ban_manager */
$ban_manager = $phpbb_container->get('ban.manager');
if (!function_exists('user_ban'))
{
include($phpbb_root_path . 'includes/functions_user.' . $phpEx);

View File

@ -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'))

View File

@ -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');

View File

@ -3156,63 +3156,18 @@ function display_ban_end_options()
*/
function display_ban_options($mode)
{
global $user, $db, $template;
global $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 = array();
foreach ($ban_rows as $row)
{
case 'user':
$banned_options[] = '<option value="' . $ban_row['ban_id'] . '">' . $ban_row['ban_item'] . '</option>';
$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 = '<option value="' . $row['ban_id'] . '">' . $row[$field] . '</option>';
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)
{
@ -3222,34 +3177,26 @@ function display_ban_options($mode)
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 = $user->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 = $user->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)
{
$options .= '<optgroup label="' . $user->lang['OPTIONS_EXCLUDED'] . '">';
$options .= implode('', $excluded_options);
$options .= '</optgroup>';
}
if ($banned_options)
{
$options .= '<optgroup label="' . $user->lang['OPTIONS_BANNED'] . '">';
@ -3258,7 +3205,7 @@ function display_ban_options($mode)
}
$template->assign_vars(array(
'S_BANNED_OPTIONS' => ($banned_options || $excluded_options) ? true : false,
'S_BANNED_OPTIONS' => (bool) $banned_options,
'BANNED_OPTIONS' => $options,
));
}

View File

@ -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'])

View File

@ -749,8 +749,8 @@ 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 ' . BAN_TABLE . '
WHERE ban_mode = \'user\' AND ' . $db->sql_in_set('ban_item', $user_ids);
$db->sql_query($sql);
// Delete the user_id from the session table
@ -915,6 +915,8 @@ 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 3.3.0-a1 (To be removed: 4.0.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
@ -926,19 +928,14 @@ function user_active_flip($mode, $user_id_ary, $reason = INACTIVE_MANUAL)
*/
function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reason, $ban_give_reason = '')
{
global $db, $user, $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 3.3.0-a1 (To be removed: 4.0.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);
}
/**
@ -3710,6 +3253,8 @@ function remove_newly_registered($user_id, $user_data = false)
/**
* Gets user ids of currently banned registered users.
*
* @deprecated 3.3.0-a1 (To be removed: 4.0.0)
*
* @param array $user_ids Array of users' ids to check for banning,
* leave empty to get complete list of banned ids
* @param bool|int $ban_end Bool True to get users currently banned
@ -3719,45 +3264,32 @@ 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";
}
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) use ($ban_end) {
return $end <= 0 || $end > (int) $ban_end;
});
}
$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;
$result_array[$user_id] = $user_id;
}
$db->sql_freeresult($result);
return $banned_ids_list;
return $result_array;
}
/**

View File

@ -112,15 +112,8 @@ if ($show_birthdays)
'FROM' => array(
USERS_TABLE => 'u',
),
'LEFT_JOIN' => array(
array(
'FROM' => array(BANLIST_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' => '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)",
);
/**
@ -140,8 +133,17 @@ if ($show_birthdays)
$rows = $db->sql_fetchrowset($result);
$db->sql_freeresult($result);
/** @var \phpbb\ban\manager $ban_manager */
$ban_manager = $phpbb_container->get('ban.manager');
$banned_users = $ban_manager->get_banned_users();
foreach ($rows as $row)
{
if (isset($banned_users[(int) $row['user_id']]))
{
continue;
}
$birthday_username = get_username_string('full', $row['user_id'], $row['username'], $row['user_colour']);
$birthday_year = (int) substr($row['user_birthday'], -4);
$birthday_age = ($birthday_year) ? max(0, $now['year'] - $birthday_year) : '';

View File

@ -445,29 +445,29 @@ if (!$get_info)
),
array(
'target' => BANLIST_TABLE,
'target' => BANS_TABLE,
'execute_first' => 'phpbb_check_username_collisions();',
'query_first' => array('target', $convert->truncate_statement . BANLIST_TABLE),
'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_reason', '', ''),
array('ban_give_reason', '', ''),
'where' => "banlist.ban_ip NOT LIKE '%.%'",
'where' => "banlist.ban_ip NOT LIKE '%.%' AMD banlist.ban_userid <> 0",
),
array(
'target' => 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', ''),
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 '%.%' AMD banlist.ban_email <> ''",
),
array(

View File

@ -1,20 +0,0 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\ban\exception;
use phpbb\exception\runtime_exception;
class no_items_specified_exception extends runtime_exception
{
}

View File

@ -24,27 +24,50 @@ class manager
const CACHE_KEY_USERS = '_banned_users';
const CACHE_TTL = 3600;
protected $ban_table;
/** @var string */
protected $bans_table;
/** @var \phpbb\cache\service */
protected $cache;
/** @var \phpbb\db\driver\driver_interface */
protected $db;
/** @var \phpbb\log\log_interface */
protected $log;
/** @var string */
protected $sessions_keys_table;
/** @var string */
protected $sessions_table;
/** @var \phpbb\di\service_collection */
protected $types;
/** @var \phpbb\user */
protected $user;
/** @var string */
protected $users_table;
public function __construct($types, \phpbb\cache\service $cache, \phpbb\db\driver\driver_interface $db, \phpbb\log\log_interface $log, \phpbb\user $user, $ban_table, $users_table = '', $sessions_table = '', $sessions_keys_table = '')
/**
* Creates a service which manages all bans. Developers can
* create their own ban types which will be handled in this.
*
* @param \phpbb\di\service_collection $types A service collection containing all ban types
* @param \phpbb\cache\service $cache A cache object
* @param \phpbb\db\driver\driver_interface $db A phpBB DBAL object
* @param \phpbb\log\log_interface $log A log object
* @param \phpbb\user $user An user 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 key table
*/
public function __construct($types, \phpbb\cache\service $cache, \phpbb\db\driver\driver_interface $db, \phpbb\log\log_interface $log, \phpbb\user $user, $bans_table, $users_table = '', $sessions_table = '', $sessions_keys_table = '')
{
$this->ban_table = $ban_table;
$this->bans_table = $bans_table;
$this->cache = $cache;
$this->db = $db;
$this->log = $log;
@ -55,6 +78,19 @@ class manager
$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($mode, array $items, \DateTimeInterface $start, \DateTimeInterface $end, $reason, $display_reason = '')
{
if ($start > $end && $end->getTimestamp() !== 0)
@ -73,7 +109,7 @@ class manager
$ban_items = $ban_mode->prepare_for_storage($items);
// Prevent duplicate bans
$sql = 'DELETE FROM ' . $this->ban_table . "
$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);
@ -93,10 +129,10 @@ class manager
if (empty($insert_array))
{
throw new no_items_specified_exception(); // TODO
return false;
}
$result = $this->db->sql_multi_insert($this->ban_table, $insert_array);
$result = $this->db->sql_multi_insert($this->bans_table, $insert_array);
if ($result === false)
{
throw new ban_insert_failed_exception(); // TODO
@ -178,8 +214,17 @@ class manager
$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
* @param bool $logging True, if log entries should be created, false otherwise.
*/
public function unban($mode, array $items, $logging = true)
{
/** @var \phpbb\ban\type\type_interface $ban_mode */
@ -192,7 +237,7 @@ class manager
$sql_ids = array_map('intval', $items);
$sql = 'SELECT ban_item
FROM ' . $this->ban_table . '
FROM ' . $this->bans_table . '
WHERE ' . $this->db->sql_in_set('ban_id', $sql_ids); // TODO (what if empty?)
$result = $this->db->sql_query($sql);
@ -203,7 +248,7 @@ class manager
}
$this->db->sql_freeresult($result);
$sql = 'DELETE FROM ' . $this->ban_table . '
$sql = 'DELETE FROM ' . $this->bans_table . '
WHERE ' . $this->db->sql_in_set('ban_id', $sql_ids);
$this->db->sql_query($sql);
@ -229,6 +274,15 @@ class manager
$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))
@ -252,12 +306,16 @@ class manager
$ban_result = $ban_mode->check($ban_rows, $user_data);
if ($ban_result !== false)
{
return $ban_result;
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)
{
@ -267,7 +325,7 @@ class manager
{
if ($ban_row['item'] == $user_data[$user_column])
{
return $ban_row;
return $ban_row + ['mode' => $mode];
}
}
else
@ -275,7 +333,7 @@ class manager
$regex = str_replace('\*', '.*?', preg_quote($ban_row['item'], '#'));
if (preg_match($regex, $user_data[$user_column]))
{
return $ban_row;
return $ban_row + ['mode' => $mode];
}
}
}
@ -286,6 +344,13 @@ class manager
return false;
}
/**
* Returns all bans for a given ban type. False, if none were found
*
* @param strng $mode The ban type for which the entries should be retrieved
*
* @return array|bool
*/
public function get_bans($mode)
{
/** @var \phpbb\ban\type\type_interface $ban_mode */
@ -297,7 +362,7 @@ class manager
$this->tidy();
$sql = 'SELECT ban_id, ban_item, ban_start, ban_end, ban_reason, ban_reason_display
FROM ' . $this->ban_table . "
FROM ' . $this->bans_table . "
WHERE ban_mode = '" . $this->db->sql_escape($mode) . "'
AND (ban_end <= 0 OR ban_end >= " . (int) time() . ')';
$result = $this->db->sql_query($sql);
@ -307,6 +372,13 @@ class manager
return $rowset;
}
/**
* 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()
{
$banned_users = $this->cache->get(self::CACHE_KEY_USERS);
@ -335,11 +407,16 @@ class manager
$sql_array = [
'SELECT' => 'u.user_id, b.ban_end',
'FROM' => [
$this->ban_table => 'b',
$this->bans_table => 'b',
$this->users_table => 'u',
],
'WHERE' => ['OR',
$where_array,
'WHERE' => ['AND',
[
['OR',
$where_array,
],
['u.user_type', '<>', USER_FOUNDER],
]
],
];
$sql = $this->db->sql_build_query('SELECT', $sql_array);
@ -380,10 +457,13 @@ class manager
});
}
/**
* Cleans up the database of e.g. stale bans
*/
public function tidy()
{
// Delete stale bans
$sql = 'DELETE FROM ' . $this->ban_table . '
$sql = 'DELETE FROM ' . $this->bans_table . '
WHERE ban_end > 0 AND ban_end < ' . (int) time();
$this->db->sql_query($sql);
@ -394,6 +474,14 @@ class manager
}
}
/**
* 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($mode)
{
/** @var \phpbb\ban\type\type_interface $type */
@ -408,13 +496,22 @@ class manager
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()
{
$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->ban_table . '
FROM ' . $this->bans_table . '
WHERE 1';
$result = $this->db->sql_query($sql);

View File

@ -27,6 +27,13 @@ abstract class base implements type_interface
/** @var string */
protected $users_table;
/**
* Creates a ban type.
*
* @param \phpbb\db\driver\driver_interface $db A phpBB DBAL object
* @param \phpbb\user $user An user object
* @param string $users_table The users table
*/
public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\user $user, $users_table)
{
$this->db = $db;

View File

@ -19,11 +19,17 @@ use phpbb\exception\runtime_exception;
class email extends base
{
/**
* {@inheritDoc}
*/
public function get_ban_log_string()
{
return 'LOG_BAN_EMAIL';
}
/**
* {@inheritDoc}
*/
public function get_unban_log_string()
{
return 'LOG_UNBAN_EMAIL';

View File

@ -27,8 +27,24 @@ class user extends base
/** @var string */
private $ban_log_string = 'LOG_BAN_USER';
/** @var string */
private $unban_log_string = 'LOG_UNBAN_USER';
/**
* Creates the user ban type
*
* @param \phpbb\db\driver\driver_interface $db A phpBB DBAL object
* @param \phpbb\log\log_interface $log A log object
* @param \phpbb\user $user An user object
* @param string $users_table The users table
*/
public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\log\log_interface $log, \phpbb\user $user, $users_table)
{
$this->log = $log;
parent::__construct($db, $user, $users_table);
}
/**
* {@inheritDoc}
*/

View File

@ -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 $db, $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
@ -1300,8 +1204,14 @@ class session
}
// Determine which message to output
$till_date = ($ban_row['end'] > 0) ? $this->format_date($ban_row['end']) : '';
$message = $this->get_ban_message($ban_row, $ban_triggered_by);
$contact_link = phpbb_get_board_contact_link($config, $phpbb_root_path, $phpEx);
$message = sprintf($this->lang[$message], $till_date, '<a href="' . $contact_link . '">', '</a>');
$message .= ($ban_row['reason']) ? '<br /><br />' . sprintf($this->lang['BOARD_BAN_REASON'], $ban_row['reason']) : '';
$message .= '<br /><br /><em>' . $this->lang['BAN_TRIGGERED_BY_' . strtoupper($ban_triggered_by)] . '</em>';
// 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'))
{