#define MAX_ADMINBANS_PER_ADMIN 1
#define MAX_ADMINBANS_PER_HEADMIN 3
//checks client ban cache or DB ban table if ckey is banned from one or more roles
//doesn't return any details, use only for if statements
/proc/is_banned_from(player_ckey, roles)
if(!player_ckey)
return
var/client/C = GLOB.directory[player_ckey]
if(C)
if(!C.ban_cache)
build_ban_cache(C)
if(islist(roles))
for(var/R in roles)
if(R in C.ban_cache)
return TRUE //they're banned from at least one role, no need to keep checking
else if(roles in C.ban_cache)
return TRUE
else
player_ckey = sanitizeSQL(player_ckey)
var/admin_where
if(GLOB.admin_datums[player_ckey] || GLOB.deadmins[player_ckey])
admin_where = " AND applies_to_admins = 1"
var/sql_roles
if(islist(roles))
sql_roles = jointext(roles, "', '")
else
sql_roles = roles
sql_roles = sanitizeSQL(sql_roles)
var/datum/DBQuery/query_check_ban = SSdbcore.NewQuery("SELECT 1 FROM [format_table_name("ban")] WHERE ckey = '[player_ckey]' AND role IN ('[sql_roles]') AND unbanned_datetime IS NULL AND (expiration_time IS NULL OR expiration_time > NOW())[admin_where]")
if(!query_check_ban.warn_execute())
qdel(query_check_ban)
return
if(query_check_ban.NextRow())
qdel(query_check_ban)
return TRUE
qdel(query_check_ban)
//checks DB ban table if a ckey, ip and/or cid is banned from a specific role
//returns an associative nested list of each matching row's ban id, bantime, ban round id, expiration time, ban duration, applies to admins, reason, key, ip, cid and banning admin's key in that order
/proc/is_banned_from_with_details(player_ckey, player_ip, player_cid, role)
if(!player_ckey && !player_ip && !player_cid)
return
role = sanitizeSQL(role)
var/list/where_list = list()
if(player_ckey)
player_ckey = sanitizeSQL(player_ckey)
where_list += "ckey = '[player_ckey]'"
if(player_ip)
player_ip = sanitizeSQL(player_ip)
where_list += "ip = INET_ATON('[player_ip]')"
if(player_cid)
player_cid = sanitizeSQL(player_cid)
where_list += "computerid = '[player_cid]'"
var/where = "([where_list.Join(" OR ")])"
var/datum/DBQuery/query_check_ban = SSdbcore.NewQuery("SELECT id, bantime, round_id, expiration_time, TIMESTAMPDIFF(MINUTE, bantime, expiration_time), applies_to_admins, reason, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE [format_table_name("player")].ckey = [format_table_name("ban")].ckey), ckey), INET_NTOA(ip), computerid, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE [format_table_name("player")].ckey = [format_table_name("ban")].a_ckey), a_ckey) FROM [format_table_name("ban")] WHERE role = '[role]' AND [where] AND unbanned_datetime IS NULL AND (expiration_time IS NULL OR expiration_time > NOW()) ORDER BY bantime DESC")
if(!query_check_ban.warn_execute())
qdel(query_check_ban)
return
. = list()
while(query_check_ban.NextRow())
. += list(list("id" = query_check_ban.item[1], "bantime" = query_check_ban.item[2], "round_id" = query_check_ban.item[3], "expiration_time" = query_check_ban.item[4], "duration" = query_check_ban.item[5], "applies_to_admins" = query_check_ban.item[6], "reason" = query_check_ban.item[7], "key" = query_check_ban.item[8], "ip" = query_check_ban.item[9], "computerid" = query_check_ban.item[10], "admin_key" = query_check_ban.item[11]))
qdel(query_check_ban)
/proc/build_ban_cache(client/C)
if(!SSdbcore.Connect())
return
if(C && istype(C))
C.ban_cache = list()
var/player_key = sanitizeSQL(C.ckey)
var/is_admin = FALSE
if(GLOB.admin_datums[C.ckey] || GLOB.deadmins[C.ckey])
is_admin = TRUE
var/datum/DBQuery/query_build_ban_cache = SSdbcore.NewQuery("SELECT role, applies_to_admins FROM [format_table_name("ban")] WHERE ckey = '[player_key]' AND unbanned_datetime IS NULL AND (expiration_time IS NULL OR expiration_time > NOW())")
if(!query_build_ban_cache.warn_execute())
qdel(query_build_ban_cache)
return
while(query_build_ban_cache.NextRow())
if(is_admin && !text2num(query_build_ban_cache.item[2]))
continue
C.ban_cache[query_build_ban_cache.item[1]] = TRUE
qdel(query_build_ban_cache)
/datum/admins/proc/ban_panel(player_key, player_ip, player_cid, role, duration = 1440, applies_to_admins, reason, edit_id, page, admin_key)
var/panel_height = 620
if(edit_id)
panel_height = 240
var/datum/browser/panel = new(usr, "banpanel", "Banning Panel", 910, panel_height)
panel.add_stylesheet("banpanelcss", 'html/admin/banpanel.css')
if(usr.client.prefs.tgui_fancy) //some browsers (IE8) have trouble with unsupported css3 elements and DOM methods that break the panel's functionality, so we won't load those if a user is in no frills tgui mode since that's for similar compatability support
panel.add_stylesheet("banpanelcss3", 'html/admin/banpanel_css3.css')
panel.add_script("banpaneljs", 'html/admin/banpanel.js')
var/list/output = list("
"
panel.set_content(jointext(output, ""))
panel.open()
/datum/admins/proc/ban_parse_href(list/href_list)
if(!check_rights(R_BAN))
return
if(!SSdbcore.Connect())
to_chat(usr, "Failed to establish database connection.")
return
var/list/error_state = list()
var/player_key
var/ip_check = FALSE
var/player_ip
var/cid_check = FALSE
var/player_cid
var/use_last_connection = FALSE
var/applies_to_admins = FALSE
var/duration
var/interval
var/severity
var/reason
var/mirror_edit
var/edit_id
var/old_key
var/old_ip
var/old_cid
var/old_applies
var/page
var/admin_key
var/list/changes = list()
var/list/roles_to_ban = list()
if(href_list["keycheck"])
player_key = href_list["keytext"]
if(!player_key)
error_state += "Key was ticked but none was provided."
if(href_list["ipcheck"])
ip_check = TRUE
if(href_list["cidcheck"])
cid_check = TRUE
if(href_list["lastconn"])
if(player_key)
use_last_connection = TRUE
else
if(ip_check)
player_ip = href_list["iptext"]
if(!player_ip && !use_last_connection)
error_state += "IP was ticked but none was provided."
if(cid_check)
player_cid = href_list["cidtext"]
if(!player_cid && !use_last_connection)
error_state += "CID was ticked but none was provided."
if(!use_last_connection && !player_ip && !player_cid && !player_key)
error_state += "At least a key, IP or CID must be provided."
if(use_last_connection && !ip_check && !cid_check)
error_state += "Use last connection was ticked, but neither IP nor CID was."
if(href_list["applyadmins"])
applies_to_admins = TRUE
switch(href_list["radioduration"])
if("permanent")
duration = null
if("temporary")
duration = href_list["duration"]
interval = href_list["intervaltype"]
if(!duration)
error_state += "Temporary ban was selected but no duration was provided."
else
error_state += "No duration was selected."
reason = href_list["reason"]
if(!reason)
error_state += "No reason was provided."
if(href_list["editid"])
edit_id = href_list["editid"]
if(href_list["mirroredit"])
mirror_edit = TRUE
old_key = href_list["oldkey"]
old_ip = href_list["oldip"]
old_cid = href_list["oldcid"]
page = href_list["page"]
admin_key = href_list["adminkey"]
if(player_key != old_key)
changes += list("Key" = "[old_key] to [player_key]")
if(player_ip != old_ip)
changes += list("IP" = "[old_ip] to [player_ip]")
if(player_cid != old_cid)
changes += list("CID" = "[old_cid] to [player_cid]")
old_applies = text2num(href_list["oldapplies"])
if(applies_to_admins != old_applies)
changes += list("Applies to admins" = "[old_applies] to [applies_to_admins]")
if(duration != href_list["oldduration"])
changes += list("Duration" = "[href_list["oldduration"]] MINUTE to [duration] [interval]")
if(reason != href_list["oldreason"])
changes += list("Reason" = "[href_list["oldreason"]] to [reason]")
if(!changes.len)
error_state += "No changes were detected."
else
severity = href_list["radioseverity"]
if(!severity)
error_state += "No severity was selected."
switch(href_list["radioban"])
if("server")
roles_to_ban += "Server"
if("role")
href_list.Remove("Command", "Security", "Engineering", "Medical", "Science", "Supply", "Silicon", "Abstract", "Civilian", "Ghost and Other Roles", "Antagonist Positions") //remove the role banner hidden input values
if(href_list[href_list.len] == "roleban_delimiter")
error_state += "Role ban was selected but no roles to ban were selected."
else
var/delimiter_pos = href_list.Find("roleban_delimiter")
href_list.Cut(1, delimiter_pos+1)//remove every list element before and including roleban_delimiter so we have a list of only the roles to ban
for(var/key in href_list) //flatten into a list of only unique keys
roles_to_ban |= key
else
error_state += "No ban type was selected."
if(error_state.len)
to_chat(usr, "Ban not [edit_id ? "edited" : "created"] because the following errors were present:\n[error_state.Join("\n")]")
return
if(edit_id)
edit_ban(edit_id, player_key, ip_check, player_ip, cid_check, player_cid, use_last_connection, applies_to_admins, duration, interval, reason, mirror_edit, old_key, old_ip, old_cid, old_applies, page, admin_key, changes)
else
create_ban(player_key, ip_check, player_ip, cid_check, player_cid, use_last_connection, applies_to_admins, duration, interval, severity, reason, roles_to_ban)
/datum/admins/proc/create_ban(player_key, ip_check, player_ip, cid_check, player_cid, use_last_connection, applies_to_admins, duration, interval, severity, reason, list/roles_to_ban)
if(!check_rights(R_BAN))
return
if(!SSdbcore.Connect())
to_chat(usr, "Failed to establish database connection.")
return
var/player_ckey = sanitizeSQL(ckey(player_key))
player_ip = sanitizeSQL(player_ip)
player_cid = sanitizeSQL(player_cid)
if(player_ckey)
var/datum/DBQuery/query_create_ban_get_player = SSdbcore.NewQuery("SELECT byond_key, INET_NTOA(ip), computerid FROM [format_table_name("player")] WHERE ckey = '[player_ckey]'")
if(!query_create_ban_get_player.warn_execute())
qdel(query_create_ban_get_player)
return
if(query_create_ban_get_player.NextRow())
player_key = query_create_ban_get_player.item[1]
if(use_last_connection)
if(ip_check)
player_ip = query_create_ban_get_player.item[2]
if(cid_check)
player_cid = query_create_ban_get_player.item[3]
else
if(use_last_connection)
if(alert(usr, "[player_key]/([player_ckey]) has not been seen before, unable to use IP and CID from last connection. Are you sure you want to create a ban for them?", "Unknown key", "Yes", "No", "Cancel") != "Yes")
qdel(query_create_ban_get_player)
return
else
if(alert(usr, "[player_key]/([player_ckey]) has not been seen before, are you sure you want to create a ban for them?", "Unknown key", "Yes", "No", "Cancel") != "Yes")
qdel(query_create_ban_get_player)
return
qdel(query_create_ban_get_player)
var/admin_ckey = sanitizeSQL(usr.client.ckey)
if(applies_to_admins)
var/datum/DBQuery/query_check_adminban_count = SSdbcore.NewQuery("SELECT COUNT(DISTINCT bantime) FROM [format_table_name("ban")] WHERE a_ckey = '[admin_ckey]' AND applies_to_admins = 1 AND unbanned_datetime IS NULL AND (expiration_time IS NULL OR expiration_time > NOW())")
if(!query_check_adminban_count.warn_execute()) //count distinct bantime to treat rolebans made at the same time as one ban
qdel(query_check_adminban_count)
return
if(query_check_adminban_count.NextRow())
var/adminban_count = text2num(query_check_adminban_count.item[1])
var/max_adminbans = MAX_ADMINBANS_PER_ADMIN
if(R_EVERYTHING && !(R_EVERYTHING & rank.can_edit_rights)) //edit rights are a more effective way to check hierarchical rank since many non-headmins have R_PERMISSIONS now
max_adminbans = MAX_ADMINBANS_PER_HEADMIN
if(adminban_count >= max_adminbans)
to_chat(usr, "You've already logged [max_adminbans] admin ban(s) or more. Do not abuse this function!")
qdel(query_check_adminban_count)
return
qdel(query_check_adminban_count)
var/admin_ip = sanitizeSQL(usr.client.address)
var/admin_cid = sanitizeSQL(usr.client.computer_id)
duration = text2num(duration)
if(interval)
interval = sanitizeSQL(interval)
else
interval = "MINUTE"
var/time_message = "[duration] [lowertext(interval)]" //no DisplayTimeText because our duration is of variable interval type
if(duration > 1) //pluralize the interval if necessary
time_message += "s"
var/note_reason = "Banned from [roles_to_ban[1] == "Server" ? "the server" : " Roles: [roles_to_ban.Join(", ")]"] [isnull(duration) ? "permanently" : "for [time_message]"] - [reason]"
reason = sanitizeSQL(reason)
var/list/clients_online = GLOB.clients.Copy()
var/list/admins_online = list()
for(var/client/C in clients_online)
if(C.holder) //deadmins aren't included since they wouldn't show up on adminwho
admins_online += C
var/who = clients_online.Join(", ")
var/adminwho = admins_online.Join(", ")
var/kn = key_name(usr)
var/kna = key_name_admin(usr)
var/sql_ban
for(var/role in roles_to_ban)
sql_ban += list(list("bantime" = "NOW()",
"server_ip" = "INET_ATON(IF('[world.internet_address]' LIKE '', '0', '[world.internet_address]'))",
"server_port" = sanitizeSQL(world.port),
"round_id" = sanitizeSQL(GLOB.round_id),
"role" = "'[sanitizeSQL(role)]'",
"expiration_time" = "IF('[duration]' LIKE '', NULL, NOW() + INTERVAL [duration ? "[duration]" : "0"] [interval])",
"applies_to_admins" = sanitizeSQL(applies_to_admins),
"reason" = "'[reason]'",
"ckey" = "IF('[player_ckey]' LIKE '', NULL, '[player_ckey]')",
"ip" = "INET_ATON(IF('[player_ip]' LIKE '', NULL, '[player_ip]'))",
"computerid" = "IF('[player_cid]' LIKE '', NULL, '[player_cid]')",
"a_ckey" = "'[admin_ckey]'",
"a_ip" = "INET_ATON(IF('[admin_ip]' LIKE '', NULL, '[admin_ip]'))",
"a_computerid" = "'[admin_cid]'",
"who" = "'[who]'",
"adminwho" = "'[adminwho]'"
))
if(!SSdbcore.MassInsert(format_table_name("ban"), sql_ban, warn = 1))
return
var/target = ban_target_string(player_key, player_ip, player_cid)
var/msg = "has created a [isnull(duration) ? "permanent" : "temporary [time_message]"] [applies_to_admins ? "admin " : ""][roles_to_ban[1] == "Server" ? "server ban" : "role ban from [roles_to_ban.len] roles"] for [target]."
log_admin_private("[kn] [msg][roles_to_ban[1] == "Server" ? "" : " Roles: [roles_to_ban.Join(", ")]"] Reason: [reason]")
message_admins("[kna] [msg][roles_to_ban[1] == "Server" ? "" : " Roles: [roles_to_ban.Join("\n")]"]\nReason: [reason]")
if(applies_to_admins)
send2tgs("BAN ALERT","[kn] [msg]")
if(player_ckey)
create_message("note", player_ckey, admin_ckey, note_reason, null, null, 0, 0, null, 0, severity)
var/client/C = GLOB.directory[player_ckey]
var/datum/admin_help/AH = admin_ticket_log(player_ckey, msg)
var/appeal_url = "No ban appeal url set!"
appeal_url = CONFIG_GET(string/banappeals)
var/is_admin = FALSE
if(C)
build_ban_cache(C)
to_chat(C, "You have been [applies_to_admins ? "admin " : ""]banned by [usr.client.key] from [roles_to_ban[1] == "Server" ? "the server" : " Roles: [roles_to_ban.Join(", ")]"].\nReason: [reason] This ban is [isnull(duration) ? "permanent." : "temporary, it will be removed in [time_message]."] The round ID is [GLOB.round_id]. To appeal this ban go to [appeal_url]")
if(GLOB.admin_datums[C.ckey] || GLOB.deadmins[C.ckey])
is_admin = TRUE
if(roles_to_ban[1] == "Server" && (!is_admin || (is_admin && applies_to_admins)))
qdel(C)
if(roles_to_ban[1] == "Server" && AH)
AH.Resolve()
for(var/client/i in GLOB.clients - C)
if(i.address == player_ip || i.computer_id == player_cid)
build_ban_cache(i)
to_chat(i, "You have been [applies_to_admins ? "admin " : ""]banned by [usr.client.key] from [roles_to_ban[1] == "Server" ? "the server" : " Roles: [roles_to_ban.Join(", ")]"].\nReason: [reason] This ban is [isnull(duration) ? "permanent." : "temporary, it will be removed in [time_message]."] The round ID is [GLOB.round_id]. To appeal this ban go to [appeal_url]")
if(GLOB.admin_datums[i.ckey] || GLOB.deadmins[i.ckey])
is_admin = TRUE
if(roles_to_ban[1] == "Server" && (!is_admin || (is_admin && applies_to_admins)))
qdel(i)
/datum/admins/proc/unban_panel(player_key, admin_key, player_ip, player_cid, page = 0)
if(!check_rights(R_BAN))
return
if(!SSdbcore.Connect())
to_chat(usr, "Failed to establish database connection.")
return
var/datum/browser/unban_panel = new(usr, "unbanpanel", "Unbanning Panel", 850, 600)
unban_panel.add_stylesheet("unbanpanelcss", 'html/admin/unbanpanel.css')
var/list/output = list("
")
output += {"
"}
if(player_key || admin_key || player_ip || player_cid)
var/list/searchlist = list()
if(player_key)
searchlist += "ckey = '[sanitizeSQL(ckey(player_key))]'"
if(admin_key)
searchlist += "a_ckey = '[sanitizeSQL(ckey(admin_key))]'"
if(player_ip)
searchlist += "ip = INET_ATON('[sanitizeSQL(player_ip)]')"
if(player_cid)
searchlist += "computerid = '[sanitizeSQL(player_cid)]'"
var/search = searchlist.Join(" AND ")
var/bancount = 0
var/bansperpage = 10
page = text2num(page)
var/datum/DBQuery/query_unban_count_bans = SSdbcore.NewQuery("SELECT COUNT(id) FROM [format_table_name("ban")] WHERE [search]")
if(!query_unban_count_bans.warn_execute())
qdel(query_unban_count_bans)
return
if(query_unban_count_bans.NextRow())
bancount = text2num(query_unban_count_bans.item[1])
qdel(query_unban_count_bans)
if(bancount > bansperpage)
output += "Page: "
var/pagecount = 1
var/list/pagelist = list()
while(bancount > 0)
pagelist += "[pagecount == page ? "\[[pagecount]\]" : "\[[pagecount]\]"]"
bancount -= bansperpage
pagecount++
output += pagelist.Join(" | ")
var/limit = " LIMIT [bansperpage * page], [bansperpage]"
var/datum/DBQuery/query_unban_search_bans = SSdbcore.NewQuery({"SELECT id, bantime, round_id, role, expiration_time, TIMESTAMPDIFF(MINUTE, bantime, expiration_time), IF(expiration_time < NOW(), 1, NULL), applies_to_admins, reason, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE [format_table_name("player")].ckey = [format_table_name("ban")].ckey), ckey), INET_NTOA(ip), computerid, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE [format_table_name("player")].ckey = [format_table_name("ban")].a_ckey), a_ckey), IF(edits IS NOT NULL, 1, NULL), unbanned_datetime, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE [format_table_name("player")].ckey = [format_table_name("ban")].unbanned_ckey), unbanned_ckey), unbanned_round_id FROM [format_table_name("ban")] WHERE [search] ORDER BY id DESC[limit]"})
if(!query_unban_search_bans.warn_execute())
qdel(query_unban_search_bans)
return
while(query_unban_search_bans.NextRow())
var/ban_id = query_unban_search_bans.item[1]
var/ban_datetime = query_unban_search_bans.item[2]
var/ban_round_id = query_unban_search_bans.item[3]
var/role = query_unban_search_bans.item[4]
//make the href for unban here so only the search parameters are passed
var/unban_href = "Unban"
var/expiration_time = query_unban_search_bans.item[5]
//we don't cast duration as num because if the duration is large enough to be converted to scientific notation by byond then the + character gets lost when passed through href causing SQL to interpret '4.321e 007' as '4'
var/duration = query_unban_search_bans.item[6]
var/expired = query_unban_search_bans.item[7]
var/applies_to_admins = text2num(query_unban_search_bans.item[8])
var/reason = query_unban_search_bans.item[9]
player_key = query_unban_search_bans.item[10]
player_ip = query_unban_search_bans.item[11]
player_cid = query_unban_search_bans.item[12]
admin_key = query_unban_search_bans.item[13]
var/edits = query_unban_search_bans.item[14]
var/unban_datetime = query_unban_search_bans.item[15]
var/unban_key = query_unban_search_bans.item[16]
var/unban_round_id = query_unban_search_bans.item[17]
var/target = ban_target_string(player_key, player_ip, player_cid)
output += "
[target][applies_to_admins ? " ADMIN" : ""] banned by [admin_key] from [role] on [ban_datetime] during round #[ban_round_id]. "
if(!expiration_time)
output += "Permanent ban."
else
output += "Duration of [DisplayTimeText(text2num(duration) MINUTES)], [expired ? "expired" : "expires"] on [expiration_time]."
if(unban_datetime)
output += " Unbanned by [unban_key] on [unban_datetime] during round #[unban_round_id]."
output += "
"
unban_panel.set_content(jointext(output, ""))
unban_panel.open()
/datum/admins/proc/unban(ban_id, player_key, player_ip, player_cid, role, page, admin_key)
if(!check_rights(R_BAN))
return
if(!SSdbcore.Connect())
to_chat(usr, "Failed to establish database connection.")
return
var/target = ban_target_string(player_key, player_ip, player_cid)
if(alert(usr, "Please confirm unban of [target] from [role].", "Unban confirmation", "Yes", "No") == "No")
return
ban_id = sanitizeSQL(ban_id)
var/admin_ckey = sanitizeSQL(usr.client.ckey)
var/admin_ip = sanitizeSQL(usr.client.address)
var/admin_cid = sanitizeSQL(usr.client.computer_id)
var/kn = key_name(usr)
var/kna = key_name_admin(usr)
var/datum/DBQuery/query_unban = SSdbcore.NewQuery("UPDATE [format_table_name("ban")] SET unbanned_datetime = NOW(), unbanned_ckey = '[admin_ckey]', unbanned_ip = INET_ATON('[admin_ip]'), unbanned_computerid = '[admin_cid]', unbanned_round_id = '[GLOB.round_id]' WHERE id = [ban_id]")
if(!query_unban.warn_execute())
qdel(query_unban)
return
qdel(query_unban)
log_admin_private("[kn] has unbanned [target] from [role].")
message_admins("[kna] has unbanned [target] from [role].")
var/client/C = GLOB.directory[player_key]
if(C)
build_ban_cache(C)
to_chat(C, "[usr.client.key] has removed a ban from [role] for your key.")
for(var/client/i in GLOB.clients - C)
if(i.address == player_ip || i.computer_id == player_cid)
build_ban_cache(i)
to_chat(i, "[usr.client.key] has removed a ban from [role] for your IP or CID.")
unban_panel(player_key, admin_key, player_ip, player_cid, page)
/datum/admins/proc/edit_ban(ban_id, player_key, ip_check, player_ip, cid_check, player_cid, use_last_connection, applies_to_admins, duration, interval, reason, mirror_edit, old_key, old_ip, old_cid, old_applies, admin_key, page, list/changes)
if(!check_rights(R_BAN))
return
if(!SSdbcore.Connect())
to_chat(usr, "Failed to establish database connection.")
return
ban_id = sanitizeSQL(ban_id)
var/player_ckey = sanitizeSQL(ckey(player_key))
player_ip = sanitizeSQL(player_ip)
player_cid = sanitizeSQL(player_cid)
var/bantime
if(player_ckey)
var/datum/DBQuery/query_edit_ban_get_player = SSdbcore.NewQuery("SELECT byond_key, (SELECT bantime FROM [format_table_name("ban")] WHERE id = [ban_id]), ip, computerid FROM [format_table_name("player")] WHERE ckey = '[player_ckey]'")
if(!query_edit_ban_get_player.warn_execute())
qdel(query_edit_ban_get_player)
return
if(query_edit_ban_get_player.NextRow())
player_key = query_edit_ban_get_player.item[1]
bantime = query_edit_ban_get_player.item[2]
if(use_last_connection)
if(ip_check)
player_ip = query_edit_ban_get_player.item[3]
if(cid_check)
player_cid = query_edit_ban_get_player.item[4]
else
if(use_last_connection)
if(alert(usr, "[player_key]/([player_ckey]) has not been seen before, unable to use IP and CID from last connection. Are you sure you want to edit a ban for them?", "Unknown key", "Yes", "No", "Cancel") != "Yes")
qdel(query_edit_ban_get_player)
return
else
if(alert(usr, "[player_key]/([player_ckey]) has not been seen before, are you sure you want to edit a ban for them?", "Unknown key", "Yes", "No", "Cancel") != "Yes")
qdel(query_edit_ban_get_player)
return
qdel(query_edit_ban_get_player)
if(applies_to_admins && (applies_to_admins != old_applies))
var/admin_ckey = sanitizeSQL(usr.client.ckey)
var/datum/DBQuery/query_check_adminban_count = SSdbcore.NewQuery("SELECT COUNT(DISTINCT bantime) FROM [format_table_name("ban")] WHERE a_ckey = '[admin_ckey]' AND applies_to_admins = 1 AND unbanned_datetime IS NULL AND (expiration_time IS NULL OR expiration_time > NOW())")
if(!query_check_adminban_count.warn_execute()) //count distinct bantime to treat rolebans made at the same time as one ban
qdel(query_check_adminban_count)
return
if(query_check_adminban_count.NextRow())
var/adminban_count = text2num(query_check_adminban_count.item[1])
var/max_adminbans = MAX_ADMINBANS_PER_ADMIN
if(R_EVERYTHING && !(R_EVERYTHING & rank.can_edit_rights)) //edit rights are a more effective way to check hierarchical rank since many non-headmins have R_PERMISSIONS now
max_adminbans = MAX_ADMINBANS_PER_HEADMIN
if(adminban_count >= max_adminbans)
to_chat(usr, "You've already logged [max_adminbans] admin ban(s) or more. Do not abuse this function!")
qdel(query_check_adminban_count)
return
qdel(query_check_adminban_count)
applies_to_admins = sanitizeSQL(applies_to_admins)
duration = sanitizeSQL(duration)
if(interval)
interval = sanitizeSQL(interval)
else
interval = "MINUTE"
reason = sanitizeSQL(reason)
var/kn = key_name(usr)
var/kna = key_name_admin(usr)
var/list/changes_text= list()
var/list/changes_keys = list()
for(var/i in changes)
changes_text += "[sanitizeSQL(i)]: [sanitizeSQL(changes[i])]"
changes_keys += i
var/where = "id = [sanitizeSQL(ban_id)]"
if(text2num(mirror_edit))
var/list/wherelist = list("bantime = '[bantime]'")
if(old_key)
wherelist += "ckey = '[sanitizeSQL(ckey(old_key))]'"
if(old_ip)
old_ip = sanitizeSQL(old_ip)
wherelist += "ip = INET_ATON(IF('[old_ip]' LIKE '', NULL, '[old_ip]'))"
if(old_cid)
wherelist += "computerid = '[sanitizeSQL(old_cid)]'"
where = wherelist.Join(" AND ")
var/datum/DBQuery/query_edit_ban = SSdbcore.NewQuery("UPDATE [format_table_name("ban")] SET expiration_time = IF('[duration]' LIKE '', NULL, bantime + INTERVAL [duration ? "[duration]" : "0"] [interval]), applies_to_admins = [applies_to_admins], reason = '[reason]', ckey = IF('[player_ckey]' LIKE '', NULL, '[player_ckey]'), ip = INET_ATON(IF('[player_ip]' LIKE '', NULL, '[player_ip]')), computerid = IF('[player_cid]' LIKE '', NULL, '[player_cid]'), edits = CONCAT(IFNULL(edits,''),'[sanitizeSQL(usr.client.key)] edited the following [jointext(changes_text, ", ")]') WHERE [where]")
if(!query_edit_ban.warn_execute())
qdel(query_edit_ban)
return
qdel(query_edit_ban)
var/changes_keys_text = jointext(changes_keys, ", ")
log_admin_private("[kn] has edited the [changes_keys_text] of a ban for [old_key ? "[old_key]" : "[old_ip]-[old_cid]"].") //if a ban doesn't have a key it must have an ip and/or a cid to have reached this point normally
message_admins("[kna] has edited the [changes_keys_text] of a ban for [old_key ? "[old_key]" : "[old_ip]-[old_cid]"].")
if(changes["Applies to admins"])
send2tgs("BAN ALERT","[kn] has edited a ban for [old_key ? "[old_key]" : "[old_ip]-[old_cid]"] to [applies_to_admins ? "" : "not"]affect admins")
var/client/C = GLOB.directory[old_key]
if(C)
build_ban_cache(C)
to_chat(C, "[usr.client.key] has edited the [changes_keys_text] of a ban for your key.")
for(var/client/i in GLOB.clients - C)
if(i.address == old_ip || i.computer_id == old_cid)
build_ban_cache(i)
to_chat(i, "[usr.client.key] has edited the [changes_keys_text] of a ban for your IP or CID.")
unban_panel(player_key, null, null, null, page)
/datum/admins/proc/ban_log(ban_id)
if(!check_rights(R_BAN))
return
if(!SSdbcore.Connect())
to_chat(usr, "Failed to establish database connection.")
return
ban_id = sanitizeSQL(ban_id)
var/datum/DBQuery/query_get_ban_edits = SSdbcore.NewQuery("SELECT edits FROM [format_table_name("ban")] WHERE id = '[ban_id]'")
if(!query_get_ban_edits.warn_execute())
qdel(query_get_ban_edits)
return
if(query_get_ban_edits.NextRow())
var/edits = query_get_ban_edits.item[1]
var/datum/browser/edit_log = new(usr, "baneditlog", "Ban edit log")
edit_log.set_content(edits)
edit_log.open()
qdel(query_get_ban_edits)
/datum/admins/proc/ban_target_string(player_key, player_ip, player_cid)
. = list()
if(player_key)
. += player_key
else
if(player_ip)
. += player_ip
else
. += "NULL"
if(player_cid)
. += player_cid
else
. += "NULL"
. = jointext(., "/")