[ticket/9687] Finish ban check and tidy methods

PHPBB3-9687
This commit is contained in:
Oliver Schramm 2018-09-29 15:23:15 +02:00 committed by Marc Alexander
parent 95de576ccd
commit c8b8675dff
No known key found for this signature in database
GPG key ID: 50E0D2423696F995
7 changed files with 194 additions and 21 deletions

View file

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

View file

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

View file

@ -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;
}
}

View file

@ -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()
{
}

View file

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

View file

@ -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();
}

View file

@ -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;
}
}