From 56789c5924abf1a4321a13ff434b0dafd2417b5d Mon Sep 17 00:00:00 2001 From: Letter N <24603524+LetterN@users.noreply.github.com> Date: Thu, 31 Dec 2020 16:46:40 +0800 Subject: [PATCH] firsthit-lib_machines --- code/__HELPERS/roundend.dm | 17 +- code/controllers/subsystem/blackbox.dm | 98 ++++--- code/controllers/subsystem/dbcore.dm | 350 ++++++++++++----------- code/controllers/subsystem/mapping.dm | 4 +- code/game/gamemodes/game_mode.dm | 33 ++- code/modules/admin/DB_ban/functions.dm | 22 +- code/modules/admin/IsBanned.dm | 2 +- code/modules/admin/admin_ranks.dm | 24 +- code/modules/admin/banjob.dm | 6 +- code/modules/admin/create_poll.dm | 6 +- code/modules/admin/ipintel.dm | 28 +- code/modules/admin/permissionedit.dm | 170 +++++++---- code/modules/admin/sql_message_system.dm | 252 +++++++++++----- code/modules/admin/topic.dm | 19 +- code/modules/client/client_procs.dm | 151 ++++++---- code/modules/client/preferences.dm | 2 +- code/modules/jobs/job_exp.dm | 16 +- code/modules/library/lib_machines.dm | 260 +++++++++-------- 18 files changed, 871 insertions(+), 589 deletions(-) diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm index e4a2e6521a..e1c1e3df07 100644 --- a/code/__HELPERS/roundend.dm +++ b/code/__HELPERS/roundend.dm @@ -586,11 +586,9 @@ var/list/sql_admins = list() for(var/i in GLOB.protected_admins) var/datum/admins/A = GLOB.protected_admins[i] - var/sql_ckey = sanitizeSQL(A.target) - var/sql_rank = sanitizeSQL(A.rank.name) - sql_admins += list(list("ckey" = "'[sql_ckey]'", "rank" = "'[sql_rank]'")) + sql_admins += list(list("ckey" = A.target, "rank" = A.rank.name)) SSdbcore.MassInsert(format_table_name("admin"), sql_admins, duplicate_key = TRUE) - var/datum/DBQuery/query_admin_rank_update = SSdbcore.NewQuery("UPDATE [format_table_name("player")] p INNER JOIN [format_table_name("admin")] a ON p.ckey = a.ckey SET p.lastadminrank = a.rank") + var/datum/db_query/query_admin_rank_update = SSdbcore.NewQuery("UPDATE [format_table_name("player")] p INNER JOIN [format_table_name("admin")] a ON p.ckey = a.ckey SET p.lastadminrank = a.rank") query_admin_rank_update.Execute() qdel(query_admin_rank_update) @@ -623,15 +621,20 @@ flags += "can_edit_flags" if(!flags.len) continue - var/sql_rank = sanitizeSQL(R.name) var/flags_to_check = flags.Join(" != [R_EVERYTHING] AND ") + " != [R_EVERYTHING]" - var/datum/DBQuery/query_check_everything_ranks = SSdbcore.NewQuery("SELECT flags, exclude_flags, can_edit_flags FROM [format_table_name("admin_ranks")] WHERE rank = '[sql_rank]' AND ([flags_to_check])") + var/datum/db_query/query_check_everything_ranks = SSdbcore.NewQuery( + "SELECT flags, exclude_flags, can_edit_flags FROM [format_table_name("admin_ranks")] WHERE rank = :rank AND ([flags_to_check])", + list("rank" = R.name) + ) if(!query_check_everything_ranks.Execute()) qdel(query_check_everything_ranks) return if(query_check_everything_ranks.NextRow()) //no row is returned if the rank already has the correct flag value var/flags_to_update = flags.Join(" = [R_EVERYTHING], ") + " = [R_EVERYTHING]" - var/datum/DBQuery/query_update_everything_ranks = SSdbcore.NewQuery("UPDATE [format_table_name("admin_ranks")] SET [flags_to_update] WHERE rank = '[sql_rank]'") + var/datum/db_query/query_update_everything_ranks = SSdbcore.NewQuery( + "UPDATE [format_table_name("admin_ranks")] SET [flags_to_update] WHERE rank = :rank", + list("rank" = R.name) + ) if(!query_update_everything_ranks.Execute()) qdel(query_update_everything_ranks) return diff --git a/code/controllers/subsystem/blackbox.dm b/code/controllers/subsystem/blackbox.dm index dc1f246e3d..455ccb8d14 100644 --- a/code/controllers/subsystem/blackbox.dm +++ b/code/controllers/subsystem/blackbox.dm @@ -39,12 +39,19 @@ SUBSYSTEM_DEF(blackbox) if(!SSdbcore.Connect()) return - var/playercount = 0 - for(var/mob/M in GLOB.player_list) - if(M.client) - playercount += 1 + var/playercount = LAZYLEN(GLOB.player_list) var/admincount = GLOB.admins.len - var/datum/DBQuery/query_record_playercount = SSdbcore.NewQuery("INSERT INTO [format_table_name("legacy_population")] (playercount, admincount, time, server_ip, server_port, round_id) VALUES ([playercount], [admincount], '[SQLtime()]', INET_ATON(IF('[world.internet_address]' LIKE '', '0', '[world.internet_address]')), '[world.port]', '[GLOB.round_id]')") + var/datum/db_query/query_record_playercount = SSdbcore.NewQuery({" + INSERT INTO [format_table_name("legacy_population")] (playercount, admincount, time, server_ip, server_port, round_id) + VALUES (:playercount, :admincount, :time, INET_ATON(:server_ip), :server_port, :round_id) + "}, list( + "playercount" = playercount, + "admincount" = admincount, + "time" = SQLtime(), + "server_ip" = world.internet_address || "0", + "server_port" = "[world.port]", + "round_id" = GLOB.round_id, + )) query_record_playercount.Execute() qdel(query_record_playercount) @@ -271,6 +278,17 @@ Versioning key = new_key key_type = new_key_type +/datum/controller/subsystem/blackbox/proc/LogAhelp(ticket, action, message, recipient, sender) + if(!SSdbcore.Connect()) + return + + var/datum/db_query/query_log_ahelp = SSdbcore.NewQuery({" + INSERT INTO [format_table_name("ticket")] (ticket, action, message, recipient, sender, server_ip, server_port, round_id, timestamp) + VALUES (:ticket, :action, :message, :recipient, :sender, INET_ATON(:server_ip), :server_port, :round_id, :time) + "}, list("ticket" = ticket, "action" = action, "message" = message, "recipient" = recipient, "sender" = sender, "server_ip" = world.internet_address || "0", "server_port" = world.port, "round_id" = GLOB.round_id, "time" = SQLtime())) + query_log_ahelp.Execute() + qdel(query_log_ahelp) + /datum/controller/subsystem/blackbox/proc/ReportDeath(mob/living/L) set waitfor = FALSE if(sealed) @@ -285,51 +303,39 @@ Versioning first_death["area"] = "[AREACOORD(L)]" first_death["damage"] = "[L.getBruteLoss()]/[L.getFireLoss()]/[L.getToxLoss()]/[L.getOxyLoss()]/[L.getCloneLoss()]" first_death["last_words"] = L.last_words - var/sqlname = L.real_name - var/sqlkey = L.ckey - var/sqljob = L.mind.assigned_role - var/sqlspecial = L.mind.special_role - var/sqlpod = get_area_name(L, TRUE) - var/laname = L.lastattacker - var/lakey = L.lastattackerckey - var/sqlbrute = L.getBruteLoss() - var/sqlfire = L.getFireLoss() - var/sqlbrain = L.getOrganLoss(ORGAN_SLOT_BRAIN) - var/sqloxy = L.getOxyLoss() - var/sqltox = L.getToxLoss() - var/sqlclone = L.getCloneLoss() - var/sqlstamina = L.getStaminaLoss() - var/x_coord = L.x - var/y_coord = L.y - var/z_coord = L.z - var/last_words = L.last_words - var/suicide = L.suiciding - var/map = SSmapping.config.map_name if(!SSdbcore.Connect()) return - sqlname = sanitizeSQL(sqlname) - sqlkey = sanitizeSQL(sqlkey) - sqljob = sanitizeSQL(sqljob) - sqlspecial = sanitizeSQL(sqlspecial) - sqlpod = sanitizeSQL(sqlpod) - laname = sanitizeSQL(laname) - lakey = sanitizeSQL(lakey) - sqlbrute = sanitizeSQL(sqlbrute) - sqlfire = sanitizeSQL(sqlfire) - sqlbrain = sanitizeSQL(sqlbrain) - sqloxy = sanitizeSQL(sqloxy) - sqltox = sanitizeSQL(sqltox) - sqlclone = sanitizeSQL(sqlclone) - sqlstamina = sanitizeSQL(sqlstamina) - x_coord = sanitizeSQL(x_coord) - y_coord = sanitizeSQL(y_coord) - z_coord = sanitizeSQL(z_coord) - last_words = sanitizeSQL(last_words) - suicide = sanitizeSQL(suicide) - map = sanitizeSQL(map) - var/datum/DBQuery/query_report_death = SSdbcore.NewQuery("INSERT INTO [format_table_name("death")] (pod, x_coord, y_coord, z_coord, mapname, server_ip, server_port, round_id, tod, job, special, name, byondkey, laname, lakey, bruteloss, fireloss, brainloss, oxyloss, toxloss, cloneloss, staminaloss, last_words, suicide) VALUES ('[sqlpod]', '[x_coord]', '[y_coord]', '[z_coord]', '[map]', INET_ATON(IF('[world.internet_address]' LIKE '', '0', '[world.internet_address]')), '[world.port]', [GLOB.round_id], '[SQLtime()]', '[sqljob]', '[sqlspecial]', '[sqlname]', '[sqlkey]', '[laname]', '[lakey]', [sqlbrute], [sqlfire], [sqlbrain], [sqloxy], [sqltox], [sqlclone], [sqlstamina], '[last_words]', [suicide])") + var/datum/db_query/query_report_death = SSdbcore.NewQuery({" + INSERT INTO [format_table_name("death")] (pod, x_coord, y_coord, z_coord, mapname, server_ip, server_port, round_id, tod, job, special, name, byondkey, laname, lakey, bruteloss, fireloss, brainloss, oxyloss, toxloss, cloneloss, staminaloss, last_words, suicide) + VALUES (:pod, :x_coord, :y_coord, :z_coord, :map, INET_ATON(:internet_address), :port, :round_id, :time, :job, :special, :name, :key, :laname, :lakey, :brute, :fire, :brain, :oxy, :tox, :clone, :stamina, :last_words, :suicide) + "}, list( + "name" = L.real_name, + "key" = L.ckey, + "job" = L.mind.assigned_role, + "special" = L.mind.special_role, + "pod" = get_area_name(L, TRUE), + "laname" = L.lastattacker, + "lakey" = L.lastattackerckey, + "brute" = L.getBruteLoss(), + "fire" = L.getFireLoss(), + "brain" = L.getOrganLoss(ORGAN_SLOT_BRAIN) || BRAIN_DAMAGE_DEATH, //getOrganLoss returns null without a brain but a value is required for this column + "oxy" = L.getOxyLoss(), + "tox" = L.getToxLoss(), + "clone" = L.getCloneLoss(), + "stamina" = L.getStaminaLoss(), + "x_coord" = L.x, + "y_coord" = L.y, + "z_coord" = L.z, + "last_words" = L.last_words, + "suicide" = L.suiciding, + "map" = SSmapping.config.map_name, + "internet_address" = world.internet_address || "0", + "port" = "[world.port]", + "round_id" = GLOB.round_id, + "time" = SQLtime(), + )) if(query_report_death) query_report_death.Execute(async = TRUE) qdel(query_report_death) diff --git a/code/controllers/subsystem/dbcore.dm b/code/controllers/subsystem/dbcore.dm index 4eff4fbf1d..b6b750fbf4 100644 --- a/code/controllers/subsystem/dbcore.dm +++ b/code/controllers/subsystem/dbcore.dm @@ -3,7 +3,7 @@ SUBSYSTEM_DEF(dbcore) flags = SS_BACKGROUND wait = 1 MINUTES init_order = INIT_ORDER_DBCORE - var/const/FAILED_DB_CONNECTION_CUTOFF = 5 + var/failed_connection_timeout = 0 var/schema_mismatch = 0 var/db_minor = 0 @@ -13,8 +13,7 @@ SUBSYSTEM_DEF(dbcore) var/last_error var/list/active_queries = list() - var/datum/BSQL_Connection/connection - var/datum/BSQL_Operation/connectOperation + var/connection // Arbitrary handle returned from rust_g. /datum/controller/subsystem/dbcore/Initialize() //We send warnings to the admins during subsystem init, as the clients will be New'd and messages @@ -29,7 +28,7 @@ SUBSYSTEM_DEF(dbcore) /datum/controller/subsystem/dbcore/fire() for(var/I in active_queries) - var/datum/DBQuery/Q = I + var/datum/db_query/Q = I if(world.time - Q.last_activity_time > (5 MINUTES)) message_admins("Found undeleted query, please check the server logs and notify coders.") log_sql("Undeleted query: \"[Q.sql]\" LA: [Q.last_activity] LAT: [Q.last_activity_time]") @@ -39,24 +38,25 @@ SUBSYSTEM_DEF(dbcore) /datum/controller/subsystem/dbcore/Recover() connection = SSdbcore.connection - connectOperation = SSdbcore.connectOperation /datum/controller/subsystem/dbcore/Shutdown() //This is as close as we can get to the true round end before Disconnect() without changing where it's called, defeating the reason this is a subsystem if(SSdbcore.Connect()) - var/datum/DBQuery/query_round_shutdown = SSdbcore.NewQuery("UPDATE [format_table_name("round")] SET shutdown_datetime = Now(), end_state = '[sanitizeSQL(SSticker.end_state)]' WHERE id = [GLOB.round_id]") + var/datum/db_query/query_round_shutdown = SSdbcore.NewQuery( + "UPDATE [format_table_name("round")] SET shutdown_datetime = Now(), end_state = :end_state WHERE id = :round_id", + list("end_state" = SSticker.end_state, "round_id" = GLOB.round_id) + ) query_round_shutdown.Execute() qdel(query_round_shutdown) if(IsConnected()) Disconnect() - world.BSQL_Shutdown() //nu /datum/controller/subsystem/dbcore/can_vv_get(var_name) - return var_name != NAMEOF(src, connection) && var_name != NAMEOF(src, active_queries) && var_name != NAMEOF(src, connectOperation) && ..() + return var_name != NAMEOF(src, connection) && var_name != NAMEOF(src, active_queries) && ..() /datum/controller/subsystem/dbcore/vv_edit_var(var_name, var_value) - if(var_name == NAMEOF(src, connection) || var_name == NAMEOF(src, connectOperation)) + if(var_name == NAMEOF(src, connection)) return FALSE return ..() @@ -64,7 +64,11 @@ SUBSYSTEM_DEF(dbcore) if(IsConnected()) return TRUE - if(failed_connections > FAILED_DB_CONNECTION_CUTOFF) //If it failed to establish a connection more than 5 times in a row, don't bother attempting to connect anymore. + if(failed_connection_timeout <= world.time) //it's been more than 5 seconds since we failed to connect, reset the counter + failed_connections = 0 + + if(failed_connections > 5) //If it failed to establish a connection more than 5 times in a row, don't bother attempting to connect for 5 seconds. + failed_connection_timeout = world.time + 50 return FALSE if(!CONFIG_GET(flag/sql_enabled)) @@ -75,32 +79,33 @@ SUBSYSTEM_DEF(dbcore) var/db = CONFIG_GET(string/feedback_database) var/address = CONFIG_GET(string/address) var/port = CONFIG_GET(number/port) + var/timeout = max(CONFIG_GET(number/async_query_timeout), CONFIG_GET(number/blocking_query_timeout)) + var/thread_limit = CONFIG_GET(number/bsql_thread_limit) - connection = new /datum/BSQL_Connection(BSQL_CONNECTION_TYPE_MARIADB, CONFIG_GET(number/async_query_timeout), CONFIG_GET(number/blocking_query_timeout), CONFIG_GET(number/bsql_thread_limit)) - var/error - if(QDELETED(connection)) - connection = null - error = last_error + var/result = json_decode(rustg_sql_connect_pool(json_encode(list( + "host" = address, + "port" = port, + "user" = user, + "pass" = pass, + "db_name" = db, + "read_timeout" = timeout, + "write_timeout" = timeout, + "max_threads" = thread_limit, + )))) + . = (result["status"] == "ok") + if (.) + connection = result["handle"] else - SSdbcore.last_error = null - connectOperation = connection.BeginConnect(address, port, user, pass, db) - if(SSdbcore.last_error) - CRASH(SSdbcore.last_error) - UNTIL(connectOperation.IsComplete()) - error = connectOperation.GetError() - . = !error - if (!.) - last_error = error - log_sql("Connect() failed | [error]") + connection = null + last_error = result["data"] + log_sql("Connect() failed | [last_error]") ++failed_connections - QDEL_NULL(connection) - QDEL_NULL(connectOperation) /datum/controller/subsystem/dbcore/proc/CheckSchemaVersion() if(CONFIG_GET(flag/sql_enabled)) if(Connect()) log_world("Database connection established.") - var/datum/DBQuery/query_db_version = NewQuery("SELECT major, minor FROM [format_table_name("schema_revision")] ORDER BY date DESC LIMIT 1") + var/datum/db_query/query_db_version = NewQuery("SELECT major, minor FROM [format_table_name("schema_revision")] ORDER BY date DESC LIMIT 1") query_db_version.Execute() if(query_db_version.NextRow()) db_major = text2num(query_db_version.item[1]) @@ -120,47 +125,46 @@ SUBSYSTEM_DEF(dbcore) /datum/controller/subsystem/dbcore/proc/SetRoundID() if(!Connect()) return - var/datum/DBQuery/query_round_initialize = SSdbcore.NewQuery("INSERT INTO [format_table_name("round")] (initialize_datetime, server_ip, server_port) VALUES (Now(), INET_ATON(IF('[world.internet_address]' LIKE '', '0', '[world.internet_address]')), '[world.port]')") - query_round_initialize.Execute() + var/datum/db_query/query_round_initialize = SSdbcore.NewQuery( + "INSERT INTO [format_table_name("round")] (initialize_datetime, server_ip, server_port) VALUES (Now(), INET_ATON(:internet_address), :port)", + list("internet_address" = world.internet_address || "0", "port" = "[world.port]") + ) + query_round_initialize.Execute(async = FALSE) + GLOB.round_id = "[query_round_initialize.last_insert_id]" qdel(query_round_initialize) - var/datum/DBQuery/query_round_last_id = SSdbcore.NewQuery("SELECT LAST_INSERT_ID()") - query_round_last_id.Execute() - if(query_round_last_id.NextRow()) - GLOB.round_id = query_round_last_id.item[1] - qdel(query_round_last_id) /datum/controller/subsystem/dbcore/proc/SetRoundStart() if(!Connect()) return - var/datum/DBQuery/query_round_start = SSdbcore.NewQuery("UPDATE [format_table_name("round")] SET start_datetime = Now() WHERE id = [GLOB.round_id]") + var/datum/db_query/query_round_start = SSdbcore.NewQuery( + "UPDATE [format_table_name("round")] SET start_datetime = Now() WHERE id = :round_id", + list("round_id" = GLOB.round_id) + ) query_round_start.Execute() qdel(query_round_start) /datum/controller/subsystem/dbcore/proc/SetRoundEnd() if(!Connect()) return - var/sql_station_name = sanitizeSQL(station_name()) - var/datum/DBQuery/query_round_end = SSdbcore.NewQuery("UPDATE [format_table_name("round")] SET end_datetime = Now(), game_mode_result = '[sanitizeSQL(SSticker.mode_result)]', station_name = '[sql_station_name]' WHERE id = [GLOB.round_id]") + var/datum/db_query/query_round_end = SSdbcore.NewQuery( + "UPDATE [format_table_name("round")] SET end_datetime = Now(), game_mode_result = :game_mode_result, station_name = :station_name WHERE id = :round_id", + list("game_mode_result" = SSticker.mode_result, "station_name" = station_name(), "round_id" = GLOB.round_id) + ) query_round_end.Execute() qdel(query_round_end) /datum/controller/subsystem/dbcore/proc/Disconnect() failed_connections = 0 - QDEL_NULL(connectOperation) - QDEL_NULL(connection) + if (connection) + rustg_sql_disconnect_pool(connection) + connection = null /datum/controller/subsystem/dbcore/proc/IsConnected() - if(!CONFIG_GET(flag/sql_enabled)) + if (!CONFIG_GET(flag/sql_enabled)) return FALSE - //block until any connect operations finish - var/datum/BSQL_Connection/_connection = connection - var/datum/BSQL_Operation/op = connectOperation - UNTIL(QDELETED(_connection) || op.IsComplete()) - return !QDELETED(connection) && !op.GetError() - -/datum/controller/subsystem/dbcore/proc/Quote(str) - if(connection) - return connection.Quote(str) + if (!connection) + return FALSE + return json_decode(rustg_sql_connected(connection))["status"] == "online" /datum/controller/subsystem/dbcore/proc/ErrorMsg() if(!CONFIG_GET(flag/sql_enabled)) @@ -170,12 +174,33 @@ SUBSYSTEM_DEF(dbcore) /datum/controller/subsystem/dbcore/proc/ReportError(error) last_error = error -/datum/controller/subsystem/dbcore/proc/NewQuery(sql_query) +/datum/controller/subsystem/dbcore/proc/NewQuery(sql_query, arguments) if(IsAdminAdvancedProcCall()) log_admin_private("ERROR: Advanced admin proc call led to sql query: [sql_query]. Query has been blocked") message_admins("ERROR: Advanced admin proc call led to sql query. Query has been blocked") return FALSE - return new /datum/DBQuery(sql_query, connection) + return new /datum/db_query(connection, sql_query, arguments) + +/datum/controller/subsystem/dbcore/proc/QuerySelect(list/querys, warn = FALSE, qdel = FALSE) + if (!islist(querys)) + if (!istype(querys, /datum/db_query)) + CRASH("Invalid query passed to QuerySelect: [querys]") + querys = list(querys) + + for (var/thing in querys) + var/datum/db_query/query = thing + if (warn) + INVOKE_ASYNC(query, /datum/db_query.proc/warn_execute) + else + INVOKE_ASYNC(query, /datum/db_query.proc/Execute) + + for (var/thing in querys) + var/datum/db_query/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. @@ -184,137 +209,135 @@ You are expected to do your own escaping of the data, and expected to provide yo The duplicate_key arg can be true to automatically generate this part of the query or set to a string that is appended to the end of the query Ignore_errors instructes mysql to continue inserting rows if some of them have errors. - the erroneous row(s) aren't inserted and there isn't really any way to know why or why errored + the erroneous row(s) aren't inserted and there isn't really any way to know why or why errored Delayed insert mode was removed in mysql 7 and only works with MyISAM type tables, It was included because it is still supported in mariadb. It does not work with duplicate_key and the mysql server ignores it in those cases */ -/datum/controller/subsystem/dbcore/proc/MassInsert(table, list/rows, duplicate_key = FALSE, ignore_errors = FALSE, delayed = FALSE, warn = FALSE, async = TRUE) +/datum/controller/subsystem/dbcore/proc/MassInsert(table, list/rows, duplicate_key = FALSE, ignore_errors = FALSE, delayed = FALSE, warn = FALSE, async = TRUE, special_columns = null) if (!table || !rows || !istype(rows)) return + + // Prepare column list var/list/columns = list() - var/list/sorted_rows = list() - + var/list/has_question_mark = list() for (var/list/row in rows) - var/list/sorted_row = list() - sorted_row.len = columns.len for (var/column in row) - var/idx = columns[column] - if (!idx) - idx = columns.len + 1 - columns[column] = idx - sorted_row.len = columns.len + columns[column] = "?" + has_question_mark[column] = TRUE + for (var/column in special_columns) + columns[column] = special_columns[column] + has_question_mark[column] = findtext(special_columns[column], "?") - sorted_row[idx] = row[column] - sorted_rows[++sorted_rows.len] = sorted_row + // Prepare SQL query full of placeholders + var/list/query_parts = list("INSERT") + if (delayed) + query_parts += " DELAYED" + if (ignore_errors) + query_parts += " IGNORE" + query_parts += " INTO " + query_parts += table + query_parts += "\n([columns.Join(", ")])\nVALUES" + + var/list/arguments = list() + var/has_row = FALSE + for (var/list/row in rows) + if (has_row) + query_parts += "," + query_parts += "\n (" + var/has_col = FALSE + for (var/column in columns) + if (has_col) + query_parts += ", " + if (has_question_mark[column]) + var/name = "p[arguments.len]" + query_parts += replacetext(columns[column], "?", ":[name]") + arguments[name] = row[column] + else + query_parts += columns[column] + has_col = TRUE + query_parts += ")" + has_row = TRUE if (duplicate_key == TRUE) var/list/column_list = list() for (var/column in columns) column_list += "[column] = VALUES([column])" - duplicate_key = "ON DUPLICATE KEY UPDATE [column_list.Join(", ")]\n" - else if (duplicate_key == FALSE) - duplicate_key = null + query_parts += "\nON DUPLICATE KEY UPDATE [column_list.Join(", ")]" + else if (duplicate_key != FALSE) + query_parts += duplicate_key - if (ignore_errors) - ignore_errors = " IGNORE" - else - ignore_errors = null - - if (delayed) - delayed = " DELAYED" - else - delayed = null - - var/list/sqlrowlist = list() - var/len = columns.len - for (var/list/row in sorted_rows) - if (length(row) != len) - row.len = len - for (var/value in row) - if (value == null) - value = "NULL" - sqlrowlist += "([row.Join(", ")])" - - sqlrowlist = " [sqlrowlist.Join(",\n ")]" - var/datum/DBQuery/Query = NewQuery("INSERT[delayed][ignore_errors] INTO [table]\n([columns.Join(", ")])\nVALUES\n[sqlrowlist]\n[duplicate_key]") + var/datum/db_query/Query = NewQuery(query_parts.Join(), arguments) if (warn) . = Query.warn_execute(async) else . = Query.Execute(async) qdel(Query) -/datum/DBQuery - var/sql // The sql query being executed. - var/list/item //list of data values populated by NextRow() +/datum/db_query + // Inputs + var/connection + var/sql + var/arguments + // Status information + var/in_progress + var/last_error var/last_activity var/last_activity_time - var/last_error - var/skip_next_is_complete - var/in_progress - var/datum/BSQL_Connection/connection - var/datum/BSQL_Operation/Query/query + // Output + var/list/list/rows + var/next_row_to_take = 1 + var/affected + var/last_insert_id -/datum/DBQuery/New(sql_query, datum/BSQL_Connection/connection) + var/list/item //list of data values populated by NextRow() + +/datum/db_query/New(connection, sql, arguments) SSdbcore.active_queries[src] = TRUE Activity("Created") item = list() - src.connection = connection - sql = sql_query -/datum/DBQuery/Destroy() + src.connection = connection + src.sql = sql + src.arguments = arguments + +/datum/db_query/Destroy() Close() SSdbcore.active_queries -= src return ..() -/datum/DBQuery/CanProcCall(proc_name) +/datum/db_query/CanProcCall(proc_name) //fuck off kevinz return FALSE -/datum/DBQuery/proc/SetQuery(new_sql) - if(in_progress) - CRASH("Attempted to set new sql while waiting on active query") - Close() - sql = new_sql - -/datum/DBQuery/proc/Activity(activity) +/datum/db_query/proc/Activity(activity) last_activity = activity last_activity_time = world.time -/datum/DBQuery/proc/warn_execute(async = FALSE) +/datum/db_query/proc/warn_execute(async = TRUE) . = Execute(async) if(!.) to_chat(usr, "A SQL error occurred during this operation, check the server logs.") -/datum/DBQuery/proc/Execute(async = FALSE, log_error = TRUE) +/datum/db_query/proc/Execute(async = TRUE, log_error = TRUE) Activity("Execute") if(in_progress) CRASH("Attempted to start a new query while waiting on the old one") - if(QDELETED(connection)) + if(!SSdbcore.IsConnected()) last_error = "No connection!" return FALSE var/start_time - var/timed_out if(!async) start_time = REALTIMEOFDAY Close() - query = connection.BeginQuery(sql) - if(!async) - timed_out = !query.WaitForCompletion() - else - in_progress = TRUE - UNTIL(query.IsComplete()) - in_progress = FALSE - skip_next_is_complete = TRUE - var/error = QDELETED(query) ? "Query object deleted!" : query.GetError() - last_error = error - . = !error + . = run_query(async) + var/timed_out = !. && findtext(last_error, "Operation timed out") if(!. && log_error) - log_sql("[error] | Query used: [sql]") + log_sql("[last_error] | Query used: [sql] | Arguments: [json_encode(arguments)]") if(!async && timed_out) log_query_debug("Query execution started at [start_time]") log_query_debug("Query execution ended at [REALTIMEOFDAY]") @@ -322,44 +345,51 @@ Delayed insert mode was removed in mysql 7 and only works with MyISAM type table log_query_debug("Query used: [sql]") slow_query_check() -/datum/DBQuery/proc/slow_query_check() +/datum/db_query/proc/run_query(async) + var/job_result_str + + if (async) + var/job_id = rustg_sql_query_async(connection, sql, json_encode(arguments)) + in_progress = TRUE + UNTIL((job_result_str = rustg_sql_check_query(job_id)) != RUSTG_JOB_NO_RESULTS_YET) + in_progress = FALSE + + if (job_result_str == RUSTG_JOB_ERROR) + last_error = job_result_str + return FALSE + else + job_result_str = rustg_sql_query_blocking(connection, sql, json_encode(arguments)) + + var/result = json_decode(job_result_str) + switch (result["status"]) + if ("ok") + rows = result["rows"] + affected = result["affected"] + last_insert_id = result["last_insert_id"] + return TRUE + if ("err") + last_error = result["data"] + return FALSE + if ("offline") + last_error = "offline" + return FALSE + +/datum/db_query/proc/slow_query_check() message_admins("HEY! A database query timed out. Did the server just hang? \[YES\]|\[NO\]") -/datum/DBQuery/proc/NextRow(async) +/datum/db_query/proc/NextRow(async = TRUE) Activity("NextRow") - UNTIL(!in_progress) - if(!skip_next_is_complete) - if(!async) - query.WaitForCompletion() - else - in_progress = TRUE - UNTIL(query.IsComplete()) - in_progress = FALSE + + if (rows && next_row_to_take <= rows.len) + item = rows[next_row_to_take] + next_row_to_take++ + return !!item else - skip_next_is_complete = FALSE + return FALSE - last_error = query.GetError() - var/list/results = query.CurrentRow() - . = results != null - - item.Cut() - //populate item array - for(var/I in results) - item += results[I] - -/datum/DBQuery/proc/ErrorMsg() +/datum/db_query/proc/ErrorMsg() return last_error -/datum/DBQuery/proc/Close() - item.Cut() - QDEL_NULL(query) - -/world/BSQL_Debug(message) - if(!CONFIG_GET(flag/bsql_debug)) - return - - //strip sensitive stuff - if(findtext(message, ": CreateConnection(")) - message = "CreateConnection CENSORED" - - log_sql("BSQL_DEBUG: [message]") +/datum/db_query/proc/Close() + rows = null + item = null diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm index 2ea3b29c91..36347c9a43 100644 --- a/code/controllers/subsystem/mapping.dm +++ b/code/controllers/subsystem/mapping.dm @@ -272,7 +272,9 @@ SUBSYSTEM_DEF(mapping) LoadGroup(FailedZs, "Station", config.map_path, config.map_file, config.traits, ZTRAITS_STATION, FALSE, config.orientation) if(SSdbcore.Connect()) - var/datum/DBQuery/query_round_map_name = SSdbcore.NewQuery("UPDATE [format_table_name("round")] SET map_name = '[config.map_name]' WHERE id = [GLOB.round_id]") + var/datum/db_query/query_round_map_name = SSdbcore.NewQuery({" + UPDATE [format_table_name("round")] SET map_name = :map_name WHERE id = :round_id + "}, list("map_name" = config.map_name, "round_id" = GLOB.round_id)) query_round_map_name.Execute() qdel(query_round_map_name) diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 3d7eeb7a8a..8bef236c5e 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -81,30 +81,43 @@ ///Everyone should now be on the station and have their normal gear. This is the place to give the special roles extra things /datum/game_mode/proc/post_setup(report) //Gamemodes can override the intercept report. Passing TRUE as the argument will force a report. - //finalize_monster_hunters() Disabled for now if(!report) report = !CONFIG_GET(flag/no_intercept_report) addtimer(CALLBACK(GLOBAL_PROC, .proc/display_roundstart_logout_report), ROUNDSTART_LOGOUT_REPORT_TIME) - if(prob(20)) //CIT CHANGE - adds a 20% chance for the security level to be the opposite of what it normally is + if(prob(20)) //cit-change flipseclevel = TRUE + + // if(CONFIG_GET(flag/reopen_roundstart_suicide_roles)) + // var/delay = CONFIG_GET(number/reopen_roundstart_suicide_roles_delay) + // if(delay) + // delay = (delay SECONDS) + // else + // delay = (4 MINUTES) //default to 4 minutes if the delay isn't defined. + // addtimer(CALLBACK(GLOBAL_PROC, .proc/reopen_roundstart_suicide_roles), delay) + if(SSdbcore.Connect()) - var/sql + var/list/to_set = list() + var/arguments = list() if(SSticker.mode) - sql += "game_mode = '[SSticker.mode]'" + to_set += "game_mode = :game_mode" + arguments["game_mode"] = SSticker.mode if(GLOB.revdata.originmastercommit) - if(sql) - sql += ", " - sql += "commit_hash = '[GLOB.revdata.originmastercommit]'" - if(sql) - var/datum/DBQuery/query_round_game_mode = SSdbcore.NewQuery("UPDATE [format_table_name("round")] SET [sql] WHERE id = [GLOB.round_id]") + to_set += "commit_hash = :commit_hash" + arguments["commit_hash"] = GLOB.revdata.originmastercommit + if(to_set.len) + arguments["round_id"] = GLOB.round_id + var/datum/db_query/query_round_game_mode = SSdbcore.NewQuery( + "UPDATE [format_table_name("round")] SET [to_set.Join(", ")] WHERE id = :round_id", + arguments + ) query_round_game_mode.Execute() qdel(query_round_game_mode) if(report) addtimer(CALLBACK(src, .proc/send_intercept, 0), rand(waittime_l, waittime_h)) generate_station_goals() gamemode_ready = TRUE - return 1 + return TRUE ///Handles late-join antag assignments diff --git a/code/modules/admin/DB_ban/functions.dm b/code/modules/admin/DB_ban/functions.dm index 39c4d2d939..1f62b487fa 100644 --- a/code/modules/admin/DB_ban/functions.dm +++ b/code/modules/admin/DB_ban/functions.dm @@ -81,7 +81,7 @@ var/banned_mob_guest_key = had_banned_mob && IsGuestKey(banned_mob.key) banned_mob = null var/sql_ckey = sanitizeSQL(ckey) - var/datum/DBQuery/query_add_ban_get_ckey = SSdbcore.NewQuery("SELECT 1 FROM [format_table_name("player")] WHERE ckey = '[sql_ckey]'") + var/datum/db_query/query_add_ban_get_ckey = SSdbcore.NewQuery("SELECT 1 FROM [format_table_name("player")] WHERE ckey = '[sql_ckey]'") if(!query_add_ban_get_ckey.warn_execute()) qdel(query_add_ban_get_ckey) return @@ -125,7 +125,7 @@ reason = sanitizeSQL(reason) var/sql_a_ckey = sanitizeSQL(a_ckey) if(maxadminbancheck) - var/datum/DBQuery/query_check_adminban_amt = SSdbcore.NewQuery("SELECT count(id) AS num FROM [format_table_name("ban")] WHERE (a_ckey = '[sql_a_ckey]') AND (bantype = 'ADMIN_PERMABAN' OR (bantype = 'ADMIN_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)") + var/datum/db_query/query_check_adminban_amt = SSdbcore.NewQuery("SELECT count(id) AS num FROM [format_table_name("ban")] WHERE (a_ckey = '[sql_a_ckey]') AND (bantype = 'ADMIN_PERMABAN' OR (bantype = 'ADMIN_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)") if(!query_check_adminban_amt.warn_execute()) qdel(query_check_adminban_amt) return @@ -149,7 +149,7 @@ var/sql_a_computerid = sanitizeSQL(a_computerid) var/sql_a_ip = sanitizeSQL(a_ip) var/sql = "INSERT INTO [format_table_name("ban")] (`bantime`,`server_ip`,`server_port`,`round_id`,`bantype`,`reason`,`job`,`duration`,`expiration_time`,`ckey`,`computerid`,`ip`,`a_ckey`,`a_computerid`,`a_ip`,`who`,`adminwho`) VALUES (Now(), INET_ATON(IF('[world.internet_address]' LIKE '', '0', '[world.internet_address]')), '[world.port]', '[GLOB.round_id]', '[bantype_str]', '[reason]', '[sql_job]', [(duration)?"[duration]":"0"], Now() + INTERVAL [(duration>0) ? duration : 0] MINUTE, '[sql_ckey]', '[sql_computerid]', INET_ATON('[sql_ip]'), '[sql_a_ckey]', '[sql_a_computerid]', INET_ATON('[sql_a_ip]'), '[who]', '[adminwho]')" - var/datum/DBQuery/query_add_ban = SSdbcore.NewQuery(sql) + var/datum/db_query/query_add_ban = SSdbcore.NewQuery(sql) if(!query_add_ban.warn_execute()) qdel(query_add_ban) return @@ -224,7 +224,7 @@ var/ban_id var/ban_number = 0 //failsafe - var/datum/DBQuery/query_unban_get_id = SSdbcore.NewQuery(sql) + var/datum/db_query/query_unban_get_id = SSdbcore.NewQuery(sql) if(!query_unban_get_id.warn_execute()) qdel(query_unban_get_id) return @@ -258,7 +258,7 @@ to_chat(usr, "Cancelled") return - var/datum/DBQuery/query_edit_ban_get_details = SSdbcore.NewQuery("SELECT IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE [format_table_name("player")].ckey = [format_table_name("ban")].ckey), ckey), duration, reason FROM [format_table_name("ban")] WHERE id = [banid]") + var/datum/db_query/query_edit_ban_get_details = SSdbcore.NewQuery("SELECT IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE [format_table_name("player")].ckey = [format_table_name("ban")].ckey), ckey), duration, reason FROM [format_table_name("ban")] WHERE id = [banid]") if(!query_edit_ban_get_details.warn_execute()) qdel(query_edit_ban_get_details) return @@ -290,7 +290,7 @@ to_chat(usr, "Cancelled") return - var/datum/DBQuery/query_edit_ban_reason = SSdbcore.NewQuery("UPDATE [format_table_name("ban")] SET reason = '[value]', edits = CONCAT(edits,'- [e_key] changed ban reason from \\\"[reason]\\\" to \\\"[value]\\\"
') WHERE id = [banid]") + var/datum/db_query/query_edit_ban_reason = SSdbcore.NewQuery("UPDATE [format_table_name("ban")] SET reason = '[value]', edits = CONCAT(edits,'- [e_key] changed ban reason from \\\"[reason]\\\" to \\\"[value]\\\"
') WHERE id = [banid]") if(!query_edit_ban_reason.warn_execute()) qdel(query_edit_ban_reason) return @@ -303,7 +303,7 @@ to_chat(usr, "Cancelled") return - var/datum/DBQuery/query_edit_ban_duration = SSdbcore.NewQuery("UPDATE [format_table_name("ban")] SET duration = [value], edits = CONCAT(edits,'- [e_key] changed ban duration from [duration] to [value]
'), expiration_time = DATE_ADD(bantime, INTERVAL [value] MINUTE) WHERE id = [banid]") + var/datum/db_query/query_edit_ban_duration = SSdbcore.NewQuery("UPDATE [format_table_name("ban")] SET duration = [value], edits = CONCAT(edits,'- [e_key] changed ban duration from [duration] to [value]
'), expiration_time = DATE_ADD(bantime, INTERVAL [value] MINUTE) WHERE id = [banid]") if(!query_edit_ban_duration.warn_execute()) qdel(query_edit_ban_duration) return @@ -333,7 +333,7 @@ var/ban_number = 0 //failsafe var/p_key - var/datum/DBQuery/query_unban_get_ckey = SSdbcore.NewQuery(sql) + var/datum/db_query/query_unban_get_ckey = SSdbcore.NewQuery(sql) if(!query_unban_get_ckey.warn_execute()) qdel(query_unban_get_ckey) return @@ -358,7 +358,7 @@ var/unban_ip = owner.address var/sql_update = "UPDATE [format_table_name("ban")] SET unbanned = 1, unbanned_datetime = Now(), unbanned_ckey = '[unban_ckey]', unbanned_computerid = '[unban_computerid]', unbanned_ip = INET_ATON('[unban_ip]') WHERE id = [id]" - var/datum/DBQuery/query_unban = SSdbcore.NewQuery(sql_update) + var/datum/db_query/query_unban = SSdbcore.NewQuery(sql_update) if(!query_unban.warn_execute()) qdel(query_unban) return @@ -461,7 +461,7 @@ var/bansperpage = 15 var/pagecount = 0 page = text2num(page) - var/datum/DBQuery/query_count_bans = SSdbcore.NewQuery("SELECT COUNT(id) FROM [format_table_name("ban")] WHERE [search]") + var/datum/db_query/query_count_bans = SSdbcore.NewQuery("SELECT COUNT(id) FROM [format_table_name("ban")] WHERE [search]") if(!query_count_bans.warn_execute()) qdel(query_count_bans) return @@ -489,7 +489,7 @@ output += "OPTIONS" output += "" var/limit = " LIMIT [bansperpage * page], [bansperpage]" - var/datum/DBQuery/query_search_bans = SSdbcore.NewQuery("SELECT id, bantime, bantype, reason, job, duration, expiration_time, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE [format_table_name("player")].ckey = [format_table_name("ban")].ckey), ckey), IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE [format_table_name("player")].ckey = [format_table_name("ban")].a_ckey), a_ckey), unbanned, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE [format_table_name("player")].ckey = [format_table_name("ban")].unbanned_ckey), unbanned_ckey), unbanned_datetime, edits, round_id FROM [format_table_name("ban")] WHERE [search] ORDER BY bantime DESC[limit]") + var/datum/db_query/query_search_bans = SSdbcore.NewQuery("SELECT id, bantime, bantype, reason, job, duration, expiration_time, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE [format_table_name("player")].ckey = [format_table_name("ban")].ckey), ckey), IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE [format_table_name("player")].ckey = [format_table_name("ban")].a_ckey), a_ckey), unbanned, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE [format_table_name("player")].ckey = [format_table_name("ban")].unbanned_ckey), unbanned_ckey), unbanned_datetime, edits, round_id FROM [format_table_name("ban")] WHERE [search] ORDER BY bantime DESC[limit]") if(!query_search_bans.warn_execute()) qdel(query_search_bans) return diff --git a/code/modules/admin/IsBanned.dm b/code/modules/admin/IsBanned.dm index 4ddb92ab19..a9a85e160d 100644 --- a/code/modules/admin/IsBanned.dm +++ b/code/modules/admin/IsBanned.dm @@ -100,7 +100,7 @@ if(computer_id) cidquery = " OR computerid = '[computer_id]' " - var/datum/DBQuery/query_ban_check = SSdbcore.NewQuery("SELECT IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE [format_table_name("player")].ckey = [format_table_name("ban")].ckey), ckey), IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE [format_table_name("player")].ckey = [format_table_name("ban")].a_ckey), a_ckey), reason, expiration_time, duration, bantime, bantype, id, round_id FROM [format_table_name("ban")] WHERE (ckey = '[ckey]' [ipquery] [cidquery]) AND (bantype = 'PERMABAN' OR bantype = 'ADMIN_PERMABAN' OR ((bantype = 'TEMPBAN' OR bantype = 'ADMIN_TEMPBAN') AND expiration_time > Now())) AND isnull(unbanned)") + var/datum/db_query/query_ban_check = SSdbcore.NewQuery("SELECT IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE [format_table_name("player")].ckey = [format_table_name("ban")].ckey), ckey), IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE [format_table_name("player")].ckey = [format_table_name("ban")].a_ckey), a_ckey), reason, expiration_time, duration, bantime, bantype, id, round_id FROM [format_table_name("ban")] WHERE (ckey = '[ckey]' [ipquery] [cidquery]) AND (bantype = 'PERMABAN' OR bantype = 'ADMIN_PERMABAN' OR ((bantype = 'TEMPBAN' OR bantype = 'ADMIN_TEMPBAN') AND expiration_time > Now())) AND isnull(unbanned)") if(!query_ban_check.Execute(async = TRUE)) qdel(query_ban_check) key_cache[key] = 0 diff --git a/code/modules/admin/admin_ranks.dm b/code/modules/admin/admin_ranks.dm index 39053b8e15..dbc98fb0d7 100644 --- a/code/modules/admin/admin_ranks.dm +++ b/code/modules/admin/admin_ranks.dm @@ -160,7 +160,7 @@ GLOBAL_PROTECT(protected_ranks) if(!no_update) sync_ranks_with_db() else - var/datum/DBQuery/query_load_admin_ranks = SSdbcore.NewQuery("SELECT rank, flags, exclude_flags, can_edit_flags FROM [format_table_name("admin_ranks")]") + var/datum/db_query/query_load_admin_ranks = SSdbcore.NewQuery("SELECT `rank`, flags, exclude_flags, can_edit_flags FROM [format_table_name("admin_ranks")]") if(!query_load_admin_ranks.Execute()) message_admins("Error loading admin ranks from database. Loading from backup.") log_sql("Error loading admin ranks from database. Loading from backup.") @@ -168,7 +168,7 @@ GLOBAL_PROTECT(protected_ranks) else while(query_load_admin_ranks.NextRow()) var/skip - var/rank_name = ckeyEx(query_load_admin_ranks.item[1]) + var/rank_name = query_load_admin_ranks.item[1] for(var/datum/admin_rank/R in GLOB.admin_ranks) if(R.name == rank_name) //this rank was already loaded from txt override skip = 1 @@ -234,20 +234,12 @@ GLOBAL_PROTECT(protected_ranks) for(var/datum/admin_rank/R in GLOB.admin_ranks) rank_names[R.name] = R //ckeys listed in admins.txt are always made admins before sql loading is attempted - var/list/lines = world.file2list("[global.config.directory]/admins.txt") - for(var/line in lines) - if(!length(line) || findtextEx(line, "#", 1, 2)) - continue - var/list/entry = splittext(line, "=") - if(entry.len < 2) - continue - var/ckey = ckey(entry[1]) - var/rank = ckeyEx(entry[2]) - if(!ckey || !rank) - continue - new /datum/admins(rank_names[rank], ckey, 0, 1) + var/admins_text = file2text("[global.config.directory]/admins.txt") + var/regex/admins_regex = new(@"^(?!#)(.+?)\s+=\s+(.+)", "gm") + while(admins_regex.Find(admins_text)) + new /datum/admins(rank_names[admins_regex.group[2]], ckey(admins_regex.group[1]), FALSE, TRUE) if(!CONFIG_GET(flag/admin_legacy_system) || dbfail) - var/datum/DBQuery/query_load_admins = SSdbcore.NewQuery("SELECT ckey, rank FROM [format_table_name("admin")] ORDER BY rank") + var/datum/db_query/query_load_admins = SSdbcore.NewQuery("SELECT ckey, `rank` FROM [format_table_name("admin")] ORDER BY `rank`") if(!query_load_admins.Execute()) message_admins("Error loading admins from database. Loading from backup.") log_sql("Error loading admins from database. Loading from backup.") @@ -255,7 +247,7 @@ GLOBAL_PROTECT(protected_ranks) else while(query_load_admins.NextRow()) var/admin_ckey = ckey(query_load_admins.item[1]) - var/admin_rank = ckeyEx(query_load_admins.item[2]) + var/admin_rank = query_load_admins.item[2] var/skip if(rank_names[admin_rank] == null) message_admins("[admin_ckey] loaded with invalid admin rank [admin_rank].") diff --git a/code/modules/admin/banjob.dm b/code/modules/admin/banjob.dm index cae1c6b22e..c6d8e9a5b0 100644 --- a/code/modules/admin/banjob.dm +++ b/code/modules/admin/banjob.dm @@ -3,8 +3,8 @@ if(!M || !istype(M) || !M.ckey) return FALSE - if(!M.client) //no cache. fallback to a datum/DBQuery - var/datum/DBQuery/query_jobban_check_ban = SSdbcore.NewQuery("SELECT reason FROM [format_table_name("ban")] WHERE ckey = '[sanitizeSQL(M.ckey)]' AND (bantype = 'JOB_PERMABAN' OR (bantype = 'JOB_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned) AND job = '[sanitizeSQL(rank)]'") + if(!M.client) //no cache. fallback to a datum/db_query + var/datum/db_query/query_jobban_check_ban = SSdbcore.NewQuery("SELECT reason FROM [format_table_name("ban")] WHERE ckey = '[sanitizeSQL(M.ckey)]' AND (bantype = 'JOB_PERMABAN' OR (bantype = 'JOB_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned) AND job = '[sanitizeSQL(rank)]'") if(!query_jobban_check_ban.warn_execute()) qdel(query_jobban_check_ban) return @@ -28,7 +28,7 @@ return if(C && istype(C)) C.jobbancache = list() - var/datum/DBQuery/query_jobban_build_cache = SSdbcore.NewQuery("SELECT job, reason FROM [format_table_name("ban")] WHERE ckey = '[sanitizeSQL(C.ckey)]' AND (bantype = 'JOB_PERMABAN' OR (bantype = 'JOB_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)") + var/datum/db_query/query_jobban_build_cache = SSdbcore.NewQuery("SELECT job, reason FROM [format_table_name("ban")] WHERE ckey = '[sanitizeSQL(C.ckey)]' AND (bantype = 'JOB_PERMABAN' OR (bantype = 'JOB_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)") if(!query_jobban_build_cache.warn_execute()) qdel(query_jobban_build_cache) return diff --git a/code/modules/admin/create_poll.dm b/code/modules/admin/create_poll.dm index 9f002f92e0..a6797ceb5f 100644 --- a/code/modules/admin/create_poll.dm +++ b/code/modules/admin/create_poll.dm @@ -35,7 +35,7 @@ if(!endtime) return endtime = sanitizeSQL(endtime) - var/datum/DBQuery/query_validate_time = SSdbcore.NewQuery("SELECT IF(STR_TO_DATE('[endtime]','%Y-%c-%d %T') > NOW(), STR_TO_DATE('[endtime]','%Y-%c-%d %T'), 0)") + var/datum/db_query/query_validate_time = SSdbcore.NewQuery("SELECT IF(STR_TO_DATE('[endtime]','%Y-%c-%d %T') > NOW(), STR_TO_DATE('[endtime]','%Y-%c-%d %T'), 0)") if(!query_validate_time.warn_execute() || QDELETED(usr) || !src) qdel(query_validate_time) return @@ -129,14 +129,14 @@ return 0 var/m1 = "[key_name(usr)] has created a new server poll. Poll type: [polltype] - Admin Only: [adminonly ? "Yes" : "No"] - Question: [question]" var/m2 = "[key_name_admin(usr)] has created a new server poll. Poll type: [polltype] - Admin Only: [adminonly ? "Yes" : "No"]
Question: [question]" - var/datum/DBQuery/query_polladd_question = SSdbcore.NewQuery("INSERT INTO [format_table_name("poll_question")] (polltype, starttime, endtime, question, adminonly, multiplechoiceoptions, createdby_ckey, createdby_ip, dontshow) VALUES ('[polltype]', '[starttime]', '[endtime]', '[question]', '[adminonly]', '[choice_amount]', '[sql_ckey]', INET_ATON('[address]'), '[dontshow]')") + var/datum/db_query/query_polladd_question = SSdbcore.NewQuery("INSERT INTO [format_table_name("poll_question")] (polltype, starttime, endtime, question, adminonly, multiplechoiceoptions, createdby_ckey, createdby_ip, dontshow) VALUES ('[polltype]', '[starttime]', '[endtime]', '[question]', '[adminonly]', '[choice_amount]', '[sql_ckey]', INET_ATON('[address]'), '[dontshow]')") if(!query_polladd_question.warn_execute()) qdel(query_polladd_question) return qdel(query_polladd_question) if(polltype != POLLTYPE_TEXT) var/pollid = 0 - var/datum/DBQuery/query_get_id = SSdbcore.NewQuery("SELECT LAST_INSERT_ID()") + var/datum/db_query/query_get_id = SSdbcore.NewQuery("SELECT LAST_INSERT_ID()") if(!query_get_id.warn_execute()) qdel(query_get_id) return diff --git a/code/modules/admin/ipintel.dm b/code/modules/admin/ipintel.dm index e0056b3e40..71c9a11acd 100644 --- a/code/modules/admin/ipintel.dm +++ b/code/modules/admin/ipintel.dm @@ -29,27 +29,27 @@ return if (!bypasscache) var/datum/ipintel/cachedintel = SSipintel.cache[ip] - if (cachedintel && cachedintel.is_valid()) + if (cachedintel?.is_valid()) cachedintel.cache = TRUE return cachedintel if(SSdbcore.Connect()) var/rating_bad = CONFIG_GET(number/ipintel_rating_bad) - var/datum/DBQuery/query_get_ip_intel = SSdbcore.NewQuery({" + var/datum/db_query/query_get_ip_intel = SSdbcore.NewQuery({" SELECT date, intel, TIMESTAMPDIFF(MINUTE,date,NOW()) FROM [format_table_name("ipintel")] WHERE - ip = INET_ATON('[ip]') + ip = INET_ATON(':ip') AND (( - intel < [rating_bad] + intel < :rating_bad AND - date + INTERVAL [CONFIG_GET(number/ipintel_save_good)] HOUR > NOW() + date + INTERVAL :save_good HOUR > NOW() ) OR ( - intel >= [rating_bad] + intel >= :rating_bad AND - date + INTERVAL [CONFIG_GET(number/ipintel_save_bad)] HOUR > NOW() + date + INTERVAL :save_bad HOUR > NOW() )) - "}) + "}, list("ip" = ip, "rating_bad" = rating_bad, "save_good" = CONFIG_GET(number/ipintel_save_good), "save_bad" = CONFIG_GET(number/ipintel_save_bad))) if(!query_get_ip_intel.Execute()) qdel(query_get_ip_intel) return @@ -67,12 +67,15 @@ if (updatecache && res.intel >= 0) SSipintel.cache[ip] = res if(SSdbcore.Connect()) - var/datum/DBQuery/query_add_ip_intel = SSdbcore.NewQuery("INSERT INTO [format_table_name("ipintel")] (ip, intel) VALUES (INET_ATON('[ip]'), [res.intel]) ON DUPLICATE KEY UPDATE intel = VALUES(intel), date = NOW()") + var/datum/db_query/query_add_ip_intel = SSdbcore.NewQuery( + "INSERT INTO [format_table_name("ipintel")] (ip, intel) VALUES (INET_ATON(:ip), :intel) ON DUPLICATE KEY UPDATE intel = VALUES(intel), date = NOW()", + list("ip" = ip, "intel" = res.intel) + ) query_add_ip_intel.Execute() qdel(query_add_ip_intel) -/proc/ip_intel_query(ip, var/retryed=0) +/proc/ip_intel_query(ip, retryed=0) . = -1 //default if (!ip) return @@ -131,8 +134,3 @@ /proc/log_ipintel(text) log_game("IPINTEL: [text]") debug_admins("IPINTEL: [text]") - - - - - diff --git a/code/modules/admin/permissionedit.dm b/code/modules/admin/permissionedit.dm index 05f7465b03..9f5dc00a48 100644 --- a/code/modules/admin/permissionedit.dm +++ b/code/modules/admin/permissionedit.dm @@ -15,21 +15,14 @@ else output += "
\[Log\]
\[Management\]" if(action == 1) - var/list/searchlist = list(" WHERE ") - if(target) - searchlist += "ckey = '[sanitizeSQL(target)]'" - if(operation) - if(target) - searchlist += " AND " - searchlist += "operation = '[sanitizeSQL(operation)]'" - var/search - if(searchlist.len > 1) - search = searchlist.Join("") var/logcount = 0 var/logssperpage = 20 var/pagecount = 0 page = text2num(page) - var/datum/DBQuery/query_count_admin_logs = SSdbcore.NewQuery("SELECT COUNT(id) FROM [format_table_name("admin_log")][search]") + var/datum/db_query/query_count_admin_logs = SSdbcore.NewQuery( + "SELECT COUNT(id) FROM [format_table_name("admin_log")] WHERE (:target IS NULL OR adminckey = :target) AND (:operation IS NULL OR operation = :operation)", + list("target" = target, "operation" = operation) + ) if(!query_count_admin_logs.warn_execute()) qdel(query_count_admin_logs) return @@ -43,8 +36,20 @@ logcount -= logssperpage pagecount++ output += "|" - var/limit = " LIMIT [logssperpage * page], [logssperpage]" - var/datum/DBQuery/query_search_admin_logs = SSdbcore.NewQuery("SELECT datetime, round_id, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = adminckey), adminckey), operation, IF(ckey IS NULL, target, byond_key), log FROM [format_table_name("admin_log")] LEFT JOIN [format_table_name("player")] ON target = ckey[search] ORDER BY datetime DESC[limit]") + var/datum/db_query/query_search_admin_logs = SSdbcore.NewQuery({" + SELECT + datetime, + round_id, + IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = adminckey), adminckey), + operation, + IF(ckey IS NULL, target, byond_key), + log + FROM [format_table_name("admin_log")] + LEFT JOIN [format_table_name("player")] ON target = ckey + WHERE (:target IS NULL OR ckey = :target) AND (:operation IS NULL OR operation = :operation) + ORDER BY datetime DESC + LIMIT :skip, :take + "}, list("target" = target, "operation" = operation, "skip" = logssperpage * page, "take" = logssperpage)) if(!query_search_admin_logs.warn_execute()) qdel(query_search_admin_logs) return @@ -59,7 +64,7 @@ qdel(query_search_admin_logs) if(action == 2) output += "

Admin ckeys with invalid ranks

" - var/datum/DBQuery/query_check_admin_errors = SSdbcore.NewQuery("SELECT IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE [format_table_name("player")].ckey = [format_table_name("admin")].ckey), ckey), [format_table_name("admin")].rank FROM [format_table_name("admin")] LEFT JOIN [format_table_name("admin_ranks")] ON [format_table_name("admin_ranks")].rank = [format_table_name("admin")].rank WHERE [format_table_name("admin_ranks")].rank IS NULL") + var/datum/db_query/query_check_admin_errors = SSdbcore.NewQuery("SELECT IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE [format_table_name("player")].ckey = [format_table_name("admin")].ckey), ckey), [format_table_name("admin")].`rank` FROM [format_table_name("admin")] LEFT JOIN [format_table_name("admin_ranks")] ON [format_table_name("admin_ranks")].`rank` = [format_table_name("admin")].`rank` WHERE [format_table_name("admin_ranks")].`rank` IS NULL") if(!query_check_admin_errors.warn_execute()) qdel(query_check_admin_errors) return @@ -70,7 +75,7 @@ output += "
" qdel(query_check_admin_errors) output += "

Unused ranks

" - var/datum/DBQuery/query_check_unused_rank = SSdbcore.NewQuery("SELECT [format_table_name("admin_ranks")].rank, flags, exclude_flags, can_edit_flags FROM [format_table_name("admin_ranks")] LEFT JOIN [format_table_name("admin")] ON [format_table_name("admin")].rank = [format_table_name("admin_ranks")].rank WHERE [format_table_name("admin")].rank IS NULL") + var/datum/db_query/query_check_unused_rank = SSdbcore.NewQuery("SELECT [format_table_name("admin_ranks")].`rank`, flags, exclude_flags, can_edit_flags FROM [format_table_name("admin_ranks")] LEFT JOIN [format_table_name("admin")] ON [format_table_name("admin")].`rank` = [format_table_name("admin_ranks")].`rank` WHERE [format_table_name("admin")].`rank` IS NULL") if(!query_check_unused_rank.warn_execute()) qdel(query_check_unused_rank) return @@ -130,7 +135,7 @@ log_admin("[key_name(usr)] attempted to edit admin permissions without sufficient rights.") return if(IsAdminAdvancedProcCall()) - to_chat(usr, "Admin Edit blocked: Advanced ProcCall detected.") + to_chat(usr, "Admin Edit blocked: Advanced ProcCall detected.", confidential = TRUE) return var/datum/asset/permissions_assets = get_asset_datum(/datum/asset/simple/permissions) permissions_assets.send(src) @@ -145,19 +150,19 @@ skip = TRUE if(!CONFIG_GET(flag/admin_legacy_system) && CONFIG_GET(flag/protect_legacy_admins) && task == "rank") if(admin_ckey in GLOB.protected_admins) - to_chat(usr, "Editing the rank of this admin is blocked by server configuration.") + to_chat(usr, "Editing the rank of this admin is blocked by server configuration.", confidential = TRUE) return if(!CONFIG_GET(flag/admin_legacy_system) && CONFIG_GET(flag/protect_legacy_ranks) && task == "permissions") if(D.rank in GLOB.protected_ranks) - to_chat(usr, "Editing the flags of this rank is blocked by server configuration.") + to_chat(usr, "Editing the flags of this rank is blocked by server configuration.", confidential = TRUE) return if(CONFIG_GET(flag/load_legacy_ranks_only) && (task == "add" || task == "rank" || task == "permissions")) - to_chat(usr, "Database rank loading is disabled, only temporary changes can be made to a rank's permissions and permanently creating a new rank is blocked.") + to_chat(usr, "Database rank loading is disabled, only temporary changes can be made to a rank's permissions and permanently creating a new rank is blocked.", confidential = TRUE) legacy_only = TRUE if(check_rights(R_DBRANKS, FALSE)) if(!skip) if(!SSdbcore.Connect()) - to_chat(usr, "Unable to connect to database, changes are temporary only.") + to_chat(usr, "Unable to connect to database, changes are temporary only.", confidential = TRUE) use_db = FALSE else use_db = alert("Permanent changes are saved to the database for future rounds, temporary changes will affect only the current round", "Permanent or Temporary?", "Permanent", "Temporary", "Cancel") @@ -165,7 +170,6 @@ return if(use_db == "Permanent") use_db = TRUE - admin_ckey = sanitizeSQL(admin_ckey) else use_db = FALSE if(QDELETED(usr)) @@ -209,26 +213,34 @@ if(!.) return FALSE if(!admin_ckey && (. in GLOB.admin_datums+GLOB.deadmins)) - to_chat(usr, "[admin_key] is already an admin.") + to_chat(usr, "[admin_key] is already an admin.", confidential = TRUE) return FALSE if(use_db) - . = sanitizeSQL(.) //if an admin exists without a datum they won't be caught by the above - var/datum/DBQuery/query_admin_in_db = SSdbcore.NewQuery("SELECT 1 FROM [format_table_name("admin")] WHERE ckey = '[.]'") + var/datum/db_query/query_admin_in_db = SSdbcore.NewQuery( + "SELECT 1 FROM [format_table_name("admin")] WHERE ckey = :ckey", + list("ckey" = .) + ) if(!query_admin_in_db.warn_execute()) qdel(query_admin_in_db) return FALSE if(query_admin_in_db.NextRow()) qdel(query_admin_in_db) - to_chat(usr, "[admin_key] already listed in admin database. Check the Management tab if they don't appear in the list of admins.") + to_chat(usr, "[admin_key] already listed in admin database. Check the Management tab if they don't appear in the list of admins.", confidential = TRUE) return FALSE qdel(query_admin_in_db) - var/datum/DBQuery/query_add_admin = SSdbcore.NewQuery("INSERT INTO [format_table_name("admin")] (ckey, rank) VALUES ('[.]', 'NEW ADMIN')") + var/datum/db_query/query_add_admin = SSdbcore.NewQuery( + "INSERT INTO [format_table_name("admin")] (ckey, `rank`) VALUES (:ckey, 'NEW ADMIN')", + list("ckey" = .) + ) if(!query_add_admin.warn_execute()) qdel(query_add_admin) return FALSE qdel(query_add_admin) - var/datum/DBQuery/query_add_admin_log = SSdbcore.NewQuery("INSERT INTO [format_table_name("admin_log")] (datetime, round_id, adminckey, adminip, operation, target, log) VALUES ('[SQLtime()]', '[GLOB.round_id]', '[sanitizeSQL(usr.ckey)]', INET_ATON('[sanitizeSQL(usr.client.address)]'), 'add admin', '[.]', 'New admin added: [.]')") + var/datum/db_query/query_add_admin_log = SSdbcore.NewQuery({" + INSERT INTO [format_table_name("admin_log")] (datetime, round_id, adminckey, adminip, operation, target, log) + VALUES (:time, :round_id, :adminckey, INET_ATON(:adminip), 'add admin', :target, CONCAT('New admin added: ', :target)) + "}, list("time" = SQLtime(), "round_id" = "[GLOB.round_id]", "adminckey" = usr.ckey, "adminip" = usr.client.address, "target" = .)) if(!query_add_admin_log.warn_execute()) qdel(query_add_admin_log) return FALSE @@ -243,12 +255,18 @@ var/m1 = "[key_name_admin(usr)] removed [admin_key] from the admins list [use_db ? "permanently" : "temporarily"]" var/m2 = "[key_name(usr)] removed [admin_key] from the admins list [use_db ? "permanently" : "temporarily"]" if(use_db) - var/datum/DBQuery/query_add_rank = SSdbcore.NewQuery("DELETE FROM [format_table_name("admin")] WHERE ckey = '[admin_ckey]'") + var/datum/db_query/query_add_rank = SSdbcore.NewQuery( + "DELETE FROM [format_table_name("admin")] WHERE ckey = :ckey", + list("ckey" = admin_ckey) + ) if(!query_add_rank.warn_execute()) qdel(query_add_rank) return qdel(query_add_rank) - var/datum/DBQuery/query_add_rank_log = SSdbcore.NewQuery("INSERT INTO [format_table_name("admin_log")] (datetime, round_id, adminckey, adminip, operation, target, log) VALUES ('[SQLtime()]', '[GLOB.round_id]', '[sanitizeSQL(usr.ckey)]', INET_ATON('[sanitizeSQL(usr.client.address)]'), 'remove admin', '[admin_ckey]', 'Admin removed: [admin_ckey]')") + var/datum/db_query/query_add_rank_log = SSdbcore.NewQuery({" + INSERT INTO [format_table_name("admin_log")] (datetime, round_id, adminckey, adminip, operation, target, log) + VALUES (:time, :round_id, :adminckey, INET_ATON(:adminip), 'remove admin', :admin_ckey, CONCAT('Admin removed: ', :admin_ckey)) + "}, list("time" = SQLtime(), "round_id" = "[GLOB.round_id]", "adminckey" = usr.ckey, "adminip" = usr.client.address, "admin_ckey" = admin_ckey)) if(!query_add_rank_log.warn_execute()) qdel(query_add_rank_log) return @@ -271,6 +289,14 @@ log_admin("[key_name(usr)] forcefully deadmined [admin_key]") D.deactivate() //after logs so the deadmined admin can see the message. +/datum/admins/proc/auto_deadmin() + to_chat(owner, "You are now a normal player.", confidential = TRUE) + var/old_owner = owner + deactivate() + message_admins("[old_owner] deadmined via auto-deadmin config.") + log_admin("[old_owner] deadmined via auto-deadmin config.") + return TRUE + /datum/admins/proc/change_admin_rank(admin_ckey, admin_key, use_db, datum/admins/D, legacy_only) var/datum/admin_rank/R var/list/rank_names = list() @@ -281,7 +307,7 @@ rank_names[R.name] = R var/new_rank = input("Please select a rank", "New rank") as null|anything in rank_names if(new_rank == "*New Rank*") - new_rank = ckeyEx(input("Please input a new rank", "New custom rank") as text|null) + new_rank = input("Please input a new rank", "New custom rank") as text|null if(!new_rank) return R = rank_names[new_rank] @@ -294,10 +320,12 @@ var/m1 = "[key_name_admin(usr)] edited the admin rank of [admin_key] to [new_rank] [use_db ? "permanently" : "temporarily"]" var/m2 = "[key_name(usr)] edited the admin rank of [admin_key] to [new_rank] [use_db ? "permanently" : "temporarily"]" if(use_db) - new_rank = sanitizeSQL(new_rank) //if a player was tempminned before having a permanent change made to their rank they won't yet be in the db var/old_rank - var/datum/DBQuery/query_admin_in_db = SSdbcore.NewQuery("SELECT rank FROM [format_table_name("admin")] WHERE ckey = '[admin_ckey]'") + var/datum/db_query/query_admin_in_db = SSdbcore.NewQuery( + "SELECT `rank` FROM [format_table_name("admin")] WHERE ckey = :admin_ckey", + list("admin_ckey" = admin_ckey) + ) if(!query_admin_in_db.warn_execute()) qdel(query_admin_in_db) return @@ -308,29 +336,44 @@ old_rank = query_admin_in_db.item[1] qdel(query_admin_in_db) //similarly if a temp rank is created it won't be in the db if someone is permanently changed to it - var/datum/DBQuery/query_rank_in_db = SSdbcore.NewQuery("SELECT 1 FROM [format_table_name("admin_ranks")] WHERE rank = '[new_rank]'") + var/datum/db_query/query_rank_in_db = SSdbcore.NewQuery( + "SELECT 1 FROM [format_table_name("admin_ranks")] WHERE `rank` = :new_rank", + list("new_rank" = new_rank) + ) if(!query_rank_in_db.warn_execute()) qdel(query_rank_in_db) return if(!query_rank_in_db.NextRow()) QDEL_NULL(query_rank_in_db) - var/datum/DBQuery/query_add_rank = SSdbcore.NewQuery("INSERT INTO [format_table_name("admin_ranks")] (rank, flags, exclude_flags, can_edit_flags) VALUES ('[new_rank]', '0', '0', '0')") + var/datum/db_query/query_add_rank = SSdbcore.NewQuery({" + INSERT INTO [format_table_name("admin_ranks")] (`rank`, flags, exclude_flags, can_edit_flags) + VALUES (:new_rank, '0', '0', '0') + "}, list("new_rank" = new_rank)) if(!query_add_rank.warn_execute()) qdel(query_add_rank) return qdel(query_add_rank) - var/datum/DBQuery/query_add_rank_log = SSdbcore.NewQuery("INSERT INTO [format_table_name("admin_log")] (datetime, round_id, adminckey, adminip, operation, target, log) VALUES ('[SQLtime()]', '[GLOB.round_id]', '[sanitizeSQL(usr.ckey)]', INET_ATON('[sanitizeSQL(usr.client.address)]'), 'add rank', '[new_rank]', 'New rank added: [new_rank]')") + var/datum/db_query/query_add_rank_log = SSdbcore.NewQuery({" + INSERT INTO [format_table_name("admin_log")] (datetime, round_id, adminckey, adminip, operation, target, log) + VALUES (:time, :round_id, :adminckey, INET_ATON(:adminip), 'add rank', :new_rank, CONCAT('New rank added: ', :new_rank)) + "}, list("time" = SQLtime(), "round_id" = "[GLOB.round_id]", "adminckey" = usr.ckey, "adminip" = usr.client.address, "new_rank" = new_rank)) if(!query_add_rank_log.warn_execute()) qdel(query_add_rank_log) return qdel(query_add_rank_log) qdel(query_rank_in_db) - var/datum/DBQuery/query_change_rank = SSdbcore.NewQuery("UPDATE [format_table_name("admin")] SET rank = '[new_rank]' WHERE ckey = '[admin_ckey]'") + var/datum/db_query/query_change_rank = SSdbcore.NewQuery( + "UPDATE [format_table_name("admin")] SET `rank` = :new_rank WHERE ckey = :admin_ckey", + list("new_rank" = new_rank, "admin_ckey" = admin_ckey) + ) if(!query_change_rank.warn_execute()) qdel(query_change_rank) return qdel(query_change_rank) - var/datum/DBQuery/query_change_rank_log = SSdbcore.NewQuery("INSERT INTO [format_table_name("admin_log")] (datetime, round_id, adminckey, adminip, operation, target, log) VALUES ('[SQLtime()]', '[GLOB.round_id]', '[sanitizeSQL(usr.ckey)]', INET_ATON('[sanitizeSQL(usr.client.address)]'), 'change admin rank', '[admin_ckey]', 'Rank of [admin_ckey] changed from [old_rank] to [new_rank]')") + var/datum/db_query/query_change_rank_log = SSdbcore.NewQuery({" + INSERT INTO [format_table_name("admin_log")] (datetime, round_id, adminckey, adminip, operation, target, log) + VALUES (:time, :round_id, :adminckey, INET_ATON(:adminip), 'change admin rank', :target, CONCAT('Rank of ', :target, ' changed from ', :old_rank, ' to ', :new_rank)) + "}, list("time" = SQLtime(), "round_id" = "[GLOB.round_id]", "adminckey" = usr.ckey, "adminip" = usr.client.address, "target" = admin_ckey, "old_rank" = old_rank, "new_rank" = new_rank)) if(!query_change_rank_log.warn_execute()) qdel(query_change_rank_log) return @@ -357,11 +400,15 @@ return var/m1 = "[key_name_admin(usr)] edited the permissions of [use_db ? " rank [D.rank.name] permanently" : "[admin_key] temporarily"]" var/m2 = "[key_name(usr)] edited the permissions of [use_db ? " rank [D.rank.name] permanently" : "[admin_key] temporarily"]" - if(use_db || legacy_only) + if(use_db && !legacy_only) + var/rank_name = D.rank.name var/old_flags var/old_exclude_flags var/old_can_edit_flags - var/datum/DBQuery/query_get_rank_flags = SSdbcore.NewQuery("SELECT flags, exclude_flags, can_edit_flags FROM [format_table_name("admin_ranks")] WHERE rank = '[D.rank.name]'") + var/datum/db_query/query_get_rank_flags = SSdbcore.NewQuery( + "SELECT flags, exclude_flags, can_edit_flags FROM [format_table_name("admin_ranks")] WHERE `rank` = :rank_name", + list("rank_name" = rank_name) + ) if(!query_get_rank_flags.warn_execute()) qdel(query_get_rank_flags) return @@ -370,12 +417,19 @@ old_exclude_flags = text2num(query_get_rank_flags.item[2]) old_can_edit_flags = text2num(query_get_rank_flags.item[3]) qdel(query_get_rank_flags) - var/datum/DBQuery/query_change_rank_flags = SSdbcore.NewQuery("UPDATE [format_table_name("admin_ranks")] SET flags = '[new_flags]', exclude_flags = '[new_exclude_flags]', can_edit_flags = '[new_can_edit_flags]' WHERE rank = '[D.rank.name]'") + var/datum/db_query/query_change_rank_flags = SSdbcore.NewQuery( + "UPDATE [format_table_name("admin_ranks")] SET flags = :new_flags, exclude_flags = :new_exclude_flags, can_edit_flags = :new_can_edit_flags WHERE `rank` = :rank_name", + list("new_flags" = new_flags, "new_exclude_flags" = new_exclude_flags, "new_can_edit_flags" = new_can_edit_flags, "rank_name" = rank_name) + ) if(!query_change_rank_flags.warn_execute()) qdel(query_change_rank_flags) return qdel(query_change_rank_flags) - var/datum/DBQuery/query_change_rank_flags_log = SSdbcore.NewQuery("INSERT INTO [format_table_name("admin_log")] (datetime, round_id, adminckey, adminip, operation, target, log) VALUES ('[SQLtime()]', '[GLOB.round_id]', '[sanitizeSQL(usr.ckey)]', INET_ATON('[sanitizeSQL(usr.client.address)]'), 'change rank flags', '[D.rank.name]', 'Permissions of [D.rank.name] changed from[rights2text(old_flags," ")][rights2text(old_exclude_flags," ", "-")][rights2text(old_can_edit_flags," ", "*")] to[rights2text(new_flags," ")][rights2text(new_exclude_flags," ", "-")][rights2text(new_can_edit_flags," ", "*")]')") + var/log_message = "Permissions of [rank_name] changed from[rights2text(old_flags," ")][rights2text(old_exclude_flags," ", "-")][rights2text(old_can_edit_flags," ", "*")] to[rights2text(new_flags," ")][rights2text(new_exclude_flags," ", "-")][rights2text(new_can_edit_flags," ", "*")]" + var/datum/db_query/query_change_rank_flags_log = SSdbcore.NewQuery({" + INSERT INTO [format_table_name("admin_log")] (datetime, round_id, adminckey, adminip, operation, target, log) + VALUES (:time, :round_id, :adminckey, INET_ATON(:adminip), 'change rank flags', :rank_name, :log) + "}, list("time" = SQLtime(), "round_id" = "[GLOB.round_id]", "adminckey" = usr.ckey, "adminip" = usr.client.address, "rank_name" = rank_name, "log" = log_message)) if(!query_change_rank_flags_log.warn_execute()) qdel(query_change_rank_flags_log) return @@ -418,33 +472,41 @@ return for(var/datum/admin_rank/R in GLOB.admin_ranks) if(R.name == admin_rank && (!(R.rights & usr.client.holder.rank.can_edit_rights) == R.rights)) - to_chat(usr, "You don't have edit rights to all the rights this rank has, rank deletion not permitted.") + to_chat(usr, "You don't have edit rights to all the rights this rank has, rank deletion not permitted.", confidential = TRUE) return if(!CONFIG_GET(flag/admin_legacy_system) && CONFIG_GET(flag/protect_legacy_ranks) && (admin_rank in GLOB.protected_ranks)) - to_chat(usr, "Deletion of protected ranks is not permitted, it must be removed from admin_ranks.txt.") + to_chat(usr, "Deletion of protected ranks is not permitted, it must be removed from admin_ranks.txt.", confidential = TRUE) return if(CONFIG_GET(flag/load_legacy_ranks_only)) - to_chat(usr, "Rank deletion not permitted while database rank loading is disabled.") + to_chat(usr, "Rank deletion not permitted while database rank loading is disabled.", confidential = TRUE) return - admin_rank = sanitizeSQL(admin_rank) - var/datum/DBQuery/query_admins_with_rank = SSdbcore.NewQuery("SELECT 1 FROM [format_table_name("admin")] WHERE rank = '[admin_rank]'") + var/datum/db_query/query_admins_with_rank = SSdbcore.NewQuery( + "SELECT 1 FROM [format_table_name("admin")] WHERE `rank` = :admin_rank", + list("admin_rank" = admin_rank) + ) if(!query_admins_with_rank.warn_execute()) qdel(query_admins_with_rank) return if(query_admins_with_rank.NextRow()) qdel(query_admins_with_rank) - to_chat(usr, "Error: Rank deletion attempted while rank still used; Tell a coder, this shouldn't happen.") + to_chat(usr, "Error: Rank deletion attempted while rank still used; Tell a coder, this shouldn't happen.", confidential = TRUE) return qdel(query_admins_with_rank) if(alert("Are you sure you want to remove [admin_rank]?","Confirm Removal","Do it","Cancel") == "Do it") var/m1 = "[key_name_admin(usr)] removed rank [admin_rank] permanently" var/m2 = "[key_name(usr)] removed rank [admin_rank] permanently" - var/datum/DBQuery/query_add_rank = SSdbcore.NewQuery("DELETE FROM [format_table_name("admin_ranks")] WHERE rank = '[admin_rank]'") + var/datum/db_query/query_add_rank = SSdbcore.NewQuery( + "DELETE FROM [format_table_name("admin_ranks")] WHERE `rank` = :admin_rank", + list("admin_rank" = admin_rank) + ) if(!query_add_rank.warn_execute()) qdel(query_add_rank) return qdel(query_add_rank) - var/datum/DBQuery/query_add_rank_log = SSdbcore.NewQuery("INSERT INTO [format_table_name("admin_log")] (datetime, round_id, adminckey, adminip, operation, target, log) VALUES ('[SQLtime()]', '[GLOB.round_id]', '[sanitizeSQL(usr.ckey)]', INET_ATON('[sanitizeSQL(usr.client.address)]'), 'remove rank', '[admin_rank]', 'Rank removed: [admin_rank]')") + var/datum/db_query/query_add_rank_log = SSdbcore.NewQuery({" + INSERT INTO [format_table_name("admin_log")] (datetime, round_id, adminckey, adminip, operation, target, log) + VALUES (:time, :round_id, :adminckey, INET_ATON(:adminip), 'remove rank', :admin_rank, CONCAT('Rank removed: ', :admin_rank)) + "}, list("time" = SQLtime(), "round_id" = "[GLOB.round_id]", "adminckey" = usr.ckey, "adminip" = usr.client.address, "admin_rank" = admin_rank)) if(!query_add_rank_log.warn_execute()) qdel(query_add_rank_log) return @@ -455,11 +517,13 @@ /datum/admins/proc/sync_lastadminrank(admin_ckey, admin_key, datum/admins/D) var/sqlrank = "Player" if (D) - sqlrank = sanitizeSQL(D.rank.name) - admin_ckey = sanitizeSQL(admin_ckey) - var/datum/DBQuery/query_sync_lastadminrank = SSdbcore.NewQuery("UPDATE [format_table_name("player")] SET lastadminrank = '[sqlrank]' WHERE ckey = '[admin_ckey]'") + sqlrank = D.rank.name + var/datum/db_query/query_sync_lastadminrank = SSdbcore.NewQuery( + "UPDATE [format_table_name("player")] SET lastadminrank = :rank WHERE ckey = :ckey", + list("rank" = sqlrank, "ckey" = admin_ckey) + ) if(!query_sync_lastadminrank.warn_execute()) qdel(query_sync_lastadminrank) return qdel(query_sync_lastadminrank) - to_chat(usr, "Sync of [admin_key] successful.") + to_chat(usr, "Sync of [admin_key] successful.", confidential = TRUE) diff --git a/code/modules/admin/sql_message_system.dm b/code/modules/admin/sql_message_system.dm index 4218d4238f..3ba309bc24 100644 --- a/code/modules/admin/sql_message_system.dm +++ b/code/modules/admin/sql_message_system.dm @@ -1,6 +1,6 @@ /proc/create_message(type, target_key, admin_ckey, text, timestamp, server, secret, logged = 1, browse, expiry, note_severity) if(!SSdbcore.Connect()) - to_chat(usr, "Failed to establish database connection.") + to_chat(usr, "Failed to establish database connection.", confidential = TRUE) return if(!type) return @@ -9,8 +9,11 @@ var/new_key = input(usr,"Who would you like to create a [type] for?","Enter a key or ckey",null) as null|text if(!new_key) return - var/new_ckey = sanitizeSQL(ckey(new_key)) - var/datum/DBQuery/query_find_ckey = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE ckey = '[new_ckey]'") + var/new_ckey = ckey(new_key) + var/datum/db_query/query_find_ckey = SSdbcore.NewQuery( + "SELECT ckey FROM [format_table_name("player")] WHERE ckey = :ckey", + list("ckey" = new_ckey) + ) if(!query_find_ckey.warn_execute()) qdel(query_find_ckey) return @@ -23,29 +26,24 @@ target_key = new_key if(QDELETED(usr)) return - if(target_ckey) - target_ckey = sanitizeSQL(target_ckey) if(!target_key) target_key = target_ckey if(!admin_ckey) admin_ckey = usr.ckey if(!admin_ckey) return - admin_ckey = sanitizeSQL(admin_ckey) if(!target_ckey) target_ckey = admin_ckey if(!text) text = input(usr,"Write your [type]","Create [type]") as null|message if(!text) return - text = sanitizeSQL(text) if(!timestamp) timestamp = SQLtime() if(!server) var/ssqlname = CONFIG_GET(string/serversqlname) if (ssqlname) server = ssqlname - server = sanitizeSQL(server) if(isnull(secret)) switch(alert("Hide note from being viewed by players?", "Secret note?","Yes","No","Cancel")) if("Yes") @@ -59,15 +57,17 @@ var/expire_time = input("Set expiry time for [type] as format YYYY-MM-DD HH:MM:SS. All times in server time. HH:MM:SS is optional and 24-hour. Must be later than current time for obvious reasons.", "Set expiry time", SQLtime()) as null|text if(!expire_time) return - expire_time = sanitizeSQL(expire_time) - var/datum/DBQuery/query_validate_expire_time = SSdbcore.NewQuery("SELECT IF(STR_TO_DATE('[expire_time]','%Y-%c-%d %T') > NOW(), STR_TO_DATE('[expire_time]','%Y-%c-%d %T'), 0)") + var/datum/db_query/query_validate_expire_time = SSdbcore.NewQuery( + "SELECT IF(STR_TO_DATE(:expire_time,'%Y-%c-%d %T') > NOW(), STR_TO_DATE(:expire_time,'%Y-%c-%d %T'), 0)", + list("expire_time" = expire_time) + ) if(!query_validate_expire_time.warn_execute()) qdel(query_validate_expire_time) return if(query_validate_expire_time.NextRow()) var/checktime = text2num(query_validate_expire_time.item[1]) if(!checktime) - to_chat(usr, "Datetime entered is improperly formatted or not later than current server time.") + to_chat(usr, "Datetime entered is improperly formatted or not later than current server time.", confidential = TRUE) qdel(query_validate_expire_time) return expiry = query_validate_expire_time.item[1] @@ -76,8 +76,23 @@ note_severity = input("Set the severity of the note.", "Severity", null, null) as null|anything in list("High", "Medium", "Minor", "None") if(!note_severity) return - note_severity = sanitizeSQL(note_severity) - var/datum/DBQuery/query_create_message = SSdbcore.NewQuery("INSERT INTO [format_table_name("messages")] (type, targetckey, adminckey, text, timestamp, server, server_ip, server_port, round_id, secret, expire_timestamp, severity) VALUES ('[type]', '[target_ckey]', '[admin_ckey]', '[text]', '[timestamp]', '[server]', INET_ATON(IF('[world.internet_address]' LIKE '', '0', '[world.internet_address]')), '[world.port]', '[GLOB.round_id]','[secret]', [expiry ? "'[expiry]'" : "NULL"], [note_severity ? "'[note_severity]'" : "NULL"])") + var/datum/db_query/query_create_message = SSdbcore.NewQuery({" + INSERT INTO [format_table_name("messages")] (type, targetckey, adminckey, text, timestamp, server, server_ip, server_port, round_id, secret, expire_timestamp, severity) + VALUES (:type, :target_ckey, :admin_ckey, :text, :timestamp, :server, INET_ATON(:internet_address), :port, :round_id, :secret, :expiry, :note_severity) + "}, list( + "type" = type, + "target_ckey" = target_ckey, + "admin_ckey" = admin_ckey, + "text" = text, + "timestamp" = timestamp, + "server" = server, + "internet_address" = world.internet_address || "0", + "port" = "[world.port]", + "round_id" = GLOB.round_id, + "secret" = secret, + "expiry" = expiry || null, + "note_severity" = note_severity, + )) var/pm = "[key_name(usr)] has created a [type][(type == "note" || type == "message" || type == "watchlist entry") ? " for [target_key]" : ""]: [text]" var/header = "[key_name_admin(usr)] has created a [type][(type == "note" || type == "message" || type == "watchlist entry") ? " for [target_key]" : ""]" if(!query_create_message.warn_execute()) @@ -96,7 +111,7 @@ /proc/delete_message(message_id, logged = 1, browse) if(!SSdbcore.Connect()) - to_chat(usr, "Failed to establish database connection.") + to_chat(usr, "Failed to establish database connection.", confidential = TRUE) return message_id = text2num(message_id) if(!message_id) @@ -106,7 +121,11 @@ var/text var/user_key_name = key_name(usr) var/user_name_admin = key_name_admin(usr) - var/datum/DBQuery/query_find_del_message = SSdbcore.NewQuery("SELECT type, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = targetckey), targetckey), text FROM [format_table_name("messages")] WHERE id = [message_id] AND deleted = 0") + var/deleted_by_ckey = usr.ckey + var/datum/db_query/query_find_del_message = SSdbcore.NewQuery( + "SELECT type, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = targetckey), targetckey), text FROM [format_table_name("messages")] WHERE id = :id AND deleted = 0", + list("id" = message_id) + ) if(!query_find_del_message.warn_execute()) qdel(query_find_del_message) return @@ -115,7 +134,10 @@ target_key = query_find_del_message.item[2] text = query_find_del_message.item[3] qdel(query_find_del_message) - var/datum/DBQuery/query_del_message = SSdbcore.NewQuery("UPDATE [format_table_name("messages")] SET deleted = 1 WHERE id = [message_id]") + var/datum/db_query/query_del_message = SSdbcore.NewQuery( + "UPDATE [format_table_name("messages")] SET deleted = 1, deleted_ckey = :deleted_ckey WHERE id = :id", + list("deleted_ckey" = deleted_by_ckey, "id" = message_id) + ) if(!query_del_message.warn_execute()) qdel(query_del_message) return @@ -132,16 +154,24 @@ /proc/edit_message(message_id, browse) if(!SSdbcore.Connect()) - to_chat(usr, "Failed to establish database connection.") + to_chat(usr, "Failed to establish database connection.", confidential = TRUE) return message_id = text2num(message_id) if(!message_id) return - var/editor_ckey = sanitizeSQL(usr.ckey) - var/editor_key = sanitizeSQL(usr.key) + var/editor_ckey = usr.ckey + var/editor_key = usr.key var/kn = key_name(usr) var/kna = key_name_admin(usr) - var/datum/DBQuery/query_find_edit_message = SSdbcore.NewQuery("SELECT type, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = targetckey), targetckey), IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = adminckey), targetckey), text FROM [format_table_name("messages")] WHERE id = [message_id] AND deleted = 0") + var/datum/db_query/query_find_edit_message = SSdbcore.NewQuery({" + SELECT + type, + IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = targetckey), targetckey), + IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = adminckey), targetckey), + text + FROM [format_table_name("messages")] + WHERE id = :id AND deleted = 0 + "}, list("id" = message_id)) if(!query_find_edit_message.warn_execute()) qdel(query_find_edit_message) return @@ -154,9 +184,12 @@ if(!new_text) qdel(query_find_edit_message) return - new_text = sanitizeSQL(new_text) - var/edit_text = sanitizeSQL("Edited by [editor_key] on [SQLtime()] from
[old_text]
to
[new_text]
") - var/datum/DBQuery/query_edit_message = SSdbcore.NewQuery("UPDATE [format_table_name("messages")] SET text = '[new_text]', lasteditor = '[editor_ckey]', edits = CONCAT(IFNULL(edits,''),'[edit_text]') WHERE id = [message_id] AND deleted = 0") + var/edit_text = "Edited by [editor_key] on [SQLtime()] from
[old_text]
to
[new_text]
" + var/datum/db_query/query_edit_message = SSdbcore.NewQuery({" + UPDATE [format_table_name("messages")] + SET text = :text, lasteditor = :lasteditor, edits = CONCAT(IFNULL(edits,''),:edit_text) + WHERE id = :id AND deleted = 0 + "}, list("text" = new_text, "lasteditor" = editor_ckey, "edit_text" = edit_text, "id" = message_id)) if(!query_edit_message.warn_execute()) qdel(query_edit_message) return @@ -171,16 +204,24 @@ /proc/edit_message_expiry(message_id, browse) if(!SSdbcore.Connect()) - to_chat(usr, "Failed to establish database connection.") + to_chat(usr, "Failed to establish database connection.", confidential = TRUE) return message_id = text2num(message_id) if(!message_id) return - var/editor_ckey = sanitizeSQL(usr.ckey) - var/editor_key = sanitizeSQL(usr.key) + var/editor_ckey = usr.ckey + var/editor_key = usr.key var/kn = key_name(usr) var/kna = key_name_admin(usr) - var/datum/DBQuery/query_find_edit_expiry_message = SSdbcore.NewQuery("SELECT type, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = targetckey), targetckey), IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = adminckey), adminckey), expire_timestamp FROM [format_table_name("messages")] WHERE id = [message_id] AND deleted = 0") + var/datum/db_query/query_find_edit_expiry_message = SSdbcore.NewQuery({" + SELECT + type, + IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = targetckey), targetckey), + IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = adminckey), adminckey), + expire_timestamp + FROM [format_table_name("messages")] + WHERE id = :id AND deleted = 0 + "}, list("id" = message_id)) if(!query_find_edit_expiry_message.warn_execute()) qdel(query_find_edit_expiry_message) return @@ -197,8 +238,9 @@ if(expire_time == "-1") new_expiry = "non-expiring" else - expire_time = sanitizeSQL(expire_time) - var/datum/DBQuery/query_validate_expire_time_edit = SSdbcore.NewQuery("SELECT IF(STR_TO_DATE('[expire_time]','%Y-%c-%d %T') > NOW(), STR_TO_DATE('[expire_time]','%Y-%c-%d %T'), 0)") + var/datum/db_query/query_validate_expire_time_edit = SSdbcore.NewQuery({" + SELECT IF(STR_TO_DATE(:expire_time,'%Y-%c-%d %T') > NOW(), STR_TO_DATE(:expire_time,'%Y-%c-%d %T'), 0) + "}, list("expire_time" = expire_time)) if(!query_validate_expire_time_edit.warn_execute()) qdel(query_validate_expire_time_edit) qdel(query_find_edit_expiry_message) @@ -206,14 +248,18 @@ if(query_validate_expire_time_edit.NextRow()) var/checktime = text2num(query_validate_expire_time_edit.item[1]) if(!checktime) - to_chat(usr, "Datetime entered is improperly formatted or not later than current server time.") + to_chat(usr, "Datetime entered is improperly formatted or not later than current server time.", confidential = TRUE) qdel(query_validate_expire_time_edit) qdel(query_find_edit_expiry_message) return new_expiry = query_validate_expire_time_edit.item[1] qdel(query_validate_expire_time_edit) - var/edit_text = sanitizeSQL("Expiration time edited by [editor_key] on [SQLtime()] from [old_expiry] to [new_expiry]
") - var/datum/DBQuery/query_edit_message_expiry = SSdbcore.NewQuery("UPDATE [format_table_name("messages")] SET expire_timestamp = [expire_time == "-1" ? "NULL" : "'[new_expiry]'"], lasteditor = '[editor_ckey]', edits = CONCAT(IFNULL(edits,''),'[edit_text]') WHERE id = [message_id] AND deleted = 0") + var/edit_text = "Expiration time edited by [editor_key] on [SQLtime()] from [old_expiry] to [new_expiry]
" + var/datum/db_query/query_edit_message_expiry = SSdbcore.NewQuery({" + UPDATE [format_table_name("messages")] + SET expire_timestamp = :expire_time, lasteditor = :lasteditor, edits = CONCAT(IFNULL(edits,''),:edit_text) + WHERE id = :id AND deleted = 0 + "}, list("expire_time" = (expire_time == "-1" ? null : new_expiry), "lasteditor" = editor_ckey, "edit_text" = edit_text, "id" = message_id)) if(!query_edit_message_expiry.warn_execute()) qdel(query_edit_message_expiry) qdel(query_find_edit_expiry_message) @@ -229,14 +275,22 @@ /proc/edit_message_severity(message_id) if(!SSdbcore.Connect()) - to_chat(usr, "Failed to establish database connection.") + to_chat(usr, "Failed to establish database connection.", confidential = TRUE) return message_id = text2num(message_id) if(!message_id) return var/kn = key_name(usr) var/kna = key_name_admin(usr) - var/datum/DBQuery/query_find_edit_note_severity = SSdbcore.NewQuery("SELECT type, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = targetckey), targetckey), IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = adminckey), adminckey), severity FROM [format_table_name("messages")] WHERE id = [message_id] AND deleted = 0") + var/datum/db_query/query_find_edit_note_severity = SSdbcore.NewQuery({" + SELECT + type, + IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = targetckey), targetckey), + IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = adminckey), adminckey), + severity + FROM [format_table_name("messages")] + WHERE id = :id AND deleted = 0 + "}, list("id" = message_id)) if(!query_find_edit_note_severity.warn_execute()) qdel(query_find_edit_note_severity) return @@ -247,15 +301,19 @@ var/old_severity = query_find_edit_note_severity.item[4] if(!old_severity) old_severity = "NA" - var/editor_key = sanitizeSQL(usr.key) - var/editor_ckey = sanitizeSQL(usr.ckey) + var/editor_key = usr.key + var/editor_ckey = usr.ckey var/new_severity = input("Set the severity of the note.", "Severity", null, null) as null|anything in list("high", "medium", "minor", "none") //lowercase for edit log consistency if(!new_severity) qdel(query_find_edit_note_severity) return - new_severity = sanitizeSQL(new_severity) - var/edit_text = sanitizeSQL("Note severity edited by [editor_key] on [SQLtime()] from [old_severity] to [new_severity]
") - var/datum/DBQuery/query_edit_note_severity = SSdbcore.NewQuery("UPDATE [format_table_name("messages")] SET severity = '[new_severity]', lasteditor = '[editor_ckey]', edits = CONCAT(IFNULL(edits,''),'[edit_text]') WHERE id = [message_id] AND deleted = 0") + new_severity = new_severity + var/edit_text = "Note severity edited by [editor_key] on [SQLtime()] from [old_severity] to [new_severity]
" + var/datum/db_query/query_edit_note_severity = SSdbcore.NewQuery({" + UPDATE [format_table_name("messages")] + SET severity = :severity, lasteditor = :lasteditor, edits = CONCAT(IFNULL(edits,''),:edit_text) + WHERE id = :id AND deleted = 0 + "}, list("severity" = new_severity, "lasteditor" = editor_ckey, "edit_text" = edit_text, "id" = message_id)) if(!query_edit_note_severity.warn_execute(async = TRUE)) qdel(query_edit_note_severity) qdel(qdel(query_find_edit_note_severity)) @@ -268,16 +326,24 @@ /proc/toggle_message_secrecy(message_id) if(!SSdbcore.Connect()) - to_chat(usr, "Failed to establish database connection.") + to_chat(usr, "Failed to establish database connection.", confidential = TRUE) return message_id = text2num(message_id) if(!message_id) return - var/editor_ckey = sanitizeSQL(usr.ckey) - var/editor_key = sanitizeSQL(usr.key) + var/editor_ckey = usr.ckey + var/editor_key = usr.key var/kn = key_name(usr) var/kna = key_name_admin(usr) - var/datum/DBQuery/query_find_message_secret = SSdbcore.NewQuery("SELECT type, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = targetckey), targetckey), IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = adminckey), targetckey), secret FROM [format_table_name("messages")] WHERE id = [message_id] AND deleted = 0") + var/datum/db_query/query_find_message_secret = SSdbcore.NewQuery({" + SELECT + type, + IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = targetckey), targetckey), + IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = adminckey), targetckey), + secret + FROM [format_table_name("messages")] + WHERE id = :id AND deleted = 0 + "}, list("id" = message_id)) if(!query_find_message_secret.warn_execute()) qdel(query_find_message_secret) return @@ -287,7 +353,11 @@ var/admin_key = query_find_message_secret.item[3] var/secret = text2num(query_find_message_secret.item[4]) var/edit_text = "Made [secret ? "not secret" : "secret"] by [editor_key] on [SQLtime()]
" - var/datum/DBQuery/query_message_secret = SSdbcore.NewQuery("UPDATE [format_table_name("messages")] SET secret = NOT secret, lasteditor = '[editor_ckey]', edits = CONCAT(IFNULL(edits,''),'[edit_text]') WHERE id = [message_id]") + var/datum/db_query/query_message_secret = SSdbcore.NewQuery({" + UPDATE [format_table_name("messages")] + SET secret = NOT secret, lasteditor = :lasteditor, edits = CONCAT(IFNULL(edits,''),:edit_text) + WHERE id = :id + "}, list("lasteditor" = editor_ckey, "edit_text" = edit_text, "id" = message_id)) if(!query_message_secret.warn_execute()) qdel(query_find_message_secret) qdel(query_message_secret) @@ -298,11 +368,9 @@ browse_messages(target_ckey = ckey(target_key), agegate = TRUE) qdel(query_find_message_secret) -/proc/browse_messages(type, target_ckey, index, linkless = FALSE, filter, agegate = FALSE, override = FALSE) - if((!override || IsAdminAdvancedProcCall()) && !check_rights(R_SENSITIVE)) - return +/proc/browse_messages(type, target_ckey, index, linkless = FALSE, filter, agegate = FALSE) if(!SSdbcore.Connect()) - to_chat(usr, "Failed to establish database connection.") + to_chat(usr, "Failed to establish database connection.", confidential = TRUE) return var/list/output = list() var/ruler = "
" @@ -329,7 +397,20 @@ else output += "Filter offline clients" output += ruler - var/datum/DBQuery/query_get_type_messages = SSdbcore.NewQuery("SELECT id, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = targetckey), targetckey), targetckey, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = adminckey), adminckey), text, timestamp, server, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = lasteditor), lasteditor), expire_timestamp FROM [format_table_name("messages")] WHERE type = '[type]' AND deleted = 0 AND (expire_timestamp > NOW() OR expire_timestamp IS NULL)") + var/datum/db_query/query_get_type_messages = SSdbcore.NewQuery({" + SELECT + id, + IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = targetckey), targetckey), + targetckey, + IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = adminckey), adminckey), + text, + timestamp, + server, + IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = lasteditor), lasteditor), + expire_timestamp + FROM [format_table_name("messages")] + WHERE type = :type AND deleted = 0 AND (expire_timestamp > NOW() OR expire_timestamp IS NULL) + "}, list("type" = type)) if(!query_get_type_messages.warn_execute()) qdel(query_get_type_messages) return @@ -362,9 +443,24 @@ output += "
[text]
" qdel(query_get_type_messages) if(target_ckey) - target_ckey = sanitizeSQL(target_ckey) var/target_key - var/datum/DBQuery/query_get_messages = SSdbcore.NewQuery("SELECT type, secret, id, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = adminckey), adminckey), text, timestamp, server, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = lasteditor), lasteditor), DATEDIFF(NOW(), timestamp), IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = targetckey), targetckey), expire_timestamp, severity FROM [format_table_name("messages")] WHERE type <> 'memo' AND targetckey = '[target_ckey]' AND deleted = 0 AND (expire_timestamp > NOW() OR expire_timestamp IS NULL) ORDER BY timestamp DESC") + var/datum/db_query/query_get_messages = SSdbcore.NewQuery({" + SELECT + type, + secret, + id, + IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = adminckey), adminckey), + text, + timestamp, + server, + IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = lasteditor), lasteditor), + DATEDIFF(NOW(), timestamp), + IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = targetckey), targetckey), + expire_timestamp, severity + FROM [format_table_name("messages")] + WHERE type <> 'memo' AND targetckey = :targetckey AND deleted = 0 AND (expire_timestamp > NOW() OR expire_timestamp IS NULL) + ORDER BY timestamp DESC + "}, list("targetckey" = target_ckey)) if(!query_get_messages.warn_execute()) qdel(query_get_messages) return @@ -442,7 +538,9 @@ notedata += data qdel(query_get_messages) if(!target_key) - var/datum/DBQuery/query_get_message_key = SSdbcore.NewQuery("SELECT byond_key FROM [format_table_name("player")] WHERE ckey = '[target_ckey]'") + var/datum/db_query/query_get_message_key = SSdbcore.NewQuery({" + SELECT byond_key FROM [format_table_name("player")] WHERE ckey = :ckey + "}, list("ckey" = target_ckey)) if(!query_get_message_key.warn_execute()) qdel(query_get_message_key) return @@ -479,8 +577,6 @@ var/search output += "
Add messageAdd watchlist entryAdd note
" output += ruler - if(!isnum(index)) - index = sanitizeSQL(index) switch(index) if(1) search = "^." @@ -488,7 +584,17 @@ search = "^\[^\[:alpha:\]\]" else search = "^[index]" - var/datum/DBQuery/query_list_messages = SSdbcore.NewQuery("SELECT DISTINCT targetckey, (SELECT byond_key FROM [format_table_name("player")] WHERE ckey = targetckey) FROM [format_table_name("messages")] WHERE type <> 'memo' AND targetckey REGEXP '[search]' AND deleted = 0 AND (expire_timestamp > NOW() OR expire_timestamp IS NULL) ORDER BY targetckey") + var/datum/db_query/query_list_messages = SSdbcore.NewQuery({" + SELECT DISTINCT + targetckey, + (SELECT byond_key FROM [format_table_name("player")] WHERE ckey = targetckey) + FROM [format_table_name("messages")] + WHERE type <> 'memo' + AND targetckey REGEXP :search + AND deleted = 0 + AND (expire_timestamp > NOW() OR expire_timestamp IS NULL) + ORDER BY targetckey + "}, list("search" = search)) if(!query_list_messages.warn_execute()) qdel(query_list_messages) return @@ -512,17 +618,24 @@ /proc/get_message_output(type, target_ckey) if(!SSdbcore.Connect()) - to_chat(usr, "Failed to establish database connection.") + to_chat(usr, "Failed to establish database connection.", confidential = TRUE) return if(!type) return var/output - if(target_ckey) - target_ckey = sanitizeSQL(target_ckey) - var/query = "SELECT id, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = adminckey), adminckey), text, timestamp, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = lasteditor), lasteditor) FROM [format_table_name("messages")] WHERE type = '[type]' AND deleted = 0 AND (expire_timestamp > NOW() OR expire_timestamp IS NULL)" - if(type == "message" || type == "watchlist entry") - query += " AND targetckey = '[target_ckey]'" - var/datum/DBQuery/query_get_message_output = SSdbcore.NewQuery(query) + var/datum/db_query/query_get_message_output = SSdbcore.NewQuery({" + SELECT + id, + IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = adminckey), adminckey), + text, + timestamp, + IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = lasteditor), lasteditor) + FROM [format_table_name("messages")] + WHERE type = :type + AND deleted = 0 + AND (expire_timestamp > NOW() OR expire_timestamp IS NULL) + AND ((type != 'message' AND type != 'watchlist entry') OR targetckey = :targetckey) + "}, list("targetckey" = target_ckey, "type" = type)) if(!query_get_message_output.warn_execute()) qdel(query_get_message_output) return @@ -536,7 +649,10 @@ if("message") output += "Admin message left by [admin_key] on [timestamp]" output += "
[text]
" - var/datum/DBQuery/query_message_read = SSdbcore.NewQuery("UPDATE [format_table_name("messages")] SET type = 'message sent' WHERE id = [message_id]") + var/datum/db_query/query_message_read = SSdbcore.NewQuery( + "UPDATE [format_table_name("messages")] SET type = 'message sent' WHERE id = :id", + list("id" = message_id) + ) if(!query_message_read.warn_execute()) qdel(query_get_message_output) qdel(query_message_read) @@ -544,7 +660,7 @@ qdel(query_message_read) if("watchlist entry") message_admins("Notice: [key_name_admin(target_ckey)] has been on the watchlist since [timestamp] and has just connected - Reason: [text]") - send2irc_adminless_only("Watchlist", "[key_name(target_ckey)] is on the watchlist and has just connected - Reason: [text]") + send2tgs_adminless_only("Watchlist", "[key_name(target_ckey)] is on the watchlist and has just connected - Reason: [text]") if("memo") output += "Memo by [admin_key] on [timestamp]" if(editor_key) @@ -576,7 +692,7 @@ var/timestamp = note.group[1] notetext = note.group[2] var/admin_ckey = note.group[3] - var/datum/DBQuery/query_convert_time = SSdbcore.NewQuery("SELECT ADDTIME(STR_TO_DATE('[timestamp]','%d-%b-%Y'), '0')") + var/datum/db_query/query_convert_time = SSdbcore.NewQuery("SELECT ADDTIME(STR_TO_DATE(:timestamp,'%d-%b-%Y'), '0')", list("timestamp" = timestamp)) if(!query_convert_time.Execute()) qdel(query_convert_time) return @@ -591,7 +707,7 @@ /*alternatively this proc can be run once to pass through every note and attempt to convert it before deleting the file, if done then AUTOCONVERT_NOTES should be turned off this proc can take several minutes to execute fully if converting and cause DD to hang if converting a lot of notes; it's not advised to do so while a server is live /proc/mass_convert_notes() - to_chat(world, "Beginning mass note conversion") + to_chat(world, "Beginning mass note conversion", confidential = TRUE) var/savefile/notesfile = new(NOTESFILE) if(!notesfile) log_game("Error: Cannot access [NOTESFILE]") @@ -599,7 +715,7 @@ this proc can take several minutes to execute fully if converting and cause DD t notesfile.cd = "/" for(var/ckey in notesfile.dir) convert_notes_sql(ckey) - to_chat(world, "Deleting NOTESFILE") + to_chat(world, "Deleting NOTESFILE", confidential = TRUE) fdel(NOTESFILE) - to_chat(world, "Finished mass note conversion, remember to turn off AUTOCONVERT_NOTES")*/ + to_chat(world, "Finished mass note conversion, remember to turn off AUTOCONVERT_NOTES", confidential = TRUE)*/ #undef NOTESFILE diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index e0434a6fea..b341f4bbfb 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -1270,8 +1270,10 @@ else if(href_list["messageedits"]) if(!check_rights(R_ADMIN)) return - var/message_id = sanitizeSQL("[href_list["messageedits"]]") - var/datum/DBQuery/query_get_message_edits = SSdbcore.NewQuery("SELECT edits FROM [format_table_name("messages")] WHERE id = '[message_id]'") + var/datum/db_query/query_get_message_edits = SSdbcore.NewQuery( + "SELECT edits FROM [format_table_name("messages")] WHERE id = :message_id", + list("message_id" = href_list["messageedits"]) + ) if(!query_get_message_edits.warn_execute()) qdel(query_get_message_edits) return @@ -2971,16 +2973,19 @@ to_chat(usr, "The client chosen is an admin! Cannot mentorize.") return if(SSdbcore.Connect()) - var/datum/DBQuery/query_get_mentor = SSdbcore.NewQuery("SELECT id FROM [format_table_name("mentor")] WHERE ckey = '[ckey]'") + var/datum/db_query/query_get_mentor = SSdbcore.NewQuery( + "SELECT id FROM [format_table_name("mentor")] WHERE ckey = :ckey", + list("ckey" = ckey) + ) if(!query_get_mentor.warn_execute()) return if(query_get_mentor.NextRow()) to_chat(usr, "[ckey] is already a mentor.") return - var/datum/DBQuery/query_add_mentor = SSdbcore.NewQuery("INSERT INTO `[format_table_name("mentor")]` (`id`, `ckey`) VALUES (null, '[ckey]')") + var/datum/db_query/query_add_mentor = SSdbcore.NewQuery("INSERT INTO `[format_table_name("mentor")]` (`id`, `ckey`) VALUES (null, '[ckey]')") if(!query_add_mentor.warn_execute()) return - var/datum/DBQuery/query_add_admin_log = SSdbcore.NewQuery("INSERT INTO `[format_table_name("admin_log")]` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Added new mentor [ckey]');") + var/datum/db_query/query_add_admin_log = SSdbcore.NewQuery("INSERT INTO `[format_table_name("admin_log")]` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Added new mentor [ckey]');") if(!query_add_admin_log.warn_execute()) return else @@ -3004,10 +3009,10 @@ C.mentor_datum = null GLOB.mentors -= C if(SSdbcore.Connect()) - var/datum/DBQuery/query_remove_mentor = SSdbcore.NewQuery("DELETE FROM [format_table_name("mentor")] WHERE ckey = '[ckey]'") + var/datum/db_query/query_remove_mentor = SSdbcore.NewQuery("DELETE FROM [format_table_name("mentor")] WHERE ckey = '[ckey]'") if(!query_remove_mentor.warn_execute()) return - var/datum/DBQuery/query_add_admin_log = SSdbcore.NewQuery("INSERT INTO `[format_table_name("admin_log")]` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Removed mentor [ckey]');") + var/datum/db_query/query_add_admin_log = SSdbcore.NewQuery("INSERT INTO `[format_table_name("admin_log")]` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Removed mentor [ckey]');") if(!query_add_admin_log.warn_execute()) return else diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 617d4a1d72..faa202ee53 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -534,14 +534,21 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( return if(!SSdbcore.Connect()) return - var/sql_ckey = sanitizeSQL(src.ckey) - var/datum/DBQuery/query_get_related_ip = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE ip = INET_ATON('[address]') AND ckey != '[sql_ckey]'") - query_get_related_ip.Execute() + var/datum/db_query/query_get_related_ip = SSdbcore.NewQuery( + "SELECT ckey FROM [format_table_name("player")] WHERE ip = INET_ATON(:address) AND ckey != :ckey", + list("address" = address, "ckey" = ckey) + ) + if(!query_get_related_ip.Execute()) + qdel(query_get_related_ip) + return related_accounts_ip = "" while(query_get_related_ip.NextRow()) related_accounts_ip += "[query_get_related_ip.item[1]], " qdel(query_get_related_ip) - var/datum/DBQuery/query_get_related_cid = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE computerid = '[computer_id]' AND ckey != '[sql_ckey]'") + var/datum/db_query/query_get_related_cid = SSdbcore.NewQuery( + "SELECT ckey FROM [format_table_name("player")] WHERE computerid = :computerid AND ckey != :ckey", + list("computerid" = computer_id, "ckey" = ckey) + ) if(!query_get_related_cid.Execute()) qdel(query_get_related_cid) return @@ -555,45 +562,40 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( else if (!GLOB.deadmins[ckey] && check_randomizer(connectiontopic)) return - var/sql_ip = sanitizeSQL(address) - var/sql_computerid = sanitizeSQL(computer_id) - var/sql_admin_rank = sanitizeSQL(admin_rank) var/new_player - var/datum/DBQuery/query_client_in_db = SSdbcore.NewQuery("SELECT 1 FROM [format_table_name("player")] WHERE ckey = '[sql_ckey]'") + var/datum/db_query/query_client_in_db = SSdbcore.NewQuery( + "SELECT 1 FROM [format_table_name("player")] WHERE ckey = :ckey", + list("ckey" = ckey) + ) if(!query_client_in_db.Execute()) qdel(query_client_in_db) return - if(!query_client_in_db.NextRow()) //new user detected - if(!holder && !GLOB.deadmins[ckey]) - if(CONFIG_GET(flag/panic_bunker) && !(ckey in GLOB.bunker_passthrough)) - log_access("Failed Login: [key] - New account attempting to connect during panic bunker") - message_admins("Failed Login: [key] - New account attempting to connect during panic bunker") - to_chat(src, "You must first join the Discord to verify your account before joining this server.
To do so, read the rules and post a request in the #station-access-requests channel under the \"Main server\" category in the Discord server linked here: https://discord.gg/E6SQuhz
If you have already done so, wait a few minutes then try again; sometimes the server needs to fully load before you can join.
") //CIT CHANGE - makes the panic bunker disconnect message point to the discord - var/list/connectiontopic_a = params2list(connectiontopic) - var/list/panic_addr = CONFIG_GET(string/panic_server_address) - if(panic_addr && !connectiontopic_a["redirect"]) - var/panic_name = CONFIG_GET(string/panic_server_name) - to_chat(src, "Sending you to [panic_name ? panic_name : panic_addr].") - winset(src, null, "command=.options") - src << link("[panic_addr]?redirect=1") - qdel(query_client_in_db) - qdel(src) - return - new_player = 1 - account_join_date = sanitizeSQL(findJoinDate()) - var/sql_key = sanitizeSQL(key) - var/datum/DBQuery/query_add_player = SSdbcore.NewQuery("INSERT INTO [format_table_name("player")] (`ckey`, `byond_key`, `firstseen`, `firstseen_round_id`, `lastseen`, `lastseen_round_id`, `ip`, `computerid`, `lastadminrank`, `accountjoindate`) VALUES ('[sql_ckey]', '[sql_key]', Now(), '[GLOB.round_id]', Now(), '[GLOB.round_id]', INET_ATON('[sql_ip]'), '[sql_computerid]', '[sql_admin_rank]', [account_join_date ? "'[account_join_date]'" : "NULL"])") - if(!query_add_player.Execute()) - qdel(query_client_in_db) - qdel(query_add_player) - return - qdel(query_add_player) - if(!account_join_date) - account_join_date = "Error" - account_age = -1 - else if(ckey in GLOB.bunker_passthrough) - GLOB.bunker_passthrough -= ckey + //If we aren't an admin, and the flag is set + if(CONFIG_GET(flag/panic_bunker) && !holder && !GLOB.deadmins[ckey] && !(ckey in GLOB.bunker_passthrough)) + var/living_recs = CONFIG_GET(number/panic_bunker_living) + //Relies on pref existing, but this proc is only called after that occurs, so we're fine. + var/minutes = get_exp_living(pure_numeric = TRUE) + if(minutes <= living_recs && !CONFIG_GET(flag/panic_bunker_interview)) + var/reject_message = "Failed Login: [key] - Account attempting to connect during panic bunker, but they do not have the required living time [minutes]/[living_recs]" + log_access(reject_message) + message_admins("[reject_message]") + var/message = CONFIG_GET(string/panic_bunker_message) + message = replacetext(message, "%minutes%", living_recs) + to_chat(src, message) + var/list/connectiontopic_a = params2list(connectiontopic) + var/list/panic_addr = CONFIG_GET(string/panic_server_address) + if(panic_addr && !connectiontopic_a["redirect"]) + var/panic_name = CONFIG_GET(string/panic_server_name) + to_chat(src, "Sending you to [panic_name ? panic_name : panic_addr].") + winset(src, null, "command=.options") + src << link("[panic_addr]?redirect=1") + qdel(query_client_in_db) + qdel(src) + return + + if(!query_client_in_db.NextRow()) + new_player = 1 if(CONFIG_GET(flag/age_verification)) //setup age verification if(!set_db_player_flags()) message_admins(usr, "ERROR: Unable to read player flags from database. Please check logs.") @@ -605,9 +607,24 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( update_flag_db(DB_FLAG_AGE_CONFIRMATION_COMPLETE, TRUE) else update_flag_db(DB_FLAG_AGE_CONFIRMATION_INCOMPLETE, TRUE) - + account_join_date = findJoinDate() + var/datum/db_query/query_add_player = SSdbcore.NewQuery({" + INSERT INTO [format_table_name("player")] (`ckey`, `byond_key`, `firstseen`, `firstseen_round_id`, `lastseen`, `lastseen_round_id`, `ip`, `computerid`, `lastadminrank`, `accountjoindate`) + VALUES (:ckey, :key, Now(), :round_id, Now(), :round_id, INET_ATON(:ip), :computerid, :adminrank, :account_join_date) + "}, list("ckey" = ckey, "key" = key, "round_id" = GLOB.round_id, "ip" = address, "computerid" = computer_id, "adminrank" = admin_rank, "account_join_date" = account_join_date || null)) + if(!query_add_player.Execute()) + qdel(query_client_in_db) + qdel(query_add_player) + return + qdel(query_add_player) + if(!account_join_date) + account_join_date = "Error" + account_age = -1 qdel(query_client_in_db) - var/datum/DBQuery/query_get_client_age = SSdbcore.NewQuery("SELECT firstseen, DATEDIFF(Now(),firstseen), accountjoindate, DATEDIFF(Now(),accountjoindate) FROM [format_table_name("player")] WHERE ckey = '[sql_ckey]'") + var/datum/db_query/query_get_client_age = SSdbcore.NewQuery( + "SELECT firstseen, DATEDIFF(Now(),firstseen), accountjoindate, DATEDIFF(Now(),accountjoindate) FROM [format_table_name("player")] WHERE ckey = :ckey", + list("ckey" = ckey) + ) if(!query_get_client_age.Execute()) qdel(query_get_client_age) return @@ -618,11 +635,14 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( account_join_date = query_get_client_age.item[3] account_age = text2num(query_get_client_age.item[4]) if(!account_age) - account_join_date = sanitizeSQL(findJoinDate()) + account_join_date = findJoinDate() if(!account_join_date) account_age = -1 else - var/datum/DBQuery/query_datediff = SSdbcore.NewQuery("SELECT DATEDIFF(Now(),'[account_join_date]')") + var/datum/db_query/query_datediff = SSdbcore.NewQuery( + "SELECT DATEDIFF(Now(), :account_join_date)", + list("account_join_date" = account_join_date) + ) if(!query_datediff.Execute()) qdel(query_datediff) return @@ -631,14 +651,20 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( qdel(query_datediff) qdel(query_get_client_age) if(!new_player) - var/datum/DBQuery/query_log_player = SSdbcore.NewQuery("UPDATE [format_table_name("player")] SET lastseen = Now(), lastseen_round_id = '[GLOB.round_id]', ip = INET_ATON('[sql_ip]'), computerid = '[sql_computerid]', lastadminrank = '[sql_admin_rank]', accountjoindate = [account_join_date ? "'[account_join_date]'" : "NULL"] WHERE ckey = '[sql_ckey]'") + var/datum/db_query/query_log_player = SSdbcore.NewQuery( + "UPDATE [format_table_name("player")] SET lastseen = Now(), lastseen_round_id = :round_id, ip = INET_ATON(:ip), computerid = :computerid, lastadminrank = :admin_rank, accountjoindate = :account_join_date WHERE ckey = :ckey", + list("round_id" = GLOB.round_id, "ip" = address, "computerid" = computer_id, "admin_rank" = admin_rank, "account_join_date" = account_join_date || null, "ckey" = ckey) + ) if(!query_log_player.Execute()) qdel(query_log_player) return qdel(query_log_player) if(!account_join_date) account_join_date = "Error" - var/datum/DBQuery/query_log_connection = SSdbcore.NewQuery("INSERT INTO `[format_table_name("connection_log")]` (`id`,`datetime`,`server_ip`,`server_port`,`round_id`,`ckey`,`ip`,`computerid`) VALUES(null,Now(),INET_ATON(IF('[world.internet_address]' LIKE '', '0', '[world.internet_address]')),'[world.port]','[GLOB.round_id]','[sql_ckey]',INET_ATON('[sql_ip]'),'[sql_computerid]')") + var/datum/db_query/query_log_connection = SSdbcore.NewQuery({" + INSERT INTO `[format_table_name("connection_log")]` (`id`,`datetime`,`server_ip`,`server_port`,`round_id`,`ckey`,`ip`,`computerid`) + VALUES(null,Now(),INET_ATON(:internet_address),:port,:round_id,:ckey,INET_ATON(:ip),:computerid) + "}, list("internet_address" = world.internet_address || "0", "port" = world.port, "round_id" = GLOB.round_id, "ckey" = ckey, "ip" = address, "computerid" = computer_id)) query_log_connection.Execute() qdel(query_log_connection) @@ -662,9 +688,11 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( CRASH("Age check regex failed for [src.ckey]") /client/proc/validate_key_in_db() - var/sql_ckey = sanitizeSQL(ckey) var/sql_key - var/datum/DBQuery/query_check_byond_key = SSdbcore.NewQuery("SELECT byond_key FROM [format_table_name("player")] WHERE ckey = '[sql_ckey]'") + var/datum/db_query/query_check_byond_key = SSdbcore.NewQuery( + "SELECT byond_key FROM [format_table_name("player")] WHERE ckey = :ckey", + list("ckey" = ckey) + ) if(!query_check_byond_key.Execute()) qdel(query_check_byond_key) return @@ -680,8 +708,11 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( if(F) var/regex/R = regex("\\tkey = \"(.+)\"") if(R.Find(F)) - var/web_key = sanitizeSQL(R.group[1]) - var/datum/DBQuery/query_update_byond_key = SSdbcore.NewQuery("UPDATE [format_table_name("player")] SET byond_key = '[web_key]' WHERE ckey = '[sql_ckey]'") + var/web_key = R.group[1] + var/datum/db_query/query_update_byond_key = SSdbcore.NewQuery( + "UPDATE [format_table_name("player")] SET byond_key = :byond_key WHERE ckey = :ckey", + list("byond_key" = web_key, "ckey" = ckey) + ) query_update_byond_key.Execute() qdel(query_update_byond_key) else @@ -698,8 +729,10 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( var/static/tokens = list() var/static/cidcheck_failedckeys = list() //to avoid spamming the admins if the same guy keeps trying. var/static/cidcheck_spoofckeys = list() - var/sql_ckey = sanitizeSQL(ckey) - var/datum/DBQuery/query_cidcheck = SSdbcore.NewQuery("SELECT computerid FROM [format_table_name("player")] WHERE ckey = '[sql_ckey]'") + var/datum/db_query/query_cidcheck = SSdbcore.NewQuery( + "SELECT computerid FROM [format_table_name("player")] WHERE ckey = :ckey", + list("ckey" = ckey) + ) query_cidcheck.Execute() var/lastcid @@ -718,7 +751,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( sleep(15 SECONDS) //Longer sleep here since this would trigger if a client tries to reconnect manually because the inital reconnect failed - //we sleep after telling the client to reconnect, so if we still exist something is up + //we sleep after telling the client to reconnect, so if we still exist something is up log_access("Forced disconnect: [key] [computer_id] [address] - CID randomizer check") qdel(src) @@ -732,7 +765,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( if (!cidcheck_failedckeys[ckey]) message_admins("[key_name(src)] has been detected as using a cid randomizer. Connection rejected.") - send2irc_adminless_only("CidRandomizer", "[key_name(src)] has been detected as using a cid randomizer. Connection rejected.") + send2tgs_adminless_only("CidRandomizer", "[key_name(src)] has been detected as using a cid randomizer. Connection rejected.") cidcheck_failedckeys[ckey] = TRUE note_randomizer_user() @@ -743,7 +776,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( else if (cidcheck_failedckeys[ckey]) message_admins("[key_name_admin(src)] has been allowed to connect after showing they removed their cid randomizer") - send2irc_adminless_only("CidRandomizer", "[key_name(src)] has been allowed to connect after showing they removed their cid randomizer.") + send2tgs_adminless_only("CidRandomizer", "[key_name(src)] has been allowed to connect after showing they removed their cid randomizer.") cidcheck_failedckeys -= ckey if (cidcheck_spoofckeys[ckey]) message_admins("[key_name_admin(src)] has been allowed to connect after appearing to have attempted to spoof a cid randomizer check because it appears they aren't spoofing one this time") @@ -774,10 +807,11 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( add_system_note("CID-Error", "Detected as using a cid randomizer.") /client/proc/add_system_note(system_ckey, message) - var/sql_system_ckey = sanitizeSQL(system_ckey) - var/sql_ckey = sanitizeSQL(ckey) //check to see if we noted them in the last day. - var/datum/DBQuery/query_get_notes = SSdbcore.NewQuery("SELECT id FROM [format_table_name("messages")] WHERE type = 'note' AND targetckey = '[sql_ckey]' AND adminckey = '[sql_system_ckey]' AND timestamp + INTERVAL 1 DAY < NOW() AND deleted = 0 AND expire_timestamp > NOW()") + var/datum/db_query/query_get_notes = SSdbcore.NewQuery( + "SELECT id FROM [format_table_name("messages")] WHERE type = 'note' AND targetckey = :targetckey AND adminckey = :adminckey AND timestamp + INTERVAL 1 DAY < NOW() AND deleted = 0 AND (expire_timestamp > NOW() OR expire_timestamp IS NULL)", + list("targetckey" = ckey, "adminckey" = system_ckey) + ) if(!query_get_notes.Execute()) qdel(query_get_notes) return @@ -786,7 +820,10 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( return qdel(query_get_notes) //regardless of above, make sure their last note is not from us, as no point in repeating the same note over and over. - query_get_notes = SSdbcore.NewQuery("SELECT adminckey FROM [format_table_name("messages")] WHERE targetckey = '[sql_ckey]' AND deleted = 0 AND expire_timestamp > NOW() ORDER BY timestamp DESC LIMIT 1") + query_get_notes = SSdbcore.NewQuery( + "SELECT adminckey FROM [format_table_name("messages")] WHERE targetckey = :targetckey AND deleted = 0 AND (expire_timestamp > NOW() OR expire_timestamp IS NULL) ORDER BY timestamp DESC LIMIT 1", + list("targetckey" = ckey) + ) if(!query_get_notes.Execute()) qdel(query_get_notes) return diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index e97f6dc3f4..0e7fda80b1 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -1333,7 +1333,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) if(href_list["jobbancheck"]) var/job = sanitizeSQL(href_list["jobbancheck"]) var/sql_ckey = sanitizeSQL(user.ckey) - var/datum/DBQuery/query_get_jobban = SSdbcore.NewQuery("SELECT reason, bantime, duration, expiration_time, 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 ckey = '[sql_ckey]' AND (bantype = 'JOB_PERMABAN' OR (bantype = 'JOB_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned) AND job = '[job]'") + var/datum/db_query/query_get_jobban = SSdbcore.NewQuery("SELECT reason, bantime, duration, expiration_time, 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 ckey = '[sql_ckey]' AND (bantype = 'JOB_PERMABAN' OR (bantype = 'JOB_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned) AND job = '[job]'") if(!query_get_jobban.warn_execute()) qdel(query_get_jobban) return diff --git a/code/modules/jobs/job_exp.dm b/code/modules/jobs/job_exp.dm index 5ff791c5f3..f982d7e96e 100644 --- a/code/modules/jobs/job_exp.dm +++ b/code/modules/jobs/job_exp.dm @@ -156,7 +156,10 @@ GLOBAL_PROTECT(exp_to_update) return -1 if(!SSdbcore.Connect()) return -1 - var/datum/DBQuery/exp_read = SSdbcore.NewQuery("SELECT job, minutes FROM [format_table_name("role_time")] WHERE ckey = '[sanitizeSQL(ckey)]'") + var/datum/db_query/exp_read = SSdbcore.NewQuery( + "SELECT job, minutes FROM [format_table_name("role_time")] WHERE ckey = :ckey", + list("ckey" = ckey) + ) if(!exp_read.Execute(async = TRUE)) qdel(exp_read) return -1 @@ -188,7 +191,10 @@ GLOBAL_PROTECT(exp_to_update) else prefs.db_flags |= newflag - var/datum/DBQuery/flag_update = SSdbcore.NewQuery("UPDATE [format_table_name("player")] SET flags = '[prefs.db_flags]' WHERE ckey='[sanitizeSQL(ckey)]'") + var/datum/db_query/flag_update = SSdbcore.NewQuery( + "UPDATE [format_table_name("player")] SET flags=:flags WHERE ckey=:ckey", + list("flags" = "[prefs.db_flags]", "ckey" = ckey) + ) if(!flag_update.Execute()) qdel(flag_update) @@ -268,7 +274,10 @@ GLOBAL_PROTECT(exp_to_update) if(!SSdbcore.Connect()) return FALSE - var/datum/DBQuery/flags_read = SSdbcore.NewQuery("SELECT flags FROM [format_table_name("player")] WHERE ckey='[ckey]'") + var/datum/db_query/flags_read = SSdbcore.NewQuery( + "SELECT flags FROM [format_table_name("player")] WHERE ckey=:ckey", + list("ckey" = ckey) + ) if(!flags_read.Execute(async = TRUE)) qdel(flags_read) @@ -280,3 +289,4 @@ GLOBAL_PROTECT(exp_to_update) prefs.db_flags = 0 //This PROBABLY won't happen, but better safe than sorry. qdel(flags_read) return TRUE + diff --git a/code/modules/library/lib_machines.dm b/code/modules/library/lib_machines.dm index 3953f5e28c..e751861d6b 100644 --- a/code/modules/library/lib_machines.dm +++ b/code/modules/library/lib_machines.dm @@ -25,12 +25,13 @@ var/title var/category = "Any" var/author - var/SQLquery - clockwork = TRUE //it'd look weird - + var/search_page = 0 + COOLDOWN_DECLARE(library_visitor_topic_cooldown) + clockwork = TRUE + /obj/machinery/computer/libraryconsole/ui_interact(mob/user) . = ..() - var/dat = "" // + var/list/dat = list() // switch(screenstate) if(0) dat += "

Search Settings


" @@ -43,13 +44,48 @@ dat += "ERROR: Unable to contact External Archive. Please contact your system administrator for assistance.
" else if(QDELETED(user)) return - else if(!SQLquery) - dat += "ERROR: Malformed search request. Please contact your system administrator for assistance.
" else dat += "" dat += "" - - var/datum/DBQuery/query_library_list_books = SSdbcore.NewQuery(SQLquery) + var/SQLsearch = "isnull(deleted) AND " + if(category == "Any") + SQLsearch += "author LIKE '%[author]%' AND title LIKE '%[title]%'" + else + SQLsearch += "author LIKE '%[author]%' AND title LIKE '%[title]%' AND category='[category]'" + var/bookcount = 0 + var/booksperpage = 20 + var/datum/db_query/query_library_count_books = SSdbcore.NewQuery({" + SELECT COUNT(id) FROM [format_table_name("library")] + WHERE isnull(deleted) + AND author LIKE CONCAT('%',:author,'%') + AND title LIKE CONCAT('%',:title,'%') + AND (:category = 'Any' OR category = :category) + "}, list("author" = author, "title" = title, "category" = category)) + if(!query_library_count_books.warn_execute()) + qdel(query_library_count_books) + return + if(query_library_count_books.NextRow()) + bookcount = text2num(query_library_count_books.item[1]) + qdel(query_library_count_books) + if(bookcount > booksperpage) + dat += "Page: " + var/pagecount = 1 + var/list/pagelist = list() + while(bookcount > 0) + pagelist += "[pagecount == search_page + 1 ? "\[[pagecount]\]" : "\[[pagecount]\]"]" + bookcount -= booksperpage + pagecount++ + dat += pagelist.Join(" | ") + search_page = text2num(search_page) + var/datum/db_query/query_library_list_books = SSdbcore.NewQuery({" + SELECT author, title, category, id + FROM [format_table_name("library")] + WHERE isnull(deleted) + AND author LIKE CONCAT('%',:author,'%') + AND title LIKE CONCAT('%',:title,'%') + AND (:category = 'Any' OR category = :category) + LIMIT :skip, :take + "}, list("author" = author, "title" = title, "category" = category, "skip" = booksperpage * search_page, "take" = booksperpage)) if(!query_library_list_books.Execute()) dat += "ERROR: Unable to retrieve book listings. Please contact your system administrator for assistance.
" else @@ -65,12 +101,15 @@ dat += "
AUTHORTITLECATEGORYSS13BN

" dat += "\[Go Back\]
" var/datum/browser/popup = new(user, "publiclibrary", name, 600, 400) - popup.set_content(dat) + popup.set_content(jointext(dat, "")) popup.open() /obj/machinery/computer/libraryconsole/Topic(href, href_list) + if(!COOLDOWN_FINISHED(src, library_visitor_topic_cooldown)) + return + COOLDOWN_START(src, library_visitor_topic_cooldown, 1 SECONDS) . = ..() - if(..()) + if(.) usr << browse(null, "window=publiclibrary") onclose(usr, "publiclibrary") return @@ -81,29 +120,24 @@ title = sanitize(newtitle) else title = null - title = sanitizeSQL(title) if(href_list["setcategory"]) var/newcategory = input("Choose a category to search for:") in list("Any", "Fiction", "Non-Fiction", "Adult", "Reference", "Religion") if(newcategory) category = sanitize(newcategory) else category = "Any" - category = sanitizeSQL(category) if(href_list["setauthor"]) var/newauthor = input("Enter an author to search for:") as text|null if(newauthor) author = sanitize(newauthor) else author = null - author = sanitizeSQL(author) if(href_list["search"]) - SQLquery = "SELECT author, title, category, id FROM [format_table_name("library")] WHERE isnull(deleted) AND " - if(category == "Any") - SQLquery += "author LIKE '%[author]%' AND title LIKE '%[title]%'" - else - SQLquery += "author LIKE '%[author]%' AND title LIKE '%[title]%' AND category='[category]'" screenstate = 1 + if(href_list["bookpagecount"]) + search_page = text2num(href_list["bookpagecount"]) + if(href_list["back"]) screenstate = 0 @@ -120,39 +154,6 @@ var/getdate var/duedate -/* - * Cachedbook datum - */ -/datum/cachedbook // Datum used to cache the SQL DB books locally in order to achieve a performance gain. - var/id - var/title - var/author - var/category - -GLOBAL_LIST(cachedbooks) // List of our cached book datums - - -/proc/load_library_db_to_cache() - if(GLOB.cachedbooks) - return - if(!SSdbcore.Connect()) - return - GLOB.cachedbooks = list() - var/datum/DBQuery/query_library_cache = SSdbcore.NewQuery("SELECT id, author, title, category FROM [format_table_name("library")] WHERE isnull(deleted)") - if(!query_library_cache.Execute()) - qdel(query_library_cache) - return - while(query_library_cache.NextRow()) - var/datum/cachedbook/newbook = new() - newbook.id = query_library_cache.item[1] - newbook.author = query_library_cache.item[2] - newbook.title = query_library_cache.item[3] - newbook.category = query_library_cache.item[4] - GLOB.cachedbooks += newbook - qdel(query_library_cache) - - - #define PRINTER_COOLDOWN 60 /* @@ -165,11 +166,15 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums /obj/machinery/computer/libraryconsole/bookmanagement name = "book inventory management console" desc = "Librarian's command station." - screenstate = 0 // 0 - Main Menu, 1 - Inventory, 2 - Checked Out, 3 - Check Out a Book verb_say = "beeps" verb_ask = "beeps" verb_exclaim = "beeps" pass_flags = PASSTABLE + + circuit = /obj/item/circuitboard/computer/libraryconsole + + var/screenstate = 0 // 0 - Main Menu, 1 - Inventory, 2 - Checked Out, 3 - Check Out a Book + var/arcanecheckout = 0 var/buffer_book var/buffer_mob @@ -178,33 +183,17 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums var/list/inventory = list() var/checkoutperiod = 5 // In minutes var/obj/machinery/libraryscanner/scanner // Book scanner that will be used when uploading books to the Archive - var/list/libcomp_menu var/page = 1 //current page of the external archives - var/cooldown = 0 + var/printer_cooldown = 0 + COOLDOWN_DECLARE(library_console_topic_cooldown) -/obj/machinery/computer/libraryconsole/bookmanagement/proc/build_library_menu() - if(libcomp_menu) - return - load_library_db_to_cache() - if(!GLOB.cachedbooks) - return - libcomp_menu = list("") - - for(var/i in 1 to GLOB.cachedbooks.len) - var/datum/cachedbook/C = GLOB.cachedbooks[i] - var/page = round(i/250)+1 - if (libcomp_menu.len < page) - libcomp_menu.len = page - libcomp_menu[page] = "" - libcomp_menu[page] += "[C.author][C.title][C.category]\[Order\]\n" - -/obj/machinery/computer/libraryconsole/bookmanagement/Initialize() +/obj/machinery/computer/bookmanagement/Initialize() . = ..() if(circuit) circuit.name = "Book Inventory Management Console (Machine Board)" - circuit.build_path = /obj/machinery/computer/libraryconsole/bookmanagement + circuit.build_path = /obj/machinery/computer/bookmanagement -/obj/machinery/computer/libraryconsole/bookmanagement/ui_interact(mob/user) +/obj/machinery/computer/bookmanagement/ui_interact(mob/user) . = ..() var/dat = "" // switch(screenstate) @@ -258,17 +247,37 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums dat += "(Return to main menu)
" if(4) dat += "

External Archive

" - build_library_menu() - - if(!GLOB.cachedbooks) + if(!SSdbcore.Connect()) dat += "ERROR: Unable to contact External Archive. Please contact your system administrator for assistance." else + var/booksperpage = 50 + var/pagecount + var/datum/db_query/query_library_count_books = SSdbcore.NewQuery("SELECT COUNT(id) FROM [format_table_name("library")] WHERE isnull(deleted)") + if(!query_library_count_books.Execute()) + qdel(query_library_count_books) + return + if(query_library_count_books.NextRow()) + pagecount = CEILING(text2num(query_library_count_books.item[1]) / booksperpage, 1) + qdel(query_library_count_books) + var/list/booklist = list() + var/datum/db_query/query_library_get_books = SSdbcore.NewQuery({" + SELECT id, author, title, category + FROM [format_table_name("library")] + WHERE isnull(deleted) + LIMIT :skip, :take + "}, list("skip" = booksperpage * (page - 1), "take" = booksperpage)) + if(!query_library_get_books.Execute()) + qdel(query_library_get_books) + return + while(query_library_get_books.NextRow()) + booklist += "[query_library_get_books.item[2]][query_library_get_books.item[3]][query_library_get_books.item[4]]\[Order\]\n" dat += "(Order book by SS13BN)

" dat += "" dat += "" - dat += libcomp_menu[clamp(page,1,libcomp_menu.len)] - dat += "" + dat += jointext(booklist, "") + dat += "" dat += "
AUTHORTITLECATEGORY
<<<< >>>>
<<<< >>>>
" + qdel(query_library_get_books) dat += "
(Return to main menu)
" if(5) dat += "

Upload a New Title

" @@ -315,39 +324,33 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums popup.set_content(dat) popup.open() -/obj/machinery/computer/libraryconsole/bookmanagement/proc/findscanner(viewrange) +/obj/machinery/computer/bookmanagement/proc/findscanner(viewrange) for(var/obj/machinery/libraryscanner/S in range(viewrange, get_turf(src))) return S return null -/obj/machinery/computer/libraryconsole/bookmanagement/proc/print_forbidden_lore(mob/user) - var/spook = pick("blood", "brass") - var/turf/T = get_turf(src) - if(spook == "blood") - new /obj/item/melee/cultblade/dagger(T) - else - new /obj/item/clockwork/slab(T) +/obj/machinery/computer/bookmanagement/proc/print_forbidden_lore(mob/user) + new /obj/item/melee/cultblade/dagger(get_turf(src)) + to_chat(user, "Your sanity barely endures the seconds spent in the vault's browsing window. The only thing to remind you of this when you stop browsing is a sinister dagger sitting on the desk. You don't even remember where it came from...") + user.visible_message("[user] stares at the blank screen for a few moments, [user.p_their()] expression frozen in fear. When [user.p_they()] finally awaken[user.p_s()] from it, [user.p_they()] look[user.p_s()] a lot older.", 2) - to_chat(user, "Your sanity barely endures the seconds spent in the vault's browsing window. The only thing to remind you of this when you stop browsing is a [spook == "blood" ? "sinister dagger" : "strange metal tablet"] sitting on the desk. You don't even remember where it came from...") - user.visible_message("[user] stares at the blank screen for a few moments, [user.p_their()] expression frozen in fear. When [user.p_they()] finally awaken[user.p_s()] from it, [user.p_they()] look[user.p_s()] a lot older.", 2) - -/obj/machinery/computer/libraryconsole/bookmanagement/attackby(obj/item/W, mob/user, params) +/obj/machinery/computer/bookmanagement/attackby(obj/item/W, mob/user, params) if(istype(W, /obj/item/barcodescanner)) var/obj/item/barcodescanner/scanner = W scanner.computer = src - to_chat(user, "[scanner]'s associated machine has been set to [src].") - audible_message("[src] lets out a low, short blip.") + to_chat(user, "[scanner]'s associated machine has been set to [src].") + audible_message("[src] lets out a low, short blip.") else return ..() -/obj/machinery/computer/libraryconsole/bookmanagement/emag_act(mob/user) - . = ..() - if(!density || obj_flags & EMAGGED) - return - obj_flags |= EMAGGED - return TRUE +/obj/machinery/computer/bookmanagement/emag_act(mob/user) + if(density && !(obj_flags & EMAGGED)) + obj_flags |= EMAGGED -/obj/machinery/computer/libraryconsole/bookmanagement/Topic(href, href_list) +/obj/machinery/computer/bookmanagement/Topic(href, href_list) + if(!COOLDOWN_FINISHED(src, library_console_topic_cooldown)) + return + COOLDOWN_START(src, library_console_topic_cooldown, 1 SECONDS) if(..()) usr << browse(null, "window=library") onclose(usr, "library") @@ -385,7 +388,7 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums if(checkoutperiod < 1) checkoutperiod = 1 if(href_list["editbook"]) - buffer_book = stripped_input(usr, "Enter the book's title:") + buffer_book = stripped_input(usr, "Enter the book's title:", max_length = 45) if(href_list["editmob"]) buffer_mob = stripped_input(usr, "Enter the recipient's name:", max_length = MAX_NAME_LEN) if(href_list["checkout"]) @@ -404,7 +407,7 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums if(b && istype(b)) inventory.Remove(b) if(href_list["setauthor"]) - var/newauthor = stripped_input(usr, "Enter the author's name: ") + var/newauthor = stripped_input(usr, "Enter the author's name: ", max_length = 45) if(newauthor) scanner.cache.author = newauthor if(href_list["setcategory"]) @@ -419,14 +422,11 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums if (!SSdbcore.Connect()) alert("Connection to Archive has been severed. Aborting.") else - - var/sqltitle = sanitizeSQL(scanner.cache.name) - var/sqlauthor = sanitizeSQL(scanner.cache.author) - var/sqlcontent = sanitizeSQL(scanner.cache.dat) - var/sqlcategory = sanitizeSQL(upload_category) - var/sqlckey = sanitizeSQL(usr.ckey) var/msg = "[key_name(usr)] has uploaded the book titled [scanner.cache.name], [length(scanner.cache.dat)] signs" - var/datum/DBQuery/query_library_upload = SSdbcore.NewQuery("INSERT INTO [format_table_name("library")] (author, title, content, category, ckey, datetime, round_id_created) VALUES ('[sqlauthor]', '[sqltitle]', '[sqlcontent]', '[sqlcategory]', '[sqlckey]', Now(), '[GLOB.round_id]')") + var/datum/db_query/query_library_upload = SSdbcore.NewQuery({" + INSERT INTO [format_table_name("library")] (author, title, content, category, ckey, datetime, round_id_created) + VALUES (:author, :title, :content, :category, :ckey, Now(), :round_id) + "}, list("title" = scanner.cache.name, "author" = scanner.cache.author, "content" = scanner.cache.dat, "category" = upload_category, "ckey" = usr.ckey, "round_id" = GLOB.round_id)) if(!query_library_upload.Execute()) qdel(query_library_upload) alert("Database error encountered uploading to Archive") @@ -439,7 +439,7 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums if(!GLOB.news_network) alert("No news network found on station. Aborting.") var/channelexists = 0 - for(var/datum/news/feed_channel/FC in GLOB.news_network.network_channels) + for(var/datum/newscaster/feed_channel/FC in GLOB.news_network.network_channels) if(FC.channel_name == "Nanotrasen Book Club") channelexists = 1 break @@ -448,7 +448,7 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums GLOB.news_network.SubmitArticle(scanner.cache.dat, "[scanner.cache.name]", "Nanotrasen Book Club", null) alert("Upload complete. Your uploaded title is now available on station newscasters.") if(href_list["orderbyid"]) - if(cooldown > world.time) + if(printer_cooldown > world.time) say("Printer unavailable. Please allow a short time before attempting to print.") else var/orderid = input("Enter your order:") as num|null @@ -457,14 +457,17 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums href_list["targetid"] = num2text(orderid) if(href_list["targetid"]) - var/sqlid = sanitizeSQL(href_list["targetid"]) + var/id = href_list["targetid"] if (!SSdbcore.Connect()) alert("Connection to Archive has been severed. Aborting.") - if(cooldown > world.time) + if(printer_cooldown > world.time) say("Printer unavailable. Please allow a short time before attempting to print.") else - cooldown = world.time + PRINTER_COOLDOWN - var/datum/DBQuery/query_library_print = SSdbcore.NewQuery("SELECT * FROM [format_table_name("library")] WHERE id=[sqlid] AND isnull(deleted)") + printer_cooldown = world.time + PRINTER_COOLDOWN + var/datum/db_query/query_library_print = SSdbcore.NewQuery( + "SELECT * FROM [format_table_name("library")] WHERE id=:id AND isnull(deleted)", + list("id" = id) + ) if(!query_library_print.Execute()) qdel(query_library_print) say("PRINTER ERROR! Failed to print document (0x0000000F)") @@ -480,24 +483,24 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums B.author = author B.dat = content B.icon_state = "book[rand(1,8)]" - visible_message("[src]'s printer hums as it produces a completely bound book. How did it do that?") + visible_message("[src]'s printer hums as it produces a completely bound book. How did it do that?") break qdel(query_library_print) if(href_list["printbible"]) - if(cooldown < world.time) + if(printer_cooldown < world.time) var/obj/item/storage/book/bible/B = new /obj/item/storage/book/bible(src.loc) - if(GLOB.bible_icon_state && GLOB.bible_item_state) + if(GLOB.bible_icon_state && GLOB.bible_inhand_icon_state) B.icon_state = GLOB.bible_icon_state - B.item_state = GLOB.bible_item_state + B.inhand_icon_state = GLOB.bible_inhand_icon_state B.name = GLOB.bible_name B.deity_name = GLOB.deity - cooldown = world.time + PRINTER_COOLDOWN + printer_cooldown = world.time + PRINTER_COOLDOWN else say("Printer currently unavailable, please wait a moment.") if(href_list["printposter"]) - if(cooldown < world.time) + if(printer_cooldown < world.time) new /obj/item/poster/random_official(src.loc) - cooldown = world.time + PRINTER_COOLDOWN + printer_cooldown = world.time + PRINTER_COOLDOWN else say("Printer currently unavailable, please wait a moment.") add_fingerprint(usr) @@ -521,7 +524,10 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums else return ..() -/obj/machinery/libraryscanner/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) +/obj/machinery/libraryscanner/attack_hand(mob/user) + . = ..() + if(.) + return usr.set_machine(src) var/dat = "" // if(cache) @@ -577,21 +583,21 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums return ..() /obj/machinery/bookbinder/proc/bind_book(mob/user, obj/item/paper/P) - if(stat) + if(machine_stat) return if(busy) to_chat(user, "The book binder is busy. Please wait for completion of previous operation.") return if(!user.transferItemToLoc(P, src)) return - user.visible_message("[user] loads some paper into [src].", "You load some paper into [src].") - audible_message("[src] begins to hum as it warms up its printing drums.") + user.visible_message("[user] loads some paper into [src].", "You load some paper into [src].") + audible_message("[src] begins to hum as it warms up its printing drums.") busy = TRUE sleep(rand(200,400)) busy = FALSE if(P) - if(!stat) - visible_message("[src] whirs as it prints and binds a new book.") + if(!machine_stat) + visible_message("[src] whirs as it prints and binds a new book.") var/obj/item/book/B = new(src.loc) B.dat = P.info B.name = "Print Job #" + "[rand(100, 999)]"