diff --git a/composer.lock b/composer.lock index efdadcd8..12147aae 100644 --- a/composer.lock +++ b/composer.lock @@ -388,12 +388,12 @@ "source": { "type": "git", "url": "https://github.com/shish/microcrud.git", - "reference": "41a8aea2af6441c212467670776dc182518c5ff4" + "reference": "6471a4c7445e872282f12d1de3730db55d5c06e2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/shish/microcrud/zipball/41a8aea2af6441c212467670776dc182518c5ff4", - "reference": "41a8aea2af6441c212467670776dc182518c5ff4", + "url": "https://api.github.com/repos/shish/microcrud/zipball/6471a4c7445e872282f12d1de3730db55d5c06e2", + "reference": "6471a4c7445e872282f12d1de3730db55d5c06e2", "shasum": "" }, "require": { @@ -429,7 +429,7 @@ "crud", "generator" ], - "time": "2019-11-28T15:23:53+00:00" + "time": "2019-11-28T15:53:53+00:00" }, { "name": "shish/microhtml", diff --git a/ext/ipban/main.php b/ext/ipban/main.php index 0fe126b9..49e0bbee 100644 --- a/ext/ipban/main.php +++ b/ext/ipban/main.php @@ -260,140 +260,68 @@ class IPBan extends Extension private function check_ip_ban() { $remote = $_SERVER['REMOTE_ADDR']; - $bans = $this->get_active_bans_sorted(); - - // bans[0] = IPs - if (isset($bans[0][$remote])) { - $this->block($remote); // never returns + list($ips, $networks) = $this->get_active_bans_grouped(); + if (isset($ips[$remote])) { + $this->block($ips[$remote]); // never returns } - - // bans[1] = CIDR nets - foreach ($bans[1] as $ip => $true) { - if (ip_in_range($remote, $ip)) { - $this->block($remote); // never returns + foreach ($networks as $range => $ban_id) { + if (ip_in_range($remote, $range)) { + $this->block($ban_id); // never returns } } } - private function block(string $remote) + private function block(int $ban_id) { global $config, $database; - $prefix = ($database->get_driver_name() == DatabaseDriver::SQLITE ? "bans." : ""); + $row = $database->get_row("SELECT * FROM bans WHERE id=:id", ["id"=>$ban_id]); - $bans = $this->get_bans(false, null); - - foreach ($bans as $row) { - $ip = $row[$prefix."ip"]; - if ( - (strstr($ip, '/') && ip_in_range($remote, $ip)) || - ($ip == $remote) - ) { - $reason = $row[$prefix.'reason']; - $admin = User::by_id($row[$prefix.'banner_id']); - $date = $row['expires']; - $msg = $config->get_string("ipban_message"); - $msg = str_replace('$IP', $ip, $msg); - $msg = str_replace('$DATE', $date, $msg); - $msg = str_replace('$ADMIN', $admin->name, $msg); - $msg = str_replace('$REASON', $reason, $msg); - $contact_link = contact_link(); - if (!empty($contact_link)) { - $msg = str_replace('$CONTACT', "Contact the staff (be sure to include this message)", $msg); - } else { - $msg = str_replace('$CONTACT', "", $msg); - } - header("HTTP/1.0 403 Forbidden"); - print "$msg"; - - exit; - } + $msg = $config->get_string("ipban_message"); + $msg = str_replace('$IP', $row["ip"], $msg); + $msg = str_replace('$DATE', $row['expires'], $msg); + $msg = str_replace('$ADMIN', User::by_id($row['banner_id'])->name, $msg); + $msg = str_replace('$REASON', $row['reason'], $msg); + $contact_link = contact_link(); + if (!empty($contact_link)) { + $msg = str_replace('$CONTACT', "Contact the staff (be sure to include this message)", $msg); + } else { + $msg = str_replace('$CONTACT', "", $msg); } - log_error("ipban", "block($remote) called but no bans matched"); + + header("HTTP/1.0 403 Forbidden"); + print "$msg"; exit; } - private function get_bans(bool $all, ?int $page) - { - global $database; - - $size = 100; - if (@$_GET['limit']) { - $size = int_escape($_GET['limit']); - } - $filters = ["1=1"]; - $args = []; - - if (!$all) { - $filters[] = "((expires > CURRENT_TIMESTAMP) OR (expires IS NULL))"; - } - if (@$_GET['s_ip']) { - $filters[] = "(ip = :ip)"; - $args['ip'] = $_GET['s_ip']; - } - if (@$_GET['s_reason']) { - $filters[] = "(reason LIKE :reason)"; - $args['reason'] = '%' . $_GET['s_reason'] . "%"; - } - if (@$_GET['s_banner']) { - $filters[] = "(banner_id = :banner_id)"; - $args['banner_id'] = User::by_name($_GET['s_banner'])->id; - } - if (@$_GET['s_added']) { - $filters[] = "(added LIKE :added)"; - $args['added'] = '%' . $_GET['s_added'] . "%"; - } - if (@$_GET['s_expires']) { - $filters[] = "(expires LIKE :expires)"; - $args['expires'] = '%' . $_GET['s_expires'] . "%"; - } - if (@$_GET['s_mode']) { - $filters[] = "(mode = :mode)"; - $args['mode'] = $_GET['s_mode']; - } - $filter = implode(" AND ", $filters); - - if (is_null($page)) { - $pager = ""; - } else { - $pager = "LIMIT :limit OFFSET :offset"; - $args["offset"] = ($page-1)*$size; - $args['limit'] = $size; - } - - return $database->get_all(" - SELECT bans.*, users.name as banner_name - FROM bans - JOIN users ON banner_id = users.id - WHERE $filter - ORDER BY expires, bans.id - $pager - ", $args); - } - // returns [ips, nets] - private function get_active_bans_sorted() + private function get_active_bans_grouped() { - global $cache; + global $cache, $database; - $cached = $cache->get("ip_bans_sorted"); + $cached = $cache->get("ip_to_ban_id_grouped"); if ($cached) { return $cached; } - $bans = $this->get_bans(false, null); - $ips = []; # "0.0.0.0" => false); - $nets = []; # "0.0.0.0/32" => false); - foreach ($bans as $row) { - if (strstr($row['ip'], '/')) { - $nets[$row['ip']] = true; + $rows = $database->get_pairs(" + SELECT ip, id + FROM bans + WHERE ((expires > CURRENT_TIMESTAMP) OR (expires IS NULL)) + "); + + $ips = []; # "0.0.0.0" => 123; + $nets = []; # "0.0.0.0/32" => 456; + foreach ($rows as $ip => $id) { + if (strstr($ip, '/')) { + $nets[$ip] = $id; } else { - $ips[$row['ip']] = true; + $ips[$ip] = $id; } } $sorted = [$ips, $nets]; - $cache->set("ip_bans_sorted", $sorted, 600); + $cache->set("ip_to_ban_id_grouped", $sorted, 600); return $sorted; } }