From b009fc749ec12129c110f1df284bea36b00770a0 Mon Sep 17 00:00:00 2001 From: Zankaria Date: Fri, 22 Mar 2024 10:49:47 +0100 Subject: [PATCH] bans.php: group deletions --- inc/bans.php | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++-- post.php | 10 ++------ 2 files changed, 70 insertions(+), 10 deletions(-) diff --git a/inc/bans.php b/inc/bans.php index 5ee51216..20970a3b 100644 --- a/inc/bans.php +++ b/inc/bans.php @@ -3,6 +3,31 @@ use Lifo\IP\CIDR; class Bans { + static private function deleteBans($ban_ids) { + $len = count($ban_ids); + if ($len === 1) { + $query = prepare('DELETE FROM ``bans`` WHERE `id` = :id'); + $query->bindValue(':id', $ban_ids[0], PDO::PARAM_INT); + $query->execute() or error(db_error()); + } elseif ($len >= 1) { + // Build the query. + $query = 'DELETE FROM ``bans`` WHERE `id` IN ('; + for ($i = 0; $i < $len; $i++) { + $query .= ":id{$i},"; + } + // Substitute the last comma with a parenthesis. + substr_replace($query, ')', strlen($query) - 1); + + // Bind the params + $query = prepare($query); + for ($i = 0; $i < $len; $i++) { + $query->bindValue(":id{$i}", (int)$ban_ids[$i], PDO::PARAM_INT); + } + + $query->execute() or error(db_error()); + } + } + static public function range_to_string($mask) { list($ipstart, $ipend) = $mask; @@ -115,7 +140,45 @@ class Bans { return array($ipstart, $ipend); } - static public function find($ip, $board = false, $get_mod_info = false) { + static public function findSingle($ip, $ban_id, $require_ban_view) { + /** + * Use OR in the query to also garbage collect bans. Ideally we should move the whole GC procedure to a separate + * script, but it will require a more important restructuring. + */ + $query = prepare( + 'SELECT ``bans``.* FROM ``bans`` + WHERE ((`ipstart` = :ip OR (:ip >= `ipstart` AND :ip <= `ipend`)) OR (``bans``.id = :id)) + ORDER BY `expires` IS NULL, `expires` DESC' + ); + + $query->bindValue(':id', $ban_id); + $query->bindValue(':ip', inet_pton($ip)); + + $query->execute() or error(db_error($query)); + + $found_ban = null; + $to_delete_list = []; + + while ($ban = $query->fetch(PDO::FETCH_ASSOC)) { + if ($ban['expires'] && ($ban['seen'] || !$require_ban_view) && $ban['expires'] < time()) { + $to_delete_list[] = $ban['id']; + } elseif ($ban['id'] === $ban_id) { + if ($ban['post']) { + $ban['post'] = json_decode($ban['post'], true); + } + $ban['mask'] = self::range_to_string(array($ban['ipstart'], $ban['ipend'])); + $found_ban = $ban; + } + } + + self::deleteBans($to_delete_list); + + rebuildThemes('bans'); + + return $found_ban; + } + + static public function find($ip, $board = false, $get_mod_info = false, $banid = null) { global $config; $query = prepare('SELECT ``bans``.*' . ($get_mod_info ? ', `username`' : '') . ' FROM ``bans`` @@ -132,10 +195,11 @@ class Bans { $query->execute() or error(db_error($query)); $ban_list = array(); + $to_delete_list = []; while ($ban = $query->fetch(PDO::FETCH_ASSOC)) { if ($ban['expires'] && ($ban['seen'] || !$config['require_ban_view']) && $ban['expires'] < time()) { - self::delete($ban['id']); + $to_delete_list[] = $ban['id']; } else { if ($ban['post']) { $ban['post'] = json_decode($ban['post'], true); @@ -145,6 +209,8 @@ class Bans { } } + self::deleteBans($to_delete_list); + return $ban_list; } diff --git a/post.php b/post.php index 2727738c..a735affe 100644 --- a/post.php +++ b/post.php @@ -1673,15 +1673,9 @@ function handle_appeal() $ban_id = (int) $_POST['ban_id']; $source_ip = $_SERVER['REMOTE_ADDR']; - $bans = Bans::find($source_ip); - foreach ($bans as $_ban) { - if ($_ban['id'] == $ban_id) { - $ban = $_ban; - break; - } - } + $ban = Bans::findSingle($_SERVER['REMOTE_ADDR'], $ban_id, $config['require_ban_view']); - if (!isset($ban)) { + if (empty($ban)) { error($config['error']['noban']); }