From 5ae1d9eac68fc9586b7006a692f396f5c4e81804 Mon Sep 17 00:00:00 2001 From: Oliver Schramm Date: Fri, 28 Sep 2018 17:09:31 +0200 Subject: [PATCH 01/54] [ticket/9687] Introduce new ban manager (WIP) PHPBB3-9687 --- .../exception/invalid_length_exception.php | 20 ++ .../exception/type_not_found_exception.php | 20 ++ phpBB/phpbb/ban/manager.php | 160 ++++++++++++++++ phpBB/phpbb/ban/type/base.php | 95 ++++++++++ phpBB/phpbb/ban/type/email.php | 63 +++++++ phpBB/phpbb/ban/type/type_interface.php | 73 ++++++++ phpBB/phpbb/ban/type/user.php | 78 ++++++++ .../db/migration/data/v330/ban_table_p1.php | 174 ++++++++++++++++++ .../db/migration/data/v330/ban_table_p2.php | 59 ++++++ 9 files changed, 742 insertions(+) create mode 100644 phpBB/phpbb/ban/exception/invalid_length_exception.php create mode 100644 phpBB/phpbb/ban/exception/type_not_found_exception.php create mode 100644 phpBB/phpbb/ban/manager.php create mode 100644 phpBB/phpbb/ban/type/base.php create mode 100644 phpBB/phpbb/ban/type/email.php create mode 100644 phpBB/phpbb/ban/type/type_interface.php create mode 100644 phpBB/phpbb/ban/type/user.php create mode 100644 phpBB/phpbb/db/migration/data/v330/ban_table_p1.php create mode 100644 phpBB/phpbb/db/migration/data/v330/ban_table_p2.php 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/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..46b46b78b7 --- /dev/null +++ b/phpBB/phpbb/ban/manager.php @@ -0,0 +1,160 @@ + + * @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; + +class manager +{ + protected $ban_table; + + protected $db; + + protected $log; + + protected $sessions_keys_table; + + protected $sessions_table; + + protected $types; + + protected $user; + + protected $users_table; + + public function __construct($types, \phpbb\db\driver\driver_interface $db, \phpbb\log\log_interface $log, \phpbb\user $user, $ban_table, $users_table = '', $sessions_table = '', $sessions_keys_table = '') + { + $this->ban_table = $ban_table; + $this->db = $db; + $this->log = $log; + $this->sessions_keys_table = $sessions_keys_table; + $this->sessions_table = $sessions_table; + $this->types = $types; + $this->user = $user; + $this->users_table = $users_table; + } + + public function ban($mode, array $items, \DateTimeInterface $start, \DateTimeInterface $end, $reason, $display_reason = '', $logging = true) + { + if (!isset($this->types[$mode])) + { + throw new type_not_found_exception(); // TODO + } + if ($start > $end && $end->getTimestamp() !== 0) + { + throw new invalid_length_exception(); // TODO + } + + /** @var \phpbb\ban\type\type_interface $ban_mode */ + $ban_mode = $this->types[$mode]; + $ban_items = $ban_mode->prepare_for_storage($items); + + // Prevent duplicate bans + $sql = 'DELETE FROM ' . $this->ban_table . " + WHERE ban_mode = '" . $this->db->sql_escape($mode) . "' + AND " . $this->db->sql_in_set('ban_item', $ban_items); + $this->db->sql_query($sql); + + $insert_array = []; + foreach ($ban_items as $ban_item) + { + $insert_array[] = [ + 'ban_mode' => $mode, + 'ban_item' => $ban_item, + 'ban_start' => $start->getTimestamp(), + 'ban_end' => $end->getTimestamp(), + 'ban_reason' => $reason, + 'ban_reason_display' => $display_reason, + ]; + } + + if (empty($insert_array)) + { + return; + } + + $result = $this->db->sql_multi_insert($this->ban_table, $insert_array); + if ($result === false) + { + // Something went wrong + // TODO throw exception + } + + if ($logging) + { + // TODO logging + } + + if (!$ban_mode->after_ban()) + { + return; + } + + $user_column = $ban_mode->get_user_column(); + if (!empty($user_column) && !empty($this->users_table)) + { + $ban_items_sql = []; + $ban_or_like = ''; + foreach ($ban_items as $ban_item) + { + if (stripos($ban_item, '*') === false) + { + $ban_items_sql[] = $ban_item; + } + else + { + $ban_or_like .= ' OR ' . $user_column . ' ' . $this->db->sql_like_expression(str_replace('*', $this->db->get_any_char(), $ban_item)); + } + } + + $sql = 'SELECT user_id + FROM ' . $this->users_table . ' + WHERE ' . $this->db->sql_in_set('u.' . $user_column, $ban_items) . $ban_or_like; + $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); + + 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); + } + } + } + + public function unban($mode, array $items, $reason, $logging = true) + { + } + + public function check(array $user_data = []) + { + } + + public function tidy() + { + } +} diff --git a/phpBB/phpbb/ban/type/base.php b/phpBB/phpbb/ban/type/base.php new file mode 100644 index 0000000000..7f49d1cc66 --- /dev/null +++ b/phpBB/phpbb/ban/type/base.php @@ -0,0 +1,95 @@ + + * @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; + +abstract class base implements type_interface +{ + /** @var \phpbb\db\driver\driver_interface */ + protected $db; + + /** @var array */ + protected $excluded; + + /** @var string */ + protected $users_table; + + public function __construct(\phpbb\db\driver\driver_interface $db, $users_table) + { + $this->db = $db; + $this->users_table = $users_table; + } + + /** + * {@inheritDoc} + */ + public function get_user_column() + { + return null; + } + + /** + * {@inheritDoc} + */ + public function after_ban() + { + return true; + } + + public function after_unban() + { + } + + /** + * {@inheritDoc} + */ + public function check(array $data) + { + return false; + } + + public function tidy() + { + } + + /** + * 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() + { + $user_column = $this->get_user_column(); + if (empty($user_column)) + { + return false; + } + + $this->excluded = []; + + $sql = "SELECT user_id, {$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; + } +} diff --git a/phpBB/phpbb/ban/type/email.php b/phpBB/phpbb/ban/type/email.php new file mode 100644 index 0000000000..4c95292c7a --- /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; + +class email extends base +{ + /** + * {@inheritDoc} + */ + public function get_type() + { + return 'email'; + } + + /** + * {@inheritDoc} + */ + public function get_user_column() + { + return 'user_email'; + } + + /** + * {@inheritDoc} + */ + public function prepare_for_storage(array $items) + { + if (!$this->get_excluded()) + { + // TODO throw exception + } + $regex = get_preg_expression('email'); + + $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)) + { + // TODO throw exception - no valid emails 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..a13681d2e1 --- /dev/null +++ b/phpBB/phpbb/ban/type/type_interface.php @@ -0,0 +1,73 @@ + + * @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(); + + /** + * 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(); + + /** + * Gives the possibility to do some clean up after banning + * Returns true if affected users should be logged out and + * false otherwise + * + * @return bool + */ + public function after_ban(); + + public function after_unban(); // ??? + + /** + * 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 true if the person is banned and false otherwise. + * + * @param array $data The user data array + * + * @return bool + */ + public function check(array $data); + + /** + * Prepares the given ban items before saving them in the database + * + * @param array $items + * + * @return array + */ + public function prepare_for_storage(array $items); + + public function tidy(); // ??? +} diff --git a/phpBB/phpbb/ban/type/user.php b/phpBB/phpbb/ban/type/user.php new file mode 100644 index 0000000000..dec17fd673 --- /dev/null +++ b/phpBB/phpbb/ban/type/user.php @@ -0,0 +1,78 @@ + + * @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; + +class user extends base +{ + public function get_type() + { + return 'user'; + } + + public function get_user_column() + { + return 'user_id'; + } + + public function prepare_for_storage(array $items) + { + if (!$this->get_excluded()) + { + // TODO throw exception + } + + $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', + '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 = []; + while ($row = $this->db->sql_fetchrow($result)) + { + $ban_items[] = (int) $row['user_id']; + } + $this->db->sql_freeresult($result); + + return $ban_items; + } +} diff --git a/phpBB/phpbb/db/migration/data/v330/ban_table_p1.php b/phpBB/phpbb/db/migration/data/v330/ban_table_p1.php new file mode 100644 index 0000000000..2b2e027a49 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v330/ban_table_p1.php @@ -0,0 +1,174 @@ + + * @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\v330; + +class ban_table_p1 extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array('\phpbb\db\migration\data\v320\default_data_type_ids'); + } + + public function update_schema() + { + return array( + 'add_tables' => array( + $this->table_prefix . 'bans' => array( + 'COLUMNS' => array( + 'ban_id' => array('ULINT', null, 'auto_increment'), + 'ban_mode' => array('VCHAR', ''), + 'ban_item' => array('STEXT_UNI', ''), + 'ban_start' => array('TIMESTAMP', 0), + 'ban_end' => array('TIMESTAMP', 0), + 'ban_reason' => array('VCHAR_UNI', ''), + 'ban_reason_display' => array('VCHAR_UNI', ''), + ), + 'PRIMARY_KEY' => 'ban_id', + 'KEYS' => array( + 'ban_end' => array('INDEX', 'ban_end'), + ), + ), + ), + ); + } + + public function revert_schema() + { + return array( + 'drop_tables' => array( + $this->table_prefix . 'bans', + ), + ); + } + + public function update_data() + { + return array( + array('custom', array(array($this, 'old_to_new'))), + ); + } + + public function revert_data() + { + return array( + array('custom', array(array($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_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' => ($row['ban_mode'] === 'user') ? (int)$row['ban_item'] : 0, + '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/v330/ban_table_p2.php b/phpBB/phpbb/db/migration/data/v330/ban_table_p2.php new file mode 100644 index 0000000000..de617a05f2 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v330/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\v330; + +class ban_table_p2 extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array('\phpbb\db\migration\data\v330\ban_table_p1'); + } + + public function update_schema() + { + return array( + 'drop_tables' => array( + $this->table_prefix . 'banlist', + ), + ); + } + + public function revert_schema() + { + return array( + 'add_tables' => array( + $this->table_prefix . 'banlist' => array( + 'COLUMNS' => array( + 'ban_id' => array('ULINT', NULL, 'auto_increment'), + 'ban_userid' => array('ULINT', 0), + 'ban_ip' => array('VCHAR:40', ''), + 'ban_email' => array('VCHAR_UNI:100', ''), + 'ban_start' => array('TIMESTAMP', 0), + 'ban_end' => array('TIMESTAMP', 0), + 'ban_exclude' => array('BOOL', 0), + 'ban_reason' => array('VCHAR_UNI', ''), + 'ban_give_reason' => array('VCHAR_UNI', ''), + ), + 'PRIMARY_KEY' => 'ban_id', + 'KEYS' => array( + 'ban_end' => array('INDEX', 'ban_end'), + 'ban_user' => array('INDEX', array('ban_userid', 'ban_exclude')), + 'ban_email' => array('INDEX', array('ban_email', 'ban_exclude')), + 'ban_ip' => array('INDEX', array('ban_ip', 'ban_exclude')), + ), + ), + ), + ); + } +} From 64af01f52861c58929c4e217fa6ddeaebad175eb Mon Sep 17 00:00:00 2001 From: Oliver Schramm Date: Sat, 29 Sep 2018 04:18:39 +0200 Subject: [PATCH 02/54] [ticket/9687] Finishing user banning and ban logging PHPBB3-9687 --- phpBB/phpbb/ban/manager.php | 113 +++++++++++++++--------- phpBB/phpbb/ban/type/base.php | 20 ++--- phpBB/phpbb/ban/type/email.php | 5 ++ phpBB/phpbb/ban/type/type_interface.php | 14 ++- phpBB/phpbb/ban/type/user.php | 58 +++++++++++- 5 files changed, 154 insertions(+), 56 deletions(-) diff --git a/phpBB/phpbb/ban/manager.php b/phpBB/phpbb/ban/manager.php index 46b46b78b7..d00b80488e 100644 --- a/phpBB/phpbb/ban/manager.php +++ b/phpBB/phpbb/ban/manager.php @@ -20,6 +20,8 @@ class manager { protected $ban_table; + protected $cache; + protected $db; protected $log; @@ -34,9 +36,10 @@ class manager protected $users_table; - public function __construct($types, \phpbb\db\driver\driver_interface $db, \phpbb\log\log_interface $log, \phpbb\user $user, $ban_table, $users_table = '', $sessions_table = '', $sessions_keys_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 = '') { $this->ban_table = $ban_table; + $this->cache = $cache; $this->db = $db; $this->log = $log; $this->sessions_keys_table = $sessions_keys_table; @@ -46,7 +49,7 @@ class manager $this->users_table = $users_table; } - public function ban($mode, array $items, \DateTimeInterface $start, \DateTimeInterface $end, $reason, $display_reason = '', $logging = true) + public function ban($mode, array $items, \DateTimeInterface $start, \DateTimeInterface $end, $reason, $display_reason = '') { if (!isset($this->types[$mode])) { @@ -64,7 +67,7 @@ class manager // Prevent duplicate bans $sql = 'DELETE FROM ' . $this->ban_table . " WHERE ban_mode = '" . $this->db->sql_escape($mode) . "' - AND " . $this->db->sql_in_set('ban_item', $ban_items); + AND " . $this->db->sql_in_set('ban_item', $ban_items); // TODO (what if empty?) $this->db->sql_query($sql); $insert_array = []; @@ -82,7 +85,7 @@ class manager if (empty($insert_array)) { - return; + return; // TODO } $result = $this->db->sql_multi_insert($this->ban_table, $insert_array); @@ -92,62 +95,86 @@ class manager // TODO throw exception } - if ($logging) + if ($ban_mode->get_log_string() !== false) { - // TODO logging + $ban_items_log = implode(', ', $ban_items); + + $this->log->add('admin', $this->user->data['user_id'], $this->user->ip, $ban_mode->get_log_string(), false, [$reason, $ban_items_log]); + $this->log->add('mod', $this->user->data['user_id'], $this->user->ip, $ban_mode->get_log_string(), false, [ + 'forum_id' => 0, + 'topic_id' => 0, + $reason, + $ban_items_log, + ]); } - if (!$ban_mode->after_ban()) - { - return; - } + $ban_data = [ + 'items' => $ban_items, + 'start' => $start, + 'end' => $end, + 'reason' => $reason, + 'display_reason' => $display_reason, + ]; - $user_column = $ban_mode->get_user_column(); - if (!empty($user_column) && !empty($this->users_table)) + if ($ban_mode->after_ban($ban_data)) { - $ban_items_sql = []; - $ban_or_like = ''; - foreach ($ban_items as $ban_item) + $user_column = $ban_mode->get_user_column(); + if (!empty($user_column) && !empty($this->users_table)) { - if (stripos($ban_item, '*') === false) + if ($user_column !== 'user_id') { - $ban_items_sql[] = $ban_item; + $ban_items_sql = []; + $ban_or_like = ''; + foreach ($ban_items as $ban_item) + { + if (stripos($ban_item, '*') === false) + { + $ban_items_sql[] = $ban_item; + } + else + { + $ban_or_like .= ' OR ' . $user_column . ' ' . $this->db->sql_like_expression(str_replace('*', $this->db->get_any_char(), $ban_item)); + } + } + + $sql = 'SELECT user_id + FROM ' . $this->users_table . ' + WHERE ' . $this->db->sql_in_set('u.' . $user_column, $ban_items_sql) . $ban_or_like; + $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 { - $ban_or_like .= ' OR ' . $user_column . ' ' . $this->db->sql_like_expression(str_replace('*', $this->db->get_any_char(), $ban_item)); + $user_ids = $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); } } - - $sql = 'SELECT user_id - FROM ' . $this->users_table . ' - WHERE ' . $this->db->sql_in_set('u.' . $user_column, $ban_items) . $ban_or_like; - $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); - - 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); - } } + + $this->cache->destroy('sql', $this->ban_table); } public function unban($mode, array $items, $reason, $logging = true) { + } public function check(array $user_data = []) diff --git a/phpBB/phpbb/ban/type/base.php b/phpBB/phpbb/ban/type/base.php index 7f49d1cc66..23e128bbb6 100644 --- a/phpBB/phpbb/ban/type/base.php +++ b/phpBB/phpbb/ban/type/base.php @@ -21,27 +21,23 @@ abstract class base implements type_interface /** @var array */ protected $excluded; + /** @var \phpbb\user */ + protected $user; + /** @var string */ protected $users_table; - public function __construct(\phpbb\db\driver\driver_interface $db, $users_table) + public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\user $user, $users_table) { $this->db = $db; + $this->user = $user; $this->users_table = $users_table; } /** * {@inheritDoc} */ - public function get_user_column() - { - return null; - } - - /** - * {@inheritDoc} - */ - public function after_ban() + public function after_ban($data) { return true; } @@ -77,7 +73,9 @@ abstract class base implements type_interface return false; } - $this->excluded = []; + $this->excluded = [ + (int)$this->user->data['user_id'] => $this->user->data[$user_column], + ]; $sql = "SELECT user_id, {$user_column} FROM {$this->users_table} diff --git a/phpBB/phpbb/ban/type/email.php b/phpBB/phpbb/ban/type/email.php index 4c95292c7a..cf584a87d3 100644 --- a/phpBB/phpbb/ban/type/email.php +++ b/phpBB/phpbb/ban/type/email.php @@ -15,6 +15,11 @@ namespace phpbb\ban\type; class email extends base { + public function get_log_string() + { + return 'LOG_BAN_EMAIL'; + } + /** * {@inheritDoc} */ diff --git a/phpBB/phpbb/ban/type/type_interface.php b/phpBB/phpbb/ban/type/type_interface.php index a13681d2e1..174c5c25bd 100644 --- a/phpBB/phpbb/ban/type/type_interface.php +++ b/phpBB/phpbb/ban/type/type_interface.php @@ -18,6 +18,14 @@ namespace phpbb\ban\type; */ interface type_interface { + /** + * Returns the language key that's used for the log entry. + * False, if there is none (and thus no logs are created) + * + * @return string|bool + */ + public function get_log_string(); + /** * Returns the type identifier for this ban type * @@ -40,9 +48,13 @@ interface type_interface * Returns true if affected users should be logged out and * false otherwise * + * @param array $data An array containing information about + * the bans, like the reason or the start + * and end of the ban + * * @return bool */ - public function after_ban(); + public function after_ban($data); public function after_unban(); // ??? diff --git a/phpBB/phpbb/ban/type/user.php b/phpBB/phpbb/ban/type/user.php index dec17fd673..0fbc5d1a13 100644 --- a/phpBB/phpbb/ban/type/user.php +++ b/phpBB/phpbb/ban/type/user.php @@ -15,16 +15,70 @@ namespace phpbb\ban\type; class user extends base { + /** @var array */ + private $banned_users; + + /** @var \phpbb\log\log_interface */ + protected $log; + + /** @var string */ + private $log_string = 'LOG_BAN_USER'; + + /** + * {@inheritDoc} + */ + public function get_log_string() + { + // Have to handle logging differently here + return false; + } + + /** + * {@inheritDoc} + */ public function get_type() { return 'user'; } + /** + * {@inheritDoc} + */ public function get_user_column() { return 'user_id'; } + /** + * {@inheritDoc} + */ + public function after_ban($data) + { + $usernames_log = implode(', ', $this->banned_users); + + $this->log->add('admin', $this->user->data['user_id'], $this->user->ip, $this->log_string, false, [$data['reason'], $usernames_log]); + $this->log->add('mod', $this->user->data['user_id'], $this->user->ip, $this->log_string, false, [ + 'forum_id' => 0, + 'topic_id' => 0, + $data['reason'], + $usernames_log, + ]); + + foreach ($this->banned_users as $user_id => $username) + { + $this->log->add('user', $this->user->data['user_id'], $this->user->ip, $this->log_string, false, [ + 'reportee_id' => $user_id, + $data['reason'], + $usernames_log, + ]); + } + + return true; + } + + /** + * {@inheritDoc} + */ public function prepare_for_storage(array $items) { if (!$this->get_excluded()) @@ -48,7 +102,7 @@ class user extends base } $sql_array = [ - 'SELECT' => 'user_id', + 'SELECT' => 'user_id, username', 'FROM' => [ $this->users_table => '', ], @@ -67,9 +121,11 @@ class user extends base $result = $this->db->sql_query($sql); $ban_items = []; + $this->banned_users = []; while ($row = $this->db->sql_fetchrow($result)) { $ban_items[] = (int) $row['user_id']; + $this->banned_users[(int) $row['user_id']] = $row['username']; } $this->db->sql_freeresult($result); From 95de576ccd2dfe0de90f3471d8f5ea1f79113696 Mon Sep 17 00:00:00 2001 From: Oliver Schramm Date: Sat, 29 Sep 2018 05:00:23 +0200 Subject: [PATCH 03/54] [ticket/9687] Add unbanning to the manager PHPBB3-9687 --- phpBB/phpbb/ban/manager.php | 50 +++++++++++++++++-- phpBB/phpbb/ban/type/base.php | 7 ++- phpBB/phpbb/ban/type/email.php | 7 ++- phpBB/phpbb/ban/type/type_interface.php | 28 +++++++++-- phpBB/phpbb/ban/type/user.php | 66 ++++++++++++++++++++++--- 5 files changed, 140 insertions(+), 18 deletions(-) diff --git a/phpBB/phpbb/ban/manager.php b/phpBB/phpbb/ban/manager.php index d00b80488e..5a79f2d836 100644 --- a/phpBB/phpbb/ban/manager.php +++ b/phpBB/phpbb/ban/manager.php @@ -95,12 +95,12 @@ class manager // TODO throw exception } - if ($ban_mode->get_log_string() !== false) + if ($ban_mode->get_ban_log_string() !== false) { $ban_items_log = implode(', ', $ban_items); - $this->log->add('admin', $this->user->data['user_id'], $this->user->ip, $ban_mode->get_log_string(), false, [$reason, $ban_items_log]); - $this->log->add('mod', $this->user->data['user_id'], $this->user->ip, $ban_mode->get_log_string(), false, [ + $this->log->add('admin', $this->user->data['user_id'], $this->user->ip, $ban_mode->get_ban_log_string(), false, [$reason, $ban_items_log]); + $this->log->add('mod', $this->user->data['user_id'], $this->user->ip, $ban_mode->get_ban_log_string(), false, [ 'forum_id' => 0, 'topic_id' => 0, $reason, @@ -172,9 +172,50 @@ class manager $this->cache->destroy('sql', $this->ban_table); } - public function unban($mode, array $items, $reason, $logging = true) + public function unban($mode, array $items) { + if (!isset($this->types[$mode])) + { + throw new type_not_found_exception(); // TODO + } + /** @var \phpbb\ban\type\type_interface $ban_mode */ + $ban_mode = $this->types[$mode]; + $sql_ids = array_map('intval', $items); + $sql = 'SELECT ban_item + FROM ' . $this->ban_table . ' + WHERE ' . $this->db->sql_in_set('ban_id', $sql_ids); // TODO (what if empty?) + $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->ban_table . ' + WHERE ' . $this->db->sql_in_set('ban_id', $sql_ids); + $this->db->sql_query($sql); + + if ($ban_mode->get_unban_log_string() !== false) + { + $unban_items_log = implode(', ', $unbanned_items); + + $this->log->add('admin', $this->user->data['user_id'], $this->user->ip, $ban_mode->get_unban_log_string(), false, [$unban_items_log]); + $this->log->add('mod', $this->user->data['user_id'], $this->user->ip, $ban_mode->get_unban_log_string(), false, [ + 'forum_id' => 0, + 'topic_id' => 0, + $unban_items_log, + ]); + } + + $unban_data = [ + 'items' => $unbanned_items, + ]; + $ban_mode->after_unban($unban_data); + + $this->cache->destroy('sql', $this->ban_table); } public function check(array $user_data = []) @@ -183,5 +224,6 @@ class manager public function tidy() { + // TODO: Delete stale bans } } diff --git a/phpBB/phpbb/ban/type/base.php b/phpBB/phpbb/ban/type/base.php index 23e128bbb6..5989e653b1 100644 --- a/phpBB/phpbb/ban/type/base.php +++ b/phpBB/phpbb/ban/type/base.php @@ -37,12 +37,15 @@ abstract class base implements type_interface /** * {@inheritDoc} */ - public function after_ban($data) + public function after_ban(array $data) { return true; } - public function after_unban() + /** + * {@inheritDoc} + */ + public function after_unban(array $data) { } diff --git a/phpBB/phpbb/ban/type/email.php b/phpBB/phpbb/ban/type/email.php index cf584a87d3..1cc5fedfea 100644 --- a/phpBB/phpbb/ban/type/email.php +++ b/phpBB/phpbb/ban/type/email.php @@ -15,11 +15,16 @@ namespace phpbb\ban\type; class email extends base { - public function get_log_string() + public function get_ban_log_string() { return 'LOG_BAN_EMAIL'; } + public function get_unban_log_string() + { + return 'LOG_UNBAN_EMAIL'; + } + /** * {@inheritDoc} */ diff --git a/phpBB/phpbb/ban/type/type_interface.php b/phpBB/phpbb/ban/type/type_interface.php index 174c5c25bd..0b6b4b4ea9 100644 --- a/phpBB/phpbb/ban/type/type_interface.php +++ b/phpBB/phpbb/ban/type/type_interface.php @@ -19,12 +19,20 @@ namespace phpbb\ban\type; interface type_interface { /** - * Returns the language key that's used for the log entry. + * Returns the language key that's used for the ban log entry. * False, if there is none (and thus no logs are created) * * @return string|bool */ - public function get_log_string(); + public function get_ban_log_string(); + + /** + * Returns the language key that's used for the unban log entry. + * False, if thee is none (and thus no logs are created) + * + * @return string|bool + */ + public function get_unban_log_string(); /** * Returns the type identifier for this ban type @@ -44,7 +52,7 @@ interface type_interface public function get_user_column(); /** - * Gives the possibility to do some clean up after banning + * Gives the possibility to do some clean up after banning. * Returns true if affected users should be logged out and * false otherwise * @@ -54,9 +62,19 @@ interface type_interface * * @return bool */ - public function after_ban($data); + public function after_ban(array $data); - public function after_unban(); // ??? + /** + * Gives the possiblity to do some clean up after unbanning. + * The return value of this method will be ignored and thus + * should be null + * + * @param array $data An array containing information about + * the unbans, e.g. the unbanned items. + * + * @return null + */ + public function after_unban(array $data); /** * In the case that get_user_column() returns null, this method diff --git a/phpBB/phpbb/ban/type/user.php b/phpBB/phpbb/ban/type/user.php index 0fbc5d1a13..85a9064399 100644 --- a/phpBB/phpbb/ban/type/user.php +++ b/phpBB/phpbb/ban/type/user.php @@ -22,17 +22,27 @@ class user extends base protected $log; /** @var string */ - private $log_string = 'LOG_BAN_USER'; + private $ban_log_string = 'LOG_BAN_USER'; + + private $unban_log_string = 'LOG_UNBAN_USER'; /** * {@inheritDoc} */ - public function get_log_string() + public function get_ban_log_string() { // Have to handle logging differently here return false; } + /** + * {@inheritDoc} + */ + public function get_unban_log_string() + { + return false; + } + /** * {@inheritDoc} */ @@ -52,12 +62,12 @@ class user extends base /** * {@inheritDoc} */ - public function after_ban($data) + public function after_ban(array $data) { $usernames_log = implode(', ', $this->banned_users); - $this->log->add('admin', $this->user->data['user_id'], $this->user->ip, $this->log_string, false, [$data['reason'], $usernames_log]); - $this->log->add('mod', $this->user->data['user_id'], $this->user->ip, $this->log_string, false, [ + $this->log->add('admin', $this->user->data['user_id'], $this->user->ip, $this->ban_log_string, false, [$data['reason'], $usernames_log]); + $this->log->add('mod', $this->user->data['user_id'], $this->user->ip, $this->ban_log_string, false, [ 'forum_id' => 0, 'topic_id' => 0, $data['reason'], @@ -66,7 +76,7 @@ class user extends base foreach ($this->banned_users as $user_id => $username) { - $this->log->add('user', $this->user->data['user_id'], $this->user->ip, $this->log_string, false, [ + $this->log->add('user', $this->user->data['user_id'], $this->user->ip, $this->ban_log_string, false, [ 'reportee_id' => $user_id, $data['reason'], $usernames_log, @@ -76,6 +86,50 @@ class user extends base return true; } + /** + * {@inheritDoc} + */ + public function after_unban(array $data) + { + $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); + + $real_user_ids = []; + $usernames = []; + while ($row = $this->db->sql_fetchrow($result)) + { + $real_user_ids[] = $row['user_id']; + $usernames[] = $row['username']; + } + $this->db->sql_freeresult($result); + + if (empty($usernames)) + { + return; + } + + $usernames_log = implode(', ', $usernames); + + $this->log->add('admin', $this->user->data['user_id'], $this->user->ip, $this->unban_log_string, false, [$usernames_log]); + $this->log->add('mod', $this->user->data['user_id'], $this->user->ip, $this->unban_log_string, false, [ + 'forum_id' => 0, + 'topic_id' => 0, + $usernames_log, + ]); + + foreach ($real_user_ids as $user_id) + { + $this->log->add('user', $this->user->data['user_id'], $this->user->ip, $this->unban_log_string, false, [ + 'reportee_id' => $user_id, + $usernames_log, + ]); + } + } + /** * {@inheritDoc} */ From c8b8675dff86e6ee48fe25ad6f6f4683df29ed82 Mon Sep 17 00:00:00 2001 From: Oliver Schramm Date: Sat, 29 Sep 2018 15:23:15 +0200 Subject: [PATCH 04/54] [ticket/9687] Finish ban check and tidy methods PHPBB3-9687 --- .../exception/no_valid_emails_exception.php | 20 +++ .../exception/no_valid_users_exception.php | 20 +++ phpBB/phpbb/ban/manager.php | 128 ++++++++++++++++-- phpBB/phpbb/ban/type/base.php | 5 +- phpBB/phpbb/ban/type/email.php | 10 +- phpBB/phpbb/ban/type/type_interface.php | 22 ++- phpBB/phpbb/ban/type/user.php | 10 +- 7 files changed, 194 insertions(+), 21 deletions(-) create mode 100644 phpBB/phpbb/ban/exception/no_valid_emails_exception.php create mode 100644 phpBB/phpbb/ban/exception/no_valid_users_exception.php 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_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/manager.php b/phpBB/phpbb/ban/manager.php index 5a79f2d836..221dbef99d 100644 --- a/phpBB/phpbb/ban/manager.php +++ b/phpBB/phpbb/ban/manager.php @@ -18,6 +18,9 @@ use phpbb\ban\exception\type_not_found_exception; class manager { + const CACHE_KEY = '_ban_info'; + const CACHE_TTL = 3600; + protected $ban_table; protected $cache; @@ -51,17 +54,18 @@ class manager public function ban($mode, array $items, \DateTimeInterface $start, \DateTimeInterface $end, $reason, $display_reason = '') { - if (!isset($this->types[$mode])) - { - throw new type_not_found_exception(); // TODO - } if ($start > $end && $end->getTimestamp() !== 0) { throw new invalid_length_exception(); // TODO } /** @var \phpbb\ban\type\type_interface $ban_mode */ - $ban_mode = $this->types[$mode]; + $ban_mode = $this->find_type($mode); + if ($ban_mode === false) + { + throw new type_not_found_exception(); // TODO + } + $ban_items = $ban_mode->prepare_for_storage($items); // Prevent duplicate bans @@ -169,17 +173,17 @@ class manager } } - $this->cache->destroy('sql', $this->ban_table); + $this->cache->destroy(self::CACHE_KEY); } public function unban($mode, array $items) { - if (!isset($this->types[$mode])) + /** @var \phpbb\ban\type\type_interface $ban_mode */ + $ban_mode = $this->find_type($mode); + if ($ban_mode === false) { throw new type_not_found_exception(); // TODO } - /** @var \phpbb\ban\type\type_interface $ban_mode */ - $ban_mode = $this->types[$mode]; $sql_ids = array_map('intval', $items); $sql = 'SELECT ban_item @@ -215,15 +219,117 @@ class manager ]; $ban_mode->after_unban($unban_data); - $this->cache->destroy('sql', $this->ban_table); + $this->cache->destroy(self::CACHE_KEY); } public function check(array $user_data = []) { + if (empty($user_data)) + { + $user_data = $this->user->data; + } + + $ban_info = $this->cache->get(self::CACHE_KEY); + if ($ban_info === false) + { + $sql = 'SELECT ban_mode, ban_item, ban_end, ban_reason_display + FROM ' . $this->ban_table . ' + WHERE 1'; + $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, $ban_info, self::CACHE_TTL); + } + + foreach ($ban_info as $mode => $ban_rows) + { + /** @var \phpbb\ban\type\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; + } + } + else + { + $user_column = $ban_mode->get_user_column(); + + foreach ($ban_rows as $ban_row) + { + if ($ban_row['end'] > 0 && $ban_row['end'] < time()) + { + if (stripos($ban_row['item'], '*') === false) + { + if ($ban_row['item'] == $user_data[$user_column]) + { + return $ban_row; + } + } + else + { + $regex = str_replace('\*', '.*?', preg_quote($ban_row['item'], '#')); + if (preg_match($regex, $user_data[$user_column])) + { + return $ban_row; + } + } + } + } + } + } + + return false; } public function tidy() { - // TODO: Delete stale bans + // Delete stale bans + $sql = 'DELETE FROM ' . $this->ban_table . ' + WHERE ban_end > 0 AND ban_end < ' . (int) time(); + $this->db->sql_query($sql); + + /** @var \phpbb\ban\type\type_interface $type */ + foreach ($this->types as $type) + { + $type->tidy(); + } + } + + protected function find_type($mode) + { + /** @var \phpbb\ban\type\type_interface $type */ + foreach ($this->types as $type) + { + if ($type->get_type() === $mode) + { + return $type; + } + } + + return false; } } diff --git a/phpBB/phpbb/ban/type/base.php b/phpBB/phpbb/ban/type/base.php index 5989e653b1..5771b02da1 100644 --- a/phpBB/phpbb/ban/type/base.php +++ b/phpBB/phpbb/ban/type/base.php @@ -52,11 +52,14 @@ abstract class base implements type_interface /** * {@inheritDoc} */ - public function check(array $data) + public function check(array $ban_rows, array $user_data) { return false; } + /** + * {@inheritDoc} + */ public function tidy() { } diff --git a/phpBB/phpbb/ban/type/email.php b/phpBB/phpbb/ban/type/email.php index 1cc5fedfea..b26d4990b6 100644 --- a/phpBB/phpbb/ban/type/email.php +++ b/phpBB/phpbb/ban/type/email.php @@ -13,6 +13,10 @@ namespace phpbb\ban\type; +use phpbb\ban\exception\no_valid_emails_exception; +use phpbb\ban\exception\no_valid_users_exception; +use phpbb\exception\runtime_exception; + class email extends base { public function get_ban_log_string() @@ -48,9 +52,9 @@ class email extends base { if (!$this->get_excluded()) { - // TODO throw exception + throw new runtime_exception(); // TODO } - $regex = get_preg_expression('email'); + $regex = '#^.*?@*|(([a-z0-9\-]+\.)+([a-z]{2,3}))$#i'; $ban_items = []; foreach ($items as $item) @@ -65,7 +69,7 @@ class email extends base if (empty($ban_items)) { - // TODO throw exception - no valid emails defined + throw new no_valid_emails_exception(); // TODO } return $ban_items; diff --git a/phpBB/phpbb/ban/type/type_interface.php b/phpBB/phpbb/ban/type/type_interface.php index 0b6b4b4ea9..143d6a3041 100644 --- a/phpBB/phpbb/ban/type/type_interface.php +++ b/phpBB/phpbb/ban/type/type_interface.php @@ -13,6 +13,8 @@ namespace phpbb\ban\type; +use phpbb\mimetype\null_guesser; + /** * Interface implemented by all ban types */ @@ -82,13 +84,17 @@ interface type_interface * Please note, that this method is basically called on every page, * so the check should perform rather fast. * - * Returns true if the person is banned and false otherwise. + * Returns an array with information about the ban, like the end or + * the reason. False if the user is not banned. * - * @param array $data The user data array + * @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 bool + * @return array|bool */ - public function check(array $data); + public function check(array $ban_rows, array $user_data); /** * Prepares the given ban items before saving them in the database @@ -99,5 +105,11 @@ interface type_interface */ public function prepare_for_storage(array $items); - public function tidy(); // ??? + /** + * Does some cleanup work for the banning mode. + * Is called before banning and unbanning and as cron job. + * + * @return null + */ + public function tidy(); } diff --git a/phpBB/phpbb/ban/type/user.php b/phpBB/phpbb/ban/type/user.php index 85a9064399..fe0e2adbe1 100644 --- a/phpBB/phpbb/ban/type/user.php +++ b/phpBB/phpbb/ban/type/user.php @@ -13,6 +13,9 @@ namespace phpbb\ban\type; +use phpbb\ban\exception\no_valid_users_exception; +use phpbb\exception\runtime_exception; + class user extends base { /** @var array */ @@ -137,7 +140,7 @@ class user extends base { if (!$this->get_excluded()) { - // TODO throw exception + throw new runtime_exception(); // TODO } $sql_usernames = []; @@ -183,6 +186,11 @@ class user extends base } $this->db->sql_freeresult($result); + if (empty($ban_items)) + { + throw new no_valid_users_exception(); // TODO + } + return $ban_items; } } From 9373fa3edbc627c4c7bba16de795e153304ddb59 Mon Sep 17 00:00:00 2001 From: Oliver Schramm Date: Sat, 29 Sep 2018 17:26:54 +0200 Subject: [PATCH 05/54] [ticket/9687] Add more useful methods to the new ban manger PHPBB3-9687 --- .../exception/ban_insert_failed_exception.php | 20 ++ .../no_items_specified_exception.php | 20 ++ phpBB/phpbb/ban/manager.php | 180 ++++++++++++++---- phpBB/phpbb/ban/type/base.php | 8 + phpBB/phpbb/ban/type/type_interface.php | 12 ++ phpBB/phpbb/ban/type/user.php | 5 + 6 files changed, 209 insertions(+), 36 deletions(-) create mode 100644 phpBB/phpbb/ban/exception/ban_insert_failed_exception.php create mode 100644 phpBB/phpbb/ban/exception/no_items_specified_exception.php diff --git a/phpBB/phpbb/ban/exception/ban_insert_failed_exception.php b/phpBB/phpbb/ban/exception/ban_insert_failed_exception.php new file mode 100644 index 0000000000..1c1a2fee7f --- /dev/null +++ b/phpBB/phpbb/ban/exception/ban_insert_failed_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 ban_insert_failed_exception extends runtime_exception +{ +} diff --git a/phpBB/phpbb/ban/exception/no_items_specified_exception.php b/phpBB/phpbb/ban/exception/no_items_specified_exception.php new file mode 100644 index 0000000000..8b68c08ded --- /dev/null +++ b/phpBB/phpbb/ban/exception/no_items_specified_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_items_specified_exception extends runtime_exception +{ +} diff --git a/phpBB/phpbb/ban/manager.php b/phpBB/phpbb/ban/manager.php index 221dbef99d..180d5a2561 100644 --- a/phpBB/phpbb/ban/manager.php +++ b/phpBB/phpbb/ban/manager.php @@ -13,12 +13,15 @@ namespace phpbb\ban; +use phpbb\ban\exception\ban_insert_failed_exception; use phpbb\ban\exception\invalid_length_exception; +use phpbb\ban\exception\no_items_specified_exception; use phpbb\ban\exception\type_not_found_exception; class manager { - const CACHE_KEY = '_ban_info'; + const CACHE_KEY_INFO = '_ban_info'; + const CACHE_KEY_USERS = '_banned_users'; const CACHE_TTL = 3600; protected $ban_table; @@ -65,13 +68,14 @@ class manager { throw new type_not_found_exception(); // TODO } + $this->tidy(); $ban_items = $ban_mode->prepare_for_storage($items); // Prevent duplicate bans $sql = 'DELETE FROM ' . $this->ban_table . " WHERE ban_mode = '" . $this->db->sql_escape($mode) . "' - AND " . $this->db->sql_in_set('ban_item', $ban_items); // TODO (what if empty?) + AND " . $this->db->sql_in_set('ban_item', $ban_items, false, true); $this->db->sql_query($sql); $insert_array = []; @@ -89,14 +93,13 @@ class manager if (empty($insert_array)) { - return; // TODO + throw new no_items_specified_exception(); // TODO } $result = $this->db->sql_multi_insert($this->ban_table, $insert_array); if ($result === false) { - // Something went wrong - // TODO throw exception + throw new ban_insert_failed_exception(); // TODO } if ($ban_mode->get_ban_log_string() !== false) @@ -173,10 +176,11 @@ class manager } } - $this->cache->destroy(self::CACHE_KEY); + $this->cache->destroy(self::CACHE_KEY_INFO); + $this->cache->destroy(self::CACHE_KEY_USERS); } - public function unban($mode, array $items) + public function unban($mode, array $items, $logging = true) { /** @var \phpbb\ban\type\type_interface $ban_mode */ $ban_mode = $this->find_type($mode); @@ -184,6 +188,7 @@ class manager { throw new type_not_found_exception(); // TODO } + $this->tidy(); $sql_ids = array_map('intval', $items); $sql = 'SELECT ban_item @@ -202,7 +207,7 @@ class manager WHERE ' . $this->db->sql_in_set('ban_id', $sql_ids); $this->db->sql_query($sql); - if ($ban_mode->get_unban_log_string() !== false) + if ($logging && $ban_mode->get_unban_log_string() !== false) { $unban_items_log = implode(', ', $unbanned_items); @@ -216,10 +221,12 @@ class manager $unban_data = [ 'items' => $unbanned_items, + 'logging' => $logging, ]; $ban_mode->after_unban($unban_data); - $this->cache->destroy(self::CACHE_KEY); + $this->cache->destroy(self::CACHE_KEY_INFO); + $this->cache->destroy(self::CACHE_KEY_USERS); } public function check(array $user_data = []) @@ -229,33 +236,7 @@ class manager $user_data = $this->user->data; } - $ban_info = $this->cache->get(self::CACHE_KEY); - if ($ban_info === false) - { - $sql = 'SELECT ban_mode, ban_item, ban_end, ban_reason_display - FROM ' . $this->ban_table . ' - WHERE 1'; - $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, $ban_info, self::CACHE_TTL); - } + $ban_info = $this->get_info_cache(); foreach ($ban_info as $mode => $ban_rows) { @@ -305,6 +286,100 @@ class manager return false; } + public function get_bans($mode) + { + /** @var \phpbb\ban\type\type_interface $ban_mode */ + $ban_mode = $this->find_type($mode); + if ($ban_mode === false) + { + throw new type_not_found_exception(); // TODO + } + $this->tidy(); + + $sql = 'SELECT ban_id, ban_item, ban_start, ban_end, ban_reason, ban_reason_display + FROM ' . $this->ban_table . " + WHERE ban_mode = '" . $this->db->sql_escape($mode) . "' + AND (ban_end <= 0 OR ban_end >= " . (int) time() . ')'; + $result = $this->db->sql_query($sql); + $rowset = $this->db->sql_fetchrowset($result); + $this->db->sql_freeresult($result); + + return $rowset; + } + + public function get_banned_users() + { + $banned_users = $this->cache->get(self::CACHE_KEY_USERS); + if ($banned_users === false) + { + $manual_modes = []; + $where_array = []; + + /** @var \phpbb\ban\type\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_array[] = ['AND', + [ + ['b.ban_item', '=', 'u.' . $user_column], + ['b.ban_mode', '=', $ban_mode->get_type()], + ], + ]; + } + + $sql_array = [ + 'SELECT' => 'u.user_id, b.ban_end', + 'FROM' => [ + $this->ban_table => 'b', + $this->users_table => 'u', + ], + 'WHERE' => ['OR', + $where_array, + ], + ]; + $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 \phpbb\ban\type\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 array_filter($banned_users, function ($end) { + return $end <= 0 || $end > time(); + }); + } + public function tidy() { // Delete stale bans @@ -332,4 +407,37 @@ class manager return false; } + + 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 . ' + WHERE 1'; + $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; + } } diff --git a/phpBB/phpbb/ban/type/base.php b/phpBB/phpbb/ban/type/base.php index 5771b02da1..7dc1c396c1 100644 --- a/phpBB/phpbb/ban/type/base.php +++ b/phpBB/phpbb/ban/type/base.php @@ -64,6 +64,14 @@ abstract class base implements type_interface { } + /** + * {@inheritDoc} + */ + public function get_banned_users() + { + return []; + } + /** * Queries users that are excluded from banning (like founders) * from the database and saves them in $this->excluded array. diff --git a/phpBB/phpbb/ban/type/type_interface.php b/phpBB/phpbb/ban/type/type_interface.php index 143d6a3041..4dfc79595f 100644 --- a/phpBB/phpbb/ban/type/type_interface.php +++ b/phpBB/phpbb/ban/type/type_interface.php @@ -96,6 +96,18 @@ interface type_interface */ 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(); + /** * Prepares the given ban items before saving them in the database * diff --git a/phpBB/phpbb/ban/type/user.php b/phpBB/phpbb/ban/type/user.php index fe0e2adbe1..3c650a5ea8 100644 --- a/phpBB/phpbb/ban/type/user.php +++ b/phpBB/phpbb/ban/type/user.php @@ -94,6 +94,11 @@ class user extends base */ public function after_unban(array $data) { + if (empty($data['logging'])) + { + return; + } + $user_ids = array_map('intval', $data['items']); $sql = 'SELECT user_id, username From 7267df431fc31d7d55175fe73f4e23dd4d3632c7 Mon Sep 17 00:00:00 2001 From: Oliver Schramm Date: Sat, 29 Sep 2018 19:25:26 +0200 Subject: [PATCH 06/54] [ticket/9687] Finish documentation and integrate the new code PHPBB3-9687 --- phpBB/includes/acp/acp_ban.php | 5 +- phpBB/includes/acp/acp_email.php | 48 +- phpBB/includes/constants.php | 2 +- phpBB/includes/functions_admin.php | 87 +-- phpBB/includes/functions_display.php | 6 +- phpBB/includes/functions_user.php | 550 ++---------------- phpBB/index.php | 20 +- phpBB/install/convertors/convert_phpbb20.php | 30 +- .../no_items_specified_exception.php | 20 - phpBB/phpbb/ban/manager.php | 131 ++++- phpBB/phpbb/ban/type/base.php | 7 + phpBB/phpbb/ban/type/email.php | 6 + phpBB/phpbb/ban/type/user.php | 16 + phpBB/phpbb/session.php | 118 +--- 14 files changed, 272 insertions(+), 774 deletions(-) delete mode 100644 phpBB/phpbb/ban/exception/no_items_specified_exception.php diff --git a/phpBB/includes/acp/acp_ban.php b/phpBB/includes/acp/acp_ban.php index 22ae9d4e7b..9335e40ff9 100644 --- a/phpBB/includes/acp/acp_ban.php +++ b/phpBB/includes/acp/acp_ban.php @@ -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); 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..04eb7d8df6 100644 --- a/phpBB/includes/functions_admin.php +++ b/phpBB/includes/functions_admin.php @@ -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[] = ''; - $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 = ''; - - 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 .= ''; - $options .= implode('', $excluded_options); - $options .= ''; - } - if ($banned_options) { $options .= ''; @@ -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, )); } 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..b910078f7b 100644 --- a/phpBB/includes/functions_user.php +++ b/phpBB/includes/functions_user.php @@ -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; } /** diff --git a/phpBB/index.php b/phpBB/index.php index 6275c92458..0b76a7343c 100644 --- a/phpBB/index.php +++ b/phpBB/index.php @@ -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) : ''; diff --git a/phpBB/install/convertors/convert_phpbb20.php b/phpBB/install/convertors/convert_phpbb20.php index 62294bf449..af114ee398 100644 --- a/phpBB/install/convertors/convert_phpbb20.php +++ b/phpBB/install/convertors/convert_phpbb20.php @@ -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( diff --git a/phpBB/phpbb/ban/exception/no_items_specified_exception.php b/phpBB/phpbb/ban/exception/no_items_specified_exception.php deleted file mode 100644 index 8b68c08ded..0000000000 --- a/phpBB/phpbb/ban/exception/no_items_specified_exception.php +++ /dev/null @@ -1,20 +0,0 @@ - - * @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 -{ -} diff --git a/phpBB/phpbb/ban/manager.php b/phpBB/phpbb/ban/manager.php index 180d5a2561..814899e9fb 100644 --- a/phpBB/phpbb/ban/manager.php +++ b/phpBB/phpbb/ban/manager.php @@ -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); diff --git a/phpBB/phpbb/ban/type/base.php b/phpBB/phpbb/ban/type/base.php index 7dc1c396c1..9fbe2c392b 100644 --- a/phpBB/phpbb/ban/type/base.php +++ b/phpBB/phpbb/ban/type/base.php @@ -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; diff --git a/phpBB/phpbb/ban/type/email.php b/phpBB/phpbb/ban/type/email.php index b26d4990b6..813000d014 100644 --- a/phpBB/phpbb/ban/type/email.php +++ b/phpBB/phpbb/ban/type/email.php @@ -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'; diff --git a/phpBB/phpbb/ban/type/user.php b/phpBB/phpbb/ban/type/user.php index 3c650a5ea8..1582c954b8 100644 --- a/phpBB/phpbb/ban/type/user.php +++ b/phpBB/phpbb/ban/type/user.php @@ -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} */ diff --git a/phpBB/phpbb/session.php b/phpBB/phpbb/session.php index 9d3f85b9be..9fd2db349a 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 $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, '', ''); + $message .= ($ban_row['reason']) ? '

' . sprintf($this->lang['BOARD_BAN_REASON'], $ban_row['reason']) : ''; + $message .= '

' . $this->lang['BAN_TRIGGERED_BY_' . strtoupper($ban_triggered_by)] . ''; + // 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')) { From 728b200cd90563c2128ea0b6ceebe3a340e751ce Mon Sep 17 00:00:00 2001 From: Oliver Schramm Date: Sun, 30 Sep 2018 03:50:49 +0200 Subject: [PATCH 07/54] [ticket/9687] Add service definitions PHPBB3-9687 --- phpBB/config/default/container/services.yml | 1 + .../config/default/container/services_ban.yml | 41 +++++++++++++++++++ phpBB/config/default/container/tables.yml | 2 +- 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 phpBB/config/default/container/services_ban.yml 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..689bb37ab9 --- /dev/null +++ b/phpBB/config/default/container/services_ban.yml @@ -0,0 +1,41 @@ +services: +# ----- Ban management ----- + ban.manager: + class: \phpbb\ban\manager + arguments: + - '@ban.type_collection' + - '@cache' + - '@dbal.conn' + - '@log' + - '@user' + - '%tables.bans%' + - '%tables.users%' + - '%tables.sessions%' + - '%tables.sessions_keys%' + +# ----- 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' + - '@user' + - '%tables.users%' + tags: + - { name: ban.type } + + ban.type.user: + class: \phpbb\ban\type\user + arguments: + - '@dbal.conn' + - '@log' + - '@user' + - '%tables.users' + 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' From 64ab1fc24cc1d563e000f6bab12de16f94887079 Mon Sep 17 00:00:00 2001 From: Oliver Schramm Date: Sun, 30 Sep 2018 04:13:12 +0200 Subject: [PATCH 08/54] [ticket/9687] Fix bugs when banning and add TODO's PHPBB3-9687 --- phpBB/config/default/container/services_ban.yml | 2 +- phpBB/phpbb/ban/manager.php | 3 ++- phpBB/phpbb/ban/type/email.php | 4 ++-- phpBB/phpbb/ban/type/user.php | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/phpBB/config/default/container/services_ban.yml b/phpBB/config/default/container/services_ban.yml index 689bb37ab9..86991b93b6 100644 --- a/phpBB/config/default/container/services_ban.yml +++ b/phpBB/config/default/container/services_ban.yml @@ -36,6 +36,6 @@ services: - '@dbal.conn' - '@log' - '@user' - - '%tables.users' + - '%tables.users%' tags: - { name: ban.type } diff --git a/phpBB/phpbb/ban/manager.php b/phpBB/phpbb/ban/manager.php index 814899e9fb..5f0e565148 100644 --- a/phpBB/phpbb/ban/manager.php +++ b/phpBB/phpbb/ban/manager.php @@ -180,9 +180,10 @@ class manager } } + // TODO: Prevent logging out founders $sql = 'SELECT user_id FROM ' . $this->users_table . ' - WHERE ' . $this->db->sql_in_set('u.' . $user_column, $ban_items_sql) . $ban_or_like; + WHERE ' . $this->db->sql_in_set('u.' . $user_column, $ban_items_sql, false, true) . $ban_or_like; $result = $this->db->sql_query($sql); $user_ids = []; diff --git a/phpBB/phpbb/ban/type/email.php b/phpBB/phpbb/ban/type/email.php index 813000d014..675eca0112 100644 --- a/phpBB/phpbb/ban/type/email.php +++ b/phpBB/phpbb/ban/type/email.php @@ -60,13 +60,13 @@ class email extends base { throw new runtime_exception(); // TODO } - $regex = '#^.*?@*|(([a-z0-9\-]+\.)+([a-z]{2,3}))$#i'; + $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)) + if (strlen($item) > 100 || !preg_match($regex, $item) || in_array($item, $this->excluded)) { continue; } diff --git a/phpBB/phpbb/ban/type/user.php b/phpBB/phpbb/ban/type/user.php index 1582c954b8..299418df17 100644 --- a/phpBB/phpbb/ban/type/user.php +++ b/phpBB/phpbb/ban/type/user.php @@ -166,7 +166,7 @@ class user extends base $sql_usernames = []; $sql_or_like = []; - foreach ($items as $item) + foreach ($items as $item) // TODO: Prevent banning Anonymous { $cleaned_username = utf8_clean_string($item); if (stripos($cleaned_username, '*') === false) From e7015bf1dd563dbe96316411e6acfce8d2cac9a1 Mon Sep 17 00:00:00 2001 From: Oliver Schramm Date: Mon, 1 Oct 2018 23:40:15 +0200 Subject: [PATCH 09/54] [ticket/9687] Fix code style and tests PHPBB3-9687 --- phpBB/includes/functions_user.php | 2 +- phpBB/phpbb/ban/manager.php | 3 +- phpBB/phpbb/ban/type/base.php | 2 +- phpBB/phpbb/ban/type/email.php | 1 - phpBB/phpbb/ban/type/type_interface.php | 2 - .../db/migration/data/v330/ban_table_p1.php | 2 +- .../db/migration/data/v330/ban_table_p2.php | 2 +- tests/dbal/boolean_processor_test.php | 9 ++-- tests/dbal/cross_join_test.php | 4 +- tests/dbal/fixtures/boolean_processor.xml | 6 ++- tests/dbal/fixtures/massmail_crossjoin.xml | 6 ++- tests/functions/fixtures/banned_users.xml | 2 +- tests/functions_user/delete_user_test.php | 2 +- tests/functions_user/fixtures/delete_user.xml | 42 +++++++++++-------- tests/session/check_ban_test.php | 4 +- tests/session/fixtures/sessions_banlist.xml | 34 ++++++++++----- tests/session/fixtures/sessions_empty.xml | 10 +++-- 17 files changed, 78 insertions(+), 55 deletions(-) diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php index b910078f7b..84b3b30e1f 100644 --- a/phpBB/includes/functions_user.php +++ b/phpBB/includes/functions_user.php @@ -749,7 +749,7 @@ function user_delete($mode, $user_ids, $retain_username = true) $db->sql_query($sql); // Delete the user_id from the banlist - $sql = 'DELETE FROM ' . BAN_TABLE . ' + $sql = 'DELETE FROM ' . BANS_TABLE . ' WHERE ban_mode = \'user\' AND ' . $db->sql_in_set('ban_item', $user_ids); $db->sql_query($sql); diff --git a/phpBB/phpbb/ban/manager.php b/phpBB/phpbb/ban/manager.php index 5f0e565148..346387349e 100644 --- a/phpBB/phpbb/ban/manager.php +++ b/phpBB/phpbb/ban/manager.php @@ -15,7 +15,6 @@ namespace phpbb\ban; use phpbb\ban\exception\ban_insert_failed_exception; use phpbb\ban\exception\invalid_length_exception; -use phpbb\ban\exception\no_items_specified_exception; use phpbb\ban\exception\type_not_found_exception; class manager @@ -189,7 +188,7 @@ class manager $user_ids = []; while ($row = $this->db->sql_fetchrow($result)) { - $user_ids[] = (int)$row['user_id']; + $user_ids[] = (int) $row['user_id']; } $this->db->sql_freeresult($result); } diff --git a/phpBB/phpbb/ban/type/base.php b/phpBB/phpbb/ban/type/base.php index 9fbe2c392b..9a1e70ab77 100644 --- a/phpBB/phpbb/ban/type/base.php +++ b/phpBB/phpbb/ban/type/base.php @@ -95,7 +95,7 @@ abstract class base implements type_interface } $this->excluded = [ - (int)$this->user->data['user_id'] => $this->user->data[$user_column], + (int) $this->user->data['user_id'] => $this->user->data[$user_column], ]; $sql = "SELECT user_id, {$user_column} diff --git a/phpBB/phpbb/ban/type/email.php b/phpBB/phpbb/ban/type/email.php index 675eca0112..1a0e515aaa 100644 --- a/phpBB/phpbb/ban/type/email.php +++ b/phpBB/phpbb/ban/type/email.php @@ -14,7 +14,6 @@ namespace phpbb\ban\type; use phpbb\ban\exception\no_valid_emails_exception; -use phpbb\ban\exception\no_valid_users_exception; use phpbb\exception\runtime_exception; class email extends base diff --git a/phpBB/phpbb/ban/type/type_interface.php b/phpBB/phpbb/ban/type/type_interface.php index 4dfc79595f..cc4e0d0790 100644 --- a/phpBB/phpbb/ban/type/type_interface.php +++ b/phpBB/phpbb/ban/type/type_interface.php @@ -13,8 +13,6 @@ namespace phpbb\ban\type; -use phpbb\mimetype\null_guesser; - /** * Interface implemented by all ban types */ diff --git a/phpBB/phpbb/db/migration/data/v330/ban_table_p1.php b/phpBB/phpbb/db/migration/data/v330/ban_table_p1.php index 2b2e027a49..f53f56a590 100644 --- a/phpBB/phpbb/db/migration/data/v330/ban_table_p1.php +++ b/phpBB/phpbb/db/migration/data/v330/ban_table_p1.php @@ -148,7 +148,7 @@ class ban_table_p1 extends \phpbb\db\migration\migration $processed_rows++; $bans[] = [ - 'ban_userid' => ($row['ban_mode'] === 'user') ? (int)$row['ban_item'] : 0, + 'ban_userid' => ($row['ban_mode'] === 'user') ? (int) $row['ban_item'] : 0, 'ban_ip' => ($row['ban_mode'] === 'ip') ? $row['ban_item'] : '', 'ban_email' => ($row['ban_mode'] === 'email') ? $row['ban_item'] : '', 'ban_start' => $row['ban_start'], diff --git a/phpBB/phpbb/db/migration/data/v330/ban_table_p2.php b/phpBB/phpbb/db/migration/data/v330/ban_table_p2.php index de617a05f2..6e1ce894d0 100644 --- a/phpBB/phpbb/db/migration/data/v330/ban_table_p2.php +++ b/phpBB/phpbb/db/migration/data/v330/ban_table_p2.php @@ -35,7 +35,7 @@ class ban_table_p2 extends \phpbb\db\migration\migration 'add_tables' => array( $this->table_prefix . 'banlist' => array( 'COLUMNS' => array( - 'ban_id' => array('ULINT', NULL, 'auto_increment'), + 'ban_id' => array('ULINT', null, 'auto_increment'), 'ban_userid' => array('ULINT', 0), 'ban_ip' => array('VCHAR:40', ''), 'ban_email' => array('VCHAR_UNI:100', ''), 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..4be21c3201 100644 --- a/tests/functions/fixtures/banned_users.xml +++ b/tests/functions/fixtures/banned_users.xml @@ -1,6 +1,6 @@ - +
ban_useridban_excludeban_end 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..1727b8a783 100644 --- a/tests/functions_user/fixtures/delete_user.xml +++ b/tests/functions_user/fixtures/delete_user.xml @@ -36,31 +36,39 @@
- +
ban_id - ban_userid - ban_email + ban_mode + ban_item + ban_start + ban_endban_reason - ban_give_reason + ban_reason_display 1 + user 2 - - - - - - 2 - 3 - - - - - - 3 + 0 0 + + + 2 + user + 3 + 0 + 0 + + + + + 3 + user + 0 + 0 + 0 +
diff --git a/tests/session/check_ban_test.php b/tests/session/check_ban_test.php index 7b0aac060c..100c039639 100644 --- a/tests/session/check_ban_test.php +++ b/tests/session/check_ban_test.php @@ -33,8 +33,8 @@ 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), + array('IP Banned, should not be banned', + false, '127.1.1.1', false, false, /* should be banned? -> */ false), ); } 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_itemban_startban_end - ban_excludeban_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_endban_reason - ban_give_reason + ban_reason_display
From 40b1d1e6fff1fedc960f8ad160d9928c9ccf26d8 Mon Sep 17 00:00:00 2001 From: Oliver Schramm Date: Fri, 5 Oct 2018 21:32:44 +0200 Subject: [PATCH 10/54] [ticket/9687] Remove dependency on log and user services PHPBB3-9687 --- .../config/default/container/services_ban.yml | 11 +- phpBB/includes/functions_user.php | 2 + phpBB/phpbb/ban/manager.php | 119 +++-------------- phpBB/phpbb/ban/type/base.php | 120 ++++++++++++++++-- phpBB/phpbb/ban/type/email.php | 28 ++-- phpBB/phpbb/ban/type/type_interface.php | 38 +++--- phpBB/phpbb/ban/type/user.php | 96 +------------- 7 files changed, 169 insertions(+), 245 deletions(-) diff --git a/phpBB/config/default/container/services_ban.yml b/phpBB/config/default/container/services_ban.yml index 86991b93b6..141374d890 100644 --- a/phpBB/config/default/container/services_ban.yml +++ b/phpBB/config/default/container/services_ban.yml @@ -6,12 +6,8 @@ services: - '@ban.type_collection' - '@cache' - '@dbal.conn' - - '@log' - - '@user' - '%tables.bans%' - '%tables.users%' - - '%tables.sessions%' - - '%tables.sessions_keys%' # ----- Ban types ----- ban.type_collection: @@ -25,8 +21,9 @@ services: class: \phpbb\ban\type\email arguments: - '@dbal.conn' - - '@user' - '%tables.users%' + - '%tables.sessions%' + - '%tables.sessions_keys%' tags: - { name: ban.type } @@ -34,8 +31,8 @@ services: class: \phpbb\ban\type\user arguments: - '@dbal.conn' - - '@log' - - '@user' - '%tables.users%' + - '%tables.sessions%' + - '%tables.sessions_keys%' tags: - { name: ban.type } diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php index 84b3b30e1f..b3bdcf1480 100644 --- a/phpBB/includes/functions_user.php +++ b/phpBB/includes/functions_user.php @@ -971,6 +971,8 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas $end->setTimestamp($ban_end); return $ban_manager->ban($mode, $items, $start, $end, $ban_reason, $ban_give_reason); + + // TODO: logging } /** diff --git a/phpBB/phpbb/ban/manager.php b/phpBB/phpbb/ban/manager.php index 346387349e..8c77c67eab 100644 --- a/phpBB/phpbb/ban/manager.php +++ b/phpBB/phpbb/ban/manager.php @@ -32,15 +32,6 @@ class manager /** @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; @@ -57,23 +48,15 @@ class manager * @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 = '') + public function __construct($types, \phpbb\cache\service $cache, \phpbb\db\driver\driver_interface $db, $bans_table, $users_table = '') { $this->bans_table = $bans_table; $this->cache = $cache; $this->db = $db; - $this->log = $log; - $this->sessions_keys_table = $sessions_keys_table; - $this->sessions_table = $sessions_table; $this->types = $types; - $this->user = $user; $this->users_table = $users_table; } @@ -103,6 +86,10 @@ class manager { throw new type_not_found_exception(); // TODO } + if (!empty($this->user)) + { + $ban_mode->set_user($this->user); + } $this->tidy(); $ban_items = $ban_mode->prepare_for_storage($items); @@ -137,19 +124,6 @@ class manager throw new ban_insert_failed_exception(); // TODO } - if ($ban_mode->get_ban_log_string() !== false) - { - $ban_items_log = implode(', ', $ban_items); - - $this->log->add('admin', $this->user->data['user_id'], $this->user->ip, $ban_mode->get_ban_log_string(), false, [$reason, $ban_items_log]); - $this->log->add('mod', $this->user->data['user_id'], $this->user->ip, $ban_mode->get_ban_log_string(), false, [ - 'forum_id' => 0, - 'topic_id' => 0, - $reason, - $ban_items_log, - ]); - } - $ban_data = [ 'items' => $ban_items, 'start' => $start, @@ -160,56 +134,7 @@ class manager if ($ban_mode->after_ban($ban_data)) { - $user_column = $ban_mode->get_user_column(); - if (!empty($user_column) && !empty($this->users_table)) - { - if ($user_column !== 'user_id') - { - $ban_items_sql = []; - $ban_or_like = ''; - foreach ($ban_items as $ban_item) - { - if (stripos($ban_item, '*') === false) - { - $ban_items_sql[] = $ban_item; - } - else - { - $ban_or_like .= ' OR ' . $user_column . ' ' . $this->db->sql_like_expression(str_replace('*', $this->db->get_any_char(), $ban_item)); - } - } - - // TODO: Prevent logging out founders - $sql = 'SELECT user_id - FROM ' . $this->users_table . ' - WHERE ' . $this->db->sql_in_set('u.' . $user_column, $ban_items_sql, false, true) . $ban_or_like; - $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 = $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); - } - } + // TODO } $this->cache->destroy(self::CACHE_KEY_INFO); @@ -223,9 +148,8 @@ class manager * * @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) + public function unban($mode, array $items) { /** @var \phpbb\ban\type\type_interface $ban_mode */ $ban_mode = $this->find_type($mode); @@ -252,23 +176,10 @@ class manager WHERE ' . $this->db->sql_in_set('ban_id', $sql_ids); $this->db->sql_query($sql); - if ($logging && $ban_mode->get_unban_log_string() !== false) - { - $unban_items_log = implode(', ', $unbanned_items); - - $this->log->add('admin', $this->user->data['user_id'], $this->user->ip, $ban_mode->get_unban_log_string(), false, [$unban_items_log]); - $this->log->add('mod', $this->user->data['user_id'], $this->user->ip, $ban_mode->get_unban_log_string(), false, [ - 'forum_id' => 0, - 'topic_id' => 0, - $unban_items_log, - ]); - } - $unban_data = [ 'items' => $unbanned_items, - 'logging' => $logging, ]; - $ban_mode->after_unban($unban_data); + $unbanned_users = $ban_mode->after_unban($unban_data); $this->cache->destroy(self::CACHE_KEY_INFO); $this->cache->destroy(self::CACHE_KEY_USERS); @@ -347,7 +258,7 @@ class manager /** * 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 + * @param string $mode The ban type for which the entries should be retrieved * * @return array|bool */ @@ -416,7 +327,7 @@ class manager $where_array, ], ['u.user_type', '<>', USER_FOUNDER], - ] + ], ], ]; $sql = $this->db->sql_build_query('SELECT', $sql_array); @@ -457,6 +368,16 @@ class manager }); } + /** + * Sets the current user to exclude from banning + * + * @param \phpbb\user $user An user object + */ + public function set_user(\phpbb\user $user) + { + $this->user = $user; + } + /** * Cleans up the database of e.g. stale bans */ diff --git a/phpBB/phpbb/ban/type/base.php b/phpBB/phpbb/ban/type/base.php index 9a1e70ab77..c269bb640e 100644 --- a/phpBB/phpbb/ban/type/base.php +++ b/phpBB/phpbb/ban/type/base.php @@ -21,6 +21,12 @@ abstract class base implements type_interface /** @var array */ protected $excluded; + /** @var string */ + protected $sessions_keys_table; + + /** @var string */ + protected $sessions_table; + /** @var \phpbb\user */ protected $user; @@ -30,15 +36,26 @@ abstract class base implements type_interface /** * 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 + * @param \phpbb\db\driver\driver_interface $db A phpBB DBAL object + * @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(\phpbb\db\driver\driver_interface $db, \phpbb\user $user, $users_table) + public function __construct(\phpbb\db\driver\driver_interface $db, $users_table, $sessions_table, $sessions_keys_table) { $this->db = $db; - $this->user = $user; $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) + { + // TODO: Implement new logging + $this->user = $user; } /** @@ -46,7 +63,7 @@ abstract class base implements type_interface */ public function after_ban(array $data) { - return true; + return $data['items']; } /** @@ -54,6 +71,7 @@ abstract class base implements type_interface */ public function after_unban(array $data) { + return $data['items']; } /** @@ -94,9 +112,12 @@ abstract class base implements type_interface return false; } - $this->excluded = [ - (int) $this->user->data['user_id'] => $this->user->data[$user_column], - ]; + $this->excluded = []; + + if (!empty($this->user)) + { + $this->excluded[(int) $this->user->data['user_id']] = $this->user->data[$user_column]; + } $sql = "SELECT user_id, {$user_column} FROM {$this->users_table} @@ -111,4 +132,85 @@ abstract class base implements type_interface 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 + */ + protected function logout_affected_users(array $ban_items) + { + $user_column = $this->get_user_column(); + + if (empty($user_column)) + { + // TODO throw ex (it's a developer exception) + } + + 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 index 1a0e515aaa..ec3e56315f 100644 --- a/phpBB/phpbb/ban/type/email.php +++ b/phpBB/phpbb/ban/type/email.php @@ -18,22 +18,6 @@ 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'; - } - /** * {@inheritDoc} */ @@ -50,6 +34,16 @@ class email extends base return 'user_email'; } + /** + * {@inheritDoc} + */ + public function after_ban(array $data) + { + $this->logout_affected_users($data['items']); + + return parent::after_ban($data); + } + /** * {@inheritDoc} */ @@ -59,7 +53,7 @@ class email extends base { throw new runtime_exception(); // TODO } - $regex = '#^.*?@.*|(([a-z0-9\-]+\.)+([a-z]{2,3}))$#i'; + $regex = '#^.*?@.*|(([a-z0-9\-]+\.)+([a-z]{2,3}))$#i'; // TODO $ban_items = []; foreach ($items as $item) diff --git a/phpBB/phpbb/ban/type/type_interface.php b/phpBB/phpbb/ban/type/type_interface.php index cc4e0d0790..d0678bc897 100644 --- a/phpBB/phpbb/ban/type/type_interface.php +++ b/phpBB/phpbb/ban/type/type_interface.php @@ -18,22 +18,6 @@ namespace phpbb\ban\type; */ interface type_interface { - /** - * Returns the language key that's used for the ban log entry. - * False, if there is none (and thus no logs are created) - * - * @return string|bool - */ - public function get_ban_log_string(); - - /** - * Returns the language key that's used for the unban log entry. - * False, if thee is none (and thus no logs are created) - * - * @return string|bool - */ - public function get_unban_log_string(); - /** * Returns the type identifier for this ban type * @@ -51,28 +35,38 @@ interface type_interface */ public function get_user_column(); + /** + * Sets a user object to the ban type to have it excluded + * from banning. + * + * @param \phpbb\user $user An user object + * + * @return null + */ + public function set_user(\phpbb\user $user); + /** * Gives the possibility to do some clean up after banning. - * Returns true if affected users should be logged out and - * false otherwise + * 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 bool + * @return mixed */ public function after_ban(array $data); /** * Gives the possiblity to do some clean up after unbanning. - * The return value of this method will be ignored and thus - * should be null + * 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 null + * @return mixed */ public function after_unban(array $data); diff --git a/phpBB/phpbb/ban/type/user.php b/phpBB/phpbb/ban/type/user.php index 299418df17..7bc2bfefaa 100644 --- a/phpBB/phpbb/ban/type/user.php +++ b/phpBB/phpbb/ban/type/user.php @@ -21,47 +21,6 @@ class user extends base /** @var array */ private $banned_users; - /** @var \phpbb\log\log_interface */ - protected $log; - - /** @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} - */ - public function get_ban_log_string() - { - // Have to handle logging differently here - return false; - } - - /** - * {@inheritDoc} - */ - public function get_unban_log_string() - { - return false; - } - /** * {@inheritDoc} */ @@ -83,26 +42,8 @@ class user extends base */ public function after_ban(array $data) { - $usernames_log = implode(', ', $this->banned_users); - - $this->log->add('admin', $this->user->data['user_id'], $this->user->ip, $this->ban_log_string, false, [$data['reason'], $usernames_log]); - $this->log->add('mod', $this->user->data['user_id'], $this->user->ip, $this->ban_log_string, false, [ - 'forum_id' => 0, - 'topic_id' => 0, - $data['reason'], - $usernames_log, - ]); - - foreach ($this->banned_users as $user_id => $username) - { - $this->log->add('user', $this->user->data['user_id'], $this->user->ip, $this->ban_log_string, false, [ - 'reportee_id' => $user_id, - $data['reason'], - $usernames_log, - ]); - } - - return true; + $this->logout_affected_users($data['items']); + return $this->banned_users; } /** @@ -110,11 +51,6 @@ class user extends base */ public function after_unban(array $data) { - if (empty($data['logging'])) - { - return; - } - $user_ids = array_map('intval', $data['items']); $sql = 'SELECT user_id, username @@ -122,36 +58,14 @@ class user extends base WHERE ' . $this->db->sql_in_set('user_id', $user_ids); $result = $this->db->sql_query($sql); - $real_user_ids = []; - $usernames = []; + $unbanned_users = []; while ($row = $this->db->sql_fetchrow($result)) { - $real_user_ids[] = $row['user_id']; - $usernames[] = $row['username']; + $unbanned_users[(int) $row['user_id']] = $row['username']; } $this->db->sql_freeresult($result); - if (empty($usernames)) - { - return; - } - - $usernames_log = implode(', ', $usernames); - - $this->log->add('admin', $this->user->data['user_id'], $this->user->ip, $this->unban_log_string, false, [$usernames_log]); - $this->log->add('mod', $this->user->data['user_id'], $this->user->ip, $this->unban_log_string, false, [ - 'forum_id' => 0, - 'topic_id' => 0, - $usernames_log, - ]); - - foreach ($real_user_ids as $user_id) - { - $this->log->add('user', $this->user->data['user_id'], $this->user->ip, $this->unban_log_string, false, [ - 'reportee_id' => $user_id, - $usernames_log, - ]); - } + return $unbanned_users; } /** From 3563f20991d8d16bb748af080af5e0b11c14e040 Mon Sep 17 00:00:00 2001 From: Oliver Schramm Date: Thu, 8 Nov 2018 20:45:17 +0100 Subject: [PATCH 11/54] [ticket/9687] Fix ban session tests for real PHPBB3-9687 --- tests/session/check_ban_test.php | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/tests/session/check_ban_test.php b/tests/session/check_ban_test.php index 100c039639..95ad89cacd 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 not be banned', - false, '127.1.1.1', false, false, /* should be banned? -> */ false), ); } @@ -53,7 +51,7 @@ 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; $phpbb_filesystem = new \phpbb\filesystem\filesystem(); @@ -73,6 +71,18 @@ 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_users', 'phpbb_sessions', 'phpbb_sessions_keys'); + $ban_type_user = new \phpbb\ban\type\user($this->db, '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); + $collection = new \phpbb\di\service_collection($phpbb_container); + $collection->add('ban.type.email'); + $collection->add('ban.type.user'); + + $ban_manager = new \phpbb\ban\manager($collection, $cache, $this->db, 'phpbb_bans', 'phpbb_users'); + $phpbb_container->set('ban.manager', $ban_manager); } protected function tearDown(): void From 9048aed1635db2c5f1d3f16ce44aa5becb894210 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Tue, 4 Jul 2023 14:48:21 +0200 Subject: [PATCH 12/54] [ticket/9687] Use new array entries for bans PHPBB3-9687 --- phpBB/includes/functions_user.php | 2 +- phpBB/phpbb/session.php | 2 +- phpBB/phpbb/user.php | 6 ++--- tests/functions/fixtures/validate_email.xml | 25 ++++++++++++--------- 4 files changed, 19 insertions(+), 16 deletions(-) diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php index b3bdcf1480..d11f7cbfeb 100644 --- a/phpBB/includes/functions_user.php +++ b/phpBB/includes/functions_user.php @@ -1493,7 +1493,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']) diff --git a/phpBB/phpbb/session.php b/phpBB/phpbb/session.php index 9fd2db349a..813a156726 100644 --- a/phpBB/phpbb/session.php +++ b/phpBB/phpbb/session.php @@ -1204,7 +1204,7 @@ class session } // Determine which message to output - $till_date = ($ban_row['end'] > 0) ? $this->format_date($ban_row['end']) : ''; + $till_date = ($ban_row && $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); 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/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_startban_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
From 9b77dd0283cfcacaf7689ba17641041dff57ee6d Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Tue, 4 Jul 2023 14:48:42 +0200 Subject: [PATCH 13/54] [ticket/9687] Fix birthday list query PHPBB3-9687 --- phpBB/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/index.php b/phpBB/index.php index 0b76a7343c..9f240d4f27 100644 --- a/phpBB/index.php +++ b/phpBB/index.php @@ -112,7 +112,7 @@ if ($show_birthdays) 'FROM' => array( USERS_TABLE => 'u', ), - 'WHERE' => '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)", ); From 7739eb2cfe914d7661ff2d9afcb0b4ab8c1ce931 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Tue, 4 Jul 2023 14:49:10 +0200 Subject: [PATCH 14/54] [ticket/9687] Fix incorrect check for ban end and invalid query PHPBB3-9687 --- phpBB/phpbb/ban/manager.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/phpbb/ban/manager.php b/phpBB/phpbb/ban/manager.php index 8c77c67eab..d4c8383a1f 100644 --- a/phpBB/phpbb/ban/manager.php +++ b/phpBB/phpbb/ban/manager.php @@ -230,7 +230,7 @@ class manager foreach ($ban_rows as $ban_row) { - if ($ban_row['end'] > 0 && $ban_row['end'] < time()) + if (!$ban_row['end'] || $ban_row['end'] > time()) { if (stripos($ban_row['item'], '*') === false) { @@ -310,7 +310,7 @@ class manager $where_array[] = ['AND', [ ['b.ban_item', '=', 'u.' . $user_column], - ['b.ban_mode', '=', $ban_mode->get_type()], + ['b.ban_mode', '=', "'{$ban_mode->get_type()}'"], ], ]; } From 8bdda472bf92f864fcee9606a1afd45d4d8e186f Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Tue, 4 Jul 2023 14:49:31 +0200 Subject: [PATCH 15/54] [ticket/9687] Fix tests PHPBB3-9687 --- tests/functions/validate_user_email_test.php | 27 +++++++++++-- tests/session/testable_factory.php | 38 +++++++++++++++---- .../phpbb_session_test_case.php | 2 +- 3 files changed, 56 insertions(+), 11 deletions(-) diff --git a/tests/functions/validate_user_email_test.php b/tests/functions/validate_user_email_test.php index fb70c3014a..08fbe93b4b 100644 --- a/tests/functions/validate_user_email_test.php +++ b/tests/functions/validate_user_email_test.php @@ -28,18 +28,39 @@ 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_users', 'phpbb_sessions', 'phpbb_sessions_keys'); + $ban_type_user = new \phpbb\ban\type\user($this->db, '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); + $collection = new \phpbb\di\service_collection($phpbb_container); + $collection->add('ban.type.email'); + $collection->add('ban.type.user'); + + $ban_manager = new \phpbb\ban\manager($collection, $cache, $this->db, 'phpbb_bans', 'phpbb_users'); + $phpbb_container->set('ban.manager', $ban_manager); } /** diff --git a/tests/session/testable_factory.php b/tests/session/testable_factory.php index bd25fa02f0..c85053770a 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 $phpbb_root_path, $phpEx; $request = $this->request = new phpbb_mock_request( array(), @@ -103,6 +105,28 @@ class phpbb_session_testable_factory $provider_collection ); + $phpbb_dispatcher = new phpbb_mock_event_dispatcher(); + + $cache_service = new \phpbb\cache\service( + $cache, + $config, + $db, + $phpbb_dispatcher, + $phpbb_root_path, + $phpEx + ); + + $ban_type_email = new \phpbb\ban\type\email($db, 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys'); + $ban_type_user = new \phpbb\ban\type\user($db, '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); + $collection = new \phpbb\di\service_collection($phpbb_container); + $collection->add('ban.type.email'); + $collection->add('ban.type.user'); + + $ban_manager = new \phpbb\ban\manager($collection, $cache_service, $db, '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() ); From d4a4dd453a1b5bb0b43438d2a45fc0db0f093d0c Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Tue, 4 Jul 2023 14:50:12 +0200 Subject: [PATCH 16/54] [ticket/9687] Move migrations to v400 PHPBB3-9687 --- phpBB/phpbb/db/migration/data/{v330 => v400}/ban_table_p1.php | 0 phpBB/phpbb/db/migration/data/{v330 => v400}/ban_table_p2.php | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename phpBB/phpbb/db/migration/data/{v330 => v400}/ban_table_p1.php (100%) rename phpBB/phpbb/db/migration/data/{v330 => v400}/ban_table_p2.php (100%) diff --git a/phpBB/phpbb/db/migration/data/v330/ban_table_p1.php b/phpBB/phpbb/db/migration/data/v400/ban_table_p1.php similarity index 100% rename from phpBB/phpbb/db/migration/data/v330/ban_table_p1.php rename to phpBB/phpbb/db/migration/data/v400/ban_table_p1.php diff --git a/phpBB/phpbb/db/migration/data/v330/ban_table_p2.php b/phpBB/phpbb/db/migration/data/v400/ban_table_p2.php similarity index 100% rename from phpBB/phpbb/db/migration/data/v330/ban_table_p2.php rename to phpBB/phpbb/db/migration/data/v400/ban_table_p2.php From d99968a80096582f0175d14d3b8073a830e34a0a Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Tue, 4 Jul 2023 14:55:07 +0200 Subject: [PATCH 17/54] [ticket/9687] Update ban migrations and clean up code PHPBB3-9687 --- .../db/migration/data/v400/ban_table_p1.php | 78 ++++++++++--------- .../db/migration/data/v400/ban_table_p2.php | 64 +++++++-------- 2 files changed, 72 insertions(+), 70 deletions(-) diff --git a/phpBB/phpbb/db/migration/data/v400/ban_table_p1.php b/phpBB/phpbb/db/migration/data/v400/ban_table_p1.php index f53f56a590..9cd9a7befc 100644 --- a/phpBB/phpbb/db/migration/data/v400/ban_table_p1.php +++ b/phpBB/phpbb/db/migration/data/v400/ban_table_p1.php @@ -11,59 +11,61 @@ * */ -namespace phpbb\db\migration\data\v330; +namespace phpbb\db\migration\data\v400; -class ban_table_p1 extends \phpbb\db\migration\migration +use phpbb\db\migration\migration; + +class ban_table_p1 extends migration { - static public function depends_on() + static public function depends_on(): array { - return array('\phpbb\db\migration\data\v320\default_data_type_ids'); + return ['\phpbb\db\migration\data\v320\default_data_type_ids']; } - public function update_schema() + public function update_schema(): array { - return array( - 'add_tables' => array( - $this->table_prefix . 'bans' => array( - 'COLUMNS' => array( - 'ban_id' => array('ULINT', null, 'auto_increment'), - 'ban_mode' => array('VCHAR', ''), - 'ban_item' => array('STEXT_UNI', ''), - 'ban_start' => array('TIMESTAMP', 0), - 'ban_end' => array('TIMESTAMP', 0), - 'ban_reason' => array('VCHAR_UNI', ''), - 'ban_reason_display' => array('VCHAR_UNI', ''), - ), + return [ + 'add_tables' => [ + $this->table_prefix . 'bans' => [ + 'COLUMNS' => [ + 'ban_id' => ['ULINT', null, 'auto_increment'], + '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' => array( - 'ban_end' => array('INDEX', 'ban_end'), - ), - ), - ), - ); + 'KEYS' => [ + 'ban_end' => ['INDEX', 'ban_end'], + ], + ], + ], + ]; } - public function revert_schema() + public function revert_schema(): array { - return array( - 'drop_tables' => array( + return [ + 'drop_tables' => [ $this->table_prefix . 'bans', - ), - ); + ], + ]; } - public function update_data() + public function update_data(): array { - return array( - array('custom', array(array($this, 'old_to_new'))), - ); + return [ + ['custom', [[$this, 'old_to_new']]], + ]; } - public function revert_data() + public function revert_data(): array { - return array( - array('custom', array(array($this, 'new_to_old'))), - ); + return [ + ['custom', [[$this, 'new_to_old']]], + ]; } public function old_to_new($start) @@ -73,7 +75,7 @@ class ban_table_p1 extends \phpbb\db\migration\migration $processed_rows = 0; $sql = 'SELECT * - FROM ' . $this->table_prefix . "banlist"; + FROM ' . $this->table_prefix . 'banlist'; $result = $this->db->sql_query_limit($sql, $limit, $start); $bans = []; @@ -139,7 +141,7 @@ class ban_table_p1 extends \phpbb\db\migration\migration $processed_rows = 0; $sql = 'SELECT * - FROM ' . $this->table_prefix . "bans"; + FROM ' . $this->table_prefix . 'bans'; $result = $this->db->sql_query_limit($sql, $limit, $start); $bans = []; diff --git a/phpBB/phpbb/db/migration/data/v400/ban_table_p2.php b/phpBB/phpbb/db/migration/data/v400/ban_table_p2.php index 6e1ce894d0..7a64284694 100644 --- a/phpBB/phpbb/db/migration/data/v400/ban_table_p2.php +++ b/phpBB/phpbb/db/migration/data/v400/ban_table_p2.php @@ -11,49 +11,49 @@ * */ -namespace phpbb\db\migration\data\v330; +namespace phpbb\db\migration\data\v400; class ban_table_p2 extends \phpbb\db\migration\migration { - static public function depends_on() + static public function depends_on(): array { - return array('\phpbb\db\migration\data\v330\ban_table_p1'); + return ['\phpbb\db\migration\data\v400\ban_table_p1']; } - public function update_schema() + public function update_schema(): array { - return array( - 'drop_tables' => array( + return [ + 'drop_tables' => [ $this->table_prefix . 'banlist', - ), - ); + ], + ]; } - public function revert_schema() + public function revert_schema(): array { - return array( - 'add_tables' => array( - $this->table_prefix . 'banlist' => array( - 'COLUMNS' => array( - 'ban_id' => array('ULINT', null, 'auto_increment'), - 'ban_userid' => array('ULINT', 0), - 'ban_ip' => array('VCHAR:40', ''), - 'ban_email' => array('VCHAR_UNI:100', ''), - 'ban_start' => array('TIMESTAMP', 0), - 'ban_end' => array('TIMESTAMP', 0), - 'ban_exclude' => array('BOOL', 0), - 'ban_reason' => array('VCHAR_UNI', ''), - 'ban_give_reason' => array('VCHAR_UNI', ''), - ), + 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' => array( - 'ban_end' => array('INDEX', 'ban_end'), - 'ban_user' => array('INDEX', array('ban_userid', 'ban_exclude')), - 'ban_email' => array('INDEX', array('ban_email', 'ban_exclude')), - 'ban_ip' => array('INDEX', array('ban_ip', 'ban_exclude')), - ), - ), - ), - ); + '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']], + ], + ], + ], + ]; } } From ec4a53169a7b14d2f101aaedb8f5df5507b6aec4 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Tue, 4 Jul 2023 21:21:54 +0200 Subject: [PATCH 18/54] [ticket/9687] Add ip banning support incl. CIDR support PHPBB3-9687 --- .../config/default/container/services_ban.yml | 10 +++ .../ban/exception/no_valid_ips_exception.php | 20 +++++ phpBB/phpbb/ban/type/ip.php | 77 +++++++++++++++++++ 3 files changed, 107 insertions(+) create mode 100644 phpBB/phpbb/ban/exception/no_valid_ips_exception.php create mode 100644 phpBB/phpbb/ban/type/ip.php diff --git a/phpBB/config/default/container/services_ban.yml b/phpBB/config/default/container/services_ban.yml index 141374d890..e9665f745f 100644 --- a/phpBB/config/default/container/services_ban.yml +++ b/phpBB/config/default/container/services_ban.yml @@ -27,6 +27,16 @@ services: tags: - { name: ban.type } + ban.type.ip: + class: \phpbb\ban\type\ip + arguments: + - '@dbal.conn' + - '%tables.users%' + - '%tables.sessions%' + - '%tables.sessions_keys%' + tags: + - { name: ban.type } + ban.type.user: class: \phpbb\ban\type\user arguments: 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/type/ip.php b/phpBB/phpbb/ban/type/ip.php new file mode 100644 index 0000000000..22ebce2ec2 --- /dev/null +++ b/phpBB/phpbb/ban/type/ip.php @@ -0,0 +1,77 @@ + + * @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 +{ + + /** + * @inheritDoc + */ + public function get_type(): string + { + return 'ip'; + } + + /** + * @inheritDoc + */ + public function get_user_column(): ?string + { + return 'user_ip'; + } + + /** + * {@inheritDoc} + */ + public function check(array $ban_rows, array $user_data) + { + return parent::check($ban_rows, $user_data); // TODO: Change the autogenerated stub + } + + /** + * @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; + } + catch (\RuntimeException $exception) + { + // IPv6 not supported, therefore IPv6 address will not be added + } + } + + if (empty($ban_items)) + { + throw new no_valid_ips_exception(); // TODO + } + + return $ban_items; + } +} From 43b35e15604a272998a8cb932729b6f927ab80c0 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Tue, 4 Jul 2023 21:23:02 +0200 Subject: [PATCH 19/54] [ticket/9687] Improve code quality of ban system PHPBB3-9687 --- phpBB/phpbb/ban/manager.php | 59 ++++++++++++++++++++----- phpBB/phpbb/ban/type/base.php | 15 ++++--- phpBB/phpbb/ban/type/email.php | 16 ++----- phpBB/phpbb/ban/type/type_interface.php | 16 +++---- phpBB/phpbb/ban/type/user.php | 6 +-- 5 files changed, 70 insertions(+), 42 deletions(-) diff --git a/phpBB/phpbb/ban/manager.php b/phpBB/phpbb/ban/manager.php index d4c8383a1f..1a2d5184a2 100644 --- a/phpBB/phpbb/ban/manager.php +++ b/phpBB/phpbb/ban/manager.php @@ -16,6 +16,7 @@ namespace phpbb\ban; use phpbb\ban\exception\ban_insert_failed_exception; use phpbb\ban\exception\invalid_length_exception; use phpbb\ban\exception\type_not_found_exception; +use phpbb\ban\type\type_interface; class manager { @@ -64,28 +65,29 @@ class manager * 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 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 + * @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 = '') + public function ban(string $mode, array $items, \DateTimeInterface $start, \DateTimeInterface $end, string $reason, string $display_reason = '') { if ($start > $end && $end->getTimestamp() !== 0) { throw new invalid_length_exception(); // TODO } - /** @var \phpbb\ban\type\type_interface $ban_mode */ + /** @var type_interface $ban_mode */ $ban_mode = $this->find_type($mode); if ($ban_mode === false) { throw new type_not_found_exception(); // TODO } + if (!empty($this->user)) { $ban_mode->set_user($this->user); @@ -151,7 +153,7 @@ class manager */ public function unban($mode, array $items) { - /** @var \phpbb\ban\type\type_interface $ban_mode */ + /** @var type_interface $ban_mode */ $ban_mode = $this->find_type($mode); if ($ban_mode === false) { @@ -205,7 +207,7 @@ class manager foreach ($ban_info as $mode => $ban_rows) { - /** @var \phpbb\ban\type\type_interface $ban_mode */ + /** @var type_interface $ban_mode */ $ban_mode = $this->find_type($mode); if ($ban_mode === false) { @@ -264,7 +266,7 @@ class manager */ public function get_bans($mode) { - /** @var \phpbb\ban\type\type_interface $ban_mode */ + /** @var type_interface $ban_mode */ $ban_mode = $this->find_type($mode); if ($ban_mode === false) { @@ -298,7 +300,7 @@ class manager $manual_modes = []; $where_array = []; - /** @var \phpbb\ban\type\type_interface $ban_mode */ + /** @var type_interface $ban_mode */ foreach ($this->types as $ban_mode) { $user_column = $ban_mode->get_user_column(); @@ -345,7 +347,7 @@ class manager } $this->db->sql_freeresult($result); - /** @var \phpbb\ban\type\type_interface $manual_mode */ + /** @var type_interface $manual_mode */ foreach ($manual_modes as $manual_mode) { $mode_banned_users = $manual_mode->get_banned_users(); @@ -368,6 +370,39 @@ class manager }); } + public function get_ban_end(\phpbb\user $user, \DateTimeInterface $ban_start, $length, $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, $user->timezone)->getTimestamp() + ); + } + else + { + trigger_error('LENGTH_BAN_INVALID', E_USER_WARNING); + } + } + } + + $ban_end = new \DateTime(); + $ban_end->setTimestamp($end_time); + + return $ban_end; + } + /** * Sets the current user to exclude from banning * @@ -388,7 +423,7 @@ class manager WHERE ban_end > 0 AND ban_end < ' . (int) time(); $this->db->sql_query($sql); - /** @var \phpbb\ban\type\type_interface $type */ + /** @var type_interface $type */ foreach ($this->types as $type) { $type->tidy(); @@ -405,7 +440,7 @@ class manager */ protected function find_type($mode) { - /** @var \phpbb\ban\type\type_interface $type */ + /** @var type_interface $type */ foreach ($this->types as $type) { if ($type->get_type() === $mode) diff --git a/phpBB/phpbb/ban/type/base.php b/phpBB/phpbb/ban/type/base.php index c269bb640e..b5d07afd6b 100644 --- a/phpBB/phpbb/ban/type/base.php +++ b/phpBB/phpbb/ban/type/base.php @@ -13,9 +13,11 @@ namespace phpbb\ban\type; +use phpbb\db\driver\driver_interface; + abstract class base implements type_interface { - /** @var \phpbb\db\driver\driver_interface */ + /** @var driver_interface */ protected $db; /** @var array */ @@ -36,12 +38,12 @@ abstract class base implements type_interface /** * Creates a ban type. * - * @param \phpbb\db\driver\driver_interface $db A phpBB DBAL object + * @param driver_interface $db A phpBB DBAL object * @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(\phpbb\db\driver\driver_interface $db, $users_table, $sessions_table, $sessions_keys_table) + public function __construct(driver_interface $db, string $users_table, string $sessions_table, string $sessions_keys_table) { $this->db = $db; $this->users_table = $users_table; @@ -52,7 +54,7 @@ abstract class base implements type_interface /** * {@inheritDoc} */ - public function set_user(\phpbb\user $user) + public function set_user(\phpbb\user $user): void { // TODO: Implement new logging $this->user = $user; @@ -63,6 +65,7 @@ abstract class base implements type_interface */ public function after_ban(array $data) { + $this->logout_affected_users($data['items']); return $data['items']; } @@ -85,14 +88,14 @@ abstract class base implements type_interface /** * {@inheritDoc} */ - public function tidy() + public function tidy(): void { } /** * {@inheritDoc} */ - public function get_banned_users() + public function get_banned_users(): array { return []; } diff --git a/phpBB/phpbb/ban/type/email.php b/phpBB/phpbb/ban/type/email.php index ec3e56315f..a3e1dd4705 100644 --- a/phpBB/phpbb/ban/type/email.php +++ b/phpBB/phpbb/ban/type/email.php @@ -21,7 +21,7 @@ class email extends base /** * {@inheritDoc} */ - public function get_type() + public function get_type(): string { return 'email'; } @@ -29,7 +29,7 @@ class email extends base /** * {@inheritDoc} */ - public function get_user_column() + public function get_user_column(): ?string { return 'user_email'; } @@ -37,17 +37,7 @@ class email extends base /** * {@inheritDoc} */ - public function after_ban(array $data) - { - $this->logout_affected_users($data['items']); - - return parent::after_ban($data); - } - - /** - * {@inheritDoc} - */ - public function prepare_for_storage(array $items) + public function prepare_for_storage(array $items): array { if (!$this->get_excluded()) { diff --git a/phpBB/phpbb/ban/type/type_interface.php b/phpBB/phpbb/ban/type/type_interface.php index d0678bc897..b807b3e018 100644 --- a/phpBB/phpbb/ban/type/type_interface.php +++ b/phpBB/phpbb/ban/type/type_interface.php @@ -23,7 +23,7 @@ interface type_interface * * @return string */ - public function get_type(); + public function get_type(): string; /** * Returns the column in the users table which contains @@ -33,7 +33,7 @@ interface type_interface * * @return string|null */ - public function get_user_column(); + public function get_user_column(): ?string; /** * Sets a user object to the ban type to have it excluded @@ -41,9 +41,9 @@ interface type_interface * * @param \phpbb\user $user An user object * - * @return null + * @return void */ - public function set_user(\phpbb\user $user); + public function set_user(\phpbb\user $user): void; /** * Gives the possibility to do some clean up after banning. @@ -98,7 +98,7 @@ interface type_interface * @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(); + public function get_banned_users(): array; /** * Prepares the given ban items before saving them in the database @@ -107,13 +107,13 @@ interface type_interface * * @return array */ - public function prepare_for_storage(array $items); + 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 null + * @return void */ - public function tidy(); + public function tidy(): void; } diff --git a/phpBB/phpbb/ban/type/user.php b/phpBB/phpbb/ban/type/user.php index 7bc2bfefaa..c6b94a0388 100644 --- a/phpBB/phpbb/ban/type/user.php +++ b/phpBB/phpbb/ban/type/user.php @@ -24,7 +24,7 @@ class user extends base /** * {@inheritDoc} */ - public function get_type() + public function get_type(): string { return 'user'; } @@ -32,7 +32,7 @@ class user extends base /** * {@inheritDoc} */ - public function get_user_column() + public function get_user_column(): string { return 'user_id'; } @@ -71,7 +71,7 @@ class user extends base /** * {@inheritDoc} */ - public function prepare_for_storage(array $items) + public function prepare_for_storage(array $items): array { if (!$this->get_excluded()) { From 026d66dab26d75036fcbec4fb60175393c3295c4 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Tue, 4 Jul 2023 21:23:22 +0200 Subject: [PATCH 20/54] [ticket/9687] Properly support banning and fix display of ban info PHPBB3-9687 --- phpBB/includes/acp/acp_ban.php | 11 +++++++++-- phpBB/includes/functions_admin.php | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/phpBB/includes/acp/acp_ban.php b/phpBB/includes/acp/acp_ban.php index 9335e40ff9..62033f7891 100644 --- a/phpBB/includes/acp/acp_ban.php +++ b/phpBB/includes/acp/acp_ban.php @@ -56,7 +56,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); @@ -94,7 +93,15 @@ 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($user, $ban_start, $ban_length, $ban_length_other); + + $ban = explode("\n", $ban); + $ban_manager->ban($mode, $ban, $ban_start, $ban_end, $ban_reason, $ban_give_reason); + + //user_ban($mode, $ban, $ban_length, $ban_length_other, $ban_exclude, $ban_reason, $ban_give_reason); /** * Use this event to perform actions after the ban has been performed diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php index 04eb7d8df6..8e784ef576 100644 --- a/phpBB/includes/functions_admin.php +++ b/phpBB/includes/functions_admin.php @@ -3163,7 +3163,7 @@ function display_ban_options($mode) $ban_rows = $ban_manager->get_bans($mode); $banned_options = array(); - foreach ($ban_rows as $row) + foreach ($ban_rows as $ban_row) { $banned_options[] = ''; From 8a5a26be87433cd8bf52a92599aa1ef93b3bdcc4 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Tue, 4 Jul 2023 21:35:40 +0200 Subject: [PATCH 21/54] [ticket/9687] Further clean up ban manager and directly pass user PHPBB3-9687 --- .../config/default/container/services_ban.yml | 1 + phpBB/phpbb/ban/manager.php | 28 +++++++++---------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/phpBB/config/default/container/services_ban.yml b/phpBB/config/default/container/services_ban.yml index e9665f745f..dfb93cfd39 100644 --- a/phpBB/config/default/container/services_ban.yml +++ b/phpBB/config/default/container/services_ban.yml @@ -6,6 +6,7 @@ services: - '@ban.type_collection' - '@cache' - '@dbal.conn' + - '@user' - '%tables.bans%' - '%tables.users%' diff --git a/phpBB/phpbb/ban/manager.php b/phpBB/phpbb/ban/manager.php index 1a2d5184a2..4dcb3ca397 100644 --- a/phpBB/phpbb/ban/manager.php +++ b/phpBB/phpbb/ban/manager.php @@ -49,15 +49,17 @@ class manager * @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\user $user User object * @param string $bans_table The bans table * @param string $users_table The users table */ - public function __construct($types, \phpbb\cache\service $cache, \phpbb\db\driver\driver_interface $db, $bans_table, $users_table = '') + public function __construct($types, \phpbb\cache\service $cache, \phpbb\db\driver\driver_interface $db, \phpbb\user $user, $bans_table, $users_table = '') { $this->bans_table = $bans_table; $this->cache = $cache; $this->db = $db; $this->types = $types; + $this->user = $user; $this->users_table = $users_table; } @@ -264,7 +266,7 @@ class manager * * @return array|bool */ - public function get_bans($mode) + public function get_bans(string $mode) { /** @var type_interface $ban_mode */ $ban_mode = $this->find_type($mode); @@ -370,7 +372,15 @@ class manager }); } - public function get_ban_end(\phpbb\user $user, \DateTimeInterface $ban_start, $length, $end_date): \DateTimeInterface + /** + * Get ban end + * + * @param \DateTimeInterface $ban_start + * @param int $length + * @param string $end_date + * @return \DateTimeInterface + */ + public function get_ban_end(\DateTimeInterface $ban_start, int $length, string $end_date): \DateTimeInterface { $current_time = $ban_start->getTimestamp(); $end_time = 0; @@ -387,7 +397,7 @@ class manager { $end_time = max( $current_time, - \DateTime::createFromFormat('Y-m-d', $end_date, $user->timezone)->getTimestamp() + \DateTime::createFromFormat('Y-m-d', $end_date, $this->user->timezone)->getTimestamp() ); } else @@ -403,16 +413,6 @@ class manager return $ban_end; } - /** - * Sets the current user to exclude from banning - * - * @param \phpbb\user $user An user object - */ - public function set_user(\phpbb\user $user) - { - $this->user = $user; - } - /** * Cleans up the database of e.g. stale bans */ From 658e8effd5adf618e540e10186d38a647d146375 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Tue, 4 Jul 2023 21:35:58 +0200 Subject: [PATCH 22/54] [ticket/9687] Clean up ACP module PHPBB3-9687 --- phpBB/includes/acp/acp_ban.php | 49 +++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/phpBB/includes/acp/acp_ban.php b/phpBB/includes/acp/acp_ban.php index 62033f7891..5d459444d0 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,10 +30,10 @@ class acp_ban function main($id, $mode) { - global $user, $template, $request, $phpbb_dispatcher, $phpbb_container; + global $language, $template, $request, $phpbb_dispatcher, $phpbb_container; global $phpbb_root_path, $phpEx; - /** @var \phpbb\ban\manager $ban_manager */ + /** @var manager $ban_manager */ $ban_manager = $phpbb_container->get('ban.manager'); if (!function_exists('user_ban')) @@ -39,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? @@ -96,13 +102,11 @@ class acp_ban $ban_start = new \DateTime(); $ban_start->setTimestamp(time()); - $ban_end = $ban_manager->get_ban_end($user, $ban_start, $ban_length, $ban_length_other); + $ban_end = $ban_manager->get_ban_end($ban_start, $ban_length, $ban_length_other); $ban = explode("\n", $ban); $ban_manager->ban($mode, $ban, $ban_start, $ban_end, $ban_reason, $ban_give_reason); - //user_ban($mode, $ban, $ban_length, $ban_length_other, $ban_exclude, $ban_reason, $ban_give_reason); - /** * Use this event to perform actions after the ban has been performed * @@ -127,43 +131,46 @@ class acp_ban ); 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_ban_exclude_explain = $language->lang(strtoupper($mode) . '_BAN_EXCLUDE_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(); @@ -178,7 +185,7 @@ class acp_ban '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', 'U_ACTION' => $this->u_action, 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=acp_ban&field=ban'), From cf0e747d512d665db210e838840c8d1f90ba340f Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 29 Jul 2023 16:22:40 +0200 Subject: [PATCH 23/54] [ticket/9687] Add tests for ban manager and fix some inconsistencies PHPBB3-9687 --- phpBB/phpbb/ban/manager.php | 34 +- phpBB/phpbb/ban/type/base.php | 10 +- phpBB/phpbb/ban/type/email.php | 6 +- phpBB/phpbb/ban/type/ip.php | 20 +- phpBB/phpbb/ban/type/user.php | 6 +- tests/ban/ban_manager_test.php | 699 +++++++++++++++++++ tests/ban/fixtures/sessions_banlist.xml | 161 +++++ tests/bootstrap.php | 2 + tests/functions/validate_user_email_test.php | 2 +- tests/session/check_ban_test.php | 7 +- tests/session/testable_factory.php | 6 +- 11 files changed, 914 insertions(+), 39 deletions(-) create mode 100644 tests/ban/ban_manager_test.php create mode 100644 tests/ban/fixtures/sessions_banlist.xml diff --git a/phpBB/phpbb/ban/manager.php b/phpBB/phpbb/ban/manager.php index 4dcb3ca397..ab3471a79d 100644 --- a/phpBB/phpbb/ban/manager.php +++ b/phpBB/phpbb/ban/manager.php @@ -76,7 +76,7 @@ class manager * * @return bool */ - public function ban(string $mode, array $items, \DateTimeInterface $start, \DateTimeInterface $end, string $reason, string $display_reason = '') + public function ban(string $mode, array $items, \DateTimeInterface $start, \DateTimeInterface $end, string $reason, string $display_reason = ''): bool { if ($start > $end && $end->getTimestamp() !== 0) { @@ -122,11 +122,7 @@ class manager return false; } - $result = $this->db->sql_multi_insert($this->bans_table, $insert_array); - if ($result === false) - { - throw new ban_insert_failed_exception(); // TODO - } + $this->db->sql_multi_insert($this->bans_table, $insert_array); $ban_data = [ 'items' => $ban_items, @@ -138,7 +134,7 @@ class manager if ($ban_mode->after_ban($ban_data)) { - // TODO + // @todo: Add logging } $this->cache->destroy(self::CACHE_KEY_INFO); @@ -153,7 +149,7 @@ class manager * @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($mode, array $items) + public function unban(string $mode, array $items) { /** @var type_interface $ban_mode */ $ban_mode = $this->find_type($mode); @@ -245,7 +241,7 @@ class manager } else { - $regex = str_replace('\*', '.*?', preg_quote($ban_row['item'], '#')); + $regex = '#^' . str_replace('\*', '.*?', preg_quote($ban_row['item'], '#')) . '$#i'; if (preg_match($regex, $user_data[$user_column])) { return $ban_row + ['mode' => $mode]; @@ -279,7 +275,7 @@ class manager $sql = 'SELECT ban_id, ban_item, ban_start, ban_end, ban_reason, ban_reason_display FROM ' . $this->bans_table . " WHERE ban_mode = '" . $this->db->sql_escape($mode) . "' - AND (ban_end <= 0 OR ban_end >= " . (int) time() . ')'; + AND (ban_end = 0 OR ban_end >= " . time() . ')'; $result = $this->db->sql_query($sql); $rowset = $this->db->sql_fetchrowset($result); $this->db->sql_freeresult($result); @@ -294,7 +290,7 @@ class manager * * @return array */ - public function get_banned_users() + public function get_banned_users(): array { $banned_users = $this->cache->get(self::CACHE_KEY_USERS); if ($banned_users === false) @@ -375,10 +371,10 @@ class manager /** * Get ban end * - * @param \DateTimeInterface $ban_start - * @param int $length - * @param string $end_date - * @return \DateTimeInterface + * @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 { @@ -402,7 +398,7 @@ class manager } else { - trigger_error('LENGTH_BAN_INVALID', E_USER_WARNING); + throw new invalid_length_exception(); } } } @@ -434,11 +430,11 @@ class manager * Finds the ban type for the given mode string. * Returns false if none was found * - * @param string $mode The mode string + * @param string $mode The mode string * * @return bool|type\type_interface */ - protected function find_type($mode) + protected function find_type(string $mode) { /** @var type_interface $type */ foreach ($this->types as $type) @@ -461,7 +457,7 @@ class manager * * @return array */ - protected function get_info_cache() + protected function get_info_cache(): array { $ban_info = $this->cache->get(self::CACHE_KEY_INFO); if ($ban_info === false) diff --git a/phpBB/phpbb/ban/type/base.php b/phpBB/phpbb/ban/type/base.php index b5d07afd6b..f404e1bdeb 100644 --- a/phpBB/phpbb/ban/type/base.php +++ b/phpBB/phpbb/ban/type/base.php @@ -107,7 +107,7 @@ abstract class base implements type_interface * * @return bool */ - protected function get_excluded() + protected function get_excluded(): bool { $user_column = $this->get_user_column(); if (empty($user_column)) @@ -119,7 +119,7 @@ abstract class base implements type_interface if (!empty($this->user)) { - $this->excluded[(int) $this->user->data['user_id']] = $this->user->data[$user_column]; + $this->excluded[$this->user->id()] = $this->user->data[$user_column]; } $sql = "SELECT user_id, {$user_column} @@ -143,15 +143,15 @@ abstract class base implements type_interface * * @param array $ban_items * - * @return array + * @return array Logged out users */ - protected function logout_affected_users(array $ban_items) + protected function logout_affected_users(array $ban_items): array { $user_column = $this->get_user_column(); if (empty($user_column)) { - // TODO throw ex (it's a developer exception) + return []; } if ($user_column !== 'user_id') diff --git a/phpBB/phpbb/ban/type/email.php b/phpBB/phpbb/ban/type/email.php index a3e1dd4705..e4c6350b76 100644 --- a/phpBB/phpbb/ban/type/email.php +++ b/phpBB/phpbb/ban/type/email.php @@ -39,10 +39,8 @@ class email extends base */ public function prepare_for_storage(array $items): array { - if (!$this->get_excluded()) - { - throw new runtime_exception(); // TODO - } + $this->get_excluded(); + $regex = '#^.*?@.*|(([a-z0-9\-]+\.)+([a-z]{2,3}))$#i'; // TODO $ban_items = []; diff --git a/phpBB/phpbb/ban/type/ip.php b/phpBB/phpbb/ban/type/ip.php index 22ebce2ec2..d6466c2407 100644 --- a/phpBB/phpbb/ban/type/ip.php +++ b/phpBB/phpbb/ban/type/ip.php @@ -18,6 +18,7 @@ use Symfony\Component\HttpFoundation\IpUtils; class ip extends base { + private const USER_IP = 'user_ip'; /** * @inheritDoc @@ -32,7 +33,7 @@ class ip extends base */ public function get_user_column(): ?string { - return 'user_ip'; + return null; } /** @@ -40,7 +41,20 @@ class ip extends base */ public function check(array $ban_rows, array $user_data) { - return parent::check($ban_rows, $user_data); // TODO: Change the autogenerated stub + 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; } /** @@ -61,10 +75,12 @@ class ip extends base $ban_items[] = $ip; } + // @codeCoverageIgnoreStart catch (\RuntimeException $exception) { // IPv6 not supported, therefore IPv6 address will not be added } + // @codeCoverageIgnoreEnd } if (empty($ban_items)) diff --git a/phpBB/phpbb/ban/type/user.php b/phpBB/phpbb/ban/type/user.php index c6b94a0388..1b8592e354 100644 --- a/phpBB/phpbb/ban/type/user.php +++ b/phpBB/phpbb/ban/type/user.php @@ -73,10 +73,8 @@ class user extends base */ public function prepare_for_storage(array $items): array { - if (!$this->get_excluded()) - { - throw new runtime_exception(); // TODO - } + // Fill excluded user list + $this->get_excluded(); $sql_usernames = []; $sql_or_like = []; diff --git a/tests/ban/ban_manager_test.php b/tests/ban/ban_manager_test.php new file mode 100644 index 0000000000..13ed2fd201 --- /dev/null +++ b/tests/ban/ban_manager_test.php @@ -0,0 +1,699 @@ +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'; + $config = new \phpbb\config\config([]); + $phpbb_dispatcher = new \phpbb_mock_event_dispatcher(); + + // Change the global cache object for this test because + // the mock cache object does not hit the database as is needed + // for this test. + $cache = new \phpbb\cache\service( + new \phpbb\cache\driver\dummy(), + $config, + $this->db, + $phpbb_dispatcher, + $phpbb_root_path, + $phpEx + ); + + $phpbb_container = new \phpbb_mock_container_builder(); + $ban_type_email = new \phpbb\ban\type\email($this->db, 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys'); + $ban_type_user = new \phpbb\ban\type\user($this->db, 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys'); + $ban_type_ip = new \phpbb\ban\type\ip($this->db, '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'); + + $this->ban_manager = new \phpbb\ban\manager($collection, $cache, $this->db, $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' => '2', + 'ban_item' => '127.0.0.1', + 'ban_start' => '1111', + 'ban_end' => '0', + 'ban_reason' => 'HAHAHA', + 'ban_reason_display' => '1', + ], + [ + 'ban_id' => '3', + 'ban_item' => '127.1.1.1', + 'ban_start' => '1111', + 'ban_end' => '0', + 'ban_reason' => 'HAHAHA', + 'ban_reason_display' => '1', + ], + [ + 'ban_id' => '6', + 'ban_item' => '10.0.0.1/28', + 'ban_start' => '1111', + 'ban_end' => '0', + 'ban_reason' => 'HAHAHA', + 'ban_reason_display' => '1', + ], + [ + 'ban_id' => '7', + 'ban_item' => '2001:4860:4860::8888/12', + 'ban_start' => '1111', + 'ban_end' => '0', + 'ban_reason' => 'HAHAHA', + 'ban_reason_display' => '1', + ], + ], + ], + [ + 'email', + [ + [ + 'ban_id' => '5', + 'ban_item' => 'bar@example.org', + 'ban_start' => '1111', + 'ban_end' => '0', + 'ban_reason' => 'HAHAHA', + 'ban_reason_display' => '1', + ], + [ + 'ban_id' => '9', + 'ban_item' => '*@foo.bar', + 'ban_start' => '1111', + 'ban_end' => '0', + 'ban_reason' => 'HAHAHA', + 'ban_reason_display' => '1', + ], + ], + ], + [ + 'user', + [ + [ + 'ban_id' => '4', + 'ban_item' => '4', + 'ban_start' => '1111', + 'ban_end' => '0', + 'ban_reason' => 'HAHAHA', + 'ban_reason_display' => '1', + ], + ], + ], + ]; + } + + /** + * @dataProvider data_get_bans + */ + public function test_get_bans($ban_type, $expected, $expected_exception = false) + { + if ($expected_exception !== false) + { + $this->expectException($expected_exception); + } + $this->assertEquals($expected, $this->ban_manager->get_bans($ban_type)); + } + + 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_users', 'phpbb_sessions', 'phpbb_sessions_keys'); + $ban_type_user = new \phpbb\ban\type\user($this->db, 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys'); + $ban_type_ip = $this->getMockBuilder(\phpbb\ban\type\ip::class) + ->setConstructorArgs([$this->db, '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'); + + $config = new \phpbb\config\config([]); + $phpbb_dispatcher = new \phpbb_mock_event_dispatcher(); + + // Change the global cache object for this test because + // the mock cache object does not hit the database as is needed + // for this test. + $cache = new \phpbb\cache\service( + new \phpbb\cache\driver\dummy(), + $config, + $this->db, + $phpbb_dispatcher, + $phpbb_root_path, + $phpEx + ); + + $ban_manager = new \phpbb\ban\manager($collection, $cache, $this->db, $user, 'phpbb_bans', 'phpbb_users'); + + $this->assertEquals( + [ + 4 => 0, + 5 => 0, + 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_users', 'phpbb_sessions', 'phpbb_sessions_keys'); + $ban_type_user = new \phpbb\ban\type\user($this->db, 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys'); + $ban_type_ip = $this->getMockBuilder(\phpbb\ban\type\ip::class) + ->setConstructorArgs([$this->db, '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'); + + $config = new \phpbb\config\config([]); + $phpbb_dispatcher = new \phpbb_mock_event_dispatcher(); + + // Change the global cache object for this test because + // the mock cache object does not hit the database as is needed + // for this test. + $cache = new \phpbb\cache\service( + new \phpbb\cache\driver\dummy(), + $config, + $this->db, + $phpbb_dispatcher, + $phpbb_root_path, + $phpEx + ); + + $ban_manager = new \phpbb\ban\manager($collection, $cache, $this->db, $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_item' => '4', + 'ban_start' => '1111', + 'ban_end' => '0', + 'ban_reason' => 'HAHAHA', + 'ban_reason_display' => '1', + ], + ], + ], + ]; + } + + /** + * @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(['foo'], $after_unban->invoke($ban_type_ip, ['items' => ['foo']])); + + $check = $base_type_reflection->getMethod('check'); + $this->assertFalse($check->invoke($ban_type_ip, [], [])); + } +} diff --git a/tests/ban/fixtures/sessions_banlist.xml b/tests/ban/fixtures/sessions_banlist.xml new file mode 100644 index 0000000000..38f6c41e26 --- /dev/null +++ b/tests/ban/fixtures/sessions_banlist.xml @@ -0,0 +1,161 @@ + + + + user_id + username_clean + user_permissions + user_sig + user_email + user_ip + user_type + + 1 + anonymous + + + + 127.0.0.1 + 2 + + + 2 + founder + + + admin@foo.bar + 21.22.23.24 + 3 + + + 3 + normal_user + + + normal_user@foo.bar + 21.22.23.25 + 0 + + + 4 + ipv6_user + + + normal_user@foo.bar + 2345:0425:2CA1:0000:0000:0567:5673:23b5 + 0 + + + 5 + 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_mode + ban_item + ban_start + ban_end + ban_reason + ban_reason_display + + 2 + ip + 127.0.0.1 + 1111 + 0 + HAHAHA + 1 + + + 3 + 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 + + + 6 + ip + 10.0.0.1/28 + 1111 + 0 + HAHAHA + 1 + + + 7 + ip + 2001:4860:4860::8888/12 + 1111 + 0 + HAHAHA + 1 + + + 8 + invalid_mode + foo + 1111 + 0 + HAHAHA + 1 + + + 9 + email + *@foo.bar + 1111 + 0 + HAHAHA + 1 + + + 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/functions/validate_user_email_test.php b/tests/functions/validate_user_email_test.php index 08fbe93b4b..404dcb5da9 100644 --- a/tests/functions/validate_user_email_test.php +++ b/tests/functions/validate_user_email_test.php @@ -59,7 +59,7 @@ class phpbb_functions_validate_user_email_test extends phpbb_database_test_case $collection->add('ban.type.email'); $collection->add('ban.type.user'); - $ban_manager = new \phpbb\ban\manager($collection, $cache, $this->db, 'phpbb_bans', 'phpbb_users'); + $ban_manager = new \phpbb\ban\manager($collection, $cache, $this->db, $this->user, 'phpbb_bans', 'phpbb_users'); $phpbb_container->set('ban.manager', $ban_manager); } diff --git a/tests/session/check_ban_test.php b/tests/session/check_ban_test.php index 95ad89cacd..0a064a817c 100644 --- a/tests/session/check_ban_test.php +++ b/tests/session/check_ban_test.php @@ -51,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, $phpbb_container; + 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(); @@ -81,7 +84,7 @@ class phpbb_session_check_ban_test extends phpbb_session_test_case $collection->add('ban.type.email'); $collection->add('ban.type.user'); - $ban_manager = new \phpbb\ban\manager($collection, $cache, $this->db, 'phpbb_bans', 'phpbb_users'); + $ban_manager = new \phpbb\ban\manager($collection, $cache, $this->db, $user, 'phpbb_bans', 'phpbb_users'); $phpbb_container->set('ban.manager', $ban_manager); } diff --git a/tests/session/testable_factory.php b/tests/session/testable_factory.php index c85053770a..ce45171be3 100644 --- a/tests/session/testable_factory.php +++ b/tests/session/testable_factory.php @@ -75,7 +75,7 @@ class phpbb_session_testable_factory { // set up all the global variables used by session global $SID, $_SID, $db, $config, $cache, $request, $phpbb_container, $phpbb_dispatcher; - global $phpbb_root_path, $phpEx; + global $user, $phpbb_root_path, $phpEx; $request = $this->request = new phpbb_mock_request( array(), @@ -90,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( @@ -124,7 +126,7 @@ class phpbb_session_testable_factory $collection->add('ban.type.email'); $collection->add('ban.type.user'); - $ban_manager = new \phpbb\ban\manager($collection, $cache_service, $db, 'phpbb_bans', 'phpbb_users'); + $ban_manager = new \phpbb\ban\manager($collection, $cache_service, $db, $user,'phpbb_bans', 'phpbb_users'); $phpbb_container->set('ban.manager', $ban_manager); $session = new phpbb_mock_session_testable; From c88a9f0b01aa7071d0516c4e38d35bf64df36b75 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 29 Jul 2023 16:41:43 +0200 Subject: [PATCH 24/54] [ticket/9687] Remove support for ban exclude PHPBB3-9687 --- phpBB/adm/style/acp_ban.html | 5 ----- phpBB/includes/acp/acp_ban.php | 6 ------ phpBB/includes/functions_user.php | 3 +-- phpBB/includes/mcp/mcp_ban.php | 10 +--------- phpBB/language/en/acp/ban.php | 4 ---- phpBB/language/en/acp/common.php | 3 --- phpBB/styles/prosilver/template/mcp_ban.html | 7 ------- tests/functions/fixtures/banned_users.xml | 10 ---------- 8 files changed, 2 insertions(+), 46 deletions(-) diff --git a/phpBB/adm/style/acp_ban.html b/phpBB/adm/style/acp_ban.html index ffea40027e..35e2028618 100644 --- a/phpBB/adm/style/acp_ban.html +++ b/phpBB/adm/style/acp_ban.html @@ -60,11 +60,6 @@
-
-

{L_BAN_EXCLUDE_EXPLAIN}
-
-
-
diff --git a/phpBB/includes/acp/acp_ban.php b/phpBB/includes/acp/acp_ban.php index 5d459444d0..b41f42fd6a 100644 --- a/phpBB/includes/acp/acp_ban.php +++ b/phpBB/includes/acp/acp_ban.php @@ -76,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. @@ -88,7 +87,6 @@ class acp_ban 'ban', 'ban_length', 'ban_length_other', - 'ban_exclude', 'ban_reason', 'ban_give_reason', 'abort_ban', @@ -115,7 +113,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 @@ -125,7 +122,6 @@ class acp_ban 'ban', 'ban_length', 'ban_length_other', - 'ban_exclude', 'ban_reason', 'ban_give_reason', ); @@ -150,7 +146,6 @@ class acp_ban $this->page_title = $language->lang(strtoupper($mode) . '_BAN'); $l_ban_explain = $language->lang(strtoupper($mode) . '_BAN_EXPLAIN'); - $l_ban_exclude_explain = $language->lang(strtoupper($mode) . '_BAN_EXCLUDE_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'); @@ -182,7 +177,6 @@ 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', diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php index d11f7cbfeb..3913b20090 100644 --- a/phpBB/includes/functions_user.php +++ b/phpBB/includes/functions_user.php @@ -921,12 +921,11 @@ function user_active_flip($mode, $user_id_ary, $reason = INACTIVE_MANUAL) * @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 $phpbb_container, $user; 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/language/en/acp/ban.php b/phpBB/language/en/acp/ban.php index 93d5cf9a8b..ad73553649 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,14 +52,12 @@ $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.', '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', @@ -76,7 +73,6 @@ $lang = array_merge($lang, array( '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', 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/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_EXPLAIN}
-
- - -
-
diff --git a/tests/functions/fixtures/banned_users.xml b/tests/functions/fixtures/banned_users.xml index 4be21c3201..4d6a6bfa40 100644 --- a/tests/functions/fixtures/banned_users.xml +++ b/tests/functions/fixtures/banned_users.xml @@ -2,13 +2,7 @@ ban_userid - ban_excludeban_end - - 1 - 1 - 0 - 2 0 @@ -17,21 +11,17 @@ 3 0 - 0 4 - 0 2 5 - 0 999999999999999999999 6 - 0 3
From 6048458a12236b72789119e2d8e947c24b60d898 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 29 Jul 2023 20:37:29 +0200 Subject: [PATCH 25/54] [ticket/9687] Remove unused exception PHPBB3-9687 --- .../exception/ban_insert_failed_exception.php | 20 ------------------- phpBB/phpbb/ban/manager.php | 1 - 2 files changed, 21 deletions(-) delete mode 100644 phpBB/phpbb/ban/exception/ban_insert_failed_exception.php diff --git a/phpBB/phpbb/ban/exception/ban_insert_failed_exception.php b/phpBB/phpbb/ban/exception/ban_insert_failed_exception.php deleted file mode 100644 index 1c1a2fee7f..0000000000 --- a/phpBB/phpbb/ban/exception/ban_insert_failed_exception.php +++ /dev/null @@ -1,20 +0,0 @@ - - * @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 ban_insert_failed_exception extends runtime_exception -{ -} diff --git a/phpBB/phpbb/ban/manager.php b/phpBB/phpbb/ban/manager.php index ab3471a79d..8ce469b5fb 100644 --- a/phpBB/phpbb/ban/manager.php +++ b/phpBB/phpbb/ban/manager.php @@ -13,7 +13,6 @@ namespace phpbb\ban; -use phpbb\ban\exception\ban_insert_failed_exception; use phpbb\ban\exception\invalid_length_exception; use phpbb\ban\exception\type_not_found_exception; use phpbb\ban\type\type_interface; From 1a4e6fe3e84514f0a584c5624c3b419dadf7b327 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 29 Jul 2023 23:09:42 +0200 Subject: [PATCH 26/54] [ticket/9687] Use Forms for template display and fix display for users PHPBB3-9687 --- phpBB/adm/style/acp_ban.html | 56 +++++++++++++++---------- phpBB/adm/style/admin.css | 4 ++ phpBB/includes/functions_admin.php | 44 ++++++++++++------- phpBB/phpbb/ban/manager.php | 18 +++----- phpBB/phpbb/ban/type/base.php | 19 +++++++++ phpBB/phpbb/ban/type/type_interface.php | 7 ++++ phpBB/phpbb/ban/type/user.php | 26 ++++++++++++ 7 files changed, 122 insertions(+), 52 deletions(-) diff --git a/phpBB/adm/style/acp_ban.html b/phpBB/adm/style/acp_ban.html index 35e2028618..147eae106b 100644 --- a/phpBB/adm/style/acp_ban.html +++ b/phpBB/adm/style/acp_ban.html @@ -11,11 +11,11 @@ @@ -85,44 +98,41 @@

{L_UNBAN_EXPLAIN}

-
+
- {L_UNBAN_TITLE} + {{ lang('UNBAN_TITLE') }} - +{% if BANNED_SELECT %}
-
-
+
+
+ {{ FormsSelect(BANNED_SELECT) }} +
-
+
-
+
-
+

-   - +   +

- {S_FORM_TOKEN} -
- - - -

{L_NO_BAN_CELL}

- {S_FORM_TOKEN} +{% else %} +

{{ lang('NO_BAN_CELL') }}

+{% endif %} + {{ S_FORM_TOKEN }} - -
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/includes/functions_admin.php b/phpBB/includes/functions_admin.php index 8e784ef576..48bb7be21c 100644 --- a/phpBB/includes/functions_admin.php +++ b/phpBB/includes/functions_admin.php @@ -3156,33 +3156,37 @@ function display_ban_end_options() */ function display_ban_options($mode) { - global $user, $template, $phpbb_container; + global $language, $user, $template, $phpbb_container; /** @var \phpbb\ban\manager $ban_manager */ $ban_manager = $phpbb_container->get('ban.manager'); $ban_rows = $ban_manager->get_bans($mode); - $banned_options = array(); + $banned_options = []; + foreach ($ban_rows as $ban_row) { - $banned_options[] = ''; + $banned_options[] = [ + 'value' => $ban_row['ban_id'], + 'label' => $ban_row['ban_item'], + ]; $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($ban_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($ban_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( @@ -3196,16 +3200,24 @@ function display_ban_options($mode) )); } - $options = ''; - if ($banned_options) + if (count($banned_options)) { - $options .= ''; - $options .= implode('', $banned_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, + ]], + ]; - $template->assign_vars(array( - 'S_BANNED_OPTIONS' => (bool) $banned_options, - 'BANNED_OPTIONS' => $options, - )); + $template->assign_vars(['BANNED_SELECT' => $banned_select]); + } } diff --git a/phpBB/phpbb/ban/manager.php b/phpBB/phpbb/ban/manager.php index 8ce469b5fb..52cae3670a 100644 --- a/phpBB/phpbb/ban/manager.php +++ b/phpBB/phpbb/ban/manager.php @@ -263,23 +263,15 @@ class manager */ public function get_bans(string $mode) { - /** @var type_interface $ban_mode */ - $ban_mode = $this->find_type($mode); - if ($ban_mode === false) + /** @var type_interface $ban_type */ + $ban_type = $this->find_type($mode); + if ($ban_type === false) { - throw new type_not_found_exception(); // TODO + throw new type_not_found_exception(); } $this->tidy(); - $sql = 'SELECT ban_id, ban_item, ban_start, ban_end, ban_reason, ban_reason_display - FROM ' . $this->bans_table . " - WHERE ban_mode = '" . $this->db->sql_escape($mode) . "' - AND (ban_end = 0 OR ban_end >= " . time() . ')'; - $result = $this->db->sql_query($sql); - $rowset = $this->db->sql_fetchrowset($result); - $this->db->sql_freeresult($result); - - return $rowset; + return $ban_type->get_ban_options(); } /** diff --git a/phpBB/phpbb/ban/type/base.php b/phpBB/phpbb/ban/type/base.php index f404e1bdeb..d82be47af7 100644 --- a/phpBB/phpbb/ban/type/base.php +++ b/phpBB/phpbb/ban/type/base.php @@ -100,6 +100,25 @@ abstract class base implements type_interface return []; } + /** + * {@inheritDoc} + */ + public function get_ban_options(): array + { + // @todo replace table constant by string + $sql = 'SELECT * + FROM ' . BANS_TABLE . ' + WHERE (ban_end >= ' . time() . " + OR ban_end = 0) + AND ban_mode = '{$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. diff --git a/phpBB/phpbb/ban/type/type_interface.php b/phpBB/phpbb/ban/type/type_interface.php index b807b3e018..0c16a24319 100644 --- a/phpBB/phpbb/ban/type/type_interface.php +++ b/phpBB/phpbb/ban/type/type_interface.php @@ -100,6 +100,13 @@ interface type_interface */ 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 * diff --git a/phpBB/phpbb/ban/type/user.php b/phpBB/phpbb/ban/type/user.php index 1b8592e354..cb5de0f8dd 100644 --- a/phpBB/phpbb/ban/type/user.php +++ b/phpBB/phpbb/ban/type/user.php @@ -68,6 +68,32 @@ class user extends base return $unbanned_users; } + /** + * {@inheritDoc} + */ + public function get_ban_options(): array + { + $ban_options = []; + + // @todo replace table constant by string + $sql = 'SELECT b.*, u.user_id, u.username, u.username_clean + FROM ' . BANS_TABLE . ' b, ' . $this->users_table . ' u + WHERE (b.ban_end >= ' . time() . " + OR b.ban_end = 0) + AND b.ban_mode = '{$this->get_type()}' + AND u.user_id = b.ban_item + ORDER BY u.username_clean ASC"; + $result = $this->db->sql_query($sql); + while ($row = $this->db->sql_fetchrow($result)) + { + $row['ban_item'] = $row['username']; + $ban_options[] = $row; + } + $this->db->sql_freeresult($result); + + return $ban_options; + } + /** * {@inheritDoc} */ From 872439b8f4158ce36a7fb680c97927754d069d71 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 29 Jul 2023 23:10:51 +0200 Subject: [PATCH 27/54] [ticket/9687] Properly display error messages in ACP PHPBB3-9687 --- phpBB/includes/acp/acp_ban.php | 9 ++++++- phpBB/phpbb/ban/manager.php | 47 +++++++++++++++++++--------------- phpBB/phpbb/ban/type/email.php | 2 +- phpBB/phpbb/ban/type/ip.php | 2 +- phpBB/phpbb/ban/type/user.php | 2 +- phpBB/phpbb/session.php | 2 +- 6 files changed, 38 insertions(+), 26 deletions(-) diff --git a/phpBB/includes/acp/acp_ban.php b/phpBB/includes/acp/acp_ban.php index b41f42fd6a..5f8261d978 100644 --- a/phpBB/includes/acp/acp_ban.php +++ b/phpBB/includes/acp/acp_ban.php @@ -103,7 +103,14 @@ class acp_ban $ban_end = $ban_manager->get_ban_end($ban_start, $ban_length, $ban_length_other); $ban = explode("\n", $ban); - $ban_manager->ban($mode, $ban, $ban_start, $ban_end, $ban_reason, $ban_give_reason); + 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 diff --git a/phpBB/phpbb/ban/manager.php b/phpBB/phpbb/ban/manager.php index 52cae3670a..f51cd371c8 100644 --- a/phpBB/phpbb/ban/manager.php +++ b/phpBB/phpbb/ban/manager.php @@ -79,14 +79,14 @@ class manager { if ($start > $end && $end->getTimestamp() !== 0) { - throw new invalid_length_exception(); // TODO + 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(); // TODO + throw new type_not_found_exception(); } if (!empty($this->user)) @@ -154,31 +154,36 @@ class manager $ban_mode = $this->find_type($mode); if ($ban_mode === false) { - throw new type_not_found_exception(); // TODO + throw new type_not_found_exception(); } $this->tidy(); $sql_ids = array_map('intval', $items); - $sql = 'SELECT ban_item - FROM ' . $this->bans_table . ' - WHERE ' . $this->db->sql_in_set('ban_id', $sql_ids); // TODO (what if empty?) - $result = $this->db->sql_query($sql); - $unbanned_items = []; - while ($row = $this->db->sql_fetchrow($result)) + if (count($sql_ids)) { - $unbanned_items[] = $row['ban_item']; + $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); + // @todo: add logging for unbanned users } - $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); $this->cache->destroy(self::CACHE_KEY_INFO); $this->cache->destroy(self::CACHE_KEY_USERS); @@ -389,7 +394,7 @@ class manager } else { - throw new invalid_length_exception(); + throw new invalid_length_exception('LENGTH_BAN_INVALID'); } } } diff --git a/phpBB/phpbb/ban/type/email.php b/phpBB/phpbb/ban/type/email.php index e4c6350b76..25feef313c 100644 --- a/phpBB/phpbb/ban/type/email.php +++ b/phpBB/phpbb/ban/type/email.php @@ -56,7 +56,7 @@ class email extends base if (empty($ban_items)) { - throw new no_valid_emails_exception(); // TODO + 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 index d6466c2407..7f8c6ee81d 100644 --- a/phpBB/phpbb/ban/type/ip.php +++ b/phpBB/phpbb/ban/type/ip.php @@ -85,7 +85,7 @@ class ip extends base if (empty($ban_items)) { - throw new no_valid_ips_exception(); // TODO + throw new no_valid_ips_exception('NO_IPS_DEFINED'); } return $ban_items; diff --git a/phpBB/phpbb/ban/type/user.php b/phpBB/phpbb/ban/type/user.php index cb5de0f8dd..ea79cffc35 100644 --- a/phpBB/phpbb/ban/type/user.php +++ b/phpBB/phpbb/ban/type/user.php @@ -147,7 +147,7 @@ class user extends base if (empty($ban_items)) { - throw new no_valid_users_exception(); // TODO + throw new no_valid_users_exception('NO_USER_SPECIFIED'); } return $ban_items; diff --git a/phpBB/phpbb/session.php b/phpBB/phpbb/session.php index 813a156726..bf7402cb6a 100644 --- a/phpBB/phpbb/session.php +++ b/phpBB/phpbb/session.php @@ -1136,7 +1136,7 @@ class session */ function check_ban($user_id = false, $user_ips = false, $user_email = false, $return = false) { - global $db, $phpbb_container, $phpbb_dispatcher; + global $phpbb_container, $phpbb_dispatcher; if (defined('IN_CHECK_BAN') || defined('SKIP_CHECK_BAN')) { From cf26a3003018958932246e2b24d4e8090fc08edd Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 29 Jul 2023 23:11:08 +0200 Subject: [PATCH 28/54] [ticket/9687] Make unbanning work again PHPBB3-9687 --- phpBB/includes/acp/acp_ban.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/includes/acp/acp_ban.php b/phpBB/includes/acp/acp_ban.php index 5f8261d978..9d853aaede 100644 --- a/phpBB/includes/acp/acp_ban.php +++ b/phpBB/includes/acp/acp_ban.php @@ -139,7 +139,7 @@ class acp_ban } else if ($unbansubmit) { - $ban = $request->variable('unban', []); + $ban = $request->variable('unban', ['']); if ($ban) { From 7b551adb2b83482fd81f055aa643ab74f2fa2c44 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 29 Jul 2023 23:11:22 +0200 Subject: [PATCH 29/54] [ticket/9687] Prevent banning of anonymous PHPBB3-9687 --- phpBB/phpbb/ban/type/user.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/phpBB/phpbb/ban/type/user.php b/phpBB/phpbb/ban/type/user.php index ea79cffc35..9598b61f29 100644 --- a/phpBB/phpbb/ban/type/user.php +++ b/phpBB/phpbb/ban/type/user.php @@ -102,9 +102,12 @@ class user extends base // Fill excluded user list $this->get_excluded(); + // Prevent banning of anonymous + $this->excluded[ANONYMOUS] = ANONYMOUS; + $sql_usernames = []; $sql_or_like = []; - foreach ($items as $item) // TODO: Prevent banning Anonymous + foreach ($items as $item) { $cleaned_username = utf8_clean_string($item); if (stripos($cleaned_username, '*') === false) From dcbd4a54aae51e95b0d5607e6cf9d450561eed8d Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 30 Jul 2023 09:35:06 +0200 Subject: [PATCH 30/54] [ticket/9687] Improve display of ban options and update tests PHPBB3-9687 --- .../config/default/container/services_ban.yml | 3 + phpBB/phpbb/ban/type/base.php | 12 ++-- phpBB/phpbb/ban/type/user.php | 2 +- tests/ban/ban_manager_test.php | 64 +++++++++++-------- tests/functions/validate_user_email_test.php | 7 +- tests/session/check_ban_test.php | 7 +- tests/session/testable_factory.php | 8 ++- 7 files changed, 67 insertions(+), 36 deletions(-) diff --git a/phpBB/config/default/container/services_ban.yml b/phpBB/config/default/container/services_ban.yml index dfb93cfd39..1a09c3a27d 100644 --- a/phpBB/config/default/container/services_ban.yml +++ b/phpBB/config/default/container/services_ban.yml @@ -22,6 +22,7 @@ services: class: \phpbb\ban\type\email arguments: - '@dbal.conn' + - '%tables.bans%' - '%tables.users%' - '%tables.sessions%' - '%tables.sessions_keys%' @@ -32,6 +33,7 @@ services: class: \phpbb\ban\type\ip arguments: - '@dbal.conn' + - '%tables.bans%' - '%tables.users%' - '%tables.sessions%' - '%tables.sessions_keys%' @@ -42,6 +44,7 @@ services: class: \phpbb\ban\type\user arguments: - '@dbal.conn' + - '%tables.bans%' - '%tables.users%' - '%tables.sessions%' - '%tables.sessions_keys%' diff --git a/phpBB/phpbb/ban/type/base.php b/phpBB/phpbb/ban/type/base.php index d82be47af7..cb442b983d 100644 --- a/phpBB/phpbb/ban/type/base.php +++ b/phpBB/phpbb/ban/type/base.php @@ -23,6 +23,9 @@ abstract class base implements type_interface /** @var array */ protected $excluded; + /** @var string */ + protected $bans_table; + /** @var string */ protected $sessions_keys_table; @@ -39,11 +42,12 @@ abstract class base implements type_interface * Creates a ban type. * * @param driver_interface $db A phpBB DBAL object - * @param string $users_table The users table - * @param string $sessions_table The sessions table - * @param string $sessions_keys_table The sessions keys table + * @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 $users_table, string $sessions_table, string $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->users_table = $users_table; diff --git a/phpBB/phpbb/ban/type/user.php b/phpBB/phpbb/ban/type/user.php index 9598b61f29..d2d4ab2b67 100644 --- a/phpBB/phpbb/ban/type/user.php +++ b/phpBB/phpbb/ban/type/user.php @@ -86,7 +86,7 @@ class user extends base $result = $this->db->sql_query($sql); while ($row = $this->db->sql_fetchrow($result)) { - $row['ban_item'] = $row['username']; + $row['ban_item'] = $row['username'] ?: $row['ban_item']; $ban_options[] = $row; } $this->db->sql_freeresult($result); diff --git a/tests/ban/ban_manager_test.php b/tests/ban/ban_manager_test.php index 13ed2fd201..15e9345fff 100644 --- a/tests/ban/ban_manager_test.php +++ b/tests/ban/ban_manager_test.php @@ -49,9 +49,9 @@ class ban_manager_test extends \phpbb_session_test_case ); $phpbb_container = new \phpbb_mock_container_builder(); - $ban_type_email = new \phpbb\ban\type\email($this->db, 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys'); - $ban_type_user = new \phpbb\ban\type\user($this->db, 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys'); - $ban_type_ip = new \phpbb\ban\type\ip($this->db, 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys'); + $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); @@ -191,6 +191,15 @@ class ban_manager_test extends \phpbb_session_test_case [ 'ip', [ + [ + 'ban_id' => '6', + '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_item' => '127.0.0.1', @@ -198,6 +207,7 @@ class ban_manager_test extends \phpbb_session_test_case 'ban_end' => '0', 'ban_reason' => 'HAHAHA', 'ban_reason_display' => '1', + 'ban_mode' => 'ip', ], [ 'ban_id' => '3', @@ -206,14 +216,7 @@ class ban_manager_test extends \phpbb_session_test_case 'ban_end' => '0', 'ban_reason' => 'HAHAHA', 'ban_reason_display' => '1', - ], - [ - 'ban_id' => '6', - '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' => '7', @@ -222,20 +225,13 @@ class ban_manager_test extends \phpbb_session_test_case 'ban_end' => '0', 'ban_reason' => 'HAHAHA', 'ban_reason_display' => '1', + 'ban_mode' => 'ip', ], ], ], [ 'email', [ - [ - 'ban_id' => '5', - 'ban_item' => 'bar@example.org', - 'ban_start' => '1111', - 'ban_end' => '0', - 'ban_reason' => 'HAHAHA', - 'ban_reason_display' => '1', - ], [ 'ban_id' => '9', 'ban_item' => '*@foo.bar', @@ -243,6 +239,16 @@ class ban_manager_test extends \phpbb_session_test_case 'ban_end' => '0', 'ban_reason' => 'HAHAHA', 'ban_reason_display' => '1', + 'ban_mode' => 'email', + ], + [ + 'ban_id' => '5', + 'ban_item' => 'bar@example.org', + 'ban_start' => '1111', + 'ban_end' => '0', + 'ban_reason' => 'HAHAHA', + 'ban_reason_display' => '1', + 'ban_mode' => 'email', ], ], ], @@ -256,6 +262,10 @@ class ban_manager_test extends \phpbb_session_test_case 'ban_end' => '0', 'ban_reason' => 'HAHAHA', 'ban_reason_display' => '1', + 'ban_mode' => 'user', + 'user_id' => '4', + 'username' => '', + 'username_clean' => 'ipv6_user', ], ], ], @@ -354,10 +364,10 @@ class ban_manager_test extends \phpbb_session_test_case global $phpbb_root_path, $phpEx; $phpbb_container = new \phpbb_mock_container_builder(); - $ban_type_email = new \phpbb\ban\type\email($this->db, 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys'); - $ban_type_user = new \phpbb\ban\type\user($this->db, 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys'); + $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_users', 'phpbb_sessions', 'phpbb_sessions_keys']) + ->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]); @@ -409,10 +419,10 @@ class ban_manager_test extends \phpbb_session_test_case global $phpbb_root_path, $phpEx; $phpbb_container = new \phpbb_mock_container_builder(); - $ban_type_email = new \phpbb\ban\type\email($this->db, 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys'); - $ban_type_user = new \phpbb\ban\type\user($this->db, 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys'); + $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_users', 'phpbb_sessions', 'phpbb_sessions_keys']) + ->setConstructorArgs([$this->db, 'phpbb_bans', 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys']) ->getMock(); $ban_type_ip->method('prepare_for_storage') ->willReturn([]); @@ -652,6 +662,10 @@ class ban_manager_test extends \phpbb_session_test_case 'ban_end' => '0', 'ban_reason' => 'HAHAHA', 'ban_reason_display' => '1', + 'ban_mode' => 'user', + 'user_id' => '4', + 'username' => '', + 'username_clean' => 'ipv6_user', ], ], ], diff --git a/tests/functions/validate_user_email_test.php b/tests/functions/validate_user_email_test.php index 404dcb5da9..f9714eef96 100644 --- a/tests/functions/validate_user_email_test.php +++ b/tests/functions/validate_user_email_test.php @@ -51,13 +51,16 @@ class phpbb_functions_validate_user_email_test extends phpbb_database_test_case ); $cache->get_driver()->purge(); - $ban_type_email = new \phpbb\ban\type\email($this->db, 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys'); - $ban_type_user = new \phpbb\ban\type\user($this->db, 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys'); + $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'); $ban_manager = new \phpbb\ban\manager($collection, $cache, $this->db, $this->user, 'phpbb_bans', 'phpbb_users'); $phpbb_container->set('ban.manager', $ban_manager); diff --git a/tests/session/check_ban_test.php b/tests/session/check_ban_test.php index 0a064a817c..bd5e082dfc 100644 --- a/tests/session/check_ban_test.php +++ b/tests/session/check_ban_test.php @@ -76,13 +76,16 @@ class phpbb_session_check_ban_test extends phpbb_session_test_case ); $phpbb_container = new phpbb_mock_container_builder(); - $ban_type_email = new \phpbb\ban\type\email($this->db, 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys'); - $ban_type_user = new \phpbb\ban\type\user($this->db, 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys'); + $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'); $ban_manager = new \phpbb\ban\manager($collection, $cache, $this->db, $user, 'phpbb_bans', 'phpbb_users'); $phpbb_container->set('ban.manager', $ban_manager); diff --git a/tests/session/testable_factory.php b/tests/session/testable_factory.php index ce45171be3..2b31b0afe5 100644 --- a/tests/session/testable_factory.php +++ b/tests/session/testable_factory.php @@ -118,13 +118,17 @@ class phpbb_session_testable_factory $phpEx ); - $ban_type_email = new \phpbb\ban\type\email($db, 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys'); - $ban_type_user = new \phpbb\ban\type\user($db, 'phpbb_users', 'phpbb_sessions', 'phpbb_sessions_keys'); + $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'); $ban_manager = new \phpbb\ban\manager($collection, $cache_service, $db, $user,'phpbb_bans', 'phpbb_users'); $phpbb_container->set('ban.manager', $ban_manager); From 2d53b8f947438dfb583b1d49e36a8d73336c90b4 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 30 Jul 2023 09:35:55 +0200 Subject: [PATCH 31/54] [ticket/9687] Remove invalid WHERE clause form query PHPBB3-9687 --- phpBB/phpbb/ban/manager.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/phpBB/phpbb/ban/manager.php b/phpBB/phpbb/ban/manager.php index f51cd371c8..4f352f4719 100644 --- a/phpBB/phpbb/ban/manager.php +++ b/phpBB/phpbb/ban/manager.php @@ -459,8 +459,7 @@ class manager if ($ban_info === false) { $sql = 'SELECT ban_mode, ban_item, ban_end, ban_reason_display - FROM ' . $this->bans_table . ' - WHERE 1'; + FROM ' . $this->bans_table; $result = $this->db->sql_query($sql); $ban_info = []; From 927f33fad3ca3d604e660cff4c319ec5b1d4e5ce Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 30 Jul 2023 10:08:44 +0200 Subject: [PATCH 32/54] [ticket/9687] Use cache driver instead of service PHPBB3-9687 --- .../config/default/container/services_ban.yml | 2 +- phpBB/phpbb/ban/manager.php | 26 +++++++----- tests/ban/ban_manager_test.php | 42 ++----------------- tests/functions/validate_user_email_test.php | 2 +- tests/session/check_ban_test.php | 2 +- tests/session/testable_factory.php | 11 +---- 6 files changed, 22 insertions(+), 63 deletions(-) diff --git a/phpBB/config/default/container/services_ban.yml b/phpBB/config/default/container/services_ban.yml index 1a09c3a27d..437911734a 100644 --- a/phpBB/config/default/container/services_ban.yml +++ b/phpBB/config/default/container/services_ban.yml @@ -4,7 +4,7 @@ services: class: \phpbb\ban\manager arguments: - '@ban.type_collection' - - '@cache' + - '@cache.driver' - '@dbal.conn' - '@user' - '%tables.bans%' diff --git a/phpBB/phpbb/ban/manager.php b/phpBB/phpbb/ban/manager.php index 4f352f4719..ed05ccafd8 100644 --- a/phpBB/phpbb/ban/manager.php +++ b/phpBB/phpbb/ban/manager.php @@ -16,6 +16,10 @@ 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\user; class manager { @@ -26,16 +30,16 @@ class manager /** @var string */ protected $bans_table; - /** @var \phpbb\cache\service */ + /** @var cache_driver */ protected $cache; - /** @var \phpbb\db\driver\driver_interface */ + /** @var driver_interface */ protected $db; - /** @var \phpbb\di\service_collection */ + /** @var service_collection */ protected $types; - /** @var \phpbb\user */ + /** @var user */ protected $user; /** @var string */ @@ -45,14 +49,14 @@ class manager * 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\user $user User object - * @param string $bans_table The bans table - * @param string $users_table The users table + * @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 user $user User object + * @param string $bans_table The bans table + * @param string $users_table The users table */ - public function __construct($types, \phpbb\cache\service $cache, \phpbb\db\driver\driver_interface $db, \phpbb\user $user, $bans_table, $users_table = '') + public function __construct(service_collection $types, cache_driver $cache, driver_interface $db, user $user, string $bans_table, string $users_table = '') { $this->bans_table = $bans_table; $this->cache = $cache; diff --git a/tests/ban/ban_manager_test.php b/tests/ban/ban_manager_test.php index 15e9345fff..86a770324d 100644 --- a/tests/ban/ban_manager_test.php +++ b/tests/ban/ban_manager_test.php @@ -36,18 +36,6 @@ class ban_manager_test extends \phpbb_session_test_case $config = new \phpbb\config\config([]); $phpbb_dispatcher = new \phpbb_mock_event_dispatcher(); - // Change the global cache object for this test because - // the mock cache object does not hit the database as is needed - // for this test. - $cache = new \phpbb\cache\service( - new \phpbb\cache\driver\dummy(), - $config, - $this->db, - $phpbb_dispatcher, - $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'); @@ -60,7 +48,7 @@ class ban_manager_test extends \phpbb_session_test_case $collection->add('ban.type.user'); $collection->add('ban.type.ip'); - $this->ban_manager = new \phpbb\ban\manager($collection, $cache, $this->db, $user, 'phpbb_bans', 'phpbb_users'); + $this->ban_manager = new \phpbb\ban\manager($collection, new \phpbb\cache\driver\dummy(), $this->db, $user, 'phpbb_bans', 'phpbb_users'); $phpbb_container->set('ban.manager', $this->ban_manager); $this->phpbb_container = $phpbb_container; } @@ -385,19 +373,7 @@ class ban_manager_test extends \phpbb_session_test_case $config = new \phpbb\config\config([]); $phpbb_dispatcher = new \phpbb_mock_event_dispatcher(); - // Change the global cache object for this test because - // the mock cache object does not hit the database as is needed - // for this test. - $cache = new \phpbb\cache\service( - new \phpbb\cache\driver\dummy(), - $config, - $this->db, - $phpbb_dispatcher, - $phpbb_root_path, - $phpEx - ); - - $ban_manager = new \phpbb\ban\manager($collection, $cache, $this->db, $user, 'phpbb_bans', 'phpbb_users'); + $ban_manager = new \phpbb\ban\manager($collection, new \phpbb\cache\driver\dummy(), $this->db, $user, 'phpbb_bans', 'phpbb_users'); $this->assertEquals( [ @@ -442,19 +418,7 @@ class ban_manager_test extends \phpbb_session_test_case $config = new \phpbb\config\config([]); $phpbb_dispatcher = new \phpbb_mock_event_dispatcher(); - // Change the global cache object for this test because - // the mock cache object does not hit the database as is needed - // for this test. - $cache = new \phpbb\cache\service( - new \phpbb\cache\driver\dummy(), - $config, - $this->db, - $phpbb_dispatcher, - $phpbb_root_path, - $phpEx - ); - - $ban_manager = new \phpbb\ban\manager($collection, $cache, $this->db, $user, 'phpbb_bans', 'phpbb_users'); + $ban_manager = new \phpbb\ban\manager($collection, new \phpbb\cache\driver\dummy(), $this->db, $user, 'phpbb_bans', 'phpbb_users'); $start_time = new \DateTime(); $start_time->setTimestamp(1000); diff --git a/tests/functions/validate_user_email_test.php b/tests/functions/validate_user_email_test.php index f9714eef96..ec19b0313f 100644 --- a/tests/functions/validate_user_email_test.php +++ b/tests/functions/validate_user_email_test.php @@ -62,7 +62,7 @@ class phpbb_functions_validate_user_email_test extends phpbb_database_test_case $collection->add('ban.type.user'); $collection->add('ban.type.ip'); - $ban_manager = new \phpbb\ban\manager($collection, $cache, $this->db, $this->user, 'phpbb_bans', 'phpbb_users'); + $ban_manager = new \phpbb\ban\manager($collection, $cache->get_driver(), $this->db, $this->user, 'phpbb_bans', 'phpbb_users'); $phpbb_container->set('ban.manager', $ban_manager); } diff --git a/tests/session/check_ban_test.php b/tests/session/check_ban_test.php index bd5e082dfc..74f2e64786 100644 --- a/tests/session/check_ban_test.php +++ b/tests/session/check_ban_test.php @@ -87,7 +87,7 @@ class phpbb_session_check_ban_test extends phpbb_session_test_case $collection->add('ban.type.user'); $collection->add('ban.type.ip'); - $ban_manager = new \phpbb\ban\manager($collection, $cache, $this->db, $user, 'phpbb_bans', 'phpbb_users'); + $ban_manager = new \phpbb\ban\manager($collection, $cache->get_driver(), $this->db, $user, 'phpbb_bans', 'phpbb_users'); $phpbb_container->set('ban.manager', $ban_manager); } diff --git a/tests/session/testable_factory.php b/tests/session/testable_factory.php index 2b31b0afe5..7b1980872b 100644 --- a/tests/session/testable_factory.php +++ b/tests/session/testable_factory.php @@ -109,15 +109,6 @@ class phpbb_session_testable_factory $phpbb_dispatcher = new phpbb_mock_event_dispatcher(); - $cache_service = new \phpbb\cache\service( - $cache, - $config, - $db, - $phpbb_dispatcher, - $phpbb_root_path, - $phpEx - ); - $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'); @@ -130,7 +121,7 @@ class phpbb_session_testable_factory $collection->add('ban.type.user'); $collection->add('ban.type.ip'); - $ban_manager = new \phpbb\ban\manager($collection, $cache_service, $db, $user,'phpbb_bans', 'phpbb_users'); + $ban_manager = new \phpbb\ban\manager($collection, $cache, $db, $user,'phpbb_bans', 'phpbb_users'); $phpbb_container->set('ban.manager', $ban_manager); $session = new phpbb_mock_session_testable; From 9b8b34e8f3f3a6a24a77b7463dd6486c8f5326f5 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 30 Jul 2023 10:08:58 +0200 Subject: [PATCH 33/54] [ticket/9687] Resolve phing sniff issues PHPBB3-9687 --- phpBB/phpbb/ban/type/email.php | 1 - phpBB/phpbb/ban/type/user.php | 1 - phpBB/phpbb/db/migration/data/v400/ban_table_p1.php | 2 +- phpBB/phpbb/db/migration/data/v400/ban_table_p2.php | 2 +- 4 files changed, 2 insertions(+), 4 deletions(-) diff --git a/phpBB/phpbb/ban/type/email.php b/phpBB/phpbb/ban/type/email.php index 25feef313c..46905994b4 100644 --- a/phpBB/phpbb/ban/type/email.php +++ b/phpBB/phpbb/ban/type/email.php @@ -14,7 +14,6 @@ namespace phpbb\ban\type; use phpbb\ban\exception\no_valid_emails_exception; -use phpbb\exception\runtime_exception; class email extends base { diff --git a/phpBB/phpbb/ban/type/user.php b/phpBB/phpbb/ban/type/user.php index d2d4ab2b67..da07b2c16b 100644 --- a/phpBB/phpbb/ban/type/user.php +++ b/phpBB/phpbb/ban/type/user.php @@ -14,7 +14,6 @@ namespace phpbb\ban\type; use phpbb\ban\exception\no_valid_users_exception; -use phpbb\exception\runtime_exception; class user extends base { diff --git a/phpBB/phpbb/db/migration/data/v400/ban_table_p1.php b/phpBB/phpbb/db/migration/data/v400/ban_table_p1.php index 9cd9a7befc..e837a1cf95 100644 --- a/phpBB/phpbb/db/migration/data/v400/ban_table_p1.php +++ b/phpBB/phpbb/db/migration/data/v400/ban_table_p1.php @@ -17,7 +17,7 @@ use phpbb\db\migration\migration; class ban_table_p1 extends migration { - static public function depends_on(): array + public static function depends_on(): array { return ['\phpbb\db\migration\data\v320\default_data_type_ids']; } diff --git a/phpBB/phpbb/db/migration/data/v400/ban_table_p2.php b/phpBB/phpbb/db/migration/data/v400/ban_table_p2.php index 7a64284694..1f31c1ec57 100644 --- a/phpBB/phpbb/db/migration/data/v400/ban_table_p2.php +++ b/phpBB/phpbb/db/migration/data/v400/ban_table_p2.php @@ -15,7 +15,7 @@ namespace phpbb\db\migration\data\v400; class ban_table_p2 extends \phpbb\db\migration\migration { - static public function depends_on(): array + public static function depends_on(): array { return ['\phpbb\db\migration\data\v400\ban_table_p1']; } From f9a0e4d6065eb216822e103f658d2bc67ab28dec Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 30 Jul 2023 18:27:25 +0200 Subject: [PATCH 34/54] [ticket/9687] Separate querie for ban options of users PHPBB3-9687 --- phpBB/phpbb/ban/type/base.php | 4 ++-- phpBB/phpbb/ban/type/user.php | 37 +++++++++++++++++++++++++---------- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/phpBB/phpbb/ban/type/base.php b/phpBB/phpbb/ban/type/base.php index cb442b983d..92b324f9b3 100644 --- a/phpBB/phpbb/ban/type/base.php +++ b/phpBB/phpbb/ban/type/base.php @@ -50,6 +50,7 @@ abstract class base implements type_interface 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; @@ -109,9 +110,8 @@ abstract class base implements type_interface */ public function get_ban_options(): array { - // @todo replace table constant by string $sql = 'SELECT * - FROM ' . BANS_TABLE . ' + FROM ' . $this->bans_table . ' WHERE (ban_end >= ' . time() . " OR ban_end = 0) AND ban_mode = '{$this->get_type()}' diff --git a/phpBB/phpbb/ban/type/user.php b/phpBB/phpbb/ban/type/user.php index da07b2c16b..7dadbf2e43 100644 --- a/phpBB/phpbb/ban/type/user.php +++ b/phpBB/phpbb/ban/type/user.php @@ -73,23 +73,40 @@ class user extends base public function get_ban_options(): array { $ban_options = []; + $ban_data = []; + $user_ids = []; - // @todo replace table constant by string - $sql = 'SELECT b.*, u.user_id, u.username, u.username_clean - FROM ' . BANS_TABLE . ' b, ' . $this->users_table . ' u - WHERE (b.ban_end >= ' . time() . " - OR b.ban_end = 0) - AND b.ban_mode = '{$this->get_type()}' - AND u.user_id = b.ban_item - ORDER BY u.username_clean ASC"; + $sql = 'SELECT b.* + FROM ' . $this->bans_table . ' b + WHERE (b.ban_end >= ' . time() . " + OR b.ban_end = 0) + AND b.ban_mode = '{$this->get_type()}'"; $result = $this->db->sql_query($sql); while ($row = $this->db->sql_fetchrow($result)) { - $row['ban_item'] = $row['username'] ?: $row['ban_item']; - $ban_options[] = $row; + $user_ids[] = $row['ban_item']; + $ban_data[$row['ban_item']] = $row; } $this->db->sql_freeresult($result); + if (count($user_ids)) + { + // Grab usernames for banned user IDs + $sql = 'SELECT user_id, username, username_clean + FROM ' . $this->users_table . ' + WHERE ' . $this->db->sql_in_set('user_id', $user_ids) . ' + ORDER BY username_clean'; + $result = $this->db->sql_query($sql); + while ($row = $this->db->sql_fetchrow($result)) + { + $ban_options[] = array_merge( + $ban_data[$row['user_id']], + $row + ); + } + $this->db->sql_freeresult($result); + } + return $ban_options; } From 0414536727f6858ddfec3b6e46d444a046de8d6e Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Mon, 31 Jul 2023 11:53:33 +0200 Subject: [PATCH 35/54] [ticket/9687] Add separate column for user_id PHPBB3-9687 --- phpBB/phpbb/ban/manager.php | 5 ++- phpBB/phpbb/ban/type/user.php | 31 ++++--------------- .../db/migration/data/v400/ban_table_p1.php | 5 ++- phpBB/phpbb/session.php | 4 +-- tests/ban/ban_manager_test.php | 8 +++++ tests/ban/fixtures/sessions_banlist.xml | 10 ++++++ 6 files changed, 34 insertions(+), 29 deletions(-) diff --git a/phpBB/phpbb/ban/manager.php b/phpBB/phpbb/ban/manager.php index ed05ccafd8..3fed881bf4 100644 --- a/phpBB/phpbb/ban/manager.php +++ b/phpBB/phpbb/ban/manager.php @@ -307,9 +307,12 @@ class manager $manual_modes[] = $ban_mode; continue; } + + $where_column = $user_column == 'user_id' ? 'b.ban_userid' : 'b.ban_item'; + $where_array[] = ['AND', [ - ['b.ban_item', '=', 'u.' . $user_column], + [$where_column, '=', 'u.' . $user_column], ['b.ban_mode', '=', "'{$ban_mode->get_type()}'"], ], ]; diff --git a/phpBB/phpbb/ban/type/user.php b/phpBB/phpbb/ban/type/user.php index 7dadbf2e43..7ad1195988 100644 --- a/phpBB/phpbb/ban/type/user.php +++ b/phpBB/phpbb/ban/type/user.php @@ -73,40 +73,21 @@ class user extends base public function get_ban_options(): array { $ban_options = []; - $ban_data = []; - $user_ids = []; - $sql = 'SELECT b.* - FROM ' . $this->bans_table . ' b + $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_mode = '{$this->get_type()}'"; + AND b.ban_userid = u.user_id + AND b.ban_mode = '{$this->get_type()}' + ORDER BY username_clean"; $result = $this->db->sql_query($sql); while ($row = $this->db->sql_fetchrow($result)) { - $user_ids[] = $row['ban_item']; - $ban_data[$row['ban_item']] = $row; + $ban_options[] = $row; } $this->db->sql_freeresult($result); - if (count($user_ids)) - { - // Grab usernames for banned user IDs - $sql = 'SELECT user_id, username, username_clean - FROM ' . $this->users_table . ' - WHERE ' . $this->db->sql_in_set('user_id', $user_ids) . ' - ORDER BY username_clean'; - $result = $this->db->sql_query($sql); - while ($row = $this->db->sql_fetchrow($result)) - { - $ban_options[] = array_merge( - $ban_data[$row['user_id']], - $row - ); - } - $this->db->sql_freeresult($result); - } - return $ban_options; } diff --git a/phpBB/phpbb/db/migration/data/v400/ban_table_p1.php b/phpBB/phpbb/db/migration/data/v400/ban_table_p1.php index e837a1cf95..f58dff52e3 100644 --- a/phpBB/phpbb/db/migration/data/v400/ban_table_p1.php +++ b/phpBB/phpbb/db/migration/data/v400/ban_table_p1.php @@ -29,6 +29,7 @@ class ban_table_p1 extends migration $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], @@ -38,6 +39,7 @@ class ban_table_p1 extends migration ], 'PRIMARY_KEY' => 'ban_id', 'KEYS' => [ + 'ban_userid' => ['INDEX', 'ban_userid'], 'ban_end' => ['INDEX', 'ban_end'], ], ], @@ -113,6 +115,7 @@ class ban_table_p1 extends migration $bans[] = [ 'ban_mode' => $mode, + 'ban_userid' => $row['ban_userid'], 'ban_item' => $item, 'ban_start' => $row['ban_start'], 'ban_end' => $row['ban_end'], @@ -150,7 +153,7 @@ class ban_table_p1 extends migration $processed_rows++; $bans[] = [ - 'ban_userid' => ($row['ban_mode'] === 'user') ? (int) $row['ban_item'] : 0, + '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'], diff --git a/phpBB/phpbb/session.php b/phpBB/phpbb/session.php index bf7402cb6a..e9011ae304 100644 --- a/phpBB/phpbb/session.php +++ b/phpBB/phpbb/session.php @@ -1209,8 +1209,8 @@ class session $contact_link = phpbb_get_board_contact_link($config, $phpbb_root_path, $phpEx); $message = sprintf($this->lang[$message], $till_date, '', ''); - $message .= ($ban_row['reason']) ? '

' . sprintf($this->lang['BOARD_BAN_REASON'], $ban_row['reason']) : ''; - $message .= '

' . $this->lang['BAN_TRIGGERED_BY_' . strtoupper($ban_triggered_by)] . ''; + $message .= ($ban_row['reason']) ? '

' . sprintf($this->lang['BOARD_BAN_REASON'], $ban_row['reason']) : ''; + $message .= '

' . $this->lang['BAN_TRIGGERED_BY_' . strtoupper($ban_triggered_by)] . ''; // 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')) diff --git a/tests/ban/ban_manager_test.php b/tests/ban/ban_manager_test.php index 86a770324d..b8af909c7d 100644 --- a/tests/ban/ban_manager_test.php +++ b/tests/ban/ban_manager_test.php @@ -181,6 +181,7 @@ class ban_manager_test extends \phpbb_session_test_case [ [ 'ban_id' => '6', + 'ban_userid' => 0, 'ban_item' => '10.0.0.1/28', 'ban_start' => '1111', 'ban_end' => '0', @@ -190,6 +191,7 @@ class ban_manager_test extends \phpbb_session_test_case ], [ 'ban_id' => '2', + 'ban_userid' => 0, 'ban_item' => '127.0.0.1', 'ban_start' => '1111', 'ban_end' => '0', @@ -199,6 +201,7 @@ class ban_manager_test extends \phpbb_session_test_case ], [ 'ban_id' => '3', + 'ban_userid' => 0, 'ban_item' => '127.1.1.1', 'ban_start' => '1111', 'ban_end' => '0', @@ -208,6 +211,7 @@ class ban_manager_test extends \phpbb_session_test_case ], [ 'ban_id' => '7', + 'ban_userid' => 0, 'ban_item' => '2001:4860:4860::8888/12', 'ban_start' => '1111', 'ban_end' => '0', @@ -222,6 +226,7 @@ class ban_manager_test extends \phpbb_session_test_case [ [ 'ban_id' => '9', + 'ban_userid' => 0, 'ban_item' => '*@foo.bar', 'ban_start' => '1111', 'ban_end' => '0', @@ -231,6 +236,7 @@ class ban_manager_test extends \phpbb_session_test_case ], [ 'ban_id' => '5', + 'ban_userid' => 0, 'ban_item' => 'bar@example.org', 'ban_start' => '1111', 'ban_end' => '0', @@ -251,6 +257,7 @@ class ban_manager_test extends \phpbb_session_test_case 'ban_reason' => 'HAHAHA', 'ban_reason_display' => '1', 'ban_mode' => 'user', + 'ban_userid' => 4, 'user_id' => '4', 'username' => '', 'username_clean' => 'ipv6_user', @@ -621,6 +628,7 @@ class ban_manager_test extends \phpbb_session_test_case [ [ 'ban_id' => '4', + 'ban_userid' => '4', 'ban_item' => '4', 'ban_start' => '1111', 'ban_end' => '0', diff --git a/tests/ban/fixtures/sessions_banlist.xml b/tests/ban/fixtures/sessions_banlist.xml index 38f6c41e26..39253d2681 100644 --- a/tests/ban/fixtures/sessions_banlist.xml +++ b/tests/ban/fixtures/sessions_banlist.xml @@ -70,6 +70,7 @@ ban_id + ban_useridban_modeban_itemban_start @@ -78,6 +79,7 @@ ban_reason_display 2 + 0 ip 127.0.0.1 1111 @@ -87,6 +89,7 @@ 3 + 0 ip 127.1.1.1 1111 @@ -96,6 +99,7 @@ 4 + 4 user 4 1111 @@ -105,6 +109,7 @@ 5 + 0 email bar@example.org 1111 @@ -114,6 +119,7 @@ 6 + 0 ip 10.0.0.1/28 1111 @@ -123,6 +129,7 @@ 7 + 0 ip 2001:4860:4860::8888/12 1111 @@ -132,6 +139,7 @@ 8 + 0 invalid_mode foo 1111 @@ -141,6 +149,7 @@ 9 + 0 email *@foo.bar 1111 @@ -149,6 +158,7 @@ 1 + 10 10 user 3 From 0be1ffd29618602e238ebd7784baa624f1362aa2 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Mon, 31 Jul 2023 16:41:34 +0200 Subject: [PATCH 36/54] [ticket/9687] Adjust queries to be compatible with postgres PHPBB3-9687 --- phpBB/includes/functions_user.php | 2 +- phpBB/phpbb/ban/type/base.php | 2 +- phpBB/phpbb/ban/type/user.php | 2 +- tests/ban/ban_manager_test.php | 8 ++++---- tests/functions_user/fixtures/delete_user.xml | 4 ++++ 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php index 3913b20090..c50e0d01ee 100644 --- a/phpBB/includes/functions_user.php +++ b/phpBB/includes/functions_user.php @@ -750,7 +750,7 @@ function user_delete($mode, $user_ids, $retain_username = true) // Delete the user_id from the banlist $sql = 'DELETE FROM ' . BANS_TABLE . ' - WHERE ban_mode = \'user\' AND ' . $db->sql_in_set('ban_item', $user_ids); + 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 diff --git a/phpBB/phpbb/ban/type/base.php b/phpBB/phpbb/ban/type/base.php index 92b324f9b3..84b9502dc1 100644 --- a/phpBB/phpbb/ban/type/base.php +++ b/phpBB/phpbb/ban/type/base.php @@ -115,7 +115,7 @@ abstract class base implements type_interface WHERE (ban_end >= ' . time() . " OR ban_end = 0) AND ban_mode = '{$this->get_type()}' - ORDER BY ban_item"; + ORDER BY ban_item, ban_id"; $result = $this->db->sql_query($sql); $rowset = $this->db->sql_fetchrowset($result); $this->db->sql_freeresult($result); diff --git a/phpBB/phpbb/ban/type/user.php b/phpBB/phpbb/ban/type/user.php index 7ad1195988..0971cf4cf4 100644 --- a/phpBB/phpbb/ban/type/user.php +++ b/phpBB/phpbb/ban/type/user.php @@ -140,7 +140,7 @@ class user extends base $this->banned_users = []; while ($row = $this->db->sql_fetchrow($result)) { - $ban_items[] = (int) $row['user_id']; + $ban_items[] = (string) $row['user_id']; $this->banned_users[(int) $row['user_id']] = $row['username']; } $this->db->sql_freeresult($result); diff --git a/tests/ban/ban_manager_test.php b/tests/ban/ban_manager_test.php index b8af909c7d..4034ad7966 100644 --- a/tests/ban/ban_manager_test.php +++ b/tests/ban/ban_manager_test.php @@ -225,9 +225,9 @@ class ban_manager_test extends \phpbb_session_test_case 'email', [ [ - 'ban_id' => '9', + 'ban_id' => '5', 'ban_userid' => 0, - 'ban_item' => '*@foo.bar', + 'ban_item' => 'bar@example.org', 'ban_start' => '1111', 'ban_end' => '0', 'ban_reason' => 'HAHAHA', @@ -235,9 +235,9 @@ class ban_manager_test extends \phpbb_session_test_case 'ban_mode' => 'email', ], [ - 'ban_id' => '5', + 'ban_id' => '9', 'ban_userid' => 0, - 'ban_item' => 'bar@example.org', + 'ban_item' => '*@foo.bar', 'ban_start' => '1111', 'ban_end' => '0', 'ban_reason' => 'HAHAHA', diff --git a/tests/functions_user/fixtures/delete_user.xml b/tests/functions_user/fixtures/delete_user.xml index 1727b8a783..c149a42429 100644 --- a/tests/functions_user/fixtures/delete_user.xml +++ b/tests/functions_user/fixtures/delete_user.xml @@ -38,6 +38,7 @@
ban_id + ban_useridban_modeban_itemban_start @@ -46,6 +47,7 @@ ban_reason_display 1 + 2 user 2 0 @@ -55,6 +57,7 @@ 2 + 3 user 3 0 @@ -64,6 +67,7 @@ 3 + 0 user 0 0 From a0bd70885d8f6106a1cf8e9753cadd4e42c05a4f Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Mon, 31 Jul 2023 17:23:50 +0200 Subject: [PATCH 37/54] [ticket/9687] Create ban message in manager and add missing sort directions PHPBB3-9687 --- .../config/default/container/services_ban.yml | 1 + phpBB/phpbb/ban/manager.php | 29 ++++++++++++++++++- phpBB/phpbb/ban/type/base.php | 2 +- phpBB/phpbb/ban/type/user.php | 2 +- phpBB/phpbb/session.php | 20 +------------ tests/ban/ban_manager_test.php | 20 +++++-------- tests/functions/validate_user_email_test.php | 2 +- tests/session/check_ban_test.php | 2 +- tests/session/testable_factory.php | 2 +- 9 files changed, 42 insertions(+), 38 deletions(-) diff --git a/phpBB/config/default/container/services_ban.yml b/phpBB/config/default/container/services_ban.yml index 437911734a..cc34d4532c 100644 --- a/phpBB/config/default/container/services_ban.yml +++ b/phpBB/config/default/container/services_ban.yml @@ -6,6 +6,7 @@ services: - '@ban.type_collection' - '@cache.driver' - '@dbal.conn' + - '@language' - '@user' - '%tables.bans%' - '%tables.users%' diff --git a/phpBB/phpbb/ban/manager.php b/phpBB/phpbb/ban/manager.php index 3fed881bf4..3303f23a25 100644 --- a/phpBB/phpbb/ban/manager.php +++ b/phpBB/phpbb/ban/manager.php @@ -19,6 +19,7 @@ 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\user; class manager @@ -39,6 +40,9 @@ class manager /** @var service_collection */ protected $types; + /** @var language */ + protected $language; + /** @var user */ protected $user; @@ -56,12 +60,14 @@ class manager * @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, user $user, string $bans_table, string $users_table = '') + public function __construct(service_collection $types, cache_driver $cache, driver_interface $db, + language $language, 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->user = $user; $this->users_table = $users_table; } @@ -491,4 +497,25 @@ class manager 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 + { + $till_date = ($ban_row && $ban_row['end'] > 0) ? $this->user->format_date($ban_row['end']) : ''; + + $ban_type = $ban_row['ban_end'] ? 'BOARD_BAN_TIME' : 'BOARD_BAN_PERM'; + $message = $this->language->lang($ban_type, $till_date, '', ''); + $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/phpbb/ban/type/base.php b/phpBB/phpbb/ban/type/base.php index 84b9502dc1..0419ebf380 100644 --- a/phpBB/phpbb/ban/type/base.php +++ b/phpBB/phpbb/ban/type/base.php @@ -115,7 +115,7 @@ abstract class base implements type_interface WHERE (ban_end >= ' . time() . " OR ban_end = 0) AND ban_mode = '{$this->get_type()}' - ORDER BY ban_item, ban_id"; + ORDER BY ban_item ASC, ban_id ASC"; $result = $this->db->sql_query($sql); $rowset = $this->db->sql_fetchrowset($result); $this->db->sql_freeresult($result); diff --git a/phpBB/phpbb/ban/type/user.php b/phpBB/phpbb/ban/type/user.php index 0971cf4cf4..66c3f3f4de 100644 --- a/phpBB/phpbb/ban/type/user.php +++ b/phpBB/phpbb/ban/type/user.php @@ -80,7 +80,7 @@ class user extends base OR b.ban_end = 0) AND b.ban_userid = u.user_id AND b.ban_mode = '{$this->get_type()}' - ORDER BY username_clean"; + ORDER BY username_clean ASC"; $result = $this->db->sql_query($sql); while ($row = $this->db->sql_fetchrow($result)) { diff --git a/phpBB/phpbb/session.php b/phpBB/phpbb/session.php index e9011ae304..bdb0ad58a5 100644 --- a/phpBB/phpbb/session.php +++ b/phpBB/phpbb/session.php @@ -1204,13 +1204,8 @@ class session } // Determine which message to output - $till_date = ($ban_row && $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, '', ''); - $message .= ($ban_row['reason']) ? '

' . sprintf($this->lang['BOARD_BAN_REASON'], $ban_row['reason']) : ''; - $message .= '

' . $this->lang['BAN_TRIGGERED_BY_' . strtoupper($ban_triggered_by)] . ''; + $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')) @@ -1254,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/tests/ban/ban_manager_test.php b/tests/ban/ban_manager_test.php index 4034ad7966..12f836fa65 100644 --- a/tests/ban/ban_manager_test.php +++ b/tests/ban/ban_manager_test.php @@ -48,7 +48,7 @@ class ban_manager_test extends \phpbb_session_test_case $collection->add('ban.type.user'); $collection->add('ban.type.ip'); - $this->ban_manager = new \phpbb\ban\manager($collection, new \phpbb\cache\driver\dummy(), $this->db, $user, 'phpbb_bans', 'phpbb_users'); + $this->ban_manager = new \phpbb\ban\manager($collection, new \phpbb\cache\driver\dummy(), $this->db, $language, $user, 'phpbb_bans', 'phpbb_users'); $phpbb_container->set('ban.manager', $this->ban_manager); $this->phpbb_container = $phpbb_container; } @@ -225,9 +225,9 @@ class ban_manager_test extends \phpbb_session_test_case 'email', [ [ - 'ban_id' => '5', + 'ban_id' => '9', 'ban_userid' => 0, - 'ban_item' => 'bar@example.org', + 'ban_item' => '*@foo.bar', 'ban_start' => '1111', 'ban_end' => '0', 'ban_reason' => 'HAHAHA', @@ -235,9 +235,9 @@ class ban_manager_test extends \phpbb_session_test_case 'ban_mode' => 'email', ], [ - 'ban_id' => '9', + 'ban_id' => '5', 'ban_userid' => 0, - 'ban_item' => '*@foo.bar', + 'ban_item' => 'bar@example.org', 'ban_start' => '1111', 'ban_end' => '0', 'ban_reason' => 'HAHAHA', @@ -377,10 +377,7 @@ class ban_manager_test extends \phpbb_session_test_case $language = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)); $user = new \phpbb\user($language, '\phpbb\datetime'); - $config = new \phpbb\config\config([]); - $phpbb_dispatcher = new \phpbb_mock_event_dispatcher(); - - $ban_manager = new \phpbb\ban\manager($collection, new \phpbb\cache\driver\dummy(), $this->db, $user, 'phpbb_bans', 'phpbb_users'); + $ban_manager = new \phpbb\ban\manager($collection, new \phpbb\cache\driver\dummy(), $this->db, $language, $user, 'phpbb_bans', 'phpbb_users'); $this->assertEquals( [ @@ -422,10 +419,7 @@ class ban_manager_test extends \phpbb_session_test_case $language = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)); $user = new \phpbb\user($language, '\phpbb\datetime'); - $config = new \phpbb\config\config([]); - $phpbb_dispatcher = new \phpbb_mock_event_dispatcher(); - - $ban_manager = new \phpbb\ban\manager($collection, new \phpbb\cache\driver\dummy(), $this->db, $user, 'phpbb_bans', 'phpbb_users'); + $ban_manager = new \phpbb\ban\manager($collection, new \phpbb\cache\driver\dummy(), $this->db, $language, $user, 'phpbb_bans', 'phpbb_users'); $start_time = new \DateTime(); $start_time->setTimestamp(1000); diff --git a/tests/functions/validate_user_email_test.php b/tests/functions/validate_user_email_test.php index ec19b0313f..c698f1263f 100644 --- a/tests/functions/validate_user_email_test.php +++ b/tests/functions/validate_user_email_test.php @@ -62,7 +62,7 @@ class phpbb_functions_validate_user_email_test extends phpbb_database_test_case $collection->add('ban.type.user'); $collection->add('ban.type.ip'); - $ban_manager = new \phpbb\ban\manager($collection, $cache->get_driver(), $this->db, $this->user, 'phpbb_bans', 'phpbb_users'); + $ban_manager = new \phpbb\ban\manager($collection, $cache->get_driver(), $this->db, $language, $this->user, 'phpbb_bans', 'phpbb_users'); $phpbb_container->set('ban.manager', $ban_manager); } diff --git a/tests/session/check_ban_test.php b/tests/session/check_ban_test.php index 74f2e64786..9dcb148f2b 100644 --- a/tests/session/check_ban_test.php +++ b/tests/session/check_ban_test.php @@ -87,7 +87,7 @@ class phpbb_session_check_ban_test extends phpbb_session_test_case $collection->add('ban.type.user'); $collection->add('ban.type.ip'); - $ban_manager = new \phpbb\ban\manager($collection, $cache->get_driver(), $this->db, $user, 'phpbb_bans', 'phpbb_users'); + $ban_manager = new \phpbb\ban\manager($collection, $cache->get_driver(), $this->db, $language, $user, 'phpbb_bans', 'phpbb_users'); $phpbb_container->set('ban.manager', $ban_manager); } diff --git a/tests/session/testable_factory.php b/tests/session/testable_factory.php index 7b1980872b..ea057674a4 100644 --- a/tests/session/testable_factory.php +++ b/tests/session/testable_factory.php @@ -121,7 +121,7 @@ class phpbb_session_testable_factory $collection->add('ban.type.user'); $collection->add('ban.type.ip'); - $ban_manager = new \phpbb\ban\manager($collection, $cache, $db, $user,'phpbb_bans', 'phpbb_users'); + $ban_manager = new \phpbb\ban\manager($collection, $cache, $db, $language, $user,'phpbb_bans', 'phpbb_users'); $phpbb_container->set('ban.manager', $ban_manager); $session = new phpbb_mock_session_testable; From 66cb07d2f4591ccfbae9266501533e9ab53421c1 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Mon, 31 Jul 2023 18:48:09 +0200 Subject: [PATCH 38/54] [ticket/9687] Fix tests on postgres PHPBB3-9687 --- phpBB/phpbb/ban/type/base.php | 2 +- phpBB/phpbb/ban/type/user.php | 2 +- tests/ban/ban_manager_test.php | 7 +++++++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/phpBB/phpbb/ban/type/base.php b/phpBB/phpbb/ban/type/base.php index 0419ebf380..92b324f9b3 100644 --- a/phpBB/phpbb/ban/type/base.php +++ b/phpBB/phpbb/ban/type/base.php @@ -115,7 +115,7 @@ abstract class base implements type_interface WHERE (ban_end >= ' . time() . " OR ban_end = 0) AND ban_mode = '{$this->get_type()}' - ORDER BY ban_item ASC, ban_id ASC"; + ORDER BY ban_item"; $result = $this->db->sql_query($sql); $rowset = $this->db->sql_fetchrowset($result); $this->db->sql_freeresult($result); diff --git a/phpBB/phpbb/ban/type/user.php b/phpBB/phpbb/ban/type/user.php index 66c3f3f4de..7e01ac8bb5 100644 --- a/phpBB/phpbb/ban/type/user.php +++ b/phpBB/phpbb/ban/type/user.php @@ -80,7 +80,7 @@ class user extends base OR b.ban_end = 0) AND b.ban_userid = u.user_id AND b.ban_mode = '{$this->get_type()}' - ORDER BY username_clean ASC"; + ORDER BY u.username_clean ASC"; $result = $this->db->sql_query($sql); while ($row = $this->db->sql_fetchrow($result)) { diff --git a/tests/ban/ban_manager_test.php b/tests/ban/ban_manager_test.php index 12f836fa65..de347568b2 100644 --- a/tests/ban/ban_manager_test.php +++ b/tests/ban/ban_manager_test.php @@ -276,6 +276,13 @@ class ban_manager_test extends \phpbb_session_test_case { $this->expectException($expected_exception); } + + // Fix weird sorting by postgres + if (is_array($expected) && $ban_type == 'email' && $this->db->get_sql_layer() == 'postgres') + { + $expected = array_reverse($expected); + } + $this->assertEquals($expected, $this->ban_manager->get_bans($ban_type)); } From 040b277fd9404e776a4a7d21f1fb95287a5d1d4e Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Mon, 31 Jul 2023 20:41:17 +0200 Subject: [PATCH 39/54] [ticket/9687] Add array reverse only for linux postgres PHPBB3-9687 --- tests/ban/ban_manager_test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ban/ban_manager_test.php b/tests/ban/ban_manager_test.php index de347568b2..65f197f404 100644 --- a/tests/ban/ban_manager_test.php +++ b/tests/ban/ban_manager_test.php @@ -278,7 +278,7 @@ class ban_manager_test extends \phpbb_session_test_case } // Fix weird sorting by postgres - if (is_array($expected) && $ban_type == 'email' && $this->db->get_sql_layer() == 'postgres') + if (strtolower(substr(PHP_OS, 0, 3)) === 'linux' && is_array($expected) && $ban_type == 'email' && $this->db->get_sql_layer() == 'postgres') { $expected = array_reverse($expected); } From 0f1886970235813aa877a5b7b40ea709488b257f Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 4 Aug 2023 22:59:25 +0200 Subject: [PATCH 40/54] [ticket/9687] Fix text inconsistency between mysql & postgres PHPBB3-9687 --- tests/ban/ban_manager_test.php | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/tests/ban/ban_manager_test.php b/tests/ban/ban_manager_test.php index 65f197f404..408c95e304 100644 --- a/tests/ban/ban_manager_test.php +++ b/tests/ban/ban_manager_test.php @@ -277,13 +277,22 @@ class ban_manager_test extends \phpbb_session_test_case $this->expectException($expected_exception); } - // Fix weird sorting by postgres - if (strtolower(substr(PHP_OS, 0, 3)) === 'linux' && is_array($expected) && $ban_type == 'email' && $this->db->get_sql_layer() == 'postgres') + $actual = $this->ban_manager->get_bans($ban_type); + // Sort both arrays by ban_item to be synced + if (is_array($expected) && !empty($actual)) { - $expected = array_reverse($expected); + 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, $this->ban_manager->get_bans($ban_type)); + $this->assertEquals($expected, $actual); } public function data_get_ban_end(): array From d7389809aa3e1e41713a300769975ea00400b6c1 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 6 Aug 2023 13:55:50 +0200 Subject: [PATCH 41/54] [ticket/9687] Add support for logging to banning system PHPBB3-9687 --- .../config/default/container/services_ban.yml | 1 + phpBB/phpbb/ban/manager.php | 54 +++++++++++++++++-- phpBB/phpbb/ban/type/base.php | 9 ++-- phpBB/phpbb/ban/type/type_interface.php | 10 ++-- phpBB/phpbb/ban/type/user.php | 4 +- tests/ban/ban_manager_test.php | 10 ++-- tests/functions/validate_user_email_test.php | 3 +- tests/session/check_ban_test.php | 3 +- tests/session/testable_factory.php | 3 +- 9 files changed, 74 insertions(+), 23 deletions(-) diff --git a/phpBB/config/default/container/services_ban.yml b/phpBB/config/default/container/services_ban.yml index cc34d4532c..c9e7c6ddb0 100644 --- a/phpBB/config/default/container/services_ban.yml +++ b/phpBB/config/default/container/services_ban.yml @@ -7,6 +7,7 @@ services: - '@cache.driver' - '@dbal.conn' - '@language' + - '@log' - '@user' - '%tables.bans%' - '%tables.users%' diff --git a/phpBB/phpbb/ban/manager.php b/phpBB/phpbb/ban/manager.php index 3303f23a25..feddc56f16 100644 --- a/phpBB/phpbb/ban/manager.php +++ b/phpBB/phpbb/ban/manager.php @@ -20,6 +20,7 @@ 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 @@ -43,6 +44,9 @@ class manager /** @var language */ protected $language; + /** @var log_interface */ + protected $log; + /** @var user */ protected $user; @@ -56,18 +60,21 @@ class manager * @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, user $user, string $bans_table, string $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; } @@ -141,9 +148,28 @@ class manager 'display_reason' => $display_reason, ]; - if ($ban_mode->after_ban($ban_data)) + // 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)) { - // @todo: Add logging + 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); @@ -192,7 +218,25 @@ class manager 'items' => $unbanned_items, ]; $unbanned_users = $ban_mode->after_unban($unban_data); - // @todo: add logging for unbanned users + + // 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); diff --git a/phpBB/phpbb/ban/type/base.php b/phpBB/phpbb/ban/type/base.php index 92b324f9b3..a331813ab5 100644 --- a/phpBB/phpbb/ban/type/base.php +++ b/phpBB/phpbb/ban/type/base.php @@ -68,18 +68,17 @@ abstract class base implements type_interface /** * {@inheritDoc} */ - public function after_ban(array $data) + public function after_ban(array $data): array { - $this->logout_affected_users($data['items']); - return $data['items']; + return $this->logout_affected_users($data['items']); } /** * {@inheritDoc} */ - public function after_unban(array $data) + public function after_unban(array $data): array { - return $data['items']; + return []; } /** diff --git a/phpBB/phpbb/ban/type/type_interface.php b/phpBB/phpbb/ban/type/type_interface.php index 0c16a24319..db86fc8ae7 100644 --- a/phpBB/phpbb/ban/type/type_interface.php +++ b/phpBB/phpbb/ban/type/type_interface.php @@ -54,21 +54,21 @@ interface type_interface * the bans, like the reason or the start * and end of the ban * - * @return mixed + * @return array List of banned users */ - public function after_ban(array $data); + public function after_ban(array $data): array; /** - * Gives the possiblity to do some clean up after unbanning. + * 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 mixed + * @return array List of unbanned users */ - public function after_unban(array $data); + public function after_unban(array $data): array; /** * In the case that get_user_column() returns null, this method diff --git a/phpBB/phpbb/ban/type/user.php b/phpBB/phpbb/ban/type/user.php index 7e01ac8bb5..c803e1b16f 100644 --- a/phpBB/phpbb/ban/type/user.php +++ b/phpBB/phpbb/ban/type/user.php @@ -39,7 +39,7 @@ class user extends base /** * {@inheritDoc} */ - public function after_ban(array $data) + public function after_ban(array $data): array { $this->logout_affected_users($data['items']); return $this->banned_users; @@ -48,7 +48,7 @@ class user extends base /** * {@inheritDoc} */ - public function after_unban(array $data) + public function after_unban(array $data): array { $user_ids = array_map('intval', $data['items']); diff --git a/tests/ban/ban_manager_test.php b/tests/ban/ban_manager_test.php index 408c95e304..a5f3620217 100644 --- a/tests/ban/ban_manager_test.php +++ b/tests/ban/ban_manager_test.php @@ -33,6 +33,7 @@ class ban_manager_test extends \phpbb_session_test_case $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(); @@ -47,8 +48,9 @@ class ban_manager_test extends \phpbb_session_test_case $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, $user, 'phpbb_bans', 'phpbb_users'); + $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; } @@ -392,8 +394,9 @@ class ban_manager_test extends \phpbb_session_test_case $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, $user, 'phpbb_bans', 'phpbb_users'); + $ban_manager = new \phpbb\ban\manager($collection, new \phpbb\cache\driver\dummy(), $this->db, $language, $phpbb_log, $user, 'phpbb_bans', 'phpbb_users'); $this->assertEquals( [ @@ -434,8 +437,9 @@ class ban_manager_test extends \phpbb_session_test_case $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, $user, 'phpbb_bans', 'phpbb_users'); + $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); diff --git a/tests/functions/validate_user_email_test.php b/tests/functions/validate_user_email_test.php index c698f1263f..a43244bd50 100644 --- a/tests/functions/validate_user_email_test.php +++ b/tests/functions/validate_user_email_test.php @@ -61,8 +61,9 @@ class phpbb_functions_validate_user_email_test extends phpbb_database_test_case $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, $this->user, 'phpbb_bans', 'phpbb_users'); + $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/session/check_ban_test.php b/tests/session/check_ban_test.php index 9dcb148f2b..44a4012d3b 100644 --- a/tests/session/check_ban_test.php +++ b/tests/session/check_ban_test.php @@ -86,8 +86,9 @@ class phpbb_session_check_ban_test extends phpbb_session_test_case $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, $user, 'phpbb_bans', 'phpbb_users'); + $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); } diff --git a/tests/session/testable_factory.php b/tests/session/testable_factory.php index ea057674a4..36e9fe6d3f 100644 --- a/tests/session/testable_factory.php +++ b/tests/session/testable_factory.php @@ -120,8 +120,9 @@ class phpbb_session_testable_factory $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, $user,'phpbb_bans', 'phpbb_users'); + $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; From 54bb32bba53ac5f0cb84e84f2ad4ff981ed6aaea Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 6 Aug 2023 13:59:23 +0200 Subject: [PATCH 42/54] [ticket/9687] Improve labeling in acp for user bans PHPBB3-9687 --- phpBB/includes/functions_admin.php | 2 +- phpBB/phpbb/ban/manager.php | 1 + phpBB/phpbb/ban/type/user.php | 1 + tests/ban/ban_manager_test.php | 72 +++++++++++++++++++++++-- tests/ban/fixtures/sessions_banlist.xml | 6 +++ 5 files changed, 78 insertions(+), 4 deletions(-) diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php index 48bb7be21c..ea9ddbaf3c 100644 --- a/phpBB/includes/functions_admin.php +++ b/phpBB/includes/functions_admin.php @@ -3168,7 +3168,7 @@ function display_ban_options($mode) { $banned_options[] = [ 'value' => $ban_row['ban_id'], - 'label' => $ban_row['ban_item'], + 'label' => $ban_row['label'] ?? $ban_row['ban_item'], ]; $time_length = ($ban_row['ban_end']) ? ($ban_row['ban_end'] - $ban_row['ban_start']) / 60 : 0; diff --git a/phpBB/phpbb/ban/manager.php b/phpBB/phpbb/ban/manager.php index feddc56f16..0acfd1e019 100644 --- a/phpBB/phpbb/ban/manager.php +++ b/phpBB/phpbb/ban/manager.php @@ -126,6 +126,7 @@ class manager $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, diff --git a/phpBB/phpbb/ban/type/user.php b/phpBB/phpbb/ban/type/user.php index c803e1b16f..a2b3f9b91b 100644 --- a/phpBB/phpbb/ban/type/user.php +++ b/phpBB/phpbb/ban/type/user.php @@ -84,6 +84,7 @@ class user extends base $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); diff --git a/tests/ban/ban_manager_test.php b/tests/ban/ban_manager_test.php index a5f3620217..4906b6781c 100644 --- a/tests/ban/ban_manager_test.php +++ b/tests/ban/ban_manager_test.php @@ -261,8 +261,9 @@ class ban_manager_test extends \phpbb_session_test_case 'ban_mode' => 'user', 'ban_userid' => 4, 'user_id' => '4', - 'username' => '', + 'username' => 'ipv6_user', 'username_clean' => 'ipv6_user', + 'label' => 'ipv6_user', ], ], ], @@ -650,8 +651,9 @@ class ban_manager_test extends \phpbb_session_test_case 'ban_reason_display' => '1', 'ban_mode' => 'user', 'user_id' => '4', - 'username' => '', + 'username' => 'ipv6_user', 'username_clean' => 'ipv6_user', + 'label' => 'ipv6_user', ], ], ], @@ -691,9 +693,73 @@ class ban_manager_test extends \phpbb_session_test_case $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(['foo'], $after_unban->invoke($ban_type_ip, ['items' => ['foo']])); + $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 index 39253d2681..c6c882fcf9 100644 --- a/tests/ban/fixtures/sessions_banlist.xml +++ b/tests/ban/fixtures/sessions_banlist.xml @@ -2,6 +2,7 @@
user_id + usernameusername_cleanuser_permissionsuser_sig @@ -11,6 +12,7 @@ 1 anonymous + anonymous @@ -20,6 +22,7 @@ 2 founder + founder admin@foo.bar @@ -29,6 +32,7 @@ 3 normal_user + normal_user normal_user@foo.bar @@ -38,6 +42,7 @@ 4 ipv6_user + ipv6_user normal_user@foo.bar @@ -47,6 +52,7 @@ 5 another_user + another_user bar@example.org From e54d54488cbc2bd14a92fe6e0caecfa11ab6ae6d Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 6 Aug 2023 13:59:43 +0200 Subject: [PATCH 43/54] [ticket/9687] Fix ban message for banned users PHPBB3-9687 --- phpBB/language/en/common.php | 4 ++-- phpBB/phpbb/ban/manager.php | 14 +++++++++++--- phpBB/phpbb/session.php | 2 +- 3 files changed, 14 insertions(+), 6 deletions(-) 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/manager.php b/phpBB/phpbb/ban/manager.php index 0acfd1e019..7455f7635c 100644 --- a/phpBB/phpbb/ban/manager.php +++ b/phpBB/phpbb/ban/manager.php @@ -554,11 +554,19 @@ class manager */ public function get_ban_message(array $ban_row, string $ban_triggered_by, string $contact_link): string { - $till_date = ($ban_row && $ban_row['end'] > 0) ? $this->user->format_date($ban_row['end']) : ''; + 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'; + } - $ban_type = $ban_row['ban_end'] ? 'BOARD_BAN_TIME' : 'BOARD_BAN_PERM'; $message = $this->language->lang($ban_type, $till_date, '', ''); - $message .= $ban_row['reason'] ? '

' . $this->language->lang('BOARD_BAN_REASON', $ban_row['reason']) : ''; + $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/session.php b/phpBB/phpbb/session.php index bdb0ad58a5..4c2471ab92 100644 --- a/phpBB/phpbb/session.php +++ b/phpBB/phpbb/session.php @@ -1170,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(); From 598f899fb86b5c477507652a81ecb00fdf98178a Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 11 Aug 2023 21:53:08 +0200 Subject: [PATCH 44/54] [ticket/9687] Fix converting phpBB2 bans PHPBB3-9687 --- phpBB/install/convertors/convert_phpbb20.php | 22 ++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/phpBB/install/convertors/convert_phpbb20.php b/phpBB/install/convertors/convert_phpbb20.php index af114ee398..e8266de86c 100644 --- a/phpBB/install/convertors/convert_phpbb20.php +++ b/phpBB/install/convertors/convert_phpbb20.php @@ -446,28 +446,38 @@ if (!$get_info) array( 'target' => BANS_TABLE, - 'execute_first' => 'phpbb_check_username_collisions();', + 'execute_first' => 'phpbb_check_username_collisions();', 'query_first' => array('target', $convert->truncate_statement . BANS_TABLE), 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_give_reason', '', ''), + array('ban_reason_display', '', ''), - 'where' => "banlist.ban_ip NOT LIKE '%.%' AMD banlist.ban_userid <> 0", + 'where' => "banlist.ban_ip NOT LIKE '%.%' AND banlist.ban_userid <> 0", ), array( 'target' => BANS_TABLE, - 'execute_first' => 'phpbb_check_username_collisions();', - 'query_first' => array('target', $convert->truncate_statement . BANS_TABLE), array('ban_mode', 'email', ''), array('ban_item', 'banlist.ban_email', ''), array('ban_reason', '', ''), array('ban_reason_display', '', ''), - 'where' => "banlist.ban_ip NOT LIKE '%.%' AMD banlist.ban_email <> ''", + '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( From 8e80d734c83c04739f8c6e8b1bb40fcc1113f101 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 11 Aug 2023 21:53:26 +0200 Subject: [PATCH 45/54] [ticket/9687] Use correct sql_error call to prevent accessing private member PHPBB3-9687 --- phpBB/install/convert/convertor.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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); From 8a15670055525839d8157f3685002592ce99e7bb Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 12 Aug 2023 12:45:27 +0200 Subject: [PATCH 46/54] [ticket/9687] Update deprecated notices and helper functions PHPBB3-9687 --- phpBB/includes/functions_user.php | 19 +++++-- phpBB/phpbb/ban/manager.php | 4 +- tests/ban/ban_manager_test.php | 1 + tests/functions/fixtures/banned_users.xml | 45 ++++++++++++++- tests/functions/phpbb_get_banned_user_ids.php | 55 ++++++++++++++++--- 5 files changed, 104 insertions(+), 20 deletions(-) diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php index c50e0d01ee..1939d0ff78 100644 --- a/phpBB/includes/functions_user.php +++ b/phpBB/includes/functions_user.php @@ -915,7 +915,7 @@ 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) +* @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 @@ -970,14 +970,12 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_reason, $ban_give_ $end->setTimestamp($ban_end); return $ban_manager->ban($mode, $items, $start, $end, $ban_reason, $ban_give_reason); - - // TODO: logging } /** * Unban User * -* @deprecated 3.3.0-a1 (To be removed: 4.0.0) +* @deprecated 4.0.0-a1 (To be removed: 4.1.0) */ function user_unban($mode, $ban) { @@ -3254,8 +3252,6 @@ 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 @@ -3283,10 +3279,21 @@ function phpbb_get_banned_user_ids($user_ids = array(), $ban_end = true) return $end <= 0 || $end > (int) $ban_end; }); } + else + { + $banned_users = array_filter($banned_users, function ($end) { + return $end <= 0 || $end > time(); + }); + } $result_array = []; foreach ($banned_users as $user_id => $_) { + if (count($user_ids) && !in_array($user_id, $user_ids)) + { + continue; + } + $result_array[$user_id] = $user_id; } diff --git a/phpBB/phpbb/ban/manager.php b/phpBB/phpbb/ban/manager.php index 7455f7635c..7586cb6dde 100644 --- a/phpBB/phpbb/ban/manager.php +++ b/phpBB/phpbb/ban/manager.php @@ -417,9 +417,7 @@ class manager $this->cache->put(self::CACHE_KEY_USERS, $banned_users, self::CACHE_TTL); } - return array_filter($banned_users, function ($end) { - return $end <= 0 || $end > time(); - }); + return $banned_users; } /** diff --git a/tests/ban/ban_manager_test.php b/tests/ban/ban_manager_test.php index 4906b6781c..2eb49686d6 100644 --- a/tests/ban/ban_manager_test.php +++ b/tests/ban/ban_manager_test.php @@ -403,6 +403,7 @@ class ban_manager_test extends \phpbb_session_test_case [ 4 => 0, 5 => 0, + 19 => 1234, 20 => 0, ], $ban_manager->get_banned_users() diff --git a/tests/functions/fixtures/banned_users.xml b/tests/functions/fixtures/banned_users.xml index 4d6a6bfa40..082f210ca3 100644 --- a/tests/functions/fixtures/banned_users.xml +++ b/tests/functions/fixtures/banned_users.xml @@ -2,27 +2,68 @@
ban_userid + ban_modeban_end 2 - 0 + user 0 3 + user 0 4 + user 2 5 - 999999999999999999999 + user + 2147485547 6 + 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/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 */ From 63473239f2c51fb9e9c4cfad1543416d5430f442 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 12 Aug 2023 22:37:13 +0200 Subject: [PATCH 47/54] [ticket/9687] Remove open todos and revert back to old regex PHPBB3-9687 --- phpBB/phpbb/ban/type/base.php | 1 - phpBB/phpbb/ban/type/email.php | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/phpBB/phpbb/ban/type/base.php b/phpBB/phpbb/ban/type/base.php index a331813ab5..70885a2847 100644 --- a/phpBB/phpbb/ban/type/base.php +++ b/phpBB/phpbb/ban/type/base.php @@ -61,7 +61,6 @@ abstract class base implements type_interface */ public function set_user(\phpbb\user $user): void { - // TODO: Implement new logging $this->user = $user; } diff --git a/phpBB/phpbb/ban/type/email.php b/phpBB/phpbb/ban/type/email.php index 46905994b4..bc70cdd00e 100644 --- a/phpBB/phpbb/ban/type/email.php +++ b/phpBB/phpbb/ban/type/email.php @@ -40,7 +40,7 @@ class email extends base { $this->get_excluded(); - $regex = '#^.*?@.*|(([a-z0-9\-]+\.)+([a-z]{2,3}))$#i'; // TODO + $regex = '#^.*?@*|(([a-z0-9\-]+\.)+([a-z]{2,3}))$#i'; $ban_items = []; foreach ($items as $item) From 21b389bb81206cbb4b85fb021a194bf02fa0b38f Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 13 Aug 2023 12:25:57 +0200 Subject: [PATCH 48/54] [ticket/9687] Require @ sign in emails PHPBB3-9687 --- phpBB/phpbb/ban/type/email.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/ban/type/email.php b/phpBB/phpbb/ban/type/email.php index bc70cdd00e..213084fc24 100644 --- a/phpBB/phpbb/ban/type/email.php +++ b/phpBB/phpbb/ban/type/email.php @@ -40,7 +40,7 @@ class email extends base { $this->get_excluded(); - $regex = '#^.*?@*|(([a-z0-9\-]+\.)+([a-z]{2,3}))$#i'; + $regex = '#^.*?@.*|(([a-z0-9\-]+\.)+([a-z]{2,3}))$#i'; $ban_items = []; foreach ($items as $item) From 51ea6d8241fffc3f59259adaa8f53e563d487190 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 13 Aug 2023 12:28:56 +0200 Subject: [PATCH 49/54] [ticket/9687] Remove exclude from banning lang strings PHPBB3-9687 --- phpBB/language/en/acp/ban.php | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/phpBB/language/en/acp/ban.php b/phpBB/language/en/acp/ban.php index ad73553649..6f15932c1e 100644 --- a/phpBB/language/en/acp/ban.php +++ b/phpBB/language/en/acp/ban.php @@ -54,20 +54,19 @@ $lang = array_merge($lang, array( 'EMAIL_BAN' => 'Ban one or more email addresses', '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_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', @@ -75,6 +74,6 @@ $lang = array_merge($lang, array( 'USER_BAN' => 'Ban one or more users by username', '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.', )); From 0901633349fa7ef476fb0fd80bac89a61a77416a Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 5 Nov 2023 20:21:13 +0100 Subject: [PATCH 50/54] [ticket/9687] Improve ban query PHPBB3-9687 --- phpBB/includes/functions_user.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php index 1939d0ff78..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 ' . BANS_TABLE . ' - WHERE ban_mode = \'user\' AND ' . $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 From 744bf162b3769f12e7128263a7fa57a8e9d5a986 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 5 Nov 2023 21:12:20 +0100 Subject: [PATCH 51/54] [ticket/9687] Adjust query to use join again PHPBB3-9687 --- phpBB/index.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/phpBB/index.php b/phpBB/index.php index 9f240d4f27..fafe5f9ff1 100644 --- a/phpBB/index.php +++ b/phpBB/index.php @@ -112,7 +112,14 @@ if ($show_birthdays) 'FROM' => array( USERS_TABLE => 'u', ), - 'WHERE' => 'u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ") + 'LEFT_JOIN' => array( + array( + 'FROM' => array(BANS_TABLE => 'b'), + 'ON' => 'u.user_id = b.ban_userid', + ), + ), + '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)", ); From eacfe7be7bfc1d6bec44164bb2a3523430b76975 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Mon, 6 Nov 2023 17:58:13 +0100 Subject: [PATCH 52/54] [ticket/9687] Remove no longer needed code after adjusting query PHPBB3-9687 --- phpBB/index.php | 9 --------- 1 file changed, 9 deletions(-) diff --git a/phpBB/index.php b/phpBB/index.php index fafe5f9ff1..bc7c1a4707 100644 --- a/phpBB/index.php +++ b/phpBB/index.php @@ -140,17 +140,8 @@ 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) : ''; From 13361a3b4b060989ee4ea8ea5719a45c72a182a1 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Mon, 6 Nov 2023 20:28:42 +0100 Subject: [PATCH 53/54] [ticket/9687] Clean up code some more PHPBB3-9687 --- phpBB/install/convertors/convert_phpbb20.php | 9 ++++++--- phpBB/phpbb/ban/type/base.php | 4 ++-- phpBB/phpbb/ban/type/user.php | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/phpBB/install/convertors/convert_phpbb20.php b/phpBB/install/convertors/convert_phpbb20.php index e8266de86c..afea6a92da 100644 --- a/phpBB/install/convertors/convert_phpbb20.php +++ b/phpBB/install/convertors/convert_phpbb20.php @@ -455,7 +455,8 @@ if (!$get_info) array('ban_reason', '', ''), array('ban_reason_display', '', ''), - 'where' => "banlist.ban_ip NOT LIKE '%.%' AND banlist.ban_userid <> 0", + 'where' => "banlist.ban_ip NOT LIKE '%.%' + AND banlist.ban_userid <> 0", ), array( @@ -466,7 +467,8 @@ if (!$get_info) array('ban_reason', '', ''), array('ban_reason_display', '', ''), - 'where' => "banlist.ban_ip NOT LIKE '%.%' AND banlist.ban_email <> ''", + 'where' => "banlist.ban_ip NOT LIKE '%.%' + AND banlist.ban_email <> ''", ), array( @@ -477,7 +479,8 @@ if (!$get_info) array('ban_reason', '', ''), array('ban_reason_display', '', ''), - 'where' => "banlist.ban_userid = 0 AND banlist.ban_ip <> ''", + 'where' => "banlist.ban_userid = 0 + AND banlist.ban_ip <> ''", ), array( diff --git a/phpBB/phpbb/ban/type/base.php b/phpBB/phpbb/ban/type/base.php index 70885a2847..1ae7080991 100644 --- a/phpBB/phpbb/ban/type/base.php +++ b/phpBB/phpbb/ban/type/base.php @@ -112,7 +112,7 @@ abstract class base implements type_interface FROM ' . $this->bans_table . ' WHERE (ban_end >= ' . time() . " OR ban_end = 0) - AND ban_mode = '{$this->get_type()}' + 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); @@ -143,7 +143,7 @@ abstract class base implements type_interface $this->excluded[$this->user->id()] = $this->user->data[$user_column]; } - $sql = "SELECT user_id, {$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); diff --git a/phpBB/phpbb/ban/type/user.php b/phpBB/phpbb/ban/type/user.php index a2b3f9b91b..bfd28e323c 100644 --- a/phpBB/phpbb/ban/type/user.php +++ b/phpBB/phpbb/ban/type/user.php @@ -79,7 +79,7 @@ class user extends base WHERE (b.ban_end >= ' . time() . " OR b.ban_end = 0) AND b.ban_userid = u.user_id - AND b.ban_mode = '{$this->get_type()}' + 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)) From 58b777b51cc613ce12924251499502e9be639a11 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Mon, 6 Nov 2023 20:30:59 +0100 Subject: [PATCH 54/54] [ticket/9687] Some more code cleanup after code review PHPBB3-9687 --- phpBB/includes/acp/acp_ban.php | 2 +- phpBB/phpbb/ban/manager.php | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/phpBB/includes/acp/acp_ban.php b/phpBB/includes/acp/acp_ban.php index 9d853aaede..61f3096b74 100644 --- a/phpBB/includes/acp/acp_ban.php +++ b/phpBB/includes/acp/acp_ban.php @@ -186,7 +186,7 @@ class acp_ban 'L_BAN_CELL' => $l_ban_cell, 'L_NO_BAN_CELL' => $l_no_ban_cell, - 'S_USERNAME_BAN' => $mode == 'user', + '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/phpbb/ban/manager.php b/phpBB/phpbb/ban/manager.php index 7586cb6dde..e48e734617 100644 --- a/phpBB/phpbb/ban/manager.php +++ b/phpBB/phpbb/ban/manager.php @@ -117,7 +117,7 @@ class manager // 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); + AND " . $this->db->sql_in_set('ban_item', $ban_items, false, true); $this->db->sql_query($sql); $insert_array = []; @@ -468,7 +468,8 @@ class manager { // Delete stale bans $sql = 'DELETE FROM ' . $this->bans_table . ' - WHERE ban_end > 0 AND ban_end < ' . (int) time(); + WHERE ban_end > 0 + AND ban_end < ' . (int) time(); $this->db->sql_query($sql); /** @var type_interface $type */