summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Foster <savetheinternet@tinyboard.org>2013-09-10 16:20:54 +1000
committerMichael Foster <savetheinternet@tinyboard.org>2013-09-10 16:20:54 +1000
commit104e2bce6d6e9d222db77b87cd9824a8b7e66105 (patch)
treee561801070f05b0e03141682f56a406ddf0d11b5
parent99fa2f7cda5c8c912ef9e2779c2d75c7d45658c9 (diff)
Combine ban checking into single SQL query. Messy/inefficient query, but good enough.
-rw-r--r--inc/functions.php60
1 files changed, 28 insertions, 32 deletions
diff --git a/inc/functions.php b/inc/functions.php
index f19e00ae..5a95c851 100644
--- a/inc/functions.php
+++ b/inc/functions.php
@@ -639,7 +639,7 @@ function displayBan($ban) {
));
}
-function checkBan($board = 0) {
+function checkBan($board = false) {
global $config;
if (!isset($_SERVER['REMOTE_ADDR'])) {
@@ -649,35 +649,33 @@ function checkBan($board = 0) {
if (event('check-ban', $board))
return true;
-
- $query = prepare("SELECT `set`, `expires`, `reason`, `board`, `seen`, `id` FROM ``bans`` WHERE (`board` IS NULL OR `board` = :board) AND `ip` = :ip ORDER BY `expires` IS NULL DESC, `expires` DESC LIMIT 1");
+
+ $query_where = array();
+ // Simple ban
+ $query_where[] = "`ip` = :ip";
+ // Range ban
+ if ($config['ban_range'])
+ $query_where[] = ":ip LIKE REPLACE(REPLACE(`ip`, '%', '!%'), '*', '%') ESCAPE '!'";
+ // Subnet mask ban
+ if ($config['ban_cidr'] && !isIPv6())
+ $query_where[] = "(
+ `ip` REGEXP '^(\[0-9]+\.\[0-9]+\.\[0-9]+\.\[0-9]+\)\/(\[0-9]+)$'
+ AND
+ :iplong >= INET_ATON(SUBSTRING_INDEX(`ip`, '/', 1))
+ AND
+ :iplong < INET_ATON(SUBSTRING_INDEX(`ip`, '/', 1)) + POW(2, 32 - SUBSTRING_INDEX(`ip`, '/', -1))
+ )";
+
+ $query = prepare('SELECT * FROM ``bans`` WHERE (`board` IS NULL' . ($board ? ' OR `board` = :board' : '') .
+ ') AND (' . implode(' OR ', $query_where) . ') ORDER BY `expires` IS NULL, `expires` DESC');
+ if ($board)
+ $query->bindValue(':board', $board);
$query->bindValue(':ip', $_SERVER['REMOTE_ADDR']);
- $query->bindValue(':board', $board);
+ if ($config['ban_cidr'] && !isIPv6())
+ $query->bindValue(':iplong', ip2long($_SERVER['REMOTE_ADDR']));
$query->execute() or error(db_error($query));
- if ($query->rowCount() < 1 && $config['ban_range']) {
- $query = prepare("SELECT `set`, `expires`, `reason`, `board`, `seen`, `id` FROM ``bans`` WHERE (`board` IS NULL OR `board` = :board) AND :ip LIKE REPLACE(REPLACE(`ip`, '%', '!%'), '*', '%') ESCAPE '!' ORDER BY `expires` IS NULL DESC, `expires` DESC LIMIT 1");
- $query->bindValue(':ip', $_SERVER['REMOTE_ADDR']);
- $query->bindValue(':board', $board);
- $query->execute() or error(db_error($query));
- }
-
- if ($query->rowCount() < 1 && $config['ban_cidr'] && !isIPv6()) {
- // my most insane SQL query yet
- $query = prepare("SELECT `set`, `expires`, `reason`, `board`, `seen`, ``bans``.`id` FROM ``bans`` WHERE (`board` IS NULL OR `board` = :board)
- AND (
- `ip` REGEXP '^(\[0-9]+\.\[0-9]+\.\[0-9]+\.\[0-9]+\)\/(\[0-9]+)$'
- AND
- :ip >= INET_ATON(SUBSTRING_INDEX(`ip`, '/', 1))
- AND
- :ip < INET_ATON(SUBSTRING_INDEX(`ip`, '/', 1)) + POW(2, 32 - SUBSTRING_INDEX(`ip`, '/', -1))
- )
- ORDER BY `expires` IS NULL DESC, `expires` DESC LIMIT 1");
- $query->bindValue(':ip', ip2long($_SERVER['REMOTE_ADDR']));
- $query->bindValue(':board', $board);
- $query->execute() or error(db_error($query));
- }
-
- if ($ban = $query->fetch(PDO::FETCH_ASSOC)) {
+
+ while ($ban = $query->fetch(PDO::FETCH_ASSOC)) {
if ($ban['expires'] && $ban['expires'] < time()) {
// Ban expired
$query = prepare("DELETE FROM ``bans`` WHERE `id` = :id");
@@ -687,11 +685,9 @@ function checkBan($board = 0) {
if ($config['require_ban_view'] && !$ban['seen']) {
displayBan($ban);
}
-
- return;
+ } else {
+ displayBan($ban);
}
-
- displayBan($ban);
}
// I'm not sure where else to put this. It doesn't really matter where; it just needs to be called every now and then to keep the ban list tidy.