Database backed stickybans.

This commit is contained in:
oranges
2019-03-17 13:33:48 +13:00
committed by yogstation13-bot
parent b663d96166
commit d8ab6375c0
13 changed files with 717 additions and 99 deletions

View File

@@ -1,15 +1,53 @@
Any time you make a change to the schema files, remember to increment the database schema version. Generally increment the minor number, major should be reserved for significant changes to the schema. Both values go up to 255.
The latest database version is 4.7; The query to update the schema revision table is:
The latest database version is 5.1; The query to update the schema revision table is:
INSERT INTO `schema_revision` (`major`, `minor`) VALUES (5, 0);
INSERT INTO `schema_revision` (`major`, `minor`) VALUES (5, 1);
or
INSERT INTO `SS13_schema_revision` (`major`, `minor`) VALUES (5, 0);
INSERT INTO `SS13_schema_revision` (`major`, `minor`) VALUES (5, 1);
In any query remember to add a prefix to the table names if you use one.
----------------------------------------------------
Version 5.1, 25 Feb 2018, by MrStonedOne
Added four tables to enable storing of stickybans in the database since byond can lose them, and to enable disabling stickybans for a round without depending on a crash free round. Existing stickybans are automagically imported to the tables.
CREATE TABLE `stickyban` (
`ckey` VARCHAR(32) NOT NULL,
`reason` VARCHAR(2048) NOT NULL,
`banning_admin` VARCHAR(32) NOT NULL,
`datetime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`ckey`)
) ENGINE=InnoDB;
CREATE TABLE `stickyban_matched_ckey` (
`stickyban` VARCHAR(32) NOT NULL,
`matched_ckey` VARCHAR(32) NOT NULL,
`first_matched` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`last_matched` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`exempt` TINYINT(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`stickyban`, `matched_ckey`)
) ENGINE=InnoDB;
CREATE TABLE `stickyban_matched_ip` (
`stickyban` VARCHAR(32) NOT NULL,
`matched_ip` INT UNSIGNED NOT NULL,
`first_matched` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`last_matched` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`stickyban`, `matched_ip`)
) ENGINE=InnoDB;
CREATE TABLE `stickyban_matched_cid` (
`stickyban` VARCHAR(32) NOT NULL,
`matched_cid` VARCHAR(32) NOT NULL,
`first_matched` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`last_matched` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`stickyban`, `matched_cid`)
) ENGINE=InnoDB;
----------------------------------------------------
Version 5.0, 28 October 2018, by Jordie0608
Modified ban table to remove the need for the `bantype` column, a python script is used to migrate data to this new format.
@@ -88,8 +126,7 @@ Added table `role_time_log` and triggers `role_timeTlogupdate`, `role_timeTlogin
CREATE TABLE `role_time_log` ( `id` BIGINT NOT NULL AUTO_INCREMENT , `ckey` VARCHAR(32) NOT NULL , `job` VARCHAR(128) NOT NULL , `delta` INT NOT NULL , `datetime` TIMESTAMP on update CURRENT_TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP , PRIMARY KEY (`id`), INDEX (`ckey`), INDEX (`job`), INDEX (`datetime`)) ENGINE = InnoDB;
DELIMITER
$$
DELIMITER $$
CREATE TRIGGER `role_timeTlogupdate` AFTER UPDATE ON `role_time` FOR EACH ROW BEGIN INSERT into role_time_log (ckey, job, delta) VALUES (NEW.CKEY, NEW.job, NEW.minutes-OLD.minutes);
END
$$
@@ -99,7 +136,7 @@ $$
CREATE TRIGGER `role_timeTlogdelete` AFTER DELETE ON `role_time` FOR EACH ROW BEGIN INSERT into role_time_log (ckey, job, delta) VALUES (OLD.ckey, OLD.job, 0-OLD.minutes);
END
$$
DELIMITER ;
----------------------------------------------------
Version 4.2, 17 April 2018, by Jordie0608

View File

@@ -462,6 +462,57 @@ $$
CREATE TRIGGER `role_timeTlogdelete` AFTER DELETE ON `role_time` FOR EACH ROW BEGIN INSERT into role_time_log (ckey, job, delta) VALUES (OLD.ckey, OLD.job, 0-OLD.minutes);
END
$$
DELIMITER ;
--
-- Table structure for table `stickyban`
--
DROP TABLE IF EXISTS `stickyban`;
CREATE TABLE `stickyban` (
`ckey` VARCHAR(32) NOT NULL,
`reason` VARCHAR(2048) NOT NULL,
`banning_admin` VARCHAR(32) NOT NULL,
`datetime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`ckey`)
) ENGINE=InnoDB;
--
-- Table structure for table `stickyban_matched_ckey`
--
DROP TABLE IF EXISTS `stickyban_matched_ckey`;
CREATE TABLE `ss13_stickyban_matched_ckey` (
`stickyban` VARCHAR(32) NOT NULL,
`matched_ckey` VARCHAR(32) NOT NULL,
`first_matched` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`last_matched` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`exempt` TINYINT(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`stickyban`, `matched_ckey`)
) ENGINE=InnoDB;
--
-- Table structure for table `ss13_stickyban_matched_ip`
--
DROP TABLE IF EXISTS `ss13_stickyban_matched_ip`;
CREATE TABLE `ss13_stickyban_matched_ip` (
`stickyban` VARCHAR(32) NOT NULL,
`matched_ip` INT UNSIGNED NOT NULL,
`first_matched` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`last_matched` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`stickyban`, `matched_ip`)
) ENGINE=InnoDB;
--
-- Table structure for table `stickyban_matched_cid`
--
DROP TABLE IF EXISTS `stickyban_matched_cid`;
CREATE TABLE `stickyban_matched_cid` (
`stickyban` VARCHAR(32) NOT NULL,
`matched_cid` VARCHAR(32) NOT NULL,
`first_matched` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`last_matched` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`stickyban`, `matched_cid`)
) ENGINE=InnoDB;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;

View File

@@ -462,6 +462,58 @@ $$
CREATE TRIGGER `SS13_role_timeTlogdelete` AFTER DELETE ON `SS13_role_time` FOR EACH ROW BEGIN INSERT into SS13_role_time_log (ckey, job, delta) VALUES (OLD.ckey, OLD.job, 0-OLD.minutes);
END
$$
DELIMITER ;
--
-- Table structure for table `SS13_stickyban`
--
DROP TABLE IF EXISTS `SS13_stickyban`;
CREATE TABLE `SS13_stickyban` (
`ckey` VARCHAR(32) NOT NULL,
`reason` VARCHAR(2048) NOT NULL,
`banning_admin` VARCHAR(32) NOT NULL,
`datetime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`ckey`)
) ENGINE=InnoDB;
--
-- Table structure for table `SS13_stickyban_matched_ckey`
--
DROP TABLE IF EXISTS `SS13_stickyban_matched_ckey`;
CREATE TABLE `SS13_stickyban_matched_ckey` (
`stickyban` VARCHAR(32) NOT NULL,
`matched_ckey` VARCHAR(32) NOT NULL,
`first_matched` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`last_matched` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`exempt` TINYINT(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`stickyban`, `matched_ckey`)
) ENGINE=InnoDB;
--
-- Table structure for table `SS13_stickyban_matched_ip`
--
DROP TABLE IF EXISTS `SS13_stickyban_matched_ip`;
CREATE TABLE `SS13_stickyban_matched_ip` (
`stickyban` VARCHAR(32) NOT NULL,
`matched_ip` INT UNSIGNED NOT NULL,
`first_matched` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`last_matched` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`stickyban`, `matched_ip`)
) ENGINE=InnoDB;
--
-- Table structure for table `SS13_stickyban_matched_cid`
--
DROP TABLE IF EXISTS `SS13_stickyban_matched_cid`;
CREATE TABLE `SS13_stickyban_matched_cid` (
`stickyban` VARCHAR(32) NOT NULL,
`matched_cid` VARCHAR(32) NOT NULL,
`first_matched` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`last_matched` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`stickyban`, `matched_cid`)
) ENGINE=InnoDB;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;

View File

@@ -81,3 +81,6 @@
#define SPAM_TRIGGER_WARNING 5 //Number of identical messages required before the spam-prevention will warn you to stfu
#define SPAM_TRIGGER_AUTOMUTE 10 //Number of identical messages required before the spam-prevention will automute you
#define STICKYBAN_DB_CACHE_TIME 10 SECONDS
#define STICKYBAN_ROGUE_CHECK_TIME 5

View File

@@ -1,7 +1,8 @@
//Update this whenever the db schema changes
//make sure you add an update to the schema_version stable in the db changelog
#define DB_MAJOR_VERSION 5
#define DB_MINOR_VERSION 0
#define DB_MINOR_VERSION 1
//Timing subsystem
//Don't run if there is an identical unique timer active

View File

@@ -177,6 +177,27 @@ SUBSYSTEM_DEF(dbcore)
return FALSE
return new /datum/DBQuery(sql_query, connection)
/datum/controller/subsystem/dbcore/proc/QuerySelect(list/querys, warn = FALSE, qdel = FALSE)
if (!islist(querys))
if (!istype(querys, /datum/DBQuery))
CRASH("Invalid query passed to QuerySelect: [querys]")
querys = list(querys)
for (var/thing in querys)
var/datum/DBQuery/query = thing
if (warn)
INVOKE_ASYNC(query, /datum/DBQuery.proc/warn_execute)
else
INVOKE_ASYNC(query, /datum/DBQuery.proc/Execute)
for (var/thing in querys)
var/datum/DBQuery/query = thing
UNTIL(!query.in_progress)
if (qdel)
qdel(query)
/*
Takes a list of rows (each row being an associated list of column => value) and inserts them via a single mass query.
Rows missing columns present in other rows will resolve to SQL NULL

View File

@@ -9,6 +9,9 @@ SUBSYSTEM_DEF(server_maint)
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
var/list/currentrun
/datum/controller/subsystem/server_maint/PreInit()
world.hub_password = "" //quickly! before the hubbies see us.
/datum/controller/subsystem/server_maint/Initialize(timeofday)
if (CONFIG_GET(flag/hub))
world.update_hub_visibility(TRUE)

View File

@@ -1,34 +1,207 @@
SUBSYSTEM_DEF(stickyban)
name = "Sticky Ban"
name = "PRISM"
init_order = INIT_ORDER_STICKY_BAN
flags = SS_NO_FIRE
var/list/cache = list()
var/list/dbcache = list()
var/list/confirmed_exempt = list()
var/dbcacheexpire = 0
/datum/controller/subsystem/stickyban/Initialize(timeofday)
var/list/bannedkeys = world.GetConfig("ban")
var/list/bannedkeys = sticky_banned_ckeys()
//sanitize the sticky ban list
//delete db bans that no longer exist in the database and add new legacy bans to the database
if (SSdbcore.Connect() || length(SSstickyban.dbcache))
for (var/oldban in (world.GetConfig("ban") - bannedkeys))
var/ckey = ckey(oldban)
if (ckey != oldban && (ckey in bannedkeys))
continue
var/list/ban = params2list(world.GetConfig("ban", oldban))
if (ban && !ban["fromdb"])
if (!import_raw_stickyban_to_db(ckey, ban))
log_world("Could not import stickyban on [oldban] into the database. Ignoring")
continue
dbcacheexpire = 0
bannedkeys += ckey
world.SetConfig("ban", oldban, null)
for (var/bannedkey in bannedkeys)
var/ckey = ckey(bannedkey)
var/list/ban = stickyban2list(world.GetConfig("ban", bannedkey))
var/list/ban = get_stickyban_from_ckey(bannedkey)
//byond stores sticky bans by key, that can end up confusing things
//i also remove it here so that if any stickybans cause a runtime, they just stop existing
world.SetConfig("ban", bannedkey, null)
//byond stores sticky bans by key, that's lame
if (ckey != bannedkey)
world.SetConfig("ban", bannedkey, null)
if (!ban["ckey"])
ban["ckey"] = ckey
//storing these can break things and isn't needed for sticky ban tracking
ban -= "IP"
ban -= "computer_id"
ban["matches_this_round"] = list()
ban["existing_user_matches_this_round"] = list()
ban["admin_matches_this_round"] = list()
cache[ckey] = ban
ban["pending_matches_this_round"] = list()
for (var/bannedckey in cache)
world.SetConfig("ban", bannedckey, list2stickyban(cache[bannedckey]))
cache[ckey] = ban
world.SetConfig("ban", ckey, list2stickyban(ban))
return ..()
/datum/controller/subsystem/stickyban/proc/Populatedbcache()
var/newdbcache = list() //so if we runtime or the db connection dies we don't kill the existing cache
var/datum/DBQuery/query_stickybans = SSdbcore.NewQuery("SELECT ckey, reason, banning_admin, datetime FROM [format_table_name("stickyban")] ORDER BY ckey")
var/datum/DBQuery/query_ckey_matches = SSdbcore.NewQuery("SELECT stickyban, matched_ckey, first_matched, last_matched, exempt FROM [format_table_name("stickyban_matched_ckey")] ORDER BY first_matched")
var/datum/DBQuery/query_cid_matches = SSdbcore.NewQuery("SELECT stickyban, matched_cid, first_matched, last_matched FROM [format_table_name("stickyban_matched_cid")] ORDER BY first_matched")
var/datum/DBQuery/query_ip_matches = SSdbcore.NewQuery("SELECT stickyban, INET_NTOA(matched_ip), first_matched, last_matched FROM [format_table_name("stickyban_matched_ip")] ORDER BY first_matched")
SSdbcore.QuerySelect(list(query_stickybans, query_ckey_matches, query_cid_matches, query_ip_matches))
if (query_stickybans.last_error)
qdel(query_stickybans)
qdel(query_ckey_matches)
qdel(query_cid_matches)
qdel(query_ip_matches)
return
while (query_stickybans.NextRow())
var/list/ban = list()
ban["ckey"] = query_stickybans.item[1]
ban["message"] = query_stickybans.item[2]
ban["reason"] = "(InGameBan)([query_stickybans.item[3]])"
ban["admin"] = query_stickybans.item[3]
ban["datetime"] = query_stickybans.item[4]
ban["type"] = list("sticky")
newdbcache["[query_stickybans.item[1]]"] = ban
if (!query_ckey_matches.last_error)
while (query_ckey_matches.NextRow())
var/list/match = list()
match["stickyban"] = query_ckey_matches.item[1]
match["matched_ckey"] = query_ckey_matches.item[2]
match["first_matched"] = query_ckey_matches.item[3]
match["last_matched"] = query_ckey_matches.item[4]
match["exempt"] = text2num(query_ckey_matches.item[5])
var/ban = newdbcache[query_ckey_matches.item[1]]
if (!ban)
continue
var/keys = ban[text2num(query_ckey_matches.item[5]) ? "whitelist" : "keys"]
if (!keys)
keys = ban[text2num(query_ckey_matches.item[5]) ? "whitelist" : "keys"] = list()
keys[query_ckey_matches.item[2]] = match
if (!query_cid_matches.last_error)
while (query_cid_matches.NextRow())
var/list/match = list()
match["stickyban"] = query_cid_matches.item[1]
match["matched_cid"] = query_cid_matches.item[2]
match["first_matched"] = query_cid_matches.item[3]
match["last_matched"] = query_cid_matches.item[4]
var/ban = newdbcache[query_cid_matches.item[1]]
if (!ban)
continue
var/computer_ids = ban["computer_id"]
if (!computer_ids)
computer_ids = ban["computer_id"] = list()
computer_ids[query_cid_matches.item[2]] = match
if (!query_ip_matches.last_error)
while (query_ip_matches.NextRow())
var/list/match = list()
match["stickyban"] = query_ip_matches.item[1]
match["matched_ip"] = query_ip_matches.item[2]
match["first_matched"] = query_ip_matches.item[3]
match["last_matched"] = query_ip_matches.item[4]
var/ban = newdbcache[query_ip_matches.item[1]]
if (!ban)
continue
var/IPs = ban["IP"]
if (!IPs)
IPs = ban["IP"] = list()
IPs[query_ip_matches.item[2]] = match
dbcache = newdbcache
dbcacheexpire = world.time+STICKYBAN_DB_CACHE_TIME
qdel(query_stickybans)
qdel(query_ckey_matches)
qdel(query_cid_matches)
qdel(query_ip_matches)
/datum/controller/subsystem/stickyban/proc/import_raw_stickyban_to_db(ckey, list/ban)
. = FALSE
if (!ban["admin"])
ban["admin"] = "LEGACY"
if (!ban["message"])
ban["message"] = "Evasion"
var/datum/DBQuery/query_create_stickyban = SSdbcore.NewQuery("INSERT IGNORE INTO [format_table_name("stickyban")] (ckey, reason, banning_admin) VALUES ('[sanitizeSQL(ckey)]', '[sanitizeSQL(ban["message"])]', '[sanitizeSQL(ban["admin"])]')")
if (!query_create_stickyban.warn_execute())
qdel(query_create_stickyban)
return
qdel(query_create_stickyban)
var/list/sqlckeys = list()
var/list/sqlcids = list()
var/list/sqlips = list()
if (ban["keys"])
var/list/keys = splittext(ban["keys"], ",")
for (var/key in keys)
var/list/sqlckey = list()
sqlckey["stickyban"] = "'[sanitizeSQL(ckey)]'"
sqlckey["matched_ckey"] = "'[sanitizeSQL(ckey(key))]'"
sqlckey["exempt"] = FALSE
sqlckeys[++sqlckeys.len] = sqlckey
if (ban["whitelist"])
var/list/keys = splittext(ban["whitelist"], ",")
for (var/key in keys)
var/list/sqlckey = list()
sqlckey["stickyban"] = "'[sanitizeSQL(ckey)]'"
sqlckey["matched_ckey"] = "'[sanitizeSQL(ckey(key))]'"
sqlckey["exempt"] = TRUE
sqlckeys[++sqlckeys.len] = sqlckey
if (ban["computer_id"])
var/list/cids = splittext(ban["computer_id"], ",")
for (var/cid in cids)
var/list/sqlcid = list()
sqlcid["stickyban"] = "'[sanitizeSQL(ckey)]'"
sqlcid["matched_cid"] = "'[sanitizeSQL(cid)]'"
sqlcids[++sqlcids.len] = sqlcid
if (ban["IP"])
var/list/ips = splittext(ban["IP"], ",")
for (var/ip in ips)
var/list/sqlip = list()
sqlip["stickyban"] = "'[sanitizeSQL(ckey)]'"
sqlip["matched_ip"] = "'[sanitizeSQL(ip)]'"
sqlips[++sqlips.len] = sqlip
if (length(sqlckeys))
SSdbcore.MassInsert(format_table_name("stickyban_matched_ckey"), sqlckeys, FALSE, TRUE)
if (length(sqlcids))
SSdbcore.MassInsert(format_table_name("stickyban_matched_cid"), sqlcids, FALSE, TRUE)
if (length(sqlips))
SSdbcore.MassInsert(format_table_name("stickyban_matched_ip"), sqlips, FALSE, TRUE)
return TRUE

View File

@@ -20,6 +20,8 @@ GLOBAL_VAR(restart_counter)
config.Load(params[OVERRIDE_CONFIG_DIRECTORY_PARAMETER])
load_admins()
//SetupLogs depends on the RoundID, so lets check
//DB schema and set RoundID if we can
SSdbcore.CheckSchemaVersion()
@@ -30,9 +32,12 @@ GLOBAL_VAR(restart_counter)
world.log = file("[GLOB.log_directory]/dd.log")
#endif
<<<<<<< HEAD
load_yogs_stuff() // yogs - Donators
refresh_admin_files() //yogs - DB support
load_admins()
=======
>>>>>>> c961d93003... Merge pull request #42899 from MrStonedOne/sqlstickybans
LoadVerbs(/datum/verbs/menu)
if(CONFIG_GET(flag/usewhitelist))
load_whitelist()

View File

@@ -2,32 +2,37 @@
//How many new ckey matches before we revert the stickyban to it's roundstart state
//These are exclusive, so once it goes over one of these numbers, it reverts the ban
#define STICKYBAN_MAX_MATCHES 20
#define STICKYBAN_MAX_EXISTING_USER_MATCHES 5 //ie, users who were connected before the ban triggered
#define STICKYBAN_MAX_ADMIN_MATCHES 2
#define STICKYBAN_MAX_MATCHES 15
#define STICKYBAN_MAX_EXISTING_USER_MATCHES 3 //ie, users who were connected before the ban triggered
#define STICKYBAN_MAX_ADMIN_MATCHES 1
/world/IsBanned(key,address,computer_id,type,real_bans_only=FALSE)
if (!key || !address || !computer_id)
/world/IsBanned(key, address, computer_id, type, real_bans_only=FALSE)
debug_world_log("isbanned(): '[args.Join("', '")]'")
if (!key || (!real_bans_only && (!address || !computer_id)))
if(real_bans_only)
return FALSE
log_access("Failed Login (invalid data): [key] [address]-[computer_id]")
return list("reason"="invalid login data", "desc"="Error: Could not check ban status, Please try again. Error message: Your computer provided invalid or blank information to the server on connection (byond username, IP, and Computer ID.) Provided information for reference: Username:'[key]' IP:'[address]' Computer ID:'[computer_id]'. (If you continue to get this error, please restart byond or contact byond support.)")
if (text2num(computer_id) == 2147483647) //this cid causes stickybans to go haywire
log_access("Failed Login (invalid cid): [key] [address]-[computer_id]")
return list("reason"="invalid login data", "desc"="Error: Could not check ban status, Please try again. Error message: Your computer provided an invalid Computer ID.)")
var/admin = 0
var/admin = FALSE
var/ckey = ckey(key)
//IsBanned can get re-called on a user in certain situations, this prevents that leading to repeated messages to admins.
var/static/list/checkedckeys = list()
//magic voodo to check for a key in a list while also adding that key to the list without having to do two associated lookups
var/message = !checkedckeys[ckey]++
if(GLOB.admin_datums[ckey] || GLOB.deadmins[ckey])
admin = 1
admin = TRUE
//Whitelist
if(CONFIG_GET(flag/usewhitelist))
if(!check_whitelist(ckey))
if (admin)
log_admin("The admin [key] has been allowed to bypass the whitelist")
message_admins("<span class='adminnotice'>The admin [key] has been allowed to bypass the whitelist</span>")
addclientmessage(ckey,"<span class='adminnotice'>You have been allowed to bypass the whitelist</span>")
if (message)
message_admins("<span class='adminnotice'>The admin [key] has been allowed to bypass the whitelist</span>")
addclientmessage(ckey,"<span class='adminnotice'>You have been allowed to bypass the whitelist</span>")
else
log_access("Failed Login: [key] - Not on whitelist")
return list("reason"="whitelist", "desc" = "\nReason: You are not on the white list for this server")
@@ -46,11 +51,13 @@
if(!real_bans_only && extreme_popcap && living_player_count() >= extreme_popcap && !admin)
log_access("Failed Login: [key] - Population cap reached")
return list("reason"="popcap", "desc"= "\nReason: [CONFIG_GET(string/extreme_popcap_message)]")
if(CONFIG_GET(flag/sql_enabled))
if(!SSdbcore.Connect())
var/msg = "Ban database connection failure. Key [ckey] not checked"
log_world(msg)
message_admins(msg)
if (message)
message_admins(msg)
else
var/list/ban_details = is_banned_from_with_details(ckey, address, computer_id, "Server")
for(var/i in ban_details)
@@ -58,12 +65,14 @@
if(text2num(i["applies_to_admins"]))
var/msg = "Admin [key] is admin banned, and has been disallowed access."
log_admin(msg)
message_admins(msg)
if (message)
message_admins(msg)
else
var/msg = "Admin [key] has been allowed to bypass a matching non-admin ban on [i["key"]] [i["ip"]]-[i["computerid"]]."
log_admin(msg)
message_admins(msg)
addclientmessage(ckey,"<span class='adminnotice'>Admin [key] has been allowed to bypass a matching non-admin ban on [i["key"]] [i["ip"]]-[i["computerid"]].</span>")
if (message)
message_admins(msg)
addclientmessage(ckey,"<span class='adminnotice'>Admin [key] has been allowed to bypass a matching non-admin ban on [i["key"]] [i["ip"]]-[i["computerid"]].</span>")
continue
var/expires = "This is a permanent ban."
if(i["expiration_time"])
@@ -74,18 +83,24 @@
[expires] If you wish to appeal this ban please use the keyword 'assistantgreytide' to register an account on the forums."} //yogs
log_access("Failed Login: [key] [computer_id] [address] - Banned (#[i["id"]])")
return list("reason"="Banned","desc"="[desc]")
var/list/ban = ..() //default pager ban stuff
if (ban)
if (!admin)
. = ban
if (real_bans_only)
return
var/bannedckey = "ERROR"
if (ban["ckey"])
bannedckey = ban["ckey"]
var/newmatch = FALSE
var/client/C = GLOB.directory[ckey]
var/cachedban = SSstickyban.cache[bannedckey]
var/list/cachedban = SSstickyban.cache[bannedckey]
//rogue ban in the process of being reverted.
if (cachedban && cachedban["reverting"])
if (cachedban && (cachedban["reverting"] || cachedban["timeout"]))
world.SetConfig("ban", bannedckey, null)
return null
if (cachedban && ckey != bannedckey)
@@ -98,51 +113,80 @@
if (newmatch && cachedban)
var/list/newmatches = cachedban["matches_this_round"]
var/list/pendingmatches = cachedban["matches_this_round"]
var/list/newmatches_connected = cachedban["existing_user_matches_this_round"]
var/list/newmatches_admin = cachedban["admin_matches_this_round"]
newmatches[ckey] = ckey
if (C)
newmatches_connected[ckey] = ckey
newmatches_connected = cachedban["existing_user_matches_this_round"]
pendingmatches[ckey] = ckey
sleep(STICKYBAN_ROGUE_CHECK_TIME)
pendingmatches -= ckey
if (admin)
newmatches_admin[ckey] = ckey
if (cachedban["reverting"] || cachedban["timeout"])
return null
newmatches[ckey] = ckey
if (\
newmatches.len > STICKYBAN_MAX_MATCHES || \
newmatches.len+pendingmatches.len > STICKYBAN_MAX_MATCHES || \
newmatches_connected.len > STICKYBAN_MAX_EXISTING_USER_MATCHES || \
newmatches_admin.len > STICKYBAN_MAX_ADMIN_MATCHES \
)
if (cachedban["reverting"])
return null
cachedban["reverting"] = TRUE
)
var/action
if (ban["fromdb"])
cachedban["timeout"] = TRUE
action = "putting it on timeout for the remainder of the round"
else
cachedban["reverting"] = TRUE
action = "reverting to its roundstart state"
world.SetConfig("ban", bannedckey, null)
log_game("Stickyban on [bannedckey] detected as rogue, reverting to its roundstart state")
message_admins("Stickyban on [bannedckey] detected as rogue, reverting to its roundstart state")
//we always report this
log_game("Stickyban on [bannedckey] detected as rogue, [action]")
message_admins("Stickyban on [bannedckey] detected as rogue, [action]")
//do not convert to timer.
spawn (5)
world.SetConfig("ban", bannedckey, null)
sleep(1)
world.SetConfig("ban", bannedckey, null)
cachedban["matches_this_round"] = list()
cachedban["existing_user_matches_this_round"] = list()
cachedban["admin_matches_this_round"] = list()
cachedban -= "reverting"
world.SetConfig("ban", bannedckey, list2stickyban(cachedban))
if (!ban["fromdb"])
cachedban = cachedban.Copy() //so old references to the list still see the ban as reverting
cachedban["matches_this_round"] = list()
cachedban["existing_user_matches_this_round"] = list()
cachedban["admin_matches_this_round"] = list()
cachedban -= "reverting"
SSstickyban.cache[bannedckey] = cachedban
world.SetConfig("ban", bannedckey, list2stickyban(cachedban))
return null
if (ban["fromdb"])
if(SSdbcore.Connect())
INVOKE_ASYNC(SSdbcore, /datum/controller/subsystem/dbcore/proc.QuerySelect, list(
SSdbcore.NewQuery("INSERT INTO [format_table_name("stickyban_matched_ckey")] (matched_ckey, stickyban) VALUES ('[sanitizeSQL(ckey)]', '[sanitizeSQL(bannedckey)]') ON DUPLICATE KEY UPDATE last_matched = now()"),
SSdbcore.NewQuery("INSERT INTO [format_table_name("stickyban_matched_ip")] (matched_ip, stickyban) VALUES ( INET_ATON('[sanitizeSQL(address)]'), '[sanitizeSQL(bannedckey)]') ON DUPLICATE KEY UPDATE last_matched = now()"),
SSdbcore.NewQuery("INSERT INTO [format_table_name("stickyban_matched_cid")] (matched_cid, stickyban) VALUES ('[sanitizeSQL(computer_id)]', '[sanitizeSQL(bannedckey)]') ON DUPLICATE KEY UPDATE last_matched = now()")
), FALSE, TRUE)
//byond will not trigger isbanned() for "global" host bans,
//ie, ones where the "apply to this game only" checkbox is not checked (defaults to not checked)
//So it's safe to let admins walk thru host/sticky bans here
if (admin)
log_admin("The admin [key] has been allowed to bypass a matching host/sticky ban on [bannedckey]")
message_admins("<span class='adminnotice'>The admin [key] has been allowed to bypass a matching host/sticky ban on [bannedckey]</span>")
addclientmessage(ckey,"<span class='adminnotice'>You have been allowed to bypass a matching host/sticky ban on [bannedckey]</span>")
if (message)
message_admins("<span class='adminnotice'>The admin [key] has been allowed to bypass a matching host/sticky ban on [bannedckey]</span>")
addclientmessage(ckey,"<span class='adminnotice'>You have been allowed to bypass a matching host/sticky ban on [bannedckey]</span>")
return null
if (C) //user is already connected!.
to_chat(C, "You are about to get disconnected for matching a sticky ban after you connected. If this turns out to be the ban evasion detection system going haywire, we will automatically detect this and revert the matches. if you feel that this is the case, please wait EXACTLY 6 seconds then reconnect using file -> reconnect to see if the match was reversed.")
to_chat(C, "You are about to get disconnected for matching a sticky ban after you connected. If this turns out to be the ban evasion detection system going haywire, we will automatically detect this and revert the matches. if you feel that this is the case, please wait EXACTLY 6 seconds then reconnect using file -> reconnect to see if the match was automatically reversed.")
var/desc = "\nReason:(StickyBan) You, or another user of this computer or connection ([bannedckey]) is banned from playing here. The ban reason is:\n[ban["message"]]\nThis ban was applied by [ban["admin"]]\nThis is a BanEvasion Detection System ban, if you think this ban is a mistake, please wait EXACTLY 6 seconds, then try again before filing an appeal. If you wish to appeal this ban please use the keyword 'assistantgreytide' to register an account on the forums.\n" //yogs
. = list("reason" = "Stickyban", "desc" = desc)

View File

@@ -7,7 +7,7 @@
if ("add")
var/list/ban = list()
var/ckey
ban["admin"] = usr.key
ban["admin"] = usr.ckey
ban["type"] = list("sticky")
ban["reason"] = "(InGameBan)([usr.key])" //this will be displayed in dd only
@@ -22,6 +22,7 @@
if (get_stickyban_from_ckey(ckey))
to_chat(usr, "<span class='adminnotice'>Error: Can not add a stickyban: User already has a current sticky ban</span>")
return
if (data["reason"])
ban["message"] = data["reason"]
@@ -31,7 +32,19 @@
return
ban["message"] = "[reason]"
if(SSdbcore.Connect())
var/datum/DBQuery/query_create_stickyban = SSdbcore.NewQuery("INSERT INTO [format_table_name("stickyban")] (ckey, reason, banning_admin) VALUES ('[sanitizeSQL(ckey)]', '[sanitizeSQL(ban["message"])]', '[sanitizeSQL(usr.ckey)]')")
if (query_create_stickyban.warn_execute())
ban["fromdb"] = TRUE
qdel(query_create_stickyban)
world.SetConfig("ban",ckey,list2stickyban(ban))
ban = stickyban2list(list2stickyban(ban))
ban["matches_this_round"] = list()
ban["existing_user_matches_this_round"] = list()
ban["admin_matches_this_round"] = list()
ban["pending_matches_this_round"] = list()
SSstickyban.cache[ckey] = ban
log_admin_private("[key_name(usr)] has stickybanned [ckey].\nReason: [ban["message"]]")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has stickybanned [ckey].\nReason: [ban["message"]]</span>")
@@ -51,6 +64,16 @@
to_chat(usr, "<span class='adminnotice'>Error: The ban disappeared.</span>")
return
world.SetConfig("ban",ckey, null)
SSstickyban.cache -= ckey
if (SSdbcore.Connect())
SSdbcore.QuerySelect(list(
SSdbcore.NewQuery("DELETE FROM [format_table_name("stickyban")] WHERE ckey = '[sanitizeSQL(ckey)]'"),
SSdbcore.NewQuery("DELETE FROM [format_table_name("stickyban_matched_ckey")] WHERE stickyban = '[sanitizeSQL(ckey)]'"),
SSdbcore.NewQuery("DELETE FROM [format_table_name("stickyban_matched_cid")] WHERE stickyban = '[sanitizeSQL(ckey)]'"),
SSdbcore.NewQuery("DELETE FROM [format_table_name("stickyban_matched_ip")] WHERE stickyban = '[sanitizeSQL(ckey)]'")
), warn = TRUE, qdel = TRUE)
log_admin_private("[key_name(usr)] removed [ckey]'s stickyban")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] removed [ckey]'s stickyban</span>")
@@ -67,18 +90,12 @@
to_chat(usr, "<span class='adminnotice'>Error: No sticky ban for [ckey] found!</span>")
return
var/found = 0
//we have to do it this way because byond keeps the case in its sticky ban matches WHY!!!
for (var/key in ban["keys"])
if (ckey(key) == alt)
found = 1
break
if (!found)
var/key = LAZYACCESS(ban["keys"], alt)
if (!key)
to_chat(usr, "<span class='adminnotice'>Error: [alt] is not linked to [ckey]'s sticky ban!</span>")
return
if (alert("Are you sure you want to disassociate [alt] from [ckey]'s sticky ban? \nNote: Nothing stops byond from re-linking them","Are you sure","Yes","No") == "No")
if (alert("Are you sure you want to disassociate [alt] from [ckey]'s sticky ban? \nNote: Nothing stops byond from re-linking them, Use \[E] to exempt them","Are you sure","Yes","No") == "No")
return
//we have to do this again incase something changes
@@ -87,19 +104,22 @@
to_chat(usr, "<span class='adminnotice'>Error: The ban disappeared.</span>")
return
found = 0
for (var/key in ban["keys"])
if (ckey(key) == alt)
ban["keys"] -= key
found = 1
break
key = LAZYACCESS(ban["keys"], alt)
if (!found)
if (!key)
to_chat(usr, "<span class='adminnotice'>Error: [alt] link to [ckey]'s sticky ban disappeared.</span>")
return
LAZYREMOVE(ban["keys"], alt)
world.SetConfig("ban",ckey,list2stickyban(ban))
SSstickyban.cache[ckey] = ban
if (SSdbcore.Connect())
var/datum/DBQuery/query_remove_stickyban_alt = SSdbcore.NewQuery("DELETE FROM [format_table_name("stickyban_matched_ckey")] WHERE stickyban = '[sanitizeSQL(ckey)]' AND matched_ckey = '[sanitizeSQL(alt)]'")
query_remove_stickyban_alt.warn_execute()
qdel(query_remove_stickyban_alt)
log_admin_private("[key_name(usr)] has disassociated [alt] from [ckey]'s sticky ban")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has disassociated [alt] from [ckey]'s sticky ban</span>")
@@ -124,14 +144,171 @@
world.SetConfig("ban",ckey,list2stickyban(ban))
SSstickyban.cache[ckey] = ban
if (SSdbcore.Connect())
var/datum/DBQuery/query_edit_stickyban = SSdbcore.NewQuery("UPDATE [format_table_name("stickyban")] SET reason = '[sanitizeSQL(reason)]' WHERE ckey = '[sanitizeSQL(ckey)]'")
query_edit_stickyban.warn_execute()
qdel(query_edit_stickyban)
log_admin_private("[key_name(usr)] has edited [ckey]'s sticky ban reason from [oldreason] to [reason]")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has edited [ckey]'s sticky ban reason from [oldreason] to [reason]</span>")
if ("exempt")
if (!data["ckey"])
return
var/ckey = data["ckey"]
if (!data["alt"])
return
var/alt = ckey(data["alt"])
var/ban = get_stickyban_from_ckey(ckey)
if (!ban)
to_chat(usr, "<span class='adminnotice'>Error: No sticky ban for [ckey] found!</span>")
return
var/key = LAZYACCESS(ban["keys"], alt)
if (!key)
to_chat(usr, "<span class='adminnotice'>Error: [alt] is not linked to [ckey]'s sticky ban!</span>")
return
if (alert("Are you sure you want to exempt [alt] from [ckey]'s sticky ban?","Are you sure","Yes","No") == "No")
return
//we have to do this again incase something changes
ban = get_stickyban_from_ckey(ckey)
if (!ban)
to_chat(usr, "<span class='adminnotice'>Error: The ban disappeared.</span>")
return
key = LAZYACCESS(ban["keys"], alt)
if (!key)
to_chat(usr, "<span class='adminnotice'>Error: [alt]'s link to [ckey]'s sticky ban disappeared.</span>")
return
LAZYREMOVE(ban["keys"], alt)
key["exempt"] = TRUE
LAZYSET(ban["whitelist"], alt, key)
world.SetConfig("ban",ckey,list2stickyban(ban))
SSstickyban.cache[ckey] = ban
if (SSdbcore.Connect())
var/datum/DBQuery/query_exempt_stickyban_alt = SSdbcore.NewQuery("UPDATE [format_table_name("stickyban_matched_ckey")] SET exempt = 1 WHERE stickyban = '[sanitizeSQL(ckey)]' AND matched_ckey = '[sanitizeSQL(alt)]'")
query_exempt_stickyban_alt.warn_execute()
qdel(query_exempt_stickyban_alt)
log_admin_private("[key_name(usr)] has exempted [alt] from [ckey]'s sticky ban")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has exempted [alt] from [ckey]'s sticky ban</span>")
if ("unexempt")
if (!data["ckey"])
return
var/ckey = data["ckey"]
if (!data["alt"])
return
var/alt = ckey(data["alt"])
var/ban = get_stickyban_from_ckey(ckey)
if (!ban)
to_chat(usr, "<span class='adminnotice'>Error: No sticky ban for [ckey] found!</span>")
return
var/key = LAZYACCESS(ban["whitelist"], alt)
if (!key)
to_chat(usr, "<span class='adminnotice'>Error: [alt] is not exempt from [ckey]'s sticky ban!</span>")
return
if (alert("Are you sure you want to unexempt [alt] from [ckey]'s sticky ban?","Are you sure","Yes","No") == "No")
return
//we have to do this again incase something changes
ban = get_stickyban_from_ckey(ckey)
if (!ban)
to_chat(usr, "<span class='adminnotice'>Error: The ban disappeared.</span>")
return
key = LAZYACCESS(ban["whitelist"], alt)
if (!key)
to_chat(usr, "<span class='adminnotice'>Error: [alt]'s exemption from [ckey]'s sticky ban disappeared.</span>")
return
LAZYREMOVE(ban["whitelist"], alt)
key["exempt"] = FALSE
LAZYSET(ban["keys"], alt, key)
world.SetConfig("ban",ckey,list2stickyban(ban))
SSstickyban.cache[ckey] = ban
if (SSdbcore.Connect())
var/datum/DBQuery/query_unexempt_stickyban_alt = SSdbcore.NewQuery("UPDATE [format_table_name("stickyban_matched_ckey")] SET exempt = 0 WHERE stickyban = '[sanitizeSQL(ckey)]' AND matched_ckey = '[sanitizeSQL(alt)]'")
query_unexempt_stickyban_alt.warn_execute()
qdel(query_unexempt_stickyban_alt)
log_admin_private("[key_name(usr)] has unexempted [alt] from [ckey]'s sticky ban")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has unexempted [alt] from [ckey]'s sticky ban</span>")
if ("timeout")
if (!data["ckey"])
return
if (!SSdbcore.Connect())
to_chat(usr, "<span class='adminnotice'>No database connection!</span>")
return
var/ckey = data["ckey"]
if (alert("Are you sure you want to put [ckey]'s stickyban on timeout until next round (or removed)?","Are you sure","Yes","No") == "No")
return
var/ban = get_stickyban_from_ckey(ckey)
if (!ban)
to_chat(usr, "<span class='adminnotice'>Error: No sticky ban for [ckey] found!</span>")
return
ban["timeout"] = TRUE
world.SetConfig("ban", ckey, null)
var/cachedban = SSstickyban.cache[ckey]
if (cachedban)
cachedban["timeout"] = TRUE
log_admin_private("[key_name(usr)] has put [ckey]'s sticky ban on timeout.")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has put [ckey]'s sticky ban on timeout.</span>")
if ("untimeout")
if (!data["ckey"])
return
if (!SSdbcore.Connect())
to_chat(usr, "<span class='adminnotice'>No database connection!</span>")
return
var/ckey = data["ckey"]
if (alert("Are you sure you want to lift the timeout on [ckey]'s stickyban?","Are you sure","Yes","No") == "No")
return
var/ban = get_stickyban_from_ckey(ckey)
var/cachedban = SSstickyban.cache[ckey]
if (cachedban)
cachedban["timeout"] = FALSE
if (!ban)
if (!cachedban)
to_chat(usr, "<span class='adminnotice'>Error: No sticky ban for [ckey] found!</span>")
return
ban = cachedban
ban["timeout"] = FALSE
world.SetConfig("ban",ckey,list2stickyban(ban))
log_admin_private("[key_name(usr)] has taken [ckey]'s sticky ban off of timeout.")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has taken [ckey]'s sticky ban off of timeout.</span>")
if ("revert")
if (!data["ckey"])
return
var/ckey = data["ckey"]
if (alert("Are you sure you want to revert the sticky ban on [ckey] to its state at round start?","Are you sure","Yes","No") == "No")
if (alert("Are you sure you want to revert the sticky ban on [ckey] to its state at round start (or last edit)?","Are you sure","Yes","No") == "No")
return
var/ban = get_stickyban_from_ckey(ckey)
if (!ban)
@@ -150,14 +327,22 @@
world.SetConfig("ban",ckey,list2stickyban(cached_ban))
/datum/admins/proc/stickyban_gethtml(ckey, ban)
. = {"
/datum/admins/proc/stickyban_gethtml(ckey)
var/ban = get_stickyban_from_ckey(ckey)
if (!ban)
return
var/timeout
if (SSdbcore.Connect())
timeout = "<a href='?_src_=holder;[HrefToken()];stickyban=[(ban["timeout"] ? "untimeout" : "timeout")]&ckey=[ckey]'>\[[(ban["timeout"] ? "untimeout" : "timeout" )]\]</a>"
else
timeout = "<a href='?_src_=holder;[HrefToken()];stickyban=revert&ckey=[ckey]'>\[revert\]</a>"
. = list({"
<a href='?_src_=holder;[HrefToken()];stickyban=remove&ckey=[ckey]'>\[-\]</a>
<a href='?_src_=holder;[HrefToken()];stickyban=revert&ckey=[ckey]'>\[revert\]</a>
[timeout]
<b>[ckey]</b>
<br />"
[ban["message"]] <b><a href='?_src_=holder;[HrefToken()];stickyban=edit&ckey=[ckey]'>\[Edit\]</a></b><br />
"}
"})
if (ban["admin"])
. += "[ban["admin"]]<br />"
else
@@ -166,19 +351,24 @@
for (var/key in ban["keys"])
if (ckey(key) == ckey)
continue
. += "<li><a href='?_src_=holder;[HrefToken()];stickyban=remove_alt&ckey=[ckey]&alt=[ckey(key)]'>\[-\]</a>[key]</li>"
. += "<li><a href='?_src_=holder;[HrefToken()];stickyban=remove_alt&ckey=[ckey]&alt=[ckey(key)]'>\[-\]</a>[key]<a href='?_src_=holder;[HrefToken()];stickyban=exempt&ckey=[ckey]&alt=[ckey(key)]'>\[E\]</a></li>"
for (var/key in ban["whitelist"])
if (ckey(key) == ckey)
continue
. += "<li><a href='?_src_=holder;[HrefToken()];stickyban=remove_alt&ckey=[ckey]&alt=[ckey(key)]'>\[-\]</a>[key]<a href='?_src_=holder;[HrefToken()];stickyban=unexempt&ckey=[ckey]&alt=[ckey(key)]'>\[UE\]</a></li>"
. += "</ol>\n"
/datum/admins/proc/stickyban_show()
if(!check_rights(R_BAN))
return
var/list/bans = sortList(world.GetConfig("ban"))
var/banhtml = ""
var/list/bans = sticky_banned_ckeys()
var/list/banhtml = list()
for(var/key in bans)
var/ckey = ckey(key)
var/ban = stickyban2list(world.GetConfig("ban",key))
banhtml += "<br /><hr />\n"
banhtml += stickyban_gethtml(ckey,ban)
banhtml += stickyban_gethtml(ckey)
var/html = {"
<head>
@@ -186,22 +376,49 @@
</head>
<body>
<h2>All Sticky Bans:</h2> <a href='?_src_=holder;[HrefToken()];stickyban=add'>\[+\]</a><br>
[banhtml]
[banhtml.Join("")]
</body>
"}
usr << browse(html,"window=stickybans;size=700x400")
/proc/sticky_banned_ckeys()
if (SSdbcore.Connect() || length(SSstickyban.dbcache))
if (SSstickyban.dbcacheexpire < world.time)
SSstickyban.Populatedbcache()
if (SSstickyban.dbcacheexpire)
return SSstickyban.dbcache.Copy()
return sortList(world.GetConfig("ban"))
/proc/get_stickyban_from_ckey(var/ckey)
. = list()
if (!ckey)
return null
ckey = ckey(ckey)
. = null
for (var/key in world.GetConfig("ban"))
if (ckey(key) == ckey)
. = stickyban2list(world.GetConfig("ban",key))
break
if (SSdbcore.Connect() || length(SSstickyban.dbcache))
if (SSstickyban.dbcacheexpire < world.time)
SSstickyban.Populatedbcache()
if (SSstickyban.dbcacheexpire)
. = SSstickyban.dbcache[ckey]
//reset the cache incase its a newer ban (but only if we didn't update the cache recently)
if (!. && SSstickyban.dbcacheexpire != world.time+STICKYBAN_DB_CACHE_TIME)
SSstickyban.dbcacheexpire = 1
SSstickyban.Populatedbcache()
. = SSstickyban.dbcache[ckey]
if (.)
var/list/cachedban = SSstickyban.cache["[ckey]"]
if (cachedban)
.["timeout"] = cachedban["timeout"]
/proc/stickyban2list(var/ban)
.["fromdb"] = TRUE
return
. = stickyban2list(world.GetConfig("ban", ckey)) || stickyban2list(world.GetConfig("ban", ckey(ckey))) || list()
if (!length(.))
return null
/proc/stickyban2list(ban, strictdb = TRUE)
if (!ban)
return null
. = params2list(ban)
@@ -212,30 +429,40 @@
var/ckey = ckey(key)
ckeys[ckey] = ckey //to make searching faster.
.["keys"] = ckeys
if (.["whitelist"])
var/keys = splittext(.["whitelist"], ",")
var/ckeys = list()
for (var/key in keys)
var/ckey = ckey(key)
ckeys[ckey] = ckey //to make searching faster.
.["whitelist"] = ckeys
.["type"] = splittext(.["type"], ",")
.["IP"] = splittext(.["IP"], ",")
.["computer_id"] = splittext(.["computer_id"], ",")
. -= "fromdb"
/proc/list2stickyban(var/list/ban)
/proc/list2stickyban(list/ban)
if (!ban || !islist(ban))
return null
. = ban.Copy()
if (.["keys"])
.["keys"] = jointext(.["keys"], ",")
if (.["IP"])
.["IP"] = jointext(.["IP"], ",")
if (.["computer_id"])
.["computer_id"] = jointext(.["computer_id"], ",")
if (.["whitelist"])
.["whitelist"] = jointext(.["whitelist"], ",")
if (.["type"])
.["type"] = jointext(.["type"], ",")
//internal tracking only, shouldn't be stored
. -= "reverting"
. -= "matches_this_round"
. -= "existing_user_matches_this_round"
. -= "admin_matches_this_round"
. -= "matches_this_round"
. -= "reverting"
. -= "pending_matches_this_round"
//storing these can sometimes cause sticky bans to start matching everybody
// and isn't even needed for sticky ban matching, as the hub tracks these separately
. -= "IP"
. -= "computer_id"
. = list2params(.)

View File

@@ -174,7 +174,7 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico
var/list/row = src.connectionHistory[i]
if (!row || row.len < 3 || (!row["ckey"] || !row["compid"] || !row["ip"])) //Passed malformed history object
return
if (world.IsBanned(row["ckey"], row["compid"], row["ip"], real_bans_only=TRUE))
if (world.IsBanned(row["ckey"], row["ip"], row["compid"], real_bans_only=TRUE))
found = row
break

View File

@@ -7,6 +7,7 @@
area = /area/space
view = "15x15"
hub = "Exadv1.spacestation13"
hub_password = "kMZy3U5jJHSiBQjr"
name = "/tg/ Station 13"
fps = 20
#ifdef FIND_REF_NO_CHECK_TICK