Index: session.php =================================================================== --- session.php (revision 9325) +++ session.php (working copy) @@ -1011,48 +1011,49 @@ $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 '; + /* This implements a rather long query to find matching banlist entries. It's not completely + unambiguous but it uses SQL's REGEX feature rather than PHP's, making it a lot more efficient than + the old implementation, which was extremely unscalable with large banlists. */ + $sql = 'SELECT ban_ip, ban_userid, ban_email, ban_exclude, ban_give_reason, ban_end' . + ' FROM ' . BANLIST_TABLE . + ' WHERE ('; + if ($user_id !== false) + { + $sql .= "ban_userid = " . $user_id; + if ($user_ips !== false or $user_email !== false) { $sql .= " OR "; } + } - // Determine which entries to check, only return those - if ($user_email === false) - { - $where_sql[] = "ban_email = ''"; - } + if ($user_ips !== false) + { + $sql .= "("; + list($octet1, $octet2, $octet3, $octet4) = split('\.', $user_ips, 4); + $sql .= "ban_ip = '" . $user_ips . "'" . + " OR '" . $octet1 . ".*' RLIKE ban_ip" . + " OR '" . $octet1 . "." . $octet2 . ".*' RLIKE ban_ip" . + " OR '" . $octet1 . "." . $octet2 . "." . $octet3 . ".*' RLIKE ban_ip" . + " OR '" . "*." . $octet2 . "." . $octet3 . "." . $octet4 . "' RLIKE ban_ip" . + " OR '" . "*." . $octet3 . "." . $octet4 . "' RLIKE ban_ip" . + " OR '" . "*." . $octet4 . "' RLIKE ban_ip" . + " OR '" . $octet1 . ".*." . $octet4 . "' RLIKE ban_ip" . + " OR '" . $octet1 . "." . $octet2 . ".*." . $octet4 . "' RLIKE ban_ip" . + " OR '" . "*." . $octet2 . ".*" . "' RLIKE ban_id" . + " OR '" . "*." . $octet2 . "." . $octet3 . ".*" . "' RLIKE ban_ip" . + " OR '" . "*." . $octet2 . ".*." . $octet4 . "' RLIKE ban_ip" . + " OR '" . $octet1 . ".*." . $octet3 . ".*" . "' RLIKE ban_ip"; + $sql .= ")"; + if ($user_email !== false) { $sql .= " OR "; } + } - if ($user_ips === false) - { - $where_sql[] = "(ban_ip = '' OR ban_exclude = 1)"; - } + if ($user_email !== false) + { + $sql .= "ban_email = '" . $user_email . "'" . " OR ban_exclude = 1"; + $search_email = str_replace(".", "*.*", $user_email); + $search_email = str_replace("@", "*@*", $search_email); + $sql .= " OR '" . $search_email . "'"; + } + $sql .= ")"; - 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 .= (sizeof($where_sql)) ? implode(' AND ', $where_sql) : ''; $result = $db->sql_query($sql, $cache_ttl); $ban_triggered_by = 'user'; @@ -2232,4 +2233,4 @@ } }