Async SQL + SSdbcore (#15007)

* Initial Commit - Async SQL

* First batch of queries

* More progress

* Nukes DB Polls

* More work

* oops

* One push

* Notes work now

* Ok these work

* Watchlist done

* Async Bans!

* Async Permissions

* Async client procs

* I officially hate preference datums

* Also these

* Async Custom Items

* Async Karma

* Async Library

* Async TOS

* Cleans out the old SQL code

* CI Sanity

* Apparently MySQL doesnt support this

* What about this

* Maybe this

* Review pass 1

* This too

* Fixes job ban loading

* Fix undeleted queries

* Prevents sensitive queries being logged

* Documentation + tweaks

* Adds a verb to force reconnect the DB

* More review tweaks

* Farie tweaks

* Fixes this
This commit is contained in:
AffectedArc07
2020-12-16 15:46:25 -05:00
committed by GitHub
parent e003d552b0
commit 2bad70717c
55 changed files with 2251 additions and 2445 deletions
+19 -11
View File
@@ -1,12 +1,6 @@
//Blocks an attempt to connect before even creating our client datum thing.
/world/IsBanned(key, address, computer_id, type, check_ipintel = TRUE)
if(!config.ban_legacy_system)
if(address)
address = sanitizeSQL(address)
if(computer_id)
computer_id = sanitizeSQL(computer_id)
if(!key || !address || !computer_id)
log_adminwarn("Failed Login (invalid data): [key] [address]-[computer_id]")
return list("reason"="invalid login data", "desc"="Error: Could not check ban status, please try again. Error message: Your computer provided invalid or blank information to the server on connection (BYOND Username, IP, and Computer ID). Provided information for reference: Username: '[key]' IP: '[address]' Computer ID: '[computer_id]'. If you continue to get this error, please restart byond or contact byond support.")
@@ -59,21 +53,33 @@
else
var/ckeytext = ckey(key)
if(!establish_db_connection())
if(!SSdbcore.IsConnected())
log_world("Ban database connection failure. Key [ckeytext] not checked")
return
var/list/sql_query_params = list(
"ckeytext" = ckeytext
)
var/ipquery = ""
var/cidquery = ""
if(address)
ipquery = " OR ip = '[address]' "
ipquery = " OR ip=:ip "
sql_query_params["ip"] = address
if(computer_id)
cidquery = " OR computerid = '[computer_id]' "
cidquery = " OR computerid=:cid "
sql_query_params["cid"] = computer_id
var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT ckey, ip, computerid, a_ckey, reason, expiration_time, duration, bantime, bantype FROM [format_table_name("ban")] WHERE (ckey = '[ckeytext]' [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 = SSdbcore.NewQuery({"
SELECT ckey, ip, computerid, a_ckey, reason, expiration_time, duration, bantime, bantype FROM [format_table_name("ban")]
WHERE (ckey=:ckeytext [ipquery] [cidquery]) AND (bantype = 'PERMABAN' OR bantype = 'ADMIN_PERMABAN'
OR ((bantype = 'TEMPBAN' OR bantype = 'ADMIN_TEMPBAN') AND expiration_time > Now())) AND isnull(unbanned)"}, sql_query_params)
query.Execute()
if(!query.warn_execute())
message_admins("Failed to do a DB ban check for [ckeytext]. You have been warned.")
qdel(query)
return
while(query.NextRow())
var/pckey = query.item[1]
@@ -113,7 +119,9 @@
. = list("reason"="[bantype]", "desc"="[desc]")
log_adminwarn("Failed Login: [key] [computer_id] [address] - Banned [.["reason"]]")
qdel(query)
return .
qdel(query)
. = ..() //default pager ban stuff
if(.)
+95 -50
View File
@@ -3,7 +3,7 @@
set category = "Server"
if(!check_rights(R_SERVER))
return
if(!GLOB.dbcon.IsConnected())
if(!SSdbcore.IsConnected())
to_chat(src, "<span class='danger'>Failed to establish database connection.</span>")
return
var/memotask = input(usr,"Choose task.","Memo") in list("Show","Write","Edit","Remove")
@@ -16,78 +16,113 @@
return
if(!task)
return
if(!GLOB.dbcon.IsConnected())
if(!SSdbcore.IsConnected())
to_chat(src, "<span class='danger'>Failed to establish database connection.</span>")
return
var/sql_ckey = sanitizeSQL(src.ckey)
switch(task)
if("Write")
var/DBQuery/query_memocheck = GLOB.dbcon.NewQuery("SELECT ckey FROM [format_table_name("memo")] WHERE ckey = '[sql_ckey]'")
if(!query_memocheck.Execute())
var/err = query_memocheck.ErrorMsg()
log_game("SQL ERROR obtaining ckey from memo table. Error : \[[err]\]\n")
var/datum/db_query/query_memocheck = SSdbcore.NewQuery(
"SELECT ckey FROM [format_table_name("memo")] WHERE ckey=:ckey",
list("ckey" = ckey)
)
if(!query_memocheck.warn_execute())
qdel(query_memocheck)
return
if(query_memocheck.NextRow())
to_chat(src, "You already have set a memo.")
qdel(query_memocheck)
return
var/memotext = input(src,"Write your Memo","Memo") as message
qdel(query_memocheck)
var/memotext = input(src, "Write your Memo", "Memo") as message
if(!memotext)
return
memotext = sanitizeSQL(memotext)
var/timestamp = SQLtime()
var/DBQuery/query_memoadd = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("memo")] (ckey, memotext, timestamp) VALUES ('[sql_ckey]', '[memotext]', '[timestamp]')")
if(!query_memoadd.Execute())
var/err = query_memoadd.ErrorMsg()
log_game("SQL ERROR adding new memo. Error : \[[err]\]\n")
var/datum/db_query/query_memoadd = SSdbcore.NewQuery(
"INSERT INTO [format_table_name("memo")] (ckey, memotext, timestamp) VALUES (:ckey, :memotext, NOW())",
list(
"ckey" = ckey,
"memotext" = memotext
)
)
if(!query_memoadd.warn_execute())
qdel(query_memoadd)
return
log_admin("[key_name(src)] has set a memo: [memotext]")
message_admins("[key_name_admin(src)] has set a memo:<br>[memotext]")
qdel(query_memoadd)
if("Edit")
var/DBQuery/query_memolist = GLOB.dbcon.NewQuery("SELECT ckey FROM [format_table_name("memo")]")
if(!query_memolist.Execute())
var/err = query_memolist.ErrorMsg()
log_game("SQL ERROR obtaining ckey from memo table. Error : \[[err]\]\n")
var/datum/db_query/query_memolist = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("memo")]")
if(!query_memolist.warn_execute())
qdel(query_memolist)
return
var/list/memolist = list()
while(query_memolist.NextRow())
var/lkey = query_memolist.item[1]
memolist += "[lkey]"
if(!memolist.len)
qdel(query_memolist)
if(!length(memolist))
to_chat(src, "No memos found in database.")
return
var/target_ckey = input(src, "Select whose memo to edit", "Select memo") as null|anything in memolist
if(!target_ckey)
return
var/target_sql_ckey = sanitizeSQL(target_ckey)
var/DBQuery/query_memofind = GLOB.dbcon.NewQuery("SELECT memotext FROM [format_table_name("memo")] WHERE ckey = '[target_sql_ckey]'")
if(!query_memofind.Execute())
var/err = query_memofind.ErrorMsg()
log_game("SQL ERROR obtaining memotext from memo table. Error : \[[err]\]\n")
var/datum/db_query/query_memofind = SSdbcore.NewQuery(
"SELECT memotext FROM [format_table_name("memo")] WHERE ckey=:ckey",
list("ckey" = target_ckey)
)
if(!query_memofind.warn_execute())
qdel(query_memofind)
return
if(query_memofind.NextRow())
var/old_memo = query_memofind.item[1]
var/new_memo = input("Input new memo", "New Memo", "[old_memo]", null) as message
if(!new_memo)
qdel(query_memofind)
return
new_memo = sanitizeSQL(new_memo)
var/edit_text = "Edited by [sql_ckey] on [SQLtime()] from<br>[old_memo]<br>to<br>[new_memo]<hr>"
edit_text = sanitizeSQL(edit_text)
var/DBQuery/update_query = GLOB.dbcon.NewQuery("UPDATE [format_table_name("memo")] SET memotext = '[new_memo]', last_editor = '[sql_ckey]', edits = CONCAT(IFNULL(edits,''),'[edit_text]') WHERE ckey = '[target_sql_ckey]'")
if(!update_query.Execute())
var/err = update_query.ErrorMsg()
log_game("SQL ERROR editing memo. Error : \[[err]\]\n")
var/edit_text = "Edited by [target_ckey] on [SQLtime()] from<br>[old_memo]<br>to<br>[new_memo]<hr>"
var/datum/db_query/update_query = SSdbcore.NewQuery(
"UPDATE [format_table_name("memo")] SET memotext=:newmemo, last_editor=:lasteditor, edits=CONCAT(IFNULL(edits,''),:edittext) WHERE ckey=:targetckey",
list(
"newmemo" = new_memo,
"lasteditor" = ckey,
"edittext" = edit_text,
"targetckey" = target_ckey
)
)
if(!update_query.warn_execute())
qdel(update_query)
qdel(query_memofind)
return
if(target_sql_ckey == sql_ckey)
if(target_ckey == ckey)
log_admin("[key_name(src)] has edited their memo from \"[old_memo]\" to \"[new_memo]\"")
message_admins("[key_name_admin(src)] has edited their memo from \"[old_memo]]\" to \"[new_memo]\"")
else
log_admin("[key_name(src)] has edited [target_sql_ckey]'s memo from \"[old_memo]\" to \"[new_memo]\"")
message_admins("[key_name_admin(src)] has edited [target_sql_ckey]'s memo from \"[old_memo]\" to \"[new_memo]\"")
log_admin("[key_name(src)] has edited [target_ckey]'s memo from \"[old_memo]\" to \"[new_memo]\"")
message_admins("[key_name_admin(src)] has edited [target_ckey]'s memo from \"[old_memo]\" to \"[new_memo]\"")
qdel(update_query)
qdel(query_memofind)
if("Show")
var/DBQuery/query_memoshow = GLOB.dbcon.NewQuery("SELECT ckey, memotext, timestamp, last_editor FROM [format_table_name("memo")]")
if(!query_memoshow.Execute())
var/err = query_memoshow.ErrorMsg()
log_game("SQL ERROR obtaining ckey, memotext, timestamp, last_editor from memo table. Error : \[[err]\]\n")
var/datum/db_query/query_memoshow = SSdbcore.NewQuery("SELECT ckey, memotext, timestamp, last_editor FROM [format_table_name("memo")]")
if(!query_memoshow.warn_execute())
qdel(query_memoshow)
return
var/output = null
while(query_memoshow.NextRow())
@@ -103,31 +138,41 @@
to_chat(src, output)
else if(!silent)
to_chat(src, "No memos found in database.")
qdel(query_memoshow)
if("Remove")
var/DBQuery/query_memodellist = GLOB.dbcon.NewQuery("SELECT ckey FROM [format_table_name("memo")]")
if(!query_memodellist.Execute())
var/err = query_memodellist.ErrorMsg()
log_game("SQL ERROR obtaining ckey from memo table. Error : \[[err]\]\n")
var/datum/db_query/query_memodellist = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("memo")]")
if(!query_memodellist.warn_execute())
qdel(query_memodellist)
return
var/list/memolist = list()
while(query_memodellist.NextRow())
var/ckey = query_memodellist.item[1]
memolist += "[ckey]"
qdel(query_memodellist)
if(!memolist.len)
to_chat(src, "No memos found in database.")
return
var/target_ckey = input(src, "Select whose memo to delete", "Select memo") as null|anything in memolist
if(!target_ckey)
return
var/target_sql_ckey = sanitizeSQL(target_ckey)
var/DBQuery/query_memodel = GLOB.dbcon.NewQuery("DELETE FROM [format_table_name("memo")] WHERE ckey = '[target_sql_ckey]'")
if(!query_memodel.Execute())
var/err = query_memodel.ErrorMsg()
log_game("SQL ERROR removing memo. Error : \[[err]\]\n")
var/datum/db_query/query_memodel = SSdbcore.NewQuery(
"DELETE FROM [format_table_name("memo")] WHERE ckey=:ckey",
list("ckey" = target_ckey)
)
if(!query_memodel.warn_execute())
qdel(query_memodel)
return
if(target_sql_ckey == sql_ckey)
qdel(query_memodel)
if(target_ckey == ckey)
log_admin("[key_name(src)] has removed their memo.")
message_admins("[key_name_admin(src)] has removed their memo.")
else
log_admin("[key_name(src)] has removed [target_sql_ckey]'s memo.")
message_admins("[key_name_admin(src)] has removed [target_sql_ckey]'s memo.")
log_admin("[key_name(src)] has removed [target_ckey]'s memo.")
message_admins("[key_name_admin(src)] has removed [target_ckey]'s memo.")
+9 -5
View File
@@ -111,16 +111,17 @@ GLOBAL_PROTECT(admin_ranks) // this shit is being protected for obvious reasons
else
//The current admin system uses SQL
establish_db_connection()
if(!GLOB.dbcon.IsConnected())
if(!SSdbcore.IsConnected())
log_world("Failed to connect to database in load_admins(). Reverting to legacy system.")
config.admin_legacy_system = 1
load_admins()
return
var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT ckey, rank, level, flags FROM [format_table_name("admin")]")
query.Execute()
var/datum/db_query/query = SSdbcore.NewQuery("SELECT ckey, rank, level, flags FROM [format_table_name("admin")]")
if(!query.warn_execute())
qdel(query)
return
while(query.NextRow())
var/ckey = query.item[1]
var/rank = query.item[2]
@@ -135,6 +136,9 @@ GLOBAL_PROTECT(admin_ranks) // this shit is being protected for obvious reasons
//find the client for a ckey if they are connected and associate them with the new admin datum
D.associate(GLOB.directory[ckey])
qdel(query)
if(!GLOB.admin_datums)
log_world("The database query in load_admins() resulted in no admins being added to the list. Reverting to legacy system.")
config.admin_legacy_system = 1
+38 -16
View File
@@ -168,7 +168,8 @@ GLOBAL_LIST_INIT(admin_verbs_debug, list(
/client/proc/jump_to_ruin,
/client/proc/toggle_medal_disable,
/client/proc/uid_log,
/client/proc/visualise_active_turfs
/client/proc/visualise_active_turfs,
/client/proc/reestablish_db_connection
))
GLOBAL_LIST_INIT(admin_verbs_possess, list(
/proc/possess,
@@ -176,7 +177,6 @@ GLOBAL_LIST_INIT(admin_verbs_possess, list(
))
GLOBAL_LIST_INIT(admin_verbs_permissions, list(
/client/proc/edit_admin_permissions,
/client/proc/create_poll,
/client/proc/big_brother
))
GLOBAL_LIST_INIT(admin_verbs_rejuv, list(
@@ -691,15 +691,23 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list(
continue
else
if(!GLOB.dbcon.IsConnected())
message_admins("Warning, MySQL database is not connected.")
if(!SSdbcore.IsConnected())
to_chat(src, "Warning, MYSQL database is not connected.")
return
var/sql_ckey = sanitizeSQL(ckey)
var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT rank FROM [format_table_name("admin")] WHERE ckey = '[sql_ckey]'")
query.Execute()
while(query.NextRow())
rank = ckeyEx(query.item[1])
var/datum/db_query/rank_read = SSdbcore.NewQuery(
"SELECT rank FROM [format_table_name("admin")] WHERE ckey=:ckey",
list("ckey" = ckey)
)
if(!rank_read.warn_execute())
qdel(rank_read)
return FALSE
while(rank_read.NextRow())
rank = ckeyEx(rank_read.item[1])
qdel(rank_read)
if(!D)
if(config.admin_legacy_system)
if(GLOB.admin_ranks[rank] == null)
@@ -709,24 +717,38 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list(
D = new(rank, GLOB.admin_ranks[rank], ckey)
else
var/sql_ckey = sanitizeSQL(ckey)
var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT ckey, rank, flags FROM [format_table_name("admin")] WHERE ckey = '[sql_ckey]'")
query.Execute()
while(query.NextRow())
var/admin_ckey = query.item[1]
var/admin_rank = query.item[2]
var/flags = query.item[3]
if(!SSdbcore.IsConnected())
to_chat(src, "Warning, MYSQL database is not connected.")
return
var/datum/db_query/admin_read = SSdbcore.NewQuery(
"SELECT ckey, rank, flags FROM [format_table_name("admin")] WHERE ckey=:ckey",
list("ckey" = ckey)
)
if(!admin_read.warn_execute())
qdel(admin_read)
return FALSE
while(admin_read.NextRow())
var/admin_ckey = admin_read.item[1]
var/admin_rank = admin_read.item[2]
var/flags = admin_read.item[3]
if(!admin_ckey)
to_chat(src, "Error while re-adminning, ckey [admin_ckey] was not found in the admin database.")
qdel(admin_read)
return
if(admin_rank == "Removed") //This person was de-adminned. They are only in the admin list for archive purposes.
to_chat(src, "Error while re-adminning, ckey [admin_ckey] is not an admin.")
qdel(admin_read)
return
if(istext(flags))
flags = text2num(flags)
D = new(admin_rank, flags, ckey)
qdel(admin_read)
var/client/C = GLOB.directory[ckey]
D.associate(C)
message_admins("[key_name_admin(usr)] re-adminned themselves.")
+11 -6
View File
@@ -39,7 +39,7 @@ DEBUG
appearance_loadbanfile()
*/
// AA 2020-11-25: This entire proc isnt even called. What the actual fuck.
/proc/appearance_loadbanfile()
if(config.ban_legacy_system)
var/savefile/S=new("data/appearance_full.ban")
@@ -51,21 +51,26 @@ DEBUG
GLOB.appearance_keylist=list()
log_admin("appearance_keylist was empty")
else
if(!establish_db_connection())
if(!SSdbcore.IsConnected())
log_world("Database connection failed. Reverting to the legacy ban system.")
config.ban_legacy_system = 1
appearance_loadbanfile()
return
//appearance bans
var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT ckey FROM [format_table_name("ban")] WHERE bantype = 'APPEARANCE_BAN' AND NOT unbanned = 1")
query.Execute()
var/datum/db_query/appearanceban_query = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("ban")] WHERE bantype = 'APPEARANCE_BAN' AND NOT unbanned = 1")
while(query.NextRow())
var/ckey = query.item[1]
if(!appearanceban_query.warn_execute())
qdel(appearanceban_query)
return FALSE
while(appearanceban_query.NextRow())
var/ckey = appearanceban_query.item[1]
GLOB.appearance_keylist.Add("[ckey]")
qdel(appearanceban_query)
/proc/appearance_savebanfile()
var/savefile/S=new("data/appearance_full.ban")
to_chat(S["keys[0]"], GLOB.appearance_keylist)
+37 -19
View File
@@ -59,34 +59,42 @@ GLOBAL_DATUM_INIT(jobban_regex, /regex, regex("(\[\\S]+) - (\[^#]+\[^# ])(?: ##
else
log_runtime(EXCEPTION("Skipping malformed job ban: [s]"))
else
if(!establish_db_connection())
if(!SSdbcore.IsConnected())
log_world("Database connection failed. Reverting to the legacy ban system.")
config.ban_legacy_system = 1
jobban_loadbanfile()
return
//Job permabans
var/DBQuery/permabans = GLOB.dbcon.NewQuery("SELECT ckey, job FROM [format_table_name("ban")] WHERE bantype = 'JOB_PERMABAN' AND isnull(unbanned)")
permabans.Execute()
// Job tempbans
var/DBQuery/tempbans = GLOB.dbcon.NewQuery("SELECT ckey, job FROM [format_table_name("ban")] WHERE bantype = 'JOB_TEMPBAN' AND isnull(unbanned) AND expiration_time > Now()")
tempbans.Execute()
var/datum/db_query/permabans = SSdbcore.NewQuery("SELECT ckey, job FROM [format_table_name("ban")] WHERE bantype = 'JOB_PERMABAN' AND isnull(unbanned)")
while(TRUE)
var/ckey
var/job
if(permabans.NextRow())
ckey = permabans.item[1]
job = permabans.item[2]
else if(tempbans.NextRow())
ckey = tempbans.item[1]
job = tempbans.item[2]
else
break
if(!permabans.warn_execute())
qdel(permabans)
return FALSE
while(permabans.NextRow())
var/ckey = permabans.item[1]
var/job = permabans.item[2]
GLOB.jobban_keylist.Add("[ckey] - [job]")
jobban_assoc_insert(ckey, job)
qdel(permabans)
// Job tempbans
var/datum/db_query/tempbans = SSdbcore.NewQuery("SELECT ckey, job FROM [format_table_name("ban")] WHERE bantype = 'JOB_TEMPBAN' AND isnull(unbanned) AND expiration_time > Now()")
if(!tempbans.warn_execute())
qdel(tempbans)
return FALSE
while(tempbans.NextRow())
var/ckey = tempbans.item[1]
var/job = tempbans.item[2]
GLOB.jobban_keylist.Add("[ckey] - [job]")
jobban_assoc_insert(ckey, job)
qdel(tempbans)
/proc/jobban_savebanfile()
var/savefile/S=new("data/job_full.ban")
S["keys[0]"] << GLOB.jobban_keylist
@@ -134,8 +142,16 @@ GLOBAL_DATUM_INIT(jobban_regex, /regex, regex("(\[\\S]+) - (\[^#]+\[^# ])(?: ##
else
//using the SQL ban system
var/is_actually_banned = FALSE
var/DBQuery/select_query = GLOB.dbcon.NewQuery("SELECT bantime, bantype, reason, job, duration, expiration_time, a_ckey FROM [format_table_name("ban")] WHERE ckey like '[ckey]' AND ((bantype like 'JOB_TEMPBAN' AND expiration_time > Now()) OR (bantype like 'JOB_PERMABAN')) AND isnull(unbanned) ORDER BY bantime DESC LIMIT 100")
select_query.Execute()
var/datum/db_query/select_query = SSdbcore.NewQuery({"
SELECT bantime, bantype, reason, job, duration, expiration_time, a_ckey FROM [format_table_name("ban")]
WHERE ckey LIKE :ckey AND ((bantype like 'JOB_TEMPBAN' AND expiration_time > Now()) OR (bantype like 'JOB_PERMABAN')) AND isnull(unbanned)
ORDER BY bantime DESC LIMIT 100"},
list("ckey" = ckey)
)
if(!select_query.warn_execute())
qdel(select_query)
return FALSE
while(select_query.NextRow())
@@ -154,6 +170,8 @@ GLOBAL_DATUM_INIT(jobban_regex, /regex, regex("(\[\\S]+) - (\[^#]+\[^# ])(?: ##
is_actually_banned = TRUE
qdel(select_query)
if(is_actually_banned)
if(config.banappeals)
to_chat(src, "<span class='warning'>You can appeal the bans at: [config.banappeals]</span>")
-202
View File
@@ -1,202 +0,0 @@
/client/proc/create_poll()
set name = "Create Server Poll"
set category = "Server"
if(!check_rights(R_SERVER))
return
if(!GLOB.dbcon.IsConnected())
to_chat(src, "<span class='danger'>Failed to establish database connection.</span>")
return
create_poll_window()
/client/proc/create_poll_window(var/errormessage = "")
if(!check_rights(R_SERVER))
return
var/output={"<!DOCTYPE html>
<html>
<head>
<script>
var numoptions = 0;
function update_vis() {
var polloptions = document.getElementById("polloptions");
var polltype = document.getElementById("polltype").value;
if(polltype == "[POLLTYPE_TEXT]") {
polloptions.style.display = "none";
} else {
polloptions.style.display = "block";
}
if(polltype == "[POLLTYPE_RATING]") {
for(var i = 0; i < numoptions; i++) {
document.getElementById("ratingoption" + i).style.display = "block";
}
} else {
for(var i = 0; i < numoptions; i++) {
document.getElementById("ratingoption" + i).style.display = "none";
}
}
if(polltype == "[POLLTYPE_MULTI]") {
document.getElementById("choiceamount").style.display = "block";
} else {
document.getElementById("choiceamount").style.display = "none";
}
}
function add_option() {
document.getElementById("polloptionsinner").innerHTML += "<div id='polloption"+numoptions+"' style='border:1px solid black;padding:10px'>"+
"Option name: <input type='text' name='createpolloption"+numoptions+"option' value='' style='width:300px'></input><br>"+
"<label><input type='checkbox' name='createpolloption"+numoptions+"percentagecalc' value='1' checked>Calculate options results as percentage?</label><br>"+
"<div id='ratingoption"+numoptions+"'>"+
"Minimum rating value: <input type='text' name='createpolloption"+numoptions+"minval' value='1'></input><br>"+
"Maximum rating value: <input type='text' name='createpolloption"+numoptions+"maxval' value='5'></input><br>"+
"Minimum rating description: <input type='text' name='createpolloption"+numoptions+"descmin' value='Terrible'></input><br>"+
"Median rating description: <input type='text' name='createpolloption"+numoptions+"descmid' value=''></input><br>"+
"Maximum rating description: <input type='text' name='createpolloption"+numoptions+"descmax' value='Great'></input>"+
"</div>";
numoptions++;
document.getElementById("createpollnumoptions").value = numoptions+"";
update_vis();
}
function del_option() {
if(numoptions <= 1) {
return;
}
numoptions--;
document.getElementById("polloptionsinner").removeChild(document.getElementById("polloption"+numoptions));
document.getElementById("createpollnumoptions").value = numoptions+"";
update_vis();
}
function onload() {
update_vis();
add_option();
}
</script>
</head>
<body onload="onload()">
<div style='text-align:center'><b>Create Player Poll</b></div><hr>
<div style='text-align:center'>[errormessage]</div>
<form name='createpoll' action='byond://' method='post' style='padding-left:30px;padding-right:30px;padding-top:10px'>
<input type='hidden' name='createpollnumoptions' id='createpollnumoptions' value='0'>
<table><tr><td style='width:50%' style="vertical-align:top"><div id='polloptions'><div id='polloptionsinner'>
</div>
<input type='button' onclick='add_option()' value="Add Option"></input>
<input type='button' onclick='del_option()' value="Delete Option"></input>
</div></td><td style="vertical-align:top">
Select a poll type: <select name='createpoll' id='polltype' onchange="update_vis()">
<option value='[POLLTYPE_OPTION]'>POLLTYPE_OPTION</option>
<option value='[POLLTYPE_TEXT]'>POLLTYPE_TEXT</option>
<option value='[POLLTYPE_RATING]'>POLLTYPE_RATING</option>
<option value='[POLLTYPE_MULTI]'>POLLTYPE_MULTI</option>
</select><br>
For how many days should this poll run? <input type='text' name='createpollduration' value='7' style='width:50px'></input><br>
Enter your question: <input type='text' name='createpollquestion' value='' style='width:300px'></input><br>
<div id='choiceamount'>Up to how many options should be chosen? <input name='choiceamount' value='2' style='width:30px'></div>
<label><input type='checkbox' name='createpolladminonly' value='1'>Admin only?</label><br>
</td></tr><tr><td colspan=2 style='text-align:center'>
<input type='submit' value='Create poll'>
</td></tr></table>
</form>
</body>
</html>"}
src << browse(output, "window=createplayerpoll;size=950x500")
/client/proc/create_poll_function(href_list)
if(!check_rights(R_SERVER))
return
var/polltype = href_list["createpoll"]
if(polltype != POLLTYPE_OPTION && polltype != POLLTYPE_TEXT && polltype != POLLTYPE_RATING && polltype != POLLTYPE_MULTI)
create_poll_window("<font color='red'>Invalid poll type</font>")
return
var/choice_amount = 0
if(polltype == POLLTYPE_MULTI)
choice_amount = text2num(href_list["choiceamount"])
if(!isnum(choice_amount) || choice_amount < 1)
create_poll_window("<font color='red'>Invalid choice amount. Must be at least 1.</font>")
return
var/poll_len = text2num(href_list["createpollduration"])
if(!isnum(poll_len) || poll_len < 1)
create_poll_window("<font color='red'>Invalid poll duration. Must be at least 1.</font>")
return
var/adminonly = text2num(href_list["createpolladminonly"]) ? 1 : 0
var/sql_ckey = sanitizeSQL(ckey)
var/question = href_list["createpollquestion"]
if(!question)
create_poll_window("<font color='red'>Question cannot be blank.</font>")
return
question = sanitizeSQL(question)
var/starttime
var/endtime
var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT Now() AS starttime, ADDDATE(Now(), INTERVAL [poll_len] DAY) AS endtime")
query.Execute()
while(query.NextRow())
starttime = query.item[1]
endtime = query.item[2]
var/pollquery = "INSERT INTO [format_table_name("poll_question")] (polltype, starttime, endtime, question, adminonly, multiplechoiceoptions, createdby_ckey, createdby_ip) VALUES ('[polltype]', '[starttime]', '[endtime]', '[question]', '[adminonly]', '[choice_amount]', '[sql_ckey]', '[address]')"
var/idquery = "SELECT id FROM [format_table_name("poll_question")] WHERE question = '[question]' AND starttime = '[starttime]' AND endtime = '[endtime]' AND createdby_ckey = '[sql_ckey]' AND createdby_ip = '[address]'"
var/list/option_queries = list()
if(polltype == POLLTYPE_MULTI || polltype == POLLTYPE_RATING || polltype == POLLTYPE_OPTION)
var/numoptions = text2num(href_list["createpollnumoptions"])
if(!numoptions)
create_poll_window("<font color='red'>Invalid number of options</font>")
return
for(var/I in 1 to numoptions)
var/option = href_list["createpolloption[I]option"]
if(!option)
create_poll_window("<font color='red'>Invalid option name for option [I]</font>")
return
option = sanitizeSQL(option)
var/percentagecalc = 0
if(text2num(href_list["createpolloption[I]percentagecalc"]))
percentagecalc = 1
var/minval = 0
var/maxval = 0
var/descmin = ""
var/descmid = ""
var/descmax = ""
if(polltype == POLLTYPE_RATING)
minval = text2num(href_list["createpolloption[I]minval"])
if(!minval)
create_poll_window("<font color='red'>Invalid minimum value for option [I]</font>")
return
maxval = text2num(href_list["createpolloption[I]maxval"])
if(!maxval)
create_poll_window("<font color='red'>Invalid maximum value for option [I]</font>")
return
if(minval >= maxval)
create_poll_window("<font color='red'>Minimum rating value can't be more than maximum rating value</font>")
return
descmin = href_list["createpolloption[I]descmin"]
if(descmin)
descmin = sanitizeSQL(descmin)
descmid = href_list["createpolloption[I]descmid"]
if(descmid)
descmid = sanitizeSQL(descmid)
descmax = href_list["createpolloption[I]descmax"]
if(descmax)
descmax = sanitizeSQL(descmax)
option_queries += "INSERT INTO [format_table_name("poll_option")] (pollid, text, percentagecalc, minval, maxval, descmin, descmid, descmax) VALUES ('{POLLID}', '[option]', '[percentagecalc]', '[minval]', '[maxval]', '[descmin]', '[descmid]', '[descmax]')"
query = GLOB.dbcon.NewQuery(pollquery)
if(!query.Execute())
var/err = query.ErrorMsg()
create_poll_window("<font color='red'>An SQL error has occured while creating your poll</font>")
log_game("SQL ERROR adding new poll question to table. Error : \[[err]\]\n")
return
var/pollid = 0
query = GLOB.dbcon.NewQuery(idquery)
if(!query.Execute())
var/err = query.ErrorMsg()
create_poll_window("<font color='red'>An SQL error has occured while creating your poll</font>")
log_game("SQL ERROR obtaining id from poll_question table. Error : \[[err]\]\n")
return
if(query.NextRow())
pollid = text2num(query.item[1])
for(var/querytext in option_queries)
query = GLOB.dbcon.NewQuery(replacetext(idquery, "{POLLID}", pollid))
if(!query.Execute())
var/err = query.ErrorMsg()
create_poll_window("<font color='red'>An SQL error has occured while creating your poll</font>")
log_game("SQL ERROR obtaining id from poll_question table. Error : \[[err]\]\n")
return
create_poll_window("<font color='#008800'>Your poll has been successfully created</font>")
return pollid
+151 -60
View File
@@ -4,8 +4,8 @@
if(!check_rights(R_BAN)) return
establish_db_connection()
if(!GLOB.dbcon.IsConnected())
if(!SSdbcore.IsConnected())
to_chat(usr, "<span class='boldannounce'>Database connection failure when attempting to make DB ban. Please freeze them and write their ckey in notepad, so they can be banned when the DB returns.</span>")
return
var/serverip = "[world.internet_address]:[world.port]"
@@ -86,16 +86,22 @@
message_admins("<font color='red'>[key_name_admin(usr)] attempted to add a ban based on a non-existent mob, with no ckey provided. Report this bug.",1)
return
var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT id FROM [format_table_name("player")] WHERE ckey = '[ckey]'")
query.Execute()
var/validckey = 0
var/datum/db_query/query = SSdbcore.NewQuery("SELECT id FROM [format_table_name("player")] WHERE ckey=:ckey", list(
"ckey" = ckey
))
if(!query.warn_execute())
qdel(query)
return
var/validckey = FALSE
if(query.NextRow())
validckey = 1
validckey = TRUE
if(!validckey)
if(!banned_mob || (banned_mob && !IsGuestKey(banned_mob.key)))
message_admins("<font color='red'>[key_name_admin(usr)] attempted to ban [ckey], but [ckey] does not exist in the player database. Please only ban actual players.</font>",1)
qdel(query)
return
qdel(query)
var/a_ckey
var/a_computerid
var/a_ip
@@ -124,25 +130,51 @@
else
adminwho += ", [C]"
reason = sanitizeSQL(reason)
if(maxadminbancheck)
var/DBQuery/adm_query = GLOB.dbcon.NewQuery("SELECT count(id) AS num FROM [format_table_name("ban")] WHERE (a_ckey = '[a_ckey]') AND (bantype = 'ADMIN_PERMABAN' OR (bantype = 'ADMIN_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)")
adm_query.Execute()
var/datum/db_query/adm_query = SSdbcore.NewQuery("SELECT count(id) AS num FROM [format_table_name("ban")] WHERE (a_ckey=:a_ckey) AND (bantype = 'ADMIN_PERMABAN' OR (bantype = 'ADMIN_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)", list(
"a_ckey" = a_ckey
))
if(!adm_query.warn_execute())
qdel(adm_query)
return
if(adm_query.NextRow())
var/adm_bans = text2num(adm_query.item[1])
if(adm_bans >= MAX_ADMIN_BANS_PER_ADMIN)
to_chat(usr, "<span class='danger'>You already logged [MAX_ADMIN_BANS_PER_ADMIN] admin ban(s) or more. Do not abuse this function!</span>")
qdel(adm_query)
return
qdel(adm_query)
var/sql = "INSERT INTO [format_table_name("ban")] (`id`,`bantime`,`serverip`,`bantype`,`reason`,`job`,`duration`,`rounds`,`expiration_time`,`ckey`,`computerid`,`ip`,`a_ckey`,`a_computerid`,`a_ip`,`who`,`adminwho`,`edits`,`unbanned`,`unbanned_datetime`,`unbanned_ckey`,`unbanned_computerid`,`unbanned_ip`) VALUES (null, Now(), '[serverip]', '[bantype_str]', '[reason]', '[job]', [(duration)?"[duration]":"0"], [(rounds)?"[rounds]":"0"], Now() + INTERVAL [(duration>0) ? duration : 0] MINUTE, '[ckey]', '[computerid]', '[ip]', '[a_ckey]', '[a_computerid]', '[a_ip]', '[who]', '[adminwho]', '', null, null, null, null, null)"
var/DBQuery/query_insert = GLOB.dbcon.NewQuery(sql)
query_insert.Execute()
var/datum/db_query/query_insert = SSdbcore.NewQuery({"
INSERT INTO [format_table_name("ban")] (`id`,`bantime`,`serverip`,`bantype`,`reason`,`job`,`duration`,`rounds`,`expiration_time`,`ckey`,`computerid`,`ip`,`a_ckey`,`a_computerid`,`a_ip`,`who`,`adminwho`,`edits`,`unbanned`,`unbanned_datetime`,`unbanned_ckey`,`unbanned_computerid`,`unbanned_ip`)
VALUES (null, Now(), :serverip, :bantype_str, :reason, :job, :duration, :rounds, Now() + INTERVAL :duration MINUTE, :ckey, :computerid, :ip, :a_ckey, :a_computerid, :a_ip, :who, :adminwho, '', null, null, null, null, null)
"}, list(
// Get ready for parameters
"serverip" = serverip,
"bantype_str" = bantype_str,
"reason" = reason,
"job" = job,
"duration" = (duration ? "[duration]" : "0"), // Strings are important here
"rounds" = (rounds ? "[rounds]" : "0"), // And here
"ckey" = ckey,
"computerid" = computerid,
"ip" = ip,
"a_ckey" = a_ckey,
"a_computerid" = a_computerid,
"a_ip" = a_ip,
"who" = who,
"adminwho" = adminwho
))
if(!query_insert.warn_execute())
qdel(query_insert)
return
qdel(query_insert)
to_chat(usr, "<span class='notice'>Ban saved to database.</span>")
message_admins("[key_name_admin(usr)] has added a [bantype_str] for [ckey] [(job)?"([job])":""] [(duration > 0)?"([duration] minutes)":""] with the reason: \"[reason]\" to the ban database.",1)
if(announce_in_discord)
SSdiscord.send2discord_simple(DISCORD_WEBHOOK_ADMIN, "**BAN ALERT** [a_ckey] applied a [bantype_str] on [ckey]")
SSdiscord.send2discord_simple(DISCORD_WEBHOOK_ADMIN, "**\[Ban]** [a_ckey] applied a [bantype_str] on [ckey]")
if(kickbannedckey)
if(banned_mob && banned_mob.client && banned_mob.client.ckey == banckey)
@@ -157,6 +189,10 @@
if(!check_rights(R_BAN)) return
if(!SSdbcore.IsConnected())
to_chat(usr, "<span class='boldannounce'>Database connection failure when attempting to remove DB ban. Please remember to unban them at a later date!.</span>")
return
var/bantype_str
var/isjobban // For job bans, which need to be removed from the job ban lists
if(bantype)
@@ -196,23 +232,28 @@
else
bantype_sql = "bantype = '[bantype_str]'"
var/sql = "SELECT id FROM [format_table_name("ban")] WHERE ckey = '[ckey]' AND [bantype_sql] AND (unbanned is null OR unbanned = false)"
var/sql = "SELECT id FROM [format_table_name("ban")] WHERE ckey=:ckey AND [bantype_sql] AND (unbanned is null OR unbanned = false)"
var/list/sql_params = list(
"ckey" = ckey
)
if(job)
sql += " AND job = '[job]'"
establish_db_connection()
if(!GLOB.dbcon.IsConnected())
return
sql += " AND job=:job"
sql_params["job"] = job
var/ban_id
var/ban_number = 0 //failsafe
var/DBQuery/query = GLOB.dbcon.NewQuery(sql)
query.Execute()
var/datum/db_query/query = SSdbcore.NewQuery(sql, sql_params)
if(!query.warn_execute())
qdel(query)
return
while(query.NextRow())
ban_id = query.item[1]
ban_number++
qdel(query)
if(ban_number == 0)
to_chat(usr, "<span class='warning'>Database update failed due to no bans fitting the search criteria. If this is not a legacy ban you should contact the database admin.</span>")
return
@@ -241,8 +282,12 @@
to_chat(usr, "Cancelled")
return
var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT ckey, duration, reason, job FROM [format_table_name("ban")] WHERE id = [banid]")
query.Execute()
var/datum/db_query/query = SSdbcore.NewQuery("SELECT ckey, duration, reason, job FROM [format_table_name("ban")] WHERE id=:banid", list(
"banid" = banid
))
if(!query.warn_execute())
qdel(query)
return
var/eckey = usr.ckey //Editing admin ckey
var/pckey //(banned) Player ckey
@@ -257,22 +302,31 @@
job = query.item[4]
else
to_chat(usr, "Invalid ban id. Contact the database admin")
qdel(query)
return
reason = sanitizeSQL(reason)
qdel(query)
var/value
switch(param)
if("reason")
if(!value)
value = input("Insert the new reason for [pckey]'s ban", "New Reason", "[reason]", null) as null|text
value = sanitizeSQL(value)
if(!value)
to_chat(usr, "Cancelled")
return
var/DBQuery/update_query = GLOB.dbcon.NewQuery("UPDATE [format_table_name("ban")] SET reason = '[value]', edits = CONCAT(edits,'- [eckey] changed ban reason from <cite><b>\\\"[reason]\\\"</b></cite> to <cite><b>\\\"[value]\\\"</b></cite><BR>') WHERE id = [banid]")
update_query.Execute()
var/edit_reason = "- [eckey] changed ban reason from <cite><b>\\\"[reason]\\\"</b></cite> to <cite><b>\\\"[value]\\\"</b></cite><BR>"
var/datum/db_query/update_query = SSdbcore.NewQuery("UPDATE [format_table_name("ban")] SET reason=:value, edits = CONCAT(IFNULL(edits,''), :edittext) WHERE id=:banid", list(
"edittext" = edit_reason,
"banid" = banid,
"value" = value
))
if(!update_query.warn_execute())
qdel(update_query)
return
qdel(update_query)
message_admins("[key_name_admin(usr)] has edited a ban for [pckey]'s reason from [reason] to [value]",1)
if("duration")
if(!value)
@@ -281,9 +335,18 @@
to_chat(usr, "Cancelled")
return
var/DBQuery/update_query = GLOB.dbcon.NewQuery("UPDATE [format_table_name("ban")] SET duration = [value], edits = CONCAT(edits,'- [eckey] changed ban duration from [duration] to [value]<br>'), expiration_time = DATE_ADD(bantime, INTERVAL [value] MINUTE) WHERE id = [banid]")
var/edittext = "- [eckey] changed ban duration from [duration] to [value]<br>"
var/datum/db_query/update_query = SSdbcore.NewQuery("UPDATE [format_table_name("ban")] SET duration=:value, edits = CONCAT(IFNULL(edits, ''), :edittext), expiration_time = DATE_ADD(bantime, INTERVAL :value MINUTE) WHERE id=:banid", list(
"edittext" = edittext,
"banid" = banid,
"value" = value
))
if(!update_query.warn_execute())
qdel(update_query)
return
qdel(update_query)
message_admins("[key_name_admin(usr)] has edited a ban for [pckey]'s duration from [duration] to [value]",1)
update_query.Execute()
if("unban")
if(alert("Unban [pckey]?", "Unban?", "Yes", "No") == "Yes")
DB_ban_unban_by_id(banid)
@@ -302,21 +365,25 @@
if(!check_rights(R_BAN))
return
var/sql = "SELECT ckey FROM [format_table_name("ban")] WHERE id = [id]"
establish_db_connection()
if(!GLOB.dbcon.IsConnected())
if(!SSdbcore.IsConnected())
to_chat(usr, "<span class='boldannounce'>Database connection failure when attempting to remove DB ban. Please remember to unban them at a later date!.</span>")
return
var/ban_number = 0 //failsafe
var/pckey
var/DBQuery/query = GLOB.dbcon.NewQuery(sql)
query.Execute()
var/datum/db_query/query = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("ban")] WHERE id=:banid", list(
"banid" = id
))
if(!query.warn_execute())
qdel(query)
return
while(query.NextRow())
pckey = query.item[1]
ban_number++
qdel(query)
if(ban_number == 0)
to_chat(usr, "<span class='warning'>Database update failed due to a ban id not being present in the database.</span>")
return
@@ -332,12 +399,19 @@
var/unban_computerid = src.owner:computer_id
var/unban_ip = src.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 = '[unban_ip]' WHERE id = [id]"
message_admins("[key_name_admin(usr)] has lifted [pckey]'s ban.",1)
var/datum/db_query/query_update = SSdbcore.NewQuery("UPDATE [format_table_name("ban")] SET unbanned = 1, unbanned_datetime = Now(), unbanned_ckey=:unban_ckey, unbanned_computerid=:unban_computerid, unbanned_ip=:unban_ip WHERE id=:id", list(
"unban_ckey" = unban_ckey,
"unban_computerid" = unban_computerid,
"unban_ip" = unban_ip,
"id" = id
))
if(!query_update.warn_execute())
qdel(query_update)
return
var/DBQuery/query_update = GLOB.dbcon.NewQuery(sql_update)
query_update.Execute()
qdel(query_update)
message_admins("[key_name_admin(usr)] has lifted [pckey]'s ban.")
flag_account_for_forum_sync(pckey)
@@ -360,8 +434,7 @@
if(!check_rights(R_BAN))
return
establish_db_connection()
if(!GLOB.dbcon.IsConnected())
if(!SSdbcore.IsConnected())
to_chat(usr, "<span class='warning'>Failed to establish database connection</span>")
return
@@ -436,8 +509,6 @@
adminckey = ckey(adminckey)
playerckey = ckey(playerckey)
playerip = sanitizeSQL(playerip)
playercid = sanitizeSQL(playercid)
if(adminckey || playerckey || playerip || playercid || dbbantype)
@@ -461,24 +532,34 @@
var/cidsearch = ""
var/bantypesearch = ""
var/list/sql_params = list()
if(!match)
if(adminckey)
adminsearch = "AND a_ckey = '[adminckey]' "
adminsearch = "AND a_ckey=:adminckey "
sql_params["adminckey"] = adminckey
if(playerckey)
playersearch = "AND ckey = '[playerckey]' "
playersearch = "AND ckey=:playerckey "
sql_params["playerckey"] = playerckey
if(playerip)
ipsearch = "AND ip = '[playerip]' "
ipsearch = "AND ip=:playerip "
sql_params["playerip"] = playerip
if(playercid)
cidsearch = "AND computerid = '[playercid]' "
cidsearch = "AND computerid=:playercid "
sql_params["playercid"] = playercid
else
if(adminckey && length(adminckey) >= 3)
adminsearch = "AND a_ckey LIKE '[adminckey]%' "
adminsearch = "AND a_ckey LIKE :adminckey "
sql_params["adminckey"] = "[adminckey]%"
if(playerckey && length(playerckey) >= 3)
playersearch = "AND ckey LIKE '[playerckey]%' "
playersearch = "AND ckey LIKE :playerckey "
sql_params["playerckey"] = "[playerckey]%"
if(playerip && length(playerip) >= 3)
ipsearch = "AND ip LIKE '[playerip]%' "
ipsearch = "AND ip LIKE :playerip "
sql_params["playerip"] = "[playerip]%"
if(playercid && length(playercid) >= 7)
cidsearch = "AND computerid LIKE '[playercid]%' "
cidsearch = "AND computerid LIKE :playercid "
sql_params["playercid"] = "[playercid]%"
if(dbbantype)
bantypesearch = "AND bantype = "
@@ -500,8 +581,13 @@
bantypesearch += "'PERMABAN' "
var/DBQuery/select_query = GLOB.dbcon.NewQuery("SELECT id, bantime, bantype, reason, job, duration, expiration_time, ckey, a_ckey, unbanned, unbanned_ckey, unbanned_datetime, edits, ip, computerid FROM [format_table_name("ban")] WHERE 1 [playersearch] [adminsearch] [ipsearch] [cidsearch] [bantypesearch] ORDER BY bantime DESC LIMIT 100")
select_query.Execute()
var/datum/db_query/select_query = SSdbcore.NewQuery({"
SELECT id, bantime, bantype, reason, job, duration, expiration_time, ckey, a_ckey, unbanned, unbanned_ckey, unbanned_datetime, edits, ip, computerid
FROM [format_table_name("ban")] WHERE 1 [playersearch] [adminsearch] [ipsearch] [cidsearch] [bantypesearch] ORDER BY bantime DESC LIMIT 100"}, sql_params)
if(!select_query.warn_execute())
qdel(select_query)
return
while(select_query.NextRow())
var/banid = select_query.item[1]
@@ -552,7 +638,7 @@
output += "</tr>"
output += "<tr bgcolor='[dcolor]'>"
output += "<td align='center' colspan='2' bgcolor=''><b>IP:</b> [ip]</td>"
output += "<td align='center' colspan='3' bgcolor=''><b>CIP:</b> [cid]</td>"
output += "<td align='center' colspan='3' bgcolor=''><b>CID:</b> [cid]</td>"
output += "</tr>"
output += "<tr bgcolor='[lcolor]'>"
output += "<td align='center' colspan='5'><b>Reason: [(unbanned) ? "" : "(<a href=\"byond://?src=[UID()];dbbanedit=reason;dbbanid=[banid]\">Edit</a>)"]</b> <cite>\"[reason]\"</cite></td>"
@@ -574,12 +660,17 @@
output += "</table></div>"
qdel(select_query)
usr << browse(output,"window=lookupbans;size=900x700")
/proc/flag_account_for_forum_sync(ckey)
if(!GLOB.dbcon)
if(!SSdbcore.IsConnected())
return
var/skey = sanitizeSQL(ckey)
var/sql = "UPDATE [format_table_name("player")] SET fupdate = 1 WHERE ckey = '[skey]'"
var/DBQuery/adm_query = GLOB.dbcon.NewQuery(sql)
adm_query.Execute()
var/datum/db_query/adm_query = SSdbcore.NewQuery("UPDATE [format_table_name("player")] SET fupdate = 1 WHERE ckey=:ckey", list(
"ckey" = ckey
))
// We do nothing with output here so we dont need to wrap the warn_execute() inside an if statement
adm_query.warn_execute()
qdel(adm_query)
+55 -37
View File
@@ -23,7 +23,6 @@
/proc/get_ip_intel(ip, bypasscache = FALSE, updatecache = TRUE)
var/datum/ipintel/res = new()
ip = sanitizeSQL(ip)
res.ip = ip
. = res
if(!ip || !config.ipintel_email || !SSipintel.enabled)
@@ -34,24 +33,28 @@
cachedintel.cache = TRUE
return cachedintel
if(GLOB.dbcon.IsConnected())
var/rating_bad = config.ipintel_rating_bad
var/DBQuery/query_get_ip_intel = GLOB.dbcon.NewQuery({"
if(SSdbcore.IsConnected())
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.ipintel_save_good] HOUR > NOW()
date + INTERVAL :save_good HOUR > NOW()
) OR (
intel >= [rating_bad]
intel >= :rating_bad
AND
date + INTERVAL [config.ipintel_save_bad] HOUR > NOW()
date + INTERVAL :save_bad HOUR > NOW()
))
"})
if(!query_get_ip_intel.Execute())
"}, list(
"ip" = ip,
"rating_bad" = config.ipintel_rating_bad,
"save_good" = config.ipintel_save_good,
"save_bad" = config.ipintel_save_bad,
))
if(!query_get_ip_intel.warn_execute())
qdel(query_get_ip_intel)
return
if(query_get_ip_intel.NextRow())
@@ -67,9 +70,16 @@
res.intel = ip_intel_query(ip)
if(updatecache && res.intel >= 0)
SSipintel.cache[ip] = res
if(GLOB.dbcon.IsConnected())
var/DBQuery/query_add_ip_intel = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("ipintel")] (ip, intel) VALUES (INET_ATON('[ip]'), [res.intel]) ON DUPLICATE KEY UPDATE intel = VALUES(intel), date = NOW()")
query_add_ip_intel.Execute()
if(SSdbcore.IsConnected())
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.warn_execute()
qdel(query_add_ip_intel)
@@ -140,7 +150,7 @@
return FALSE
if(!config.ipintel_whitelist)
return FALSE
if(!GLOB.dbcon.IsConnected())
if(!SSdbcore.IsConnected())
return FALSE
if(!ipintel_badip_check(t_ip))
return FALSE
@@ -157,12 +167,16 @@
if(!valid_hours)
log_debug("ipintel_badip_check reports misconfigured ipintel_save_bad directive")
return FALSE
target_ip = sanitizeSQL(target_ip)
rating_bad = sanitizeSQL(rating_bad)
valid_hours = sanitizeSQL(valid_hours)
var/check_sql = {"SELECT * FROM [format_table_name("ipintel")] WHERE ip = INET_ATON('[target_ip]') AND intel >= [rating_bad] AND (date + INTERVAL [valid_hours] HOUR) > NOW()"}
var/DBQuery/query_get_ip_intel = GLOB.dbcon.NewQuery(check_sql)
if(!query_get_ip_intel.Execute())
var/datum/db_query/query_get_ip_intel = SSdbcore.NewQuery({"
SELECT * FROM [format_table_name("ipintel")] WHERE ip = INET_ATON(:target_ip)
AND intel >= :rating_bad AND (date + INTERVAL :valid_hours HOUR) > NOW()"},
list(
"target_ip" = target_ip,
"rating_bad" = rating_bad,
"valid_hours" = valid_hours
)
)
if(!query_get_ip_intel.warn_execute())
log_debug("ipintel_badip_check reports failed query execution")
qdel(query_get_ip_intel)
return FALSE
@@ -175,36 +189,40 @@
/proc/vpn_whitelist_check(target_ckey)
if(!config.ipintel_whitelist)
return FALSE
var/target_sql_ckey = ckey(target_ckey)
var/DBQuery/query_whitelist_check = GLOB.dbcon.NewQuery("SELECT * FROM [format_table_name("vpn_whitelist")] WHERE ckey = '[target_sql_ckey]'")
if(!query_whitelist_check.Execute())
var/err = query_whitelist_check.ErrorMsg()
log_debug("SQL ERROR on proc/vpn_whitelist_check for ckey '[target_sql_ckey]'. Error : \[[err]\]\n")
var/datum/db_query/query_whitelist_check = SSdbcore.NewQuery("SELECT * FROM [format_table_name("vpn_whitelist")] WHERE ckey=:ckey", list(
"ckey" = target_ckey
))
if(!query_whitelist_check.warn_execute())
qdel(query_whitelist_check)
return FALSE
if(query_whitelist_check.NextRow())
qdel(query_whitelist_check)
return TRUE // At least one row in the whitelist names their ckey. That means they are whitelisted.
qdel(query_whitelist_check)
return FALSE
/proc/vpn_whitelist_add(target_ckey)
var/target_sql_ckey = ckey(target_ckey)
var/reason_string = input(usr, "Enter link to the URL of their whitelist request on the forum.","Reason required") as message|null
if(!reason_string)
return FALSE
reason_string = sanitizeSQL(reason_string)
var/DBQuery/query_whitelist_add = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("vpn_whitelist")] (ckey,reason) VALUES ('[target_sql_ckey]','[reason_string]')")
if(!query_whitelist_add.Execute())
var/err = query_whitelist_add.ErrorMsg()
log_debug("SQL ERROR on proc/vpn_whitelist_add for ckey '[target_sql_ckey]'. Error : \[[err]\]\n")
var/datum/db_query/query_whitelist_add = SSdbcore.NewQuery("INSERT INTO [format_table_name("vpn_whitelist")] (ckey,reason) VALUES (:targetckey, :reason)", list(
"targetckey" = target_ckey,
"reason" = reason_string
))
if(!query_whitelist_add.warn_execute())
qdel(query_whitelist_add)
return FALSE
qdel(query_whitelist_add)
return TRUE
/proc/vpn_whitelist_remove(target_ckey)
var/target_sql_ckey = ckey(target_ckey)
var/DBQuery/query_whitelist_remove = GLOB.dbcon.NewQuery("DELETE FROM [format_table_name("vpn_whitelist")] WHERE ckey = '[target_sql_ckey]'")
if(!query_whitelist_remove.Execute())
var/err = query_whitelist_remove.ErrorMsg()
log_debug("SQL ERROR on proc/vpn_whitelist_remove for ckey '[target_sql_ckey]'. Error : \[[err]\]\n")
var/datum/db_query/query_whitelist_remove = SSdbcore.NewQuery("DELETE FROM [format_table_name("vpn_whitelist")] WHERE ckey=:targetckey", list(
"targetckey" = target_ckey
))
if(!query_whitelist_remove.warn_execute())
qdel(query_whitelist_remove)
return FALSE
qdel(query_whitelist_remove)
return TRUE
/proc/vpn_whitelist_panel(target_ckey as text)
@@ -60,9 +60,7 @@
if(!check_rights(R_PERMISSIONS))
return
establish_db_connection()
if(!GLOB.dbcon.IsConnected())
if(!SSdbcore.IsConnected())
to_chat(usr, "<span class='warning'>Failed to establish database connection</span>")
return
@@ -77,28 +75,63 @@
if(!istext(adm_ckey) || !istext(new_rank))
return
var/DBQuery/select_query = GLOB.dbcon.NewQuery("SELECT id FROM [format_table_name("admin")] WHERE ckey = '[adm_ckey]'")
select_query.Execute()
var/datum/db_query/select_query = SSdbcore.NewQuery("SELECT id FROM [format_table_name("admin")] WHERE ckey=:adm_ckey", list(
"adm_ckey" = adm_ckey
))
if(!select_query.warn_execute())
qdel(select_query)
return
var/new_admin = 1
var/new_admin = TRUE
var/admin_id
while(select_query.NextRow())
new_admin = 0
new_admin = FALSE
admin_id = text2num(select_query.item[1])
qdel(select_query)
flag_account_for_forum_sync(adm_ckey)
if(new_admin)
var/DBQuery/insert_query = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("admin")] (`id`, `ckey`, `rank`, `level`, `flags`) VALUES (null, '[adm_ckey]', '[new_rank]', -1, 0)")
insert_query.Execute()
var/DBQuery/log_query = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("admin_log")] (`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (Now() , '[usr.ckey]', '[usr.client.address]', 'Added new admin [adm_ckey] to rank [new_rank]');")
log_query.Execute()
var/datum/db_query/insert_query = SSdbcore.NewQuery("INSERT INTO [format_table_name("admin")] (`id`, `ckey`, `rank`, `level`, `flags`) VALUES (null, :adm_ckey, :new_rank, -1, 0)", list(
"adm_ckey" = adm_ckey,
"new_rank" = new_rank
))
if(!insert_query.warn_execute())
qdel(insert_query)
return
qdel(insert_query)
var/logtxt = "Added new admin [adm_ckey] to rank [new_rank]"
var/datum/db_query/log_query = SSdbcore.NewQuery("INSERT INTO [format_table_name("admin_log")] (`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (Now() , :uckey, :uip, :logtxt)", list(
"uckey" = usr.ckey,
"uip" = usr.client.address,
"logtxt" = logtxt
))
if(!log_query.warn_execute())
qdel(log_query)
return
qdel(log_query)
to_chat(usr, "<span class='notice'>New admin added.</span>")
else
if(!isnull(admin_id) && isnum(admin_id))
var/DBQuery/insert_query = GLOB.dbcon.NewQuery("UPDATE [format_table_name("admin")] SET rank = '[new_rank]' WHERE id = [admin_id]")
insert_query.Execute()
var/DBQuery/log_query = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("admin_log")] (`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (Now() , '[usr.ckey]', '[usr.client.address]', 'Edited the rank of [adm_ckey] to [new_rank]');")
log_query.Execute()
var/datum/db_query/insert_query = SSdbcore.NewQuery("UPDATE [format_table_name("admin")] SET rank=:new_rank WHERE id=:admin_id", list(
"new_rank" = new_rank,
"admin_id" = admin_id,
))
if(!insert_query.warn_execute())
qdel(insert_query)
return
qdel(insert_query)
var/logtxt = "Edited the rank of [adm_ckey] to [new_rank]"
var/datum/db_query/log_query = SSdbcore.NewQuery("INSERT INTO [format_table_name("admin_log")] (`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (Now() , :uckey, :uip, :logtxt)", list(
"uckey" = usr.ckey,
"uip" = usr.client.address,
"logtxt" = logtxt,
))
if(!log_query.warn_execute())
qdel(log_query)
return
qdel(log_query)
to_chat(usr, "<span class='notice'>Admin rank changed.</span>")
/datum/admins/proc/log_admin_permission_modification(var/adm_ckey, var/new_permission)
@@ -116,8 +149,7 @@
if(!check_rights(R_PERMISSIONS))
return
establish_db_connection()
if(!GLOB.dbcon.IsConnected())
if(!SSdbcore.IsConnected())
to_chat(usr, "<span class='warning'>Failed to establish database connection</span>")
return
@@ -135,8 +167,12 @@
if(!istext(adm_ckey) || !isnum(new_permission))
return
var/DBQuery/select_query = GLOB.dbcon.NewQuery("SELECT id, flags FROM [format_table_name("admin")] WHERE ckey = '[adm_ckey]'")
select_query.Execute()
var/datum/db_query/select_query = SSdbcore.NewQuery("SELECT id, flags FROM [format_table_name("admin")] WHERE ckey=:adm_ckey", list(
"adm_ckey" = adm_ckey
))
if(!select_query.warn_execute())
qdel(select_query)
return
var/admin_id
var/admin_rights
@@ -144,32 +180,72 @@
admin_id = text2num(select_query.item[1])
admin_rights = text2num(select_query.item[2])
qdel(select_query)
if(!admin_id)
return
flag_account_for_forum_sync(adm_ckey)
if(admin_rights & new_permission) //This admin already has this permission, so we are removing it.
var/DBQuery/insert_query = GLOB.dbcon.NewQuery("UPDATE [format_table_name("admin")] SET flags = [admin_rights & ~new_permission] WHERE id = [admin_id]")
insert_query.Execute()
var/DBQuery/log_query = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("admin_log")] (`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (Now() , '[usr.ckey]', '[usr.client.address]', 'Removed permission [rights2text(new_permission)] (flag = [new_permission]) to admin [adm_ckey]');")
log_query.Execute()
var/datum/db_query/insert_query = SSdbcore.NewQuery("UPDATE [format_table_name("admin")] SET flags=:newflags WHERE id=:admin_id", list(
"newflags" = (admin_rights & ~new_permission),
"admin_id" = admin_id
))
if(!insert_query.warn_execute())
qdel(insert_query)
return
qdel(insert_query)
var/logtxt = "Removed permission [rights2text(new_permission)] (flag = [new_permission]) to admin [adm_ckey]"
var/datum/db_query/log_query = SSdbcore.NewQuery({"
INSERT INTO [format_table_name("admin_log")] (`datetime` ,`adminckey` ,`adminip` ,`log`)
VALUES (Now() , :uckey, :uip, :logtxt)"}, list(
"uckey" = usr.ckey,
"uip" = usr.client.address,
"logtxt" = logtxt
))
if(!log_query.warn_execute())
qdel(log_query)
return
qdel(log_query)
to_chat(usr, "<span class='notice'>Permission removed.</span>")
else //This admin doesn't have this permission, so we are adding it.
var/DBQuery/insert_query = GLOB.dbcon.NewQuery("UPDATE [format_table_name("admin")] SET flags = '[admin_rights | new_permission]' WHERE id = [admin_id]")
insert_query.Execute()
var/DBQuery/log_query = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("admin_log")] (`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (Now() , '[usr.ckey]', '[usr.client.address]', 'Added permission [rights2text(new_permission)] (flag = [new_permission]) to admin [adm_ckey]')")
log_query.Execute()
var/datum/db_query/insert_query = SSdbcore.NewQuery("UPDATE [format_table_name("admin")] SET flags=:newflags WHERE id=:admin_id", list(
"newflags" = (admin_rights | new_permission),
"admin_id" = admin_id
))
if(!insert_query.warn_execute())
qdel(insert_query)
return
qdel(insert_query)
var/logtxt = "Added permission [rights2text(new_permission)] (flag = [new_permission]) to admin [adm_ckey]"
var/datum/db_query/log_query = SSdbcore.NewQuery({"
INSERT INTO [format_table_name("admin_log")] (`datetime` ,`adminckey` ,`adminip` ,`log`)
VALUES (Now() , :uckey, :uip, :logtxt)"}, list(
"uckey" = usr.ckey,
"uip" = usr.client.address,
"logtxt" = logtxt
))
if(!log_query.warn_execute())
qdel(log_query)
return
qdel(log_query)
to_chat(usr, "<span class='notice'>Permission added.</span>")
/datum/admins/proc/updateranktodb(ckey,newrank)
establish_db_connection()
if(!GLOB.dbcon.IsConnected())
if(!SSdbcore.IsConnected())
return
if(!check_rights(R_PERMISSIONS))
return
var/sql_ckey = sanitizeSQL(ckey)
var/sql_admin_rank = sanitizeSQL(newrank)
var/DBQuery/query_update = GLOB.dbcon.NewQuery("UPDATE [format_table_name("player")] SET lastadminrank = '[sql_admin_rank]' WHERE ckey = '[sql_ckey]'")
query_update.Execute()
flag_account_for_forum_sync(sql_ckey)
var/datum/db_query/query_update = SSdbcore.NewQuery("UPDATE [format_table_name("player")] SET lastadminrank=:admin_rank WHERE ckey=:ckey", list(
"admin_rank" = newrank,
"ckey" = ckey
))
if(!query_update.warn_execute())
qdel(query_update)
return
qdel(query_update)
flag_account_for_forum_sync(ckey)
+80 -49
View File
@@ -1,7 +1,8 @@
/proc/add_note(target_ckey, notetext, timestamp, adminckey, logged = 1, server, checkrights = 1)
// Do not attemtp to remove the blank string from the server arg. It will break DB saving.
/proc/add_note(target_ckey, notetext, timestamp, adminckey, logged = 1, server = "", checkrights = 1)
if(checkrights && !check_rights(R_ADMIN|R_MOD))
return
if(!GLOB.dbcon.IsConnected())
if(!SSdbcore.IsConnected())
if(usr)
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
return
@@ -14,17 +15,27 @@
else
target_ckey = ckey(target_ckey)
var/DBQuery/query_find_ckey = GLOB.dbcon.NewQuery("SELECT ckey, exp FROM [format_table_name("player")] WHERE ckey = '[target_ckey]'")
if(!query_find_ckey.Execute())
var/err = query_find_ckey.ErrorMsg()
log_game("SQL ERROR obtaining ckey from player table. Error : \[[err]\]\n")
var/datum/db_query/query_find_ckey = SSdbcore.NewQuery("SELECT ckey, exp FROM [format_table_name("player")] WHERE ckey=:ckey", list(
"ckey" = target_ckey
))
if(!query_find_ckey.warn_execute())
qdel(query_find_ckey)
return
if(!query_find_ckey.NextRow())
var/ckey_found = FALSE
var/exp_data
while(query_find_ckey.NextRow())
exp_data = query_find_ckey.item[2]
ckey_found = TRUE
qdel(query_find_ckey)
if(!ckey_found)
if(usr)
to_chat(usr, "<span class='redtext'>[target_ckey] has not been seen before, you can only add notes to known players.</span>")
return
var/exp_data = query_find_ckey.item[2]
var/crew_number = 0
if(exp_data)
var/list/play_records = params2list(exp_data)
@@ -34,25 +45,32 @@
notetext = input(usr,"Write your note","Add Note") as message|null
if(!notetext)
return
notetext = sanitizeSQL(notetext)
if(!timestamp)
timestamp = SQLtime()
if(!adminckey)
adminckey = usr.ckey
if(!adminckey)
return
else if(usr && (usr.ckey == ckey(adminckey))) // Don't ckeyize special note sources
adminckey = ckey(adminckey)
var/admin_sql_ckey = sanitizeSQL(adminckey)
if(!server)
if(config && config.server_name)
server = config.server_name
server = sanitizeSQL(server)
var/DBQuery/query_noteadd = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("notes")] (ckey, timestamp, notetext, adminckey, server, crew_playtime) VALUES ('[target_ckey]', '[timestamp]', '[notetext]', '[admin_sql_ckey]', '[server]', '[crew_number]')")
if(!query_noteadd.Execute())
var/err = query_noteadd.ErrorMsg()
log_game("SQL ERROR adding new note to table. Error : \[[err]\]\n")
var/datum/db_query/query_noteadd = SSdbcore.NewQuery({"
INSERT INTO [format_table_name("notes")] (ckey, timestamp, notetext, adminckey, server, crew_playtime)
VALUES (:targetckey, NOW(), :notetext, :adminkey, :server, :crewnum)
"}, list(
"targetckey" = target_ckey,
"notetext" = notetext,
"adminkey" = adminckey,
"server" = server,
"crewnum" = crew_number
))
if(!query_noteadd.warn_execute())
qdel(query_noteadd)
return
qdel(query_noteadd)
if(logged)
log_admin("[usr ? key_name(usr) : adminckey] has added a note to [target_ckey]: [notetext]")
message_admins("[usr ? key_name_admin(usr) : adminckey] has added a note to [target_ckey]:<br>[notetext]")
@@ -64,27 +82,33 @@
var/ckey
var/notetext
var/adminckey
if(!GLOB.dbcon.IsConnected())
if(!SSdbcore.IsConnected())
if(usr)
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
return
if(!note_id)
return
note_id = text2num(note_id)
var/DBQuery/query_find_note_del = GLOB.dbcon.NewQuery("SELECT ckey, notetext, adminckey FROM [format_table_name("notes")] WHERE id = [note_id]")
if(!query_find_note_del.Execute())
var/err = query_find_note_del.ErrorMsg()
log_game("SQL ERROR obtaining ckey, notetext, adminckey from player table. Error : \[[err]\]\n")
var/datum/db_query/query_find_note_del = SSdbcore.NewQuery("SELECT ckey, notetext, adminckey FROM [format_table_name("notes")] WHERE id=:note_id", list(
"note_id" = note_id
))
if(!query_find_note_del.warn_execute())
qdel(query_find_note_del)
return
if(query_find_note_del.NextRow())
ckey = query_find_note_del.item[1]
notetext = query_find_note_del.item[2]
adminckey = query_find_note_del.item[3]
var/DBQuery/query_del_note = GLOB.dbcon.NewQuery("DELETE FROM [format_table_name("notes")] WHERE id = [note_id]")
if(!query_del_note.Execute())
var/err = query_del_note.ErrorMsg()
log_game("SQL ERROR removing note from table. Error : \[[err]\]\n")
qdel(query_find_note_del)
var/datum/db_query/query_del_note = SSdbcore.NewQuery("DELETE FROM [format_table_name("notes")] WHERE id=:note_id", list(
"note_id" = note_id
))
if(!query_del_note.warn_execute())
qdel(query_del_note)
return
qdel(query_del_note)
log_admin("[usr ? key_name(usr) : "Bot"] has removed a note made by [adminckey] from [ckey]: [notetext]")
message_admins("[usr ? key_name_admin(usr) : "Bot"] has removed a note made by [adminckey] from [ckey]:<br>[notetext]")
show_note(ckey)
@@ -92,7 +116,7 @@
/proc/edit_note(note_id)
if(!check_rights(R_ADMIN|R_MOD))
return
if(!GLOB.dbcon.IsConnected())
if(!SSdbcore.IsConnected())
if(usr)
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
return
@@ -100,11 +124,11 @@
return
note_id = text2num(note_id)
var/target_ckey
var/sql_ckey = usr.ckey
var/DBQuery/query_find_note_edit = GLOB.dbcon.NewQuery("SELECT ckey, notetext, adminckey FROM [format_table_name("notes")] WHERE id = [note_id]")
if(!query_find_note_edit.Execute())
var/err = query_find_note_edit.ErrorMsg()
log_game("SQL ERROR obtaining notetext from notes table. Error : \[[err]\]\n")
var/datum/db_query/query_find_note_edit = SSdbcore.NewQuery("SELECT ckey, notetext, adminckey FROM [format_table_name("notes")] WHERE id=:note_id", list(
"note_id" = note_id
))
if(!query_find_note_edit.warn_execute())
qdel(query_find_note_edit)
return
if(query_find_note_edit.NextRow())
target_ckey = query_find_note_edit.item[1]
@@ -113,17 +137,20 @@
var/new_note = input("Input new note", "New Note", "[old_note]") as message|null
if(!new_note)
return
new_note = sanitizeSQL(new_note)
var/edit_text = "Edited by [sql_ckey] on [SQLtime()] from \"[old_note]\" to \"[new_note]\"<hr>"
edit_text = sanitizeSQL(edit_text)
var/DBQuery/query_update_note = GLOB.dbcon.NewQuery("UPDATE [format_table_name("notes")] SET notetext = '[new_note]', last_editor = '[sql_ckey]', edits = CONCAT(IFNULL(edits,''),'[edit_text]') WHERE id = [note_id]")
if(!query_update_note.Execute())
var/err = query_update_note.ErrorMsg()
log_game("SQL ERROR editing note. Error : \[[err]\]\n")
var/edit_text = "Edited by [usr.ckey] on [SQLtime()] from \"[old_note]\" to \"[new_note]\"<hr>"
var/datum/db_query/query_update_note = SSdbcore.NewQuery("UPDATE [format_table_name("notes")] SET notetext=:new_note, last_editor=:akey, edits = CONCAT(IFNULL(edits,''),:edit_text) WHERE id=:note_id", list(
"new_note" = new_note,
"akey" = usr.ckey,
"edit_text" = edit_text,
"note_id" = note_id
))
if(!query_update_note.warn_execute())
qdel(query_update_note)
return
log_admin("[usr ? key_name(usr) : "Bot"] has edited [target_ckey]'s note made by [adminckey] from \"[old_note]\" to \"[new_note]\"")
message_admins("[usr ? key_name_admin(usr) : "Bot"] has edited [target_ckey]'s note made by [adminckey] from \"[old_note]\" to \"[new_note]\"")
show_note(target_ckey)
qdel(query_update_note)
/proc/show_note(target_ckey, index, linkless = 0)
if(!check_rights(R_ADMIN|R_MOD))
@@ -143,10 +170,13 @@
output = navbar
if(target_ckey)
var/target_sql_ckey = ckey(target_ckey)
var/DBQuery/query_get_notes = GLOB.dbcon.NewQuery("SELECT id, timestamp, notetext, adminckey, last_editor, server, crew_playtime FROM [format_table_name("notes")] WHERE ckey = '[target_sql_ckey]' ORDER BY timestamp")
if(!query_get_notes.Execute())
var/err = query_get_notes.ErrorMsg()
log_game("SQL ERROR obtaining ckey, notetext, adminckey, last_editor, server, crew_playtime from notes table. Error : \[[err]\]\n")
var/datum/db_query/query_get_notes = SSdbcore.NewQuery({"
SELECT id, timestamp, notetext, adminckey, last_editor, server, crew_playtime
FROM [format_table_name("notes")] WHERE ckey=:targetkey ORDER BY timestamp"}, list(
"targetkey" = target_sql_ckey
))
if(!query_get_notes.warn_execute())
qdel(query_get_notes)
return
output += "<h2><center>Notes of [target_ckey]</center></h2>"
if(!linkless)
@@ -171,13 +201,12 @@
if(last_editor)
output += " <font size='2'>Last edit by [last_editor] <a href='?_src_=holder;noteedits=[id]'>(Click here to see edit log)</a></font>"
output += "<br>[notetext]<hr style='background:#000000; border:0; height:1px'>"
qdel(query_get_notes)
else if(index)
var/index_ckey
var/search
output += "<center><a href='?_src_=holder;addnoteempty=1'>\[Add Note\]</a></center>"
output += ruler
if(!isnum(index))
index = sanitizeSQL(index)
switch(index)
if(1)
search = "^."
@@ -185,10 +214,11 @@
search = "^\[^\[:alpha:\]\]"
else
search = "^[index]"
var/DBQuery/query_list_notes = GLOB.dbcon.NewQuery("SELECT DISTINCT ckey FROM [format_table_name("notes")] WHERE ckey REGEXP '[search]' ORDER BY ckey")
if(!query_list_notes.Execute())
var/err = query_list_notes.ErrorMsg()
log_game("SQL ERROR obtaining ckey from notes table. Error : \[[err]\]\n")
var/datum/db_query/query_list_notes = SSdbcore.NewQuery("SELECT DISTINCT ckey FROM [format_table_name("notes")] WHERE ckey REGEXP :search ORDER BY ckey", list(
"search" = search
))
if(!query_list_notes.warn_execute())
qdel(query_list_notes)
return
to_chat(usr, "<span class='notice'>Started regex note search for [search]. Please wait for results...</span>")
message_admins("[usr.ckey] has started a note search with the following regex: [search] | CPU usage may be higher.")
@@ -196,6 +226,7 @@
index_ckey = query_list_notes.item[1]
output += "<a href='?_src_=holder;shownoteckey=[index_ckey]'>[index_ckey]</a><br>"
CHECK_TICK
qdel(query_list_notes)
message_admins("The note search started by [usr.ckey] has complete. CPU should return to normal.")
else
output += "<center><a href='?_src_=holder;addnoteempty=1'>\[Add Note\]</a></center>"
+53 -28
View File
@@ -962,15 +962,17 @@
show_note(index = target)
else if(href_list["noteedits"])
var/note_id = sanitizeSQL("[href_list["noteedits"]]")
var/DBQuery/query_noteedits = GLOB.dbcon.NewQuery("SELECT edits FROM [format_table_name("notes")] WHERE id = '[note_id]'")
if(!query_noteedits.Execute())
var/err = query_noteedits.ErrorMsg()
log_game("SQL ERROR obtaining edits from notes table. Error : \[[err]\]\n")
var/note_id = text2num(href_list["noteedits"])
var/datum/db_query/query_noteedits = SSdbcore.NewQuery("SELECT edits FROM [format_table_name("notes")] WHERE id=:note_id", list(
"note_id" = note_id
))
if(!query_noteedits.warn_execute())
qdel(query_noteedits)
return
if(query_noteedits.NextRow())
var/edit_log = query_noteedits.item[1]
usr << browse(edit_log,"window=noteedits")
qdel(query_noteedits)
else if(href_list["removejobban"])
if(!check_rights(R_BAN)) return
@@ -1080,15 +1082,17 @@
usr.client.watchlist_show()
else if(href_list["watcheditlog"])
var/target_ckey = sanitizeSQL("[href_list["watcheditlog"]]")
var/DBQuery/query_watchedits = GLOB.dbcon.NewQuery("SELECT edits FROM [format_table_name("watch")] WHERE ckey = '[target_ckey]'")
if(!query_watchedits.Execute())
var/err = query_watchedits.ErrorMsg()
log_game("SQL ERROR obtaining edits from watch table. Error : \[[err]\]\n")
var/target_ckey = href_list["watcheditlog"]
var/datum/db_query/query_watchedits = SSdbcore.NewQuery("SELECT edits FROM [format_table_name("watch")] WHERE ckey=:targetkey", list(
"targetkey" = target_ckey
))
if(!query_watchedits.warn_execute())
qdel(query_watchedits)
return
if(query_watchedits.NextRow())
var/edit_log = query_watchedits.item[1]
usr << browse(edit_log,"window=watchedits")
qdel(query_watchedits)
else if(href_list["mute"])
if(!check_rights(R_ADMIN|R_MOD))
@@ -2784,15 +2788,17 @@
else if(href_list["memoeditlist"])
if(!check_rights(R_SERVER)) return
var/sql_key = sanitizeSQL("[href_list["memoeditlist"]]")
var/DBQuery/query_memoedits = GLOB.dbcon.NewQuery("SELECT edits FROM [format_table_name("memo")] WHERE (ckey = '[sql_key]')")
if(!query_memoedits.Execute())
var/err = query_memoedits.ErrorMsg()
log_game("SQL ERROR obtaining edits from memo table. Error : \[[err]\]\n")
var/sql_key = href_list["memoeditlist"]
var/datum/db_query/query_memoedits = SSdbcore.NewQuery("SELECT edits FROM [format_table_name("memo")] WHERE (ckey=:sql_key)", list(
"sql_key" = sql_key
))
if(!query_memoedits.warn_execute())
qdel(query_memoedits)
return
if(query_memoedits.NextRow())
var/edit_log = query_memoedits.item[1]
usr << browse(edit_log,"window=memoeditlist")
qdel(query_memoedits)
else if(href_list["secretsfun"])
if(!check_rights(R_SERVER|R_EVENT)) return
@@ -3370,13 +3376,14 @@
// Library stuff
else if(href_list["library_book_id"])
var/isbn = sanitizeSQL(href_list["library_book_id"])
var/isbn = text2num(href_list["library_book_id"])
if(href_list["view_library_book"])
var/DBQuery/query_view_book = GLOB.dbcon.NewQuery("SELECT content, title FROM [format_table_name("library")] WHERE id=[isbn]")
if(!query_view_book.Execute())
var/err = query_view_book.ErrorMsg()
log_game("SQL ERROR viewing book. Error : \[[err]\]\n")
var/datum/db_query/query_view_book = SSdbcore.NewQuery("SELECT content, title FROM [format_table_name("library")] WHERE id=:isbn", list(
"isbn" = isbn
))
if(!query_view_book.warn_execute())
qdel(query_view_book)
return
var/content = ""
@@ -3393,27 +3400,32 @@
popup.set_content(dat)
popup.open(0)
qdel(query_view_book)
log_admin("[key_name(usr)] has viewed the book [isbn].")
message_admins("[key_name_admin(usr)] has viewed the book [isbn].")
return
else if(href_list["unflag_library_book"])
var/DBQuery/query_unflag_book = GLOB.dbcon.NewQuery("UPDATE [format_table_name("library")] SET flagged = 0 WHERE id=[isbn]")
if(!query_unflag_book.Execute())
var/err = query_unflag_book.ErrorMsg()
log_game("SQL ERROR unflagging book. Error : \[[err]\]\n")
var/datum/db_query/query_unflag_book = SSdbcore.NewQuery("UPDATE [format_table_name("library")] SET flagged = 0 WHERE id=:isbn", list(
"isbn" = isbn
))
if(!query_unflag_book.warn_execute())
qdel(query_unflag_book)
return
qdel(query_unflag_book)
log_admin("[key_name(usr)] has unflagged the book [isbn].")
message_admins("[key_name_admin(usr)] has unflagged the book [isbn].")
else if(href_list["delete_library_book"])
var/DBQuery/query_delbook = GLOB.dbcon.NewQuery("DELETE FROM [format_table_name("library")] WHERE id=[isbn]")
if(!query_delbook.Execute())
var/err = query_delbook.ErrorMsg()
log_game("SQL ERROR deleting book. Error : \[[err]\]\n")
var/datum/db_query/query_delbook = SSdbcore.NewQuery("DELETE FROM [format_table_name("library")] WHERE id=:isbn", list(
"isbn" = isbn
))
if(!query_delbook.warn_execute())
qdel(query_delbook)
return
qdel(query_delbook)
log_admin("[key_name(usr)] has deleted the book [isbn].")
message_admins("[key_name_admin(usr)] has deleted the book [isbn].")
@@ -3446,6 +3458,19 @@
if(!check_rights(R_ADMIN))
return
create_ccbdb_lookup(href_list["open_ccbdb"])
else if(href_list["slowquery"])
if(!check_rights(R_ADMIN))
return
message_admins("[key_name_admin(usr)] started responding to a query hang report") // So multiple admins dont try file the same report
var/answer = href_list["slowquery"]
if(answer == "yes")
log_sql("[usr.key] | Reported a server hang")
if(alert(usr, "Had you just pressed any admin buttons which could lag the server?", "Query server hang report", "Yes", "No") == "Yes")
var/response = input(usr,"What were you just doing?","Query server hang report") as null|text
if(response)
log_sql("[usr.key] | [response]")
else if(answer == "no")
log_sql("[usr.key] | Reported no server hang. Please investigate")
/client/proc/create_eventmob_for(var/mob/living/carbon/human/H, var/killthem = 0)
+59 -42
View File
@@ -5,31 +5,36 @@
var/new_ckey = ckey(clean_input("Who would you like to add to the watchlist?","Enter a ckey",null))
if(!new_ckey)
return
new_ckey = sanitizeSQL(new_ckey)
var/DBQuery/query_watchfind = GLOB.dbcon.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE ckey = '[new_ckey]'")
if(!query_watchfind.Execute())
var/err = query_watchfind.ErrorMsg()
log_game("SQL ERROR obtaining ckey from player table. Error : \[[err]\]\n")
var/datum/db_query/query_watchfind = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE ckey=:new_ckey", list(
"new_ckey" = new_ckey
))
if(!query_watchfind.warn_execute())
qdel(query_watchfind)
return
if(!query_watchfind.NextRow())
to_chat(usr, "<span class='redtext'>[new_ckey] has not been seen before, you can only add known players.</span>")
qdel(query_watchfind)
return
else
target_ckey = new_ckey
var/target_sql_ckey = sanitizeSQL(target_ckey)
if(check_watchlist(target_sql_ckey))
to_chat(usr, "<span class='redtext'>[target_sql_ckey] is already on the watchlist.</span>")
if(check_watchlist(target_ckey))
to_chat(usr, "<span class='redtext'>[target_ckey] is already on the watchlist.</span>")
return
var/reason = input(usr,"Please state the reason","Reason") as message|null
if(!reason)
return
reason = sanitizeSQL(reason)
var/timestamp = SQLtime()
var/adminckey = usr.ckey
if(!adminckey)
return
var/admin_sql_ckey = sanitizeSQL(adminckey)
var/DBQuery/query_watchadd = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("watch")] (ckey, reason, adminckey, timestamp) VALUES ('[target_sql_ckey]', '[reason]', '[admin_sql_ckey]', '[timestamp]')")
var/datum/db_query/query_watchadd = SSdbcore.NewQuery({"
INSERT INTO [format_table_name("watch")] (ckey, reason, adminckey, timestamp)
VALUES (:targetkey, :reason, :adminkey, NOW())"},
list(
"targetkey" = target_ckey,
"reason" = reason,
"adminkey" = adminckey
)
)
if(!query_watchadd.Execute())
var/err = query_watchadd.ErrorMsg()
log_game("SQL ERROR during adding new watch entry. Error : \[[err]\]\n")
@@ -37,17 +42,18 @@
log_admin("[key_name(usr)] has added [target_ckey] to the watchlist - Reason: [reason]")
message_admins("[key_name_admin(usr)] has added [target_ckey] to the watchlist - Reason: [reason]", 1)
if(browse)
watchlist_show(target_sql_ckey)
watchlist_show(target_ckey)
/client/proc/watchlist_remove(target_ckey, browse = 0)
if(!check_rights(R_ADMIN))
return
var/target_sql_ckey = sanitizeSQL(target_ckey)
var/DBQuery/query_watchdel = GLOB.dbcon.NewQuery("DELETE FROM [format_table_name("watch")] WHERE ckey = '[target_sql_ckey]'")
if(!query_watchdel.Execute())
var/err = query_watchdel.ErrorMsg()
log_game("SQL ERROR during removing watch entry. Error : \[[err]\]\n")
var/datum/db_query/query_watchdel = SSdbcore.NewQuery("DELETE FROM [format_table_name("watch")] WHERE ckey=:target_ckey", list(
"target_ckey" = target_ckey
))
if(!query_watchdel.warn_execute())
qdel(query_watchdel)
return
qdel(query_watchdel)
log_admin("[key_name(usr)] has removed [target_ckey] from the watchlist")
message_admins("[key_name_admin(usr)] has removed [target_ckey] from the watchlist", 1)
if(browse)
@@ -56,30 +62,36 @@
/client/proc/watchlist_edit(target_ckey, browse = 0)
if(!check_rights(R_ADMIN))
return
var/target_sql_ckey = sanitizeSQL(target_ckey)
var/DBQuery/query_watchreason = GLOB.dbcon.NewQuery("SELECT reason FROM [format_table_name("watch")] WHERE ckey = '[target_sql_ckey]'")
if(!query_watchreason.Execute())
var/err = query_watchreason.ErrorMsg()
log_game("SQL ERROR obtaining reason from watch table. Error : \[[err]\]\n")
var/datum/db_query/query_watchreason = SSdbcore.NewQuery("SELECT reason FROM [format_table_name("watch")] WHERE ckey=:target_ckey", list(
"target_ckey" = target_ckey
))
if(!query_watchreason.warn_execute())
qdel(query_watchreason)
return
if(query_watchreason.NextRow())
var/watch_reason = query_watchreason.item[1]
var/new_reason = input("Input the new reason", "New Reason", "[watch_reason]") as message|null
new_reason = sanitizeSQL(new_reason)
if(!new_reason || new_reason == watch_reason)
return
var/sql_ckey = sanitizeSQL(usr.ckey)
var/sql_ckey = usr.ckey
var/edit_text = "Edited by [sql_ckey] on [SQLtime()] from \"[watch_reason]\" to \"[new_reason]\""
edit_text = sanitizeSQL(edit_text)
var/DBQuery/query_watchupdate = GLOB.dbcon.NewQuery("UPDATE [format_table_name("watch")] SET reason = '[new_reason]', last_editor = '[sql_ckey]', edits = CONCAT(IFNULL(edits,''),'[edit_text]') WHERE ckey = '[target_sql_ckey]'")
if(!query_watchupdate.Execute())
var/err = query_watchupdate.ErrorMsg()
log_game("SQL ERROR editing watchlist reason. Error : \[[err]\]\n")
var/datum/db_query/query_watchupdate = SSdbcore.NewQuery("UPDATE [format_table_name("watch")] SET reason=:new_reason, last_editor=:sql_ckey, edits = CONCAT(IFNULL(edits,''), :edit_text) WHERE ckey=:target_ckey", list(
"new_reason" = new_reason,
"sql_ckey" = sql_ckey,
"edit_text" = edit_text,
"target_ckey" = target_ckey
))
if(!query_watchupdate.warn_execute())
qdel(query_watchupdate)
qdel(query_watchreason)
return
qdel(query_watchupdate)
log_admin("[key_name(usr)] has edited [target_ckey]'s watchlist reason from \"[watch_reason]\" to \"[new_reason]\"")
message_admins("[key_name_admin(usr)] has edited [target_ckey]'s watchlist reason from \"[watch_reason]\" to \"[new_reason]\"")
if(browse)
watchlist_show(target_sql_ckey)
watchlist_show(target_ckey)
qdel(query_watchreason)
/client/proc/watchlist_show(search)
if(!check_rights(R_ADMIN))
@@ -95,11 +107,12 @@
search = "^[search]"
else
search = "^."
search = sanitizeSQL(search)
var/DBQuery/query_watchlist = GLOB.dbcon.NewQuery("SELECT ckey, reason, adminckey, timestamp, last_editor FROM [format_table_name("watch")] WHERE ckey REGEXP '[search]' ORDER BY ckey")
if(!query_watchlist.Execute())
var/err = query_watchlist.ErrorMsg()
log_game("SQL ERROR obtaining ckey, reason, adminckey, timestamp, last_editor from watch table. Error : \[[err]\]\n")
var/datum/db_query/query_watchlist = SSdbcore.NewQuery("SELECT ckey, reason, adminckey, timestamp, last_editor FROM [format_table_name("watch")] WHERE ckey REGEXP :search ORDER BY ckey", list(
"search" = search
))
if(!query_watchlist.warn_execute())
qdel(query_watchlist)
return
while(query_watchlist.NextRow())
var/ckey = query_watchlist.item[1]
@@ -112,15 +125,19 @@
output += " <font size='2'>Last edit by [last_editor] <a href='?_src_=holder;watcheditlog=[ckey]'>(Click here to see edit log)</a></font>"
output += "<br>[reason]<hr style='background:#000000; border:0; height:1px'>"
usr << browse(output, "window=watchwin;size=900x500")
qdel(query_watchlist)
/proc/check_watchlist(target_ckey)
var/target_sql_ckey = sanitizeSQL(target_ckey)
var/DBQuery/query_watch = GLOB.dbcon.NewQuery("SELECT reason FROM [format_table_name("watch")] WHERE ckey = '[target_sql_ckey]'")
if(!query_watch.Execute())
var/err = query_watch.ErrorMsg()
log_game("SQL ERROR obtaining reason from watch table. Error : \[[err]\]\n")
var/datum/db_query/query_watch = SSdbcore.NewQuery("SELECT reason FROM [format_table_name("watch")] WHERE ckey=:target_ckey", list(
"target_ckey" = target_ckey
))
if(!query_watch.warn_execute())
qdel(query_watch)
return
if(query_watch.NextRow())
return query_watch.item[1]
var/entry = query_watch.item[1]
qdel(query_watch)
return entry
else
qdel(query_watch)
return 0
+149 -143
View File
@@ -188,73 +188,6 @@
if("prefs") return prefs.process_link(usr,href_list)
if("vars") return view_var_Topic(href,href_list,hsrc)
//Polls and shit
if(href_list["showpoll"])
handle_player_polling()
return
if(href_list["createpollwindow"])
create_poll_window()
return
if(href_list["createpoll"])
create_poll_function(href_list)
return
if(href_list["pollid"])
var/pollid = href_list["pollid"]
if(istext(pollid))
pollid = text2num(pollid)
if(isnum(pollid))
poll_player(pollid)
return
if(href_list["pollresults"])
var/pollid = href_list["pollresults"]
if(istext(pollid))
pollid = text2num(pollid)
if(isnum(pollid))
poll_results(pollid)
if(href_list["votepollid"] && href_list["votetype"])
if(!can_vote())
return // No voting.
var/pollid = text2num(href_list["votepollid"])
var/votetype = href_list["votetype"]
switch(votetype)
if("OPTION")
var/optionid = text2num(href_list["voteoptionid"])
vote_on_poll(pollid, optionid)
if("TEXT")
var/replytext = href_list["replytext"]
log_text_poll_reply(pollid, replytext)
if("NUMVAL")
var/id_min = text2num(href_list["minid"])
var/id_max = text2num(href_list["maxid"])
if( (id_max - id_min) > 100 ) //Basic exploit prevention
to_chat(usr, "The option ID difference is too big. Please contact administration or the database admin.")
return
for(var/optionid = id_min; optionid <= id_max; optionid++)
if(!isnull(href_list["o[optionid]"])) //Test if this optionid was replied to
var/rating
if(href_list["o[optionid]"] == "abstain")
rating = null
else
rating = text2num(href_list["o[optionid]"])
if(!isnum(rating))
return
vote_on_numval_poll(pollid, optionid, rating)
if("MULTICHOICE")
var/id_min = text2num(href_list["minoptionid"])
var/id_max = text2num(href_list["maxoptionid"])
if( (id_max - id_min) > 100 ) //Basic exploit prevention
to_chat(usr, "The option ID difference is too big. Please contact administration or the database admin.")
return
for(var/optionid = id_min; optionid <= id_max; optionid++)
if(!isnull(href_list["option_[optionid]"])) //Test if this optionid was selected
vote_on_poll(pollid, optionid, 1)
src << browse(null, "window=playerpoll")
handle_player_polling()
if(href_list["ssdwarning"])
ssd_warning_acknowledged = TRUE
to_chat(src, "<span class='notice'>SSD warning acknowledged.</span>")
@@ -337,8 +270,6 @@
to_chat(src, "<span class='warning'>If the title screen is black, resources are still downloading. Please be patient until the title screen appears.</span>")
GLOB.clients += src
GLOB.directory[ckey] = src
//Admin Authorisation
// Automatically makes localhost connection an admin
@@ -362,6 +293,12 @@
if(world.byond_version >= 511 && byond_version >= 511 && prefs.clientfps)
fps = prefs.clientfps
// This has to go here to avoid issues
// If you sleep past this point, you will get SSinput errors as well as goonchat errors
// DO NOT STUFF RANDOM SQL QUERIES BELOW THIS POINT WITHOUT USING `INVOKE_ASYNC()` OR SIMILAR
// YOU WILL BREAK STUFF. SERIOUSLY. -aa07
GLOB.clients += src
spawn() // Goonchat does some non-instant checks in start()
chatOutput.start()
@@ -372,7 +309,8 @@
if(holder)
on_holder_add()
add_admin_verbs()
admin_memo_output("Show", 0, 1)
// Must be async because any sleeps (happen in sql queries) will break connectings clients
INVOKE_ASYNC(src, .proc/admin_memo_output, "Show", FALSE, TRUE)
// Forcibly enable hardware-accelerated graphics, as we need them for the lighting overlays.
// (but turn them off first, since sometimes BYOND doesn't turn them on properly otherwise)
@@ -382,7 +320,6 @@
winset(src, null, "command=\".configure graphics-hwmode on\"")
log_client_to_db(tdata)
. = ..() //calls mob.Login()
@@ -406,11 +343,9 @@
if(prefs.toggles & PREFTOGGLE_DISABLE_KARMA) // activates if karma is disabled
if(establish_db_connection())
to_chat(src,"<span class='notice'>You have disabled karma gains.") // reminds those who have it disabled
to_chat(src,"<span class='notice'>You have disabled karma gains.") // reminds those who have it disabled
else
if(establish_db_connection())
to_chat(src,"<span class='notice'>You have enabled karma gains.")
to_chat(src,"<span class='notice'>You have enabled karma gains.")
generate_clickcatcher()
apply_clickcatcher()
@@ -482,11 +417,11 @@
/client/proc/donator_check()
set waitfor = FALSE // This needs to run async because any sleep() inside /client/New() breaks stuff badly
if(IsGuestKey(key))
return
establish_db_connection()
if(!GLOB.dbcon.IsConnected())
if(!SSdbcore.IsConnected())
return
if(check_rights(R_ADMIN, 0, mob)) // Yes, the mob is required, regardless of other examples in this file, it won't work otherwise
@@ -495,33 +430,44 @@
return
//Donator stuff.
var/DBQuery/query_donor_select = GLOB.dbcon.NewQuery("SELECT ckey, tier, active FROM `[format_table_name("donators")]` WHERE ckey = '[ckey]'")
query_donor_select.Execute()
var/datum/db_query/query_donor_select = SSdbcore.NewQuery("SELECT ckey, tier, active FROM `[format_table_name("donators")]` WHERE ckey=:ckey", list(
"ckey" = ckey
))
if(!query_donor_select.warn_execute())
qdel(query_donor_select)
return
while(query_donor_select.NextRow())
if(!text2num(query_donor_select.item[3]))
// Inactive donator.
donator_level = 0
qdel(query_donor_select)
return
donator_level = text2num(query_donor_select.item[2])
donor_loadout_points()
break
qdel(query_donor_select)
/client/proc/donor_loadout_points()
if(donator_level > 0 && prefs)
prefs.max_gear_slots = config.max_loadout_points + 5
/client/proc/log_client_to_db(connectiontopic)
set waitfor = FALSE // This needs to run async because any sleep() inside /client/New() breaks stuff badly
if(IsGuestKey(key))
return
establish_db_connection()
if(!GLOB.dbcon.IsConnected())
if(!SSdbcore.IsConnected())
return
var/datum/db_query/query = SSdbcore.NewQuery("SELECT id, datediff(Now(),firstseen) as age FROM [format_table_name("player")] WHERE ckey=:ckey", list(
"ckey" = ckey
))
if(!query.warn_execute())
qdel(query)
return
var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT id, datediff(Now(),firstseen) as age FROM [format_table_name("player")] WHERE ckey = '[ckey]'")
query.Execute()
var/sql_id = 0
player_age = 0 // New players won't have an entry so knowing we have a connection we set this to zero to be updated if there is a record.
while(query.NextRow())
@@ -529,22 +475,33 @@
player_age = text2num(query.item[2])
break
var/DBQuery/query_ip = GLOB.dbcon.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE ip = '[address]'")
query_ip.Execute()
qdel(query)
var/datum/db_query/query_ip = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE ip=:address", list(
"address" = address
))
if(!query_ip.warn_execute())
qdel(query_ip)
return
related_accounts_ip = list()
while(query_ip.NextRow())
if(ckey != query_ip.item[1])
related_accounts_ip.Add("[query_ip.item[1]]")
qdel(query_ip)
var/datum/db_query/query_cid = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE computerid=:cid", list(
"cid" = computer_id
))
if(!query_cid.warn_execute())
qdel(query_cid)
return
var/DBQuery/query_cid = GLOB.dbcon.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE computerid = '[computer_id]'")
query_cid.Execute()
related_accounts_cid = list()
while(query_cid.NextRow())
if(ckey != query_cid.item[1])
related_accounts_cid.Add("[query_cid.item[1]]")
qdel(query_cid)
var/admin_rank = "Player"
if(holder)
@@ -573,18 +530,19 @@
if(!isnum(sql_id))
return
var/sql_ip = sanitizeSQL(address)
var/sql_computerid = sanitizeSQL(computer_id)
var/sql_admin_rank = sanitizeSQL(admin_rank)
if(sql_id)
//Player already identified previously, we need to just update the 'lastseen', 'ip' and 'computer_id' variables
var/DBQuery/query_update = GLOB.dbcon.NewQuery("UPDATE [format_table_name("player")] SET lastseen = Now(), ip = '[sql_ip]', computerid = '[sql_computerid]', lastadminrank = '[sql_admin_rank]' WHERE id = [sql_id]")
if(!query_update.Execute())
var/err = query_update.ErrorMsg()
log_game("SQL ERROR during log_client_to_db (update). Error : \[[err]\]\n")
message_admins("SQL ERROR during log_client_to_db (update). Error : \[[err]\]\n")
var/datum/db_query/query_update = SSdbcore.NewQuery("UPDATE [format_table_name("player")] SET lastseen = Now(), ip=:sql_ip, computerid=:sql_cid, lastadminrank=:sql_ar WHERE id=:sql_id", list(
"sql_ip" = address,
"sql_cid" = computer_id,
"sql_ar" = admin_rank,
"sql_id" = sql_id
))
if(!query_update.warn_execute())
qdel(query_update)
return
qdel(query_update)
// After the regular update
INVOKE_ASYNC(src, /client/.proc/get_byond_account_date, FALSE) // Async to avoid other procs in the client chain being delayed by a web request
else
@@ -597,18 +555,30 @@
qdel(src)
return // Dont insert or they can just go in again
var/DBQuery/query_insert = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("player")] (id, ckey, firstseen, lastseen, ip, computerid, lastadminrank) VALUES (null, '[ckey]', Now(), Now(), '[sql_ip]', '[sql_computerid]', '[sql_admin_rank]')")
if(!query_insert.Execute())
var/err = query_insert.ErrorMsg()
log_game("SQL ERROR during log_client_to_db (insert). Error : \[[err]\]\n")
message_admins("SQL ERROR during log_client_to_db (insert). Error : \[[err]\]\n")
var/datum/db_query/query_insert = SSdbcore.NewQuery("INSERT INTO [format_table_name("player")] (id, ckey, firstseen, lastseen, ip, computerid, lastadminrank) VALUES (null, :ckey, Now(), Now(), :ip, :cid, :rank)", list(
"ckey" = ckey,
"ip" = address,
"cid" = computer_id,
"rank" = admin_rank
))
if(!query_insert.warn_execute())
qdel(query_insert)
return
qdel(query_insert)
// This is their first connection instance, so TRUE here to nofiy admins
// This needs to happen here to ensure they actually have a row to update
INVOKE_ASYNC(src, /client/.proc/get_byond_account_date, TRUE) // Async to avoid other procs in the client chain being delayed by a web request
// Log player connections to DB
var/DBQuery/query_accesslog = GLOB.dbcon.NewQuery("INSERT INTO `[format_table_name("connection_log")]`(`datetime`,`ckey`,`ip`,`computerid`) VALUES(Now(),'[ckey]','[sql_ip]','[sql_computerid]');")
query_accesslog.Execute()
var/datum/db_query/query_accesslog = SSdbcore.NewQuery("INSERT INTO `[format_table_name("connection_log")]`(`datetime`,`ckey`,`ip`,`computerid`) VALUES(Now(), :ckey, :ip, :cid)", list(
"ckey" = ckey,
"ip" = address,
"cid" = computer_id
))
// We do nothing with output here, or anything else after, so we dont need to if() wrap it
// If you ever extend this proc below this point, please wrap these with an if() in the same way its done above
query_accesslog.warn_execute()
qdel(query_accesslog)
/client/proc/check_ip_intel()
set waitfor = 0 //we sleep when getting the intel, no need to hold up the client connection while we sleep
@@ -655,16 +625,29 @@
to_chat(src, "<B>You have no verified forum account. <a href='?src=[UID()];link_forum_account=true'>VERIFY FORUM ACCOUNT</a></B>")
/client/proc/create_oauth_token()
var/DBQuery/query_find_token = GLOB.dbcon.NewQuery("SELECT token FROM [format_table_name("oauth_tokens")] WHERE ckey = '[ckey]' limit 1")
if(!query_find_token.Execute())
log_debug("create_oauth_token: failed db read")
var/datum/db_query/query_find_token = SSdbcore.NewQuery("SELECT token FROM [format_table_name("oauth_tokens")] WHERE ckey=:ckey limit 1", list(
"ckey" = ckey
))
// These queries have log_error=FALSE to avoid auth tokens being in plaintext logs
if(!query_find_token.warn_execute(log_error=FALSE))
qdel(query_find_token)
return
if(query_find_token.NextRow())
qdel(query_find_token)
return query_find_token.item[1]
qdel(query_find_token)
var/tokenstr = md5("[rand(0,9999)][world.time][rand(0,9999)][ckey][rand(0,9999)][address][rand(0,9999)][computer_id][rand(0,9999)]")
var/DBQuery/query_insert_token = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("oauth_tokens")] (ckey, token) VALUES('[ckey]','[tokenstr]')")
if(!query_insert_token.Execute())
var/datum/db_query/query_insert_token = SSdbcore.NewQuery("INSERT INTO [format_table_name("oauth_tokens")] (ckey, token) VALUES(:ckey, :tokenstr)", list(
"ckey" = ckey,
"tokenstr" = tokenstr,
))
// These queries have log_error=FALSE to avoid auth tokens being in plaintext logs
if(!query_insert_token.warn_execute(log_error=FALSE))
qdel(query_insert_token)
return
qdel(query_insert_token)
return tokenstr
/client/proc/link_forum_account(fromban)
@@ -677,15 +660,19 @@
if(!fromban)
to_chat(src, "Your forum account is already set.")
return
var/DBQuery/query_find_link = GLOB.dbcon.NewQuery("SELECT fuid FROM [format_table_name("player")] WHERE ckey = '[ckey]' limit 1")
if(!query_find_link.Execute())
log_debug("link_forum_account: failed db read")
var/datum/db_query/query_find_link = SSdbcore.NewQuery("SELECT fuid FROM [format_table_name("player")] WHERE ckey=:ckey LIMIT 1", list(
"ckey" = ckey
))
if(!query_find_link.warn_execute())
qdel(query_find_link)
return
if(query_find_link.NextRow())
if(query_find_link.item[1])
if(!fromban)
to_chat(src, "Your forum account is already set. (" + query_find_link.item[1] + ")")
qdel(query_find_link)
return
qdel(query_find_link)
var/tokenid = create_oauth_token()
if(!tokenid)
to_chat(src, "link_forum_account: unable to create token")
@@ -705,6 +692,7 @@
// Returns true if a randomizer is being used
/client/proc/check_randomizer(topic)
set waitfor = FALSE // Yes I know this is already called from an async proc but someone may change that without thinking properly
. = FALSE
if(connection != "seeker") //Invalid connection type.
return null
@@ -721,12 +709,17 @@
var/oldcid = cidcheck[ckey]
if(!oldcid)
var/DBQuery/query_cidcheck = GLOB.dbcon.NewQuery("SELECT computerid FROM [format_table_name("player")] WHERE ckey = '[ckey]'")
query_cidcheck.Execute()
var/datum/db_query/query_cidcheck = SSdbcore.NewQuery("SELECT computerid FROM [format_table_name("player")] WHERE ckey=:ckey", list(
"ckey" = ckey
))
if(!query_cidcheck.warn_execute())
qdel(query_cidcheck)
return
var/lastcid = computer_id
if(query_cidcheck.NextRow())
lastcid = query_cidcheck.item[1]
qdel(query_cidcheck)
if(computer_id != lastcid)
// Their current CID does not match what the DB says - OFF WITH THEIR HEAD
@@ -786,23 +779,30 @@
var/const/adminckey = "CID-Error"
// Check for notes in the last day - only 1 note per 24 hours
var/DBQuery/query_get_notes = GLOB.dbcon.NewQuery("SELECT id from [format_table_name("notes")] WHERE ckey = '[ckey]' AND adminckey = '[adminckey]' AND timestamp + INTERVAL 1 DAY < NOW()")
if(!query_get_notes.Execute())
var/err = query_get_notes.ErrorMsg()
log_game("SQL ERROR obtaining id from notes table. Error : \[[err]\]\n")
var/datum/db_query/query_get_notes = SSdbcore.NewQuery("SELECT id from [format_table_name("notes")] WHERE ckey=:ckey AND adminckey=:adminckey AND timestamp + INTERVAL 1 DAY < NOW()", list(
"ckey" = ckey,
"adminckey" = adminckey
))
if(!query_get_notes.warn_execute())
qdel(query_get_notes)
return
if(query_get_notes.NextRow())
qdel(query_get_notes)
return
qdel(query_get_notes)
// Only add a note if their most recent note isn't from the randomizer blocker, either
query_get_notes = GLOB.dbcon.NewQuery("SELECT adminckey FROM [format_table_name("notes")] WHERE ckey = '[ckey]' ORDER BY timestamp DESC LIMIT 1")
if(!query_get_notes.Execute())
var/err = query_get_notes.ErrorMsg()
log_game("SQL ERROR obtaining adminckey from notes table. Error : \[[err]\]\n")
var/datum/db_query/query_get_note = SSdbcore.NewQuery("SELECT adminckey FROM [format_table_name("notes")] WHERE ckey=:ckey ORDER BY timestamp DESC LIMIT 1", list(
"ckey" = ckey
))
if(!query_get_note.warn_execute())
qdel(query_get_note)
return
if(query_get_notes.NextRow())
if(query_get_notes.item[1] == adminckey)
if(query_get_note.NextRow())
if(query_get_note.item[1] == adminckey)
qdel(query_get_note)
return
qdel(query_get_note)
add_note(ckey, "Detected as using a cid randomizer.", null, adminckey, logged = 0)
/client/proc/cid_check_reconnect()
@@ -1043,17 +1043,19 @@
/client/proc/get_byond_account_date(notify = FALSE)
// First we see if the client has a saved date in the DB
var/sql_ckey = sanitizeSQL(ckey)
var/DBQuery/query_date = GLOB.dbcon.NewQuery("SELECT byond_date, DATEDIFF(Now(), byond_date) FROM [format_table_name("player")] WHERE ckey = '[sql_ckey]'")
if(!query_date.Execute())
var/err = query_date.ErrorMsg()
log_game("SQL ERROR during get_byond_account_date (Line 1047). Error: \[[err]\]\n")
message_admins("SQL ERROR during get_byond_account_date (Line 1047). Error: \[[err]\]\n")
var/datum/db_query/query_date = SSdbcore.NewQuery("SELECT byond_date, DATEDIFF(Now(), byond_date) FROM [format_table_name("player")] WHERE ckey=:ckey", list(
"ckey" = ckey
))
if(!query_date.warn_execute())
qdel(query_date)
return
while(query_date.NextRow())
byondacc_date = query_date.item[1]
byondacc_age = max(text2num(query_date.item[2]), 0) // Ensure account isnt negative days old
qdel(query_date)
// They have a date, lets bail
if(byondacc_date)
return
@@ -1067,22 +1069,26 @@
byondacc_date = byond_data["general"]["joined"]
// Now save it
var/sql_date = sanitizeSQL(byondacc_date) // Yes, this is top level paranoia
var/DBQuery/query_update = GLOB.dbcon.NewQuery("UPDATE [format_table_name("player")] SET byond_date = '[sql_date]' WHERE ckey = '[sql_ckey]'")
if(!query_update.Execute())
var/err = query_update.ErrorMsg()
log_game("SQL ERROR during get_byond_account_date (Line 1071). Error: \[[err]\]\n")
message_admins("SQL ERROR during get_byond_account_date (Line 1071). Error: \[[err]\]\n")
var/datum/db_query/query_update = SSdbcore.NewQuery("UPDATE [format_table_name("player")] SET byond_date=:date WHERE ckey=:ckey", list(
"date" = byondacc_date,
"ckey" = ckey
))
if(!query_update.warn_execute())
qdel(query_update)
return
qdel(query_update)
// Now retrieve the age again because BYOND doesnt have native methods for this
var/DBQuery/query_age = GLOB.dbcon.NewQuery("SELECT DATEDIFF(Now(), byond_date) FROM [format_table_name("player")] WHERE ckey = '[sql_ckey]'")
if(!query_age.Execute())
var/err = query_age.ErrorMsg()
log_game("SQL ERROR during get_byond_account_date (Line 1078). Error: \[[err]\]\n")
message_admins("SQL ERROR during get_byond_account_date (Line 1078). Error: \[[err]\]\n")
var/datum/db_query/query_age = SSdbcore.NewQuery("SELECT DATEDIFF(Now(), byond_date) FROM [format_table_name("player")] WHERE ckey=:ckey", list(
"ckey" = ckey
))
if(!query_age.warn_execute())
qdel(query_age)
return
while(query_age.NextRow())
byondacc_age = max(text2num(query_age.item[1]), 0) // Ensure account isnt negative days old
qdel(query_age)
// Notify admins on new clients connecting, if the byond account age is less than a config value
if(notify && (byondacc_age < config.byond_account_age_threshold))
@@ -2306,16 +2306,18 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
/datum/preferences/proc/open_load_dialog(mob/user)
var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT slot,real_name FROM [format_table_name("characters")] WHERE ckey='[user.ckey]' ORDER BY slot")
var/datum/db_query/query = SSdbcore.NewQuery("SELECT slot, real_name FROM [format_table_name("characters")] WHERE ckey=:ckey ORDER BY slot", list(
"ckey" = user.ckey
))
var/list/slotnames[max_save_slots]
if(!query.Execute())
var/err = query.ErrorMsg()
log_game("SQL ERROR during character slot loading. Error : \[[err]\]\n")
message_admins("SQL ERROR during character slot loading. Error : \[[err]\]\n")
if(!query.warn_execute())
qdel(query)
return
while(query.NextRow())
slotnames[text2num(query.item[1])] = query.item[2]
qdel(query)
var/dat = "<body>"
dat += "<tt><center>"
@@ -1,6 +1,6 @@
/datum/preferences/proc/load_preferences(client/C)
var/DBQuery/query = GLOB.dbcon.NewQuery({"SELECT
var/datum/db_query/query = SSdbcore.NewQuery({"SELECT
ooccolor,
UI_style,
UI_style_color,
@@ -18,13 +18,12 @@
fuid,
parallax
FROM [format_table_name("player")]
WHERE ckey='[C.ckey]'"}
)
WHERE ckey=:ckey"}, list(
"ckey" = C.ckey
))
if(!query.Execute())
var/err = query.ErrorMsg()
log_game("SQL ERROR during loading player preferences. Error : \[[err]\]\n")
message_admins("SQL ERROR during loading player preferences. Error : \[[err]\]\n")
if(!query.warn_execute())
qdel(query)
return
@@ -47,6 +46,8 @@
fuid = text2num(query.item[15])
parallax = text2num(query.item[16])
qdel(query)
//Sanitize
ooccolor = sanitize_hexcolor(ooccolor, initial(ooccolor))
UI_style = sanitize_inlist(UI_style, list("White", "Midnight"), initial(UI_style))
@@ -73,30 +74,48 @@
log_runtime(EXCEPTION("[C.key] had a malformed role entry: '[role]'. Removing!"), src)
be_special -= role
var/DBQuery/query = GLOB.dbcon.NewQuery({"UPDATE [format_table_name("player")]
var/datum/db_query/query = SSdbcore.NewQuery({"UPDATE [format_table_name("player")]
SET
ooccolor='[ooccolor]',
UI_style='[UI_style]',
UI_style_color='[UI_style_color]',
UI_style_alpha='[UI_style_alpha]',
be_role='[sanitizeSQL(list2params(be_special))]',
default_slot='[default_slot]',
toggles='[num2text(toggles, CEILING(log(10, (TOGGLES_TOTAL)), 1))]',
toggles_2='[num2text(toggles2, CEILING(log(10, (TOGGLES_2_TOTAL)), 1))]',
atklog='[atklog]',
sound='[sound]',
volume='[volume]',
lastchangelog='[lastchangelog]',
clientfps='[clientfps]',
parallax='[parallax]'
WHERE ckey='[C.ckey]'"}
ooccolor=:ooccolour,
UI_style=:ui_style,
UI_style_color=:ui_colour,
UI_style_alpha=:ui_alpha,
be_role=:berole,
default_slot=:defaultslot,
toggles=:toggles,
toggles_2=:toggles2,
atklog=:atklog,
sound=:sound,
volume=:volume,
lastchangelog=:lastchangelog,
clientfps=:clientfps,
parallax=:parallax
WHERE ckey=:ckey"}, list(
// OH GOD THE PARAMETERS
"ooccolour" = ooccolor,
"ui_style" = UI_style,
"ui_colour" = UI_style_color,
"ui_alpha" = UI_style_alpha,
"berole" = list2params(be_special),
"defaultslot" = default_slot,
// Even though its a number in the DB, you have to use num2text here, otherwise byond adds scientific notation to the number
"toggles" = num2text(toggles, CEILING(log(10, (TOGGLES_TOTAL)), 1)),
"toggles2" = num2text(toggles2, CEILING(log(10, (TOGGLES_2_TOTAL)), 1)),
"atklog" = atklog,
"sound" = sound,
"volume" = volume,
"lastchangelog" = lastchangelog,
"clientfps" = clientfps,
"parallax" = parallax,
"ckey" = C.ckey
)
)
if(!query.Execute())
var/err = query.ErrorMsg()
log_game("SQL ERROR during saving player preferences. Error : \[[err]\]\n")
message_admins("SQL ERROR during saving player preferences. Error : \[[err]\]\n")
if(!query.warn_execute())
qdel(query)
return
qdel(query)
return 1
/datum/preferences/proc/load_character(client/C,slot)
@@ -106,11 +125,17 @@
slot = sanitize_integer(slot, 1, max_save_slots, initial(default_slot))
if(slot != default_slot)
default_slot = slot
var/DBQuery/firstquery = GLOB.dbcon.NewQuery("UPDATE [format_table_name("player")] SET default_slot=[slot] WHERE ckey='[C.ckey]'")
firstquery.Execute()
var/datum/db_query/firstquery = SSdbcore.NewQuery("UPDATE [format_table_name("player")] SET default_slot=:slot WHERE ckey=:ckey", list(
"slot" = slot,
"ckey" = C.ckey
))
if(!firstquery.warn_execute())
qdel(firstquery)
return
qdel(firstquery)
// Let's not have this explode if you sneeze on the DB
var/DBQuery/query = GLOB.dbcon.NewQuery({"SELECT
var/datum/db_query/query = SSdbcore.NewQuery({"SELECT
OOC_Notes,
real_name,
name_is_always_random,
@@ -163,11 +188,12 @@
body_accessory,
gear,
autohiss
FROM [format_table_name("characters")] WHERE ckey='[C.ckey]' AND slot='[slot]'"})
if(!query.Execute())
var/err = query.ErrorMsg()
log_game("SQL ERROR during character slot loading. Error : \[[err]\]\n")
message_admins("SQL ERROR during character slot loading. Error : \[[err]\]\n")
FROM [format_table_name("characters")] WHERE ckey=:ckey AND slot=:slot"}, list(
"ckey" = C.ckey,
"slot" = slot
))
if(!query.warn_execute())
qdel(query)
return
while(query.NextRow())
@@ -244,6 +270,7 @@
saved = TRUE
qdel(query)
//Sanitize
var/datum/species/SP = GLOB.all_species[species]
metadata = sanitize_text(metadata, initial(metadata))
@@ -325,74 +352,139 @@
if(!isemptylist(loadout_gear))
gearlist = list2params(loadout_gear)
var/DBQuery/firstquery = GLOB.dbcon.NewQuery("SELECT slot FROM [format_table_name("characters")] WHERE ckey='[C.ckey]' ORDER BY slot")
firstquery.Execute()
var/datum/db_query/firstquery = SSdbcore.NewQuery("SELECT slot FROM [format_table_name("characters")] WHERE ckey=:ckey ORDER BY slot", list(
"ckey" = C.ckey
))
if(!firstquery.warn_execute())
qdel(firstquery)
return
while(firstquery.NextRow())
if(text2num(firstquery.item[1]) == default_slot)
var/DBQuery/query = GLOB.dbcon.NewQuery({"UPDATE [format_table_name("characters")] SET OOC_Notes='[sanitizeSQL(metadata)]',
real_name='[sanitizeSQL(real_name)]',
name_is_always_random='[be_random_name]',
gender='[gender]',
age='[age]',
species='[sanitizeSQL(species)]',
language='[sanitizeSQL(language)]',
hair_colour='[h_colour]',
secondary_hair_colour='[h_sec_colour]',
facial_hair_colour='[f_colour]',
secondary_facial_hair_colour='[f_sec_colour]',
skin_tone='[s_tone]',
skin_colour='[s_colour]',
marking_colours='[sanitizeSQL(markingcolourslist)]',
head_accessory_colour='[hacc_colour]',
hair_style_name='[sanitizeSQL(h_style)]',
facial_style_name='[sanitizeSQL(f_style)]',
marking_styles='[sanitizeSQL(markingstyleslist)]',
head_accessory_style_name='[sanitizeSQL(ha_style)]',
alt_head_name='[sanitizeSQL(alt_head)]',
eye_colour='[e_colour]',
underwear='[underwear]',
undershirt='[undershirt]',
backbag='[backbag]',
b_type='[b_type]',
alternate_option='[alternate_option]',
job_support_high='[job_support_high]',
job_support_med='[job_support_med]',
job_support_low='[job_support_low]',
job_medsci_high='[job_medsci_high]',
job_medsci_med='[job_medsci_med]',
job_medsci_low='[job_medsci_low]',
job_engsec_high='[job_engsec_high]',
job_engsec_med='[job_engsec_med]',
job_engsec_low='[job_engsec_low]',
job_karma_high='[job_karma_high]',
job_karma_med='[job_karma_med]',
job_karma_low='[job_karma_low]',
flavor_text='[sanitizeSQL(flavor_text)]',
med_record='[sanitizeSQL(med_record)]',
sec_record='[sanitizeSQL(sec_record)]',
gen_record='[sanitizeSQL(gen_record)]',
player_alt_titles='[playertitlelist]',
disabilities='[disabilities]',
organ_data='[organlist]',
rlimb_data='[rlimblist]',
nanotrasen_relation='[nanotrasen_relation]',
speciesprefs='[speciesprefs]',
socks='[socks]',
body_accessory='[body_accessory]',
gear='[gearlist]',
autohiss='[autohiss_mode]'
WHERE ckey='[C.ckey]'
AND slot='[default_slot]'"}
var/datum/db_query/query = SSdbcore.NewQuery({"UPDATE [format_table_name("characters")]
SET
OOC_Notes=:metadata,
real_name=:real_name,
name_is_always_random=:be_random_name,
gender=:gender,
age=:age,
species=:species,
language=:language,
hair_colour=:h_colour,
secondary_hair_colour=:h_sec_colour,
facial_hair_colour=:f_colour,
secondary_facial_hair_colour=:f_sec_colour,
skin_tone=:s_tone,
skin_colour=:s_colour,
marking_colours=:markingcolourslist,
head_accessory_colour=:hacc_colour,
hair_style_name=:h_style,
facial_style_name=:f_style,
marking_styles=:markingstyleslist,
head_accessory_style_name=:ha_style,
alt_head_name=:alt_head,
eye_colour=:e_colour,
underwear=:underwear,
undershirt=:undershirt,
backbag=:backbag,
b_type=:b_type,
alternate_option=:alternate_option,
job_support_high=:job_support_high,
job_support_med=:job_support_med,
job_support_low=:job_support_low,
job_medsci_high=:job_medsci_high,
job_medsci_med=:job_medsci_med,
job_medsci_low=:job_medsci_low,
job_engsec_high=:job_engsec_high,
job_engsec_med=:job_engsec_med,
job_engsec_low=:job_engsec_low,
job_karma_high=:job_karma_high,
job_karma_med=:job_karma_med,
job_karma_low=:job_karma_low,
flavor_text=:flavor_text,
med_record=:med_record,
sec_record=:sec_record,
gen_record=:gen_record,
player_alt_titles=:playertitlelist,
disabilities=:disabilities,
organ_data=:organlist,
rlimb_data=:rlimblist,
nanotrasen_relation=:nanotrasen_relation,
speciesprefs=:speciesprefs,
socks=:socks,
body_accessory=:body_accessory,
gear=:gearlist,
autohiss=:autohiss_mode
WHERE ckey=:ckey
AND slot=:slot"}, list(
// OH GOD SO MANY PARAMETERS
"metadata" = metadata,
"real_name" = real_name,
"be_random_name" = be_random_name,
"gender" = gender,
"age" = age,
"species" = species,
"language" = language,
"h_colour" = h_colour,
"h_sec_colour" = h_sec_colour,
"f_colour" = f_colour,
"f_sec_colour" = f_sec_colour,
"s_tone" = s_tone,
"s_colour" = s_colour,
"markingcolourslist" = markingcolourslist,
"hacc_colour" = hacc_colour,
"h_style" = h_style,
"f_style" = f_style,
"markingstyleslist" = markingstyleslist,
"ha_style" = ha_style,
"alt_head" = alt_head,
"e_colour" = e_colour,
"underwear" = underwear,
"undershirt" = undershirt,
"backbag" = backbag,
"b_type" = b_type,
"alternate_option" = alternate_option,
"job_support_high" = job_support_high,
"job_support_med" = job_support_med,
"job_support_low" = job_support_low,
"job_medsci_high" = job_medsci_high,
"job_medsci_med" = job_medsci_med,
"job_medsci_low" = job_medsci_low,
"job_engsec_high" = job_engsec_high,
"job_engsec_med" = job_engsec_med,
"job_engsec_low" = job_engsec_low,
"job_karma_high" = job_karma_high,
"job_karma_med" = job_karma_med,
"job_karma_low" = job_karma_low,
"flavor_text" = flavor_text,
"med_record" = med_record,
"sec_record" = sec_record,
"gen_record" = gen_record,
"playertitlelist" = (playertitlelist ? playertitlelist : ""), // This it intentnional. It wont work without it!
"disabilities" = disabilities,
"organlist" = (organlist ? organlist : ""),
"rlimblist" = (rlimblist ? rlimblist : ""),
"nanotrasen_relation" = nanotrasen_relation,
"speciesprefs" = speciesprefs,
"socks" = socks,
"body_accessory" = (body_accessory ? body_accessory : ""),
"gearlist" = (gearlist ? gearlist : ""),
"autohiss_mode" = autohiss_mode,
"ckey" = C.ckey,
"slot" = default_slot
)
)
if(!query.Execute())
var/err = query.ErrorMsg()
log_game("SQL ERROR during character slot saving. Error : \[[err]\]\n")
message_admins("SQL ERROR during character slot saving. Error : \[[err]\]\n")
if(!query.warn_execute())
qdel(firstquery)
qdel(query)
return
qdel(firstquery)
qdel(query)
return 1
qdel(firstquery)
var/DBQuery/query = GLOB.dbcon.NewQuery({"
var/datum/db_query/query = SSdbcore.NewQuery({"
INSERT INTO [format_table_name("characters")] (ckey, slot, OOC_Notes, real_name, name_is_always_random, gender,
age, species, language,
hair_colour, secondary_hair_colour,
@@ -421,57 +513,112 @@
socks, body_accessory, gear, autohiss)
VALUES
('[C.ckey]', '[default_slot]', '[sanitizeSQL(metadata)]', '[sanitizeSQL(real_name)]', '[be_random_name]','[gender]',
'[age]', '[sanitizeSQL(species)]', '[sanitizeSQL(language)]',
'[h_colour]', '[h_sec_colour]',
'[f_colour]', '[f_sec_colour]',
'[s_tone]', '[s_colour]',
'[sanitizeSQL(markingcolourslist)]',
'[hacc_colour]',
'[sanitizeSQL(h_style)]',
'[sanitizeSQL(f_style)]',
'[sanitizeSQL(markingstyleslist)]',
'[sanitizeSQL(ha_style)]',
'[sanitizeSQL(alt_head)]',
'[e_colour]',
'[underwear]', '[undershirt]',
'[backbag]', '[b_type]', '[alternate_option]',
'[job_support_high]', '[job_support_med]', '[job_support_low]',
'[job_medsci_high]', '[job_medsci_med]', '[job_medsci_low]',
'[job_engsec_high]', '[job_engsec_med]', '[job_engsec_low]',
'[job_karma_high]', '[job_karma_med]', '[job_karma_low]',
'[sanitizeSQL(flavor_text)]',
'[sanitizeSQL(med_record)]',
'[sanitizeSQL(sec_record)]',
'[sanitizeSQL(gen_record)]',
'[playertitlelist]',
'[disabilities]', '[organlist]', '[rlimblist]', '[nanotrasen_relation]', '[speciesprefs]',
'[socks]', '[body_accessory]', '[gearlist]', '[autohiss_mode]')
(:ckey, :slot, :metadata, :name, :be_random_name, :gender,
:age, :species, :language,
:h_colour, :h_sec_colour,
:f_colour, :f_sec_colour,
:s_tone, :s_colour,
:markingcolourslist,
:hacc_colour,
:h_style,
:f_style,
:markingstyleslist,
:ha_style,
:alt_head,
:e_colour,
:underwear, :undershirt,
:backbag, :b_type, :alternate_option,
:job_support_high, :job_support_med, :job_support_low,
:job_medsci_high, :job_medsci_med, :job_medsci_low,
:job_engsec_high, :job_engsec_med, :job_engsec_low,
:job_karma_high, :job_karma_med, :job_karma_low,
:flavor_text,
:med_record,
:sec_record,
:gen_record,
:playertitlelist,
:disabilities, :organlist, :rlimblist, :nanotrasen_relation, :speciesprefs,
:socks, :body_accessory, :gearlist, :autohiss_mode)
"}
)
"}, list(
// This has too many params for anyone to look at this without going insae
"ckey" = C.ckey,
"slot" = default_slot,
"metadata" = metadata,
"name" = real_name,
"be_random_name" = be_random_name,
"gender" = gender,
"age" = age,
"species" = species,
"language" = language,
"h_colour" = h_colour,
"h_sec_colour" = h_sec_colour,
"f_colour" = f_colour,
"f_sec_colour" = f_sec_colour,
"s_tone" = s_tone,
"s_colour" = s_colour,
"markingcolourslist" = markingcolourslist,
"hacc_colour" = hacc_colour,
"h_style" = h_style,
"f_style" = f_style,
"markingstyleslist" = markingstyleslist,
"ha_style" = ha_style,
"alt_head" = alt_head,
"e_colour" = e_colour,
"underwear" = underwear,
"undershirt" = undershirt,
"backbag" = backbag,
"b_type" = b_type,
"alternate_option" = alternate_option,
"job_support_high" = job_support_high,
"job_support_med" = job_support_med,
"job_support_low" = job_support_low,
"job_medsci_high" = job_medsci_high,
"job_medsci_med" = job_medsci_med,
"job_medsci_low" = job_medsci_low,
"job_engsec_high" = job_engsec_high,
"job_engsec_med" = job_engsec_med,
"job_engsec_low" = job_engsec_low,
"job_karma_high" = job_karma_high,
"job_karma_med" = job_karma_med,
"job_karma_low" = job_karma_low,
"flavor_text" = flavor_text,
"med_record" = med_record,
"sec_record" = sec_record,
"gen_record" = gen_record,
"playertitlelist" = (playertitlelist ? playertitlelist : ""), // This it intentnional. It wont work without it!
"disabilities" = disabilities,
"organlist" = (organlist ? organlist : ""),
"rlimblist" = (rlimblist ? rlimblist : ""),
"nanotrasen_relation" = nanotrasen_relation,
"speciesprefs" = speciesprefs,
"socks" = socks,
"body_accessory" = (body_accessory ? body_accessory : ""),
"gearlist" = (gearlist ? gearlist : ""),
"autohiss_mode" = autohiss_mode
))
if(!query.Execute())
var/err = query.ErrorMsg()
log_game("SQL ERROR during character slot saving. Error : \[[err]\]\n")
message_admins("SQL ERROR during character slot saving. Error : \[[err]\]\n")
if(!query.warn_execute())
qdel(query)
return
qdel(query)
saved = TRUE
return 1
/datum/preferences/proc/load_random_character_slot(client/C)
var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT slot FROM [format_table_name("characters")] WHERE ckey='[C.ckey]' ORDER BY slot")
var/datum/db_query/query = SSdbcore.NewQuery("SELECT slot FROM [format_table_name("characters")] WHERE ckey=:ckey ORDER BY slot", list(
"ckey" = C.ckey
))
var/list/saves = list()
if(!query.Execute())
var/err = query.ErrorMsg()
log_game("SQL ERROR during random character slot picking. Error : \[[err]\]\n")
message_admins("SQL ERROR during random character slot picking. Error : \[[err]\]\n")
if(!query.warn_execute())
qdel(query)
return
while(query.NextRow())
saves += text2num(query.item[1])
qdel(query)
if(!saves.len)
load_character(C)
@@ -482,17 +629,31 @@
/datum/preferences/proc/clear_character_slot(client/C)
. = FALSE
// Is there a character in that slot?
var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT slot FROM [format_table_name("characters")] WHERE ckey='[C.ckey]' AND slot='[default_slot]'")
query.Execute()
if(!query.RowCount())
var/datum/db_query/query = SSdbcore.NewQuery("SELECT slot FROM [format_table_name("characters")] WHERE ckey=:ckey AND slot=:slot", list(
"ckey" = C.ckey,
"slot" = default_slot
))
if(!query.warn_execute())
qdel(query)
return
var/DBQuery/query2 = GLOB.dbcon.NewQuery("DELETE FROM [format_table_name("characters")] WHERE ckey='[C.ckey]' AND slot='[default_slot]'")
if(!query2.Execute())
var/err = query2.ErrorMsg()
log_game("SQL ERROR during character slot clearing. Error : \[[err]\]\n")
message_admins("SQL ERROR during character slot clearing. Error : \[[err]\]\n")
if(!query.NextRow())
qdel(query)
return
qdel(query)
var/datum/db_query/delete_query = SSdbcore.NewQuery("DELETE FROM [format_table_name("characters")] WHERE ckey=:ckey AND slot=:slot", list(
"ckey" = C.ckey,
"slot" = default_slot
))
if(!delete_query.warn_execute())
qdel(delete_query)
return
qdel(delete_query)
saved = FALSE
return TRUE
+12 -4
View File
@@ -1,10 +1,17 @@
/proc/EquipCustomItems(mob/living/carbon/human/M)
if(!establish_db_connection())
if(!SSdbcore.IsConnected())
return
// Grab the info we want.
var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT cuiPath, cuiPropAdjust, cuiJobMask, cuiDescription, cuiItemName FROM [format_table_name("customuseritems")] WHERE cuiCKey='[M.ckey]' AND (cuiRealName='[sanitizeSQL(M.real_name)]' OR cuiRealName='*')")
query.Execute()
var/datum/db_query/query = SSdbcore.NewQuery({"
SELECT cuiPath, cuiPropAdjust, cuiJobMask, cuiDescription, cuiItemName FROM [format_table_name("customuseritems")]
WHERE cuiCKey=:ckey AND (cuiRealName=:realname OR cuiRealName='*')"}, list(
"ckey" = M.ckey,
"realname" = M.real_name
))
if(!query.warn_execute())
qdel(query)
return
while(query.NextRow())
var/path = text2path(query.item[1])
@@ -12,7 +19,7 @@
var/jobmask = query.item[3]
var/ok = 0
if(!path || !ispath(path))
log_debug("Incorrect database entry found in table 'customuseritems' path value = [path], cuiPath is null. cuiCKey='[M.ckey]' AND (cuiRealName='[sanitizeSQL(M.real_name)]' OR cuiRealName='*'")
log_debug("Incorrect database entry found in table 'customuseritems' path value = [path], cuiPath is null. cuiCKey='[M.ckey]' AND (cuiRealName='[M.real_name]' OR cuiRealName='*'")
continue
if(jobmask != "*")
var/list/allowed_jobs = splittext(jobmask,",")
@@ -66,6 +73,7 @@
HackProperties(Item,propadjust)
M.regenerate_icons()
qdel(query)
// This is hacky, but since it's difficult as fuck to make a proper parser in BYOND without killing the server, here it is. - N3X
/proc/HackProperties(var/mob/living/carbon/human/M,var/obj/item/I,var/script)
+183 -108
View File
@@ -3,51 +3,73 @@
Part of karma purchase is handled in client_procs.dm */
/proc/sql_report_karma(var/mob/spender, var/mob/receiver)
var/sqlspendername = sanitizeSQL(spender.name)
var/sqlspenderkey = sanitizeSQL(spender.ckey)
var/sqlreceivername = sanitizeSQL(receiver.name)
var/sqlreceiverkey = sanitizeSQL(receiver.ckey)
var/sqlreceiverrole = "None"
var/sqlreceiverspecial = "None"
var/sqlspenderip = spender.client.address
var/receiverrole = "None"
var/receiverspecial = "None"
if(receiver.mind)
if(receiver.mind.special_role)
sqlreceiverspecial = sanitizeSQL(receiver.mind.special_role)
receiverspecial = receiver.mind.special_role
if(receiver.mind.assigned_role)
sqlreceiverrole = sanitizeSQL(receiver.mind.assigned_role)
receiverrole = receiver.mind.assigned_role
if(!GLOB.dbcon.IsConnected())
log_game("SQL ERROR during karma logging. Failed to connect.")
if(!SSdbcore.IsConnected())
return
var/datum/db_query/log_query = SSdbcore.NewQuery({"
INSERT INTO [format_table_name("karma")] (spendername, spenderkey, receivername, receiverkey, receiverrole, receiverspecial, spenderip, time)
VALUES (:sname, :skey, :rname, :rkey, :rrole, :rspecial, :sip, Now())"}, list(
"sname" = spender.name,
"skey" = spender.ckey,
"rname" = receiver.name,
"rkey" = receiver.ckey,
"rrole" = receiverrole,
"rspecial" = receiverspecial,
"sip" = spender.client.address
))
if(!log_query.warn_execute())
qdel(log_query)
return
qdel(log_query)
var/datum/db_query/select_spender = SSdbcore.NewQuery("SELECT id, karma FROM [format_table_name("karmatotals")] WHERE byondkey=:rkey", list(
"rkey" = receiver.ckey
))
if(!select_spender.warn_execute())
qdel(select_spender)
return
var/karma
var/id
while(select_spender.NextRow())
id = select_spender.item[1]
karma = text2num(select_spender.item[2])
qdel(select_spender)
if(karma == null)
karma = 1
var/datum/db_query/insert_query = SSdbcore.NewQuery("INSERT INTO [format_table_name("karmatotals")] (byondkey, karma) VALUES (:rkey, :karma)", list(
"rkey" = receiver.ckey,
"karma" = karma
))
if(!insert_query.warn_execute())
qdel(insert_query)
return
qdel(insert_query)
else
var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss")
var/DBQuery/query = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("karma")] (spendername, spenderkey, receivername, receiverkey, receiverrole, receiverspecial, spenderip, time) VALUES ('[sqlspendername]', '[sqlspenderkey]', '[sqlreceivername]', '[sqlreceiverkey]', '[sqlreceiverrole]', '[sqlreceiverspecial]', '[sqlspenderip]', '[sqltime]')")
if(!query.Execute())
var/err = query.ErrorMsg()
log_game("SQL ERROR during karma logging. Error : \[[err]\]\n")
query = GLOB.dbcon.NewQuery("SELECT * FROM [format_table_name("karmatotals")] WHERE byondkey='[sqlreceiverkey]'")
query.Execute()
var/karma
var/id
while(query.NextRow())
id = query.item[1]
karma = text2num(query.item[3])
if(karma == null)
karma = 1
query = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("karmatotals")] (byondkey, karma) VALUES ('[sqlreceiverkey]', [karma])")
if(!query.Execute())
var/err = query.ErrorMsg()
log_game("SQL ERROR during karmatotal logging (adding new key). Error : \[[err]\]\n")
else
karma++
query = GLOB.dbcon.NewQuery("UPDATE [format_table_name("karmatotals")] SET karma=[karma] WHERE id=[id]")
if(!query.Execute())
var/err = query.ErrorMsg()
log_game("SQL ERROR during karmatotal logging (updating existing entry). Error : \[[err]\]\n")
karma++
var/datum/db_query/update_query = SSdbcore.NewQuery("UPDATE [format_table_name("karmatotals")] SET karma=:karma WHERE id=:id", list(
"karma" = karma,
"id" = id
))
if(!update_query.warn_execute())
qdel(update_query)
return
qdel(update_query)
GLOBAL_LIST_EMPTY(karma_spenders)
@@ -168,20 +190,24 @@ GLOBAL_LIST_EMPTY(karma_spenders)
/client/proc/verify_karma()
var/currentkarma = 0
var/sanitzedkey = sanitizeSQL(src.ckey)
if(!GLOB.dbcon.IsConnected())
if(!SSdbcore.IsConnected())
to_chat(usr, "<span class='warning'>Unable to connect to karma database. Please try again later.<br></span>")
return
else
var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT karma, karmaspent FROM [format_table_name("karmatotals")] WHERE byondkey='[sanitzedkey]'")
query.Execute()
var/totalkarma
var/karmaspent
while(query.NextRow())
totalkarma = query.item[1]
karmaspent = query.item[2]
currentkarma = (text2num(totalkarma) - text2num(karmaspent))
var/datum/db_query/query = SSdbcore.NewQuery("SELECT karma, karmaspent FROM [format_table_name("karmatotals")] WHERE byondkey=:ckey", list(
"ckey" = ckey
))
if(!query.warn_execute())
qdel(query)
return
var/totalkarma
var/karmaspent
while(query.NextRow())
totalkarma = query.item[1]
karmaspent = query.item[2]
qdel(query)
currentkarma = (text2num(totalkarma) - text2num(karmaspent))
return currentkarma
@@ -196,9 +222,12 @@ GLOBAL_LIST_EMPTY(karma_spenders)
karmashopmenu()
/client/proc/karmashopmenu()
var/sanitzedkey = sanitizeSQL(usr.ckey)
var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT * FROM [format_table_name("whitelist")] WHERE ckey='[sanitzedkey]'")
query.Execute()
var/datum/db_query/query = SSdbcore.NewQuery("SELECT ckey, job, species FROM [format_table_name("whitelist")] WHERE ckey=:ckey", list(
"ckey" = ckey
))
if(!query.warn_execute())
qdel(query)
return
var/list/joblist
var/list/specieslist
@@ -206,9 +235,11 @@ GLOBAL_LIST_EMPTY(karma_spenders)
var/dbspecies
var/dbckey
while(query.NextRow())
dbckey = query.item[2]
dbjob = query.item[3]
dbspecies = query.item[4]
dbckey = query.item[1]
dbjob = query.item[2]
dbspecies = query.item[3]
qdel(query)
if(dbckey)
joblist = splittext(dbjob,",")
@@ -349,60 +380,81 @@ GLOBAL_LIST_EMPTY(karma_spenders)
karmashopmenu()
/client/proc/DB_job_unlock(var/job,var/cost)
var/sanitzedkey = sanitizeSQL(usr.ckey)
var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT * FROM [format_table_name("whitelist")] WHERE ckey='[sanitzedkey]'")
query.Execute()
var/datum/db_query/select_query = SSdbcore.NewQuery("SELECT ckey, job FROM [format_table_name("whitelist")] WHERE ckey=:ckey", list(
"ckey" = ckey
))
if(!select_query.warn_execute())
qdel(select_query)
return
var/dbjob
var/dbckey
while(query.NextRow())
dbckey = query.item[2]
dbjob = query.item[3]
while(select_query.NextRow())
dbckey = select_query.item[1]
dbjob = select_query.item[2]
qdel(select_query)
if(!dbckey)
query = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("whitelist")] (ckey, job) VALUES ('[sanitzedkey]','[job]')")
if(!query.Execute())
queryErrorLog(query.ErrorMsg(),"adding new key")
var/datum/db_query/insert_query = SSdbcore.NewQuery("INSERT INTO [format_table_name("whitelist")] (ckey, job) VALUES (:ckey, :job)", list(
"ckey" = ckey,
"job" = job
))
if(!insert_query.warn_execute())
qdel(insert_query)
return
else
to_chat(usr, "You have unlocked [job].")
message_admins("[key_name(usr)] has unlocked [job].")
message_admins("[key_name(usr)] has unlocked [job].") // why do we admin log this
karmacharge(cost)
qdel(insert_query)
if(dbckey)
var/list/joblist = splittext(dbjob,",")
if(!(job in joblist))
joblist += job
var/newjoblist = jointext(joblist,",")
query = GLOB.dbcon.NewQuery("UPDATE [format_table_name("whitelist")] SET job='[newjoblist]' WHERE ckey='[dbckey]'")
if(!query.Execute())
queryErrorLog(query.ErrorMsg(),"updating existing entry")
var/datum/db_query/update_query = SSdbcore.NewQuery("UPDATE [format_table_name("whitelist")] SET job=:newjoblist WHERE ckey=:ckey", list(
"newjoblist" = newjoblist,
"ckey" = ckey
))
if(!update_query.warn_execute())
qdel(update_query)
return
else
to_chat(usr, "You have unlocked [job].")
message_admins("[key_name(usr)] has unlocked [job].")
karmacharge(cost)
qdel(update_query)
else
to_chat(usr, "You already have this job unlocked!")
return
/client/proc/DB_species_unlock(var/species,var/cost)
var/sanitzedkey = sanitizeSQL(usr.ckey)
var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT * FROM [format_table_name("whitelist")] WHERE ckey='[sanitzedkey]'")
query.Execute()
var/datum/db_query/select_query = SSdbcore.NewQuery("SELECT ckey, species FROM [format_table_name("whitelist")] WHERE ckey=:ckey", list(
"ckey" = ckey
))
if(!select_query.warn_execute())
qdel(select_query)
return
var/dbspecies
var/dbckey
while(query.NextRow())
dbckey = query.item[2]
dbspecies = query.item[4]
while(select_query.NextRow())
dbckey = select_query.item[1]
dbspecies = select_query.item[2]
if(!dbckey)
query = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("whitelist")] (ckey, species) VALUES ('[sanitzedkey]','[species]')")
if(!query.Execute())
queryErrorLog(query.ErrorMsg(),"adding new key")
var/datum/db_query/insert_query = SSdbcore.NewQuery("INSERT INTO [format_table_name("whitelist")] (ckey, species) VALUES (:ckey, :species)", list(
"ckey" = ckey,
"species" = species
))
if(!insert_query.warn_execute())
qdel(insert_query)
return
else
to_chat(usr, "You have unlocked [species].")
message_admins("[key_name(usr)] has unlocked [species].")
qdel(insert_query)
karmacharge(cost)
if(dbckey)
@@ -410,40 +462,50 @@ GLOBAL_LIST_EMPTY(karma_spenders)
if(!(species in specieslist))
specieslist += species
var/newspecieslist = jointext(specieslist,",")
query = GLOB.dbcon.NewQuery("UPDATE [format_table_name("whitelist")] SET species='[newspecieslist]' WHERE ckey='[dbckey]'")
if(!query.Execute())
queryErrorLog(query.ErrorMsg(),"updating existing entry")
var/datum/db_query/update_query = SSdbcore.NewQuery("UPDATE [format_table_name("whitelist")] SET species=:newspecieslist WHERE ckey=:ckey", list(
"newspecieslist" = newspecieslist,
"ckey" = ckey
))
if(!update_query.warn_execute())
qdel(update_query)
return
else
to_chat(usr, "You have unlocked [species].")
message_admins("[key_name(usr)] has unlocked [species].")
qdel(update_query)
karmacharge(cost)
else
to_chat(usr, "You already have this species unlocked!")
return
/client/proc/karmacharge(var/cost,var/refund = FALSE)
var/sanitzedkey = sanitizeSQL(usr.ckey)
var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT * FROM [format_table_name("karmatotals")] WHERE byondkey='[sanitzedkey]'")
query.Execute()
var/datum/db_query/select_query = SSdbcore.NewQuery("SELECT karmaspent FROM [format_table_name("karmatotals")] WHERE byondkey=:ckey", list(
"ckey" = ckey
))
if(!select_query.warn_execute())
qdel(select_query)
return
while(query.NextRow())
var/spent = text2num(query.item[4])
while(select_query.NextRow())
var/spent = text2num(select_query.item[1])
if(refund)
spent -= cost
else
spent += cost
query = GLOB.dbcon.NewQuery("UPDATE [format_table_name("karmatotals")] SET karmaspent=[spent] WHERE byondkey='[sanitzedkey]'")
if(!query.Execute())
queryErrorLog(query.ErrorMsg(),"updating existing entry")
var/datum/db_query/update_query = SSdbcore.NewQuery("UPDATE [format_table_name("karmatotals")] SET karmaspent=:spent WHERE byondkey=:ckey", list(
"spent" = spent,
"ckey" = ckey
))
if(!update_query.warn_execute())
qdel(update_query)
return
else
to_chat(usr, "You have been [refund ? "refunded" : "charged"] [cost] karma.")
message_admins("[key_name(usr)] has been [refund ? "refunded" : "charged"] [cost] karma.")
qdel(update_query)
return
/client/proc/karmarefund(var/type,var/name,var/cost)
var/sanitzedkey = sanitizeSQL(usr.ckey)
switch(name)
if("Tajaran Ambassador","Unathi Ambassador","Skrell Ambassador","Diona Ambassador","Kidan Ambassador",
"Slime People Ambassador","Grey Ambassador","Vox Ambassador","Customs Officer")
@@ -454,37 +516,50 @@ GLOBAL_LIST_EMPTY(karma_spenders)
to_chat(usr, "<span class='warning'>That job is not refundable.</span>")
return
var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT * FROM [format_table_name("whitelist")] WHERE ckey='[sanitzedkey]'")
query.Execute()
var/datum/db_query/query = SSdbcore.NewQuery("SELECT ckey, job, species FROM [format_table_name("whitelist")] WHERE ckey=:ckey", list(
"ckey" = ckey
))
if(!query.warn_execute())
qdel(query)
return
var/dbjob
var/dbspecies
var/dbckey
while(query.NextRow())
dbckey = query.item[2]
dbjob = query.item[3]
dbspecies = query.item[4]
dbckey = query.item[1]
dbjob = query.item[2]
dbspecies = query.item[3]
qdel(query)
if(dbckey)
var/list/typelist = list()
var/statement
switch(type)
if("job")
typelist = splittext(dbjob,",")
statement = "UPDATE [format_table_name("whitelist")] SET job=:newtypelist WHERE ckey=:ckey"
if("species")
typelist = splittext(dbspecies,",")
statement = "UPDATE [format_table_name("whitelist")] SET species=:newtypelist WHERE ckey=:ckey"
else
to_chat(usr, "<span class='warning'>Type [type] is not a valid column.</span>")
if(name in typelist)
typelist -= name
var/newtypelist = jointext(typelist,",")
query = GLOB.dbcon.NewQuery("UPDATE [format_table_name("whitelist")] SET [type]='[newtypelist]' WHERE ckey='[dbckey]'")
if(!query.Execute())
queryErrorLog(query.ErrorMsg(),"updating existing entry")
var/datum/db_query/update_query = SSdbcore.NewQuery(statement, list(
"ckey" = ckey,
"newtypelist" = newtypelist
))
if(!update_query.warn_execute())
qdel(update_query)
return
else
to_chat(usr, "You have been refunded [cost] karma for [type] [name].")
message_admins("[key_name(usr)] has been refunded [cost] karma for [type] [name].")
qdel(update_query)
karmacharge(text2num(cost),1)
else
to_chat(usr, "<span class='warning'>You have not bought [name].</span>")
@@ -492,23 +567,23 @@ GLOBAL_LIST_EMPTY(karma_spenders)
else
to_chat(usr, "<span class='warning'>Your ckey ([dbckey]) was not found.</span>")
/client/proc/queryErrorLog(err = null, errType)
log_game("SQL ERROR during whitelist logging ([errType]]). Error : \[[err]\]\n")
message_admins("SQL ERROR during whitelist logging ([errType]]). Error : \[[err]\]\n")
/client/proc/checkpurchased(var/name = null) // If the first parameter is null, return a full list of purchases
var/sanitzedkey = sanitizeSQL(usr.ckey)
var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT * FROM [format_table_name("whitelist")] WHERE ckey='[sanitzedkey]'")
query.Execute()
var/datum/db_query/query = SSdbcore.NewQuery("SELECT ckey, job, species FROM [format_table_name("whitelist")] WHERE ckey=:ckey", list(
"ckey" = ckey
))
if(!query.warn_execute())
qdel(query)
return
var/dbjob
var/dbspecies
var/dbckey
while(query.NextRow())
dbckey = query.item[2]
dbjob = query.item[3]
dbspecies = query.item[4]
dbckey = query.item[1]
dbjob = query.item[2]
dbspecies = query.item[3]
qdel(query)
if(dbckey)
var/list/joblist = splittext(dbjob,",")
var/list/specieslist = splittext(dbspecies,",")
+10 -8
View File
@@ -10,12 +10,14 @@
if(!isbn)
return
var/DBQuery/query_delbook = GLOB.dbcon.NewQuery("DELETE FROM [format_table_name("library")] WHERE id=[isbn]")
if(!query_delbook.Execute())
var/err = query_delbook.ErrorMsg()
log_game("SQL ERROR deleting book. Error : \[[err]\]\n")
var/datum/db_query/query_delbook = SSdbcore.NewQuery("DELETE FROM [format_table_name("library")] WHERE id=:isbn", list(
"isbn" = text2num(isbn) // just to be sure
))
if(!query_delbook.warn_execute())
qdel(query_delbook)
return
qdel(query_delbook)
log_admin("[key_name(usr)] has deleted the book [isbn].")
message_admins("[key_name_admin(usr)] has deleted the book [isbn].")
@@ -35,10 +37,9 @@
var/dat = "<table><tr><th>ISBN</th><th>Title</th><th>Total Flags</th><th>Options</th></tr>"
var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT id, title, flagged FROM [format_table_name("library")] WHERE flagged > 0 ORDER BY flagged DESC")
if(!query.Execute())
var/err = query.ErrorMsg()
log_game("SQL ERROR getting flagged books. Error : \[[err]\]\n")
var/datum/db_query/query = SSdbcore.NewQuery("SELECT id, title, flagged FROM [format_table_name("library")] WHERE flagged > 0 ORDER BY flagged DESC")
if(!query.warn_execute())
qdel(query)
return
var/books = 0
@@ -52,6 +53,7 @@
dat += "</td>"
dat += "</table>"
qdel(query)
if(!books)
dat = "<h1>No flagged books! :)</h1>"
+37 -20
View File
@@ -31,48 +31,65 @@
/obj/machinery/computer/library/proc/get_page(var/page_num)
var/searchquery = ""
var/where = 0
var/list/sql_params = list()
if(query)
if(query.title && query.title != "")
searchquery += " WHERE title LIKE '%[sanitizeSQL(query.title)]%'"
searchquery += " WHERE title LIKE :title"
sql_params["title"] = "%[query.title]%"
where = 1
if(query.author && query.author != "")
searchquery += " [!where ? "WHERE" : "AND"] author LIKE '%[sanitizeSQL(query.author)]%'"
searchquery += " [!where ? "WHERE" : "AND"] author LIKE :author"
sql_params["author"] = "%[query.author]%"
where = 1
if(query.category && query.category != "")
searchquery += " [!where ? "WHERE" : "AND"] category LIKE '%[sanitizeSQL(query.category)]%'"
searchquery += " [!where ? "WHERE" : "AND"] category LIKE :cat"
sql_params["cat"] = "%[query.category]%"
if(query.category == "Fiction")
searchquery += " AND category NOT LIKE '%Non-Fiction%'"
where = 1
// This one doesnt take player input directly, so it doesnt require params
searchquery += " [!where ? "WHERE" : "AND"] flagged < [MAX_BOOK_FLAGS]"
var/sql = "SELECT id, author, title, category, ckey, flagged FROM [format_table_name("library")] [searchquery] LIMIT [(page_num - 1) * LIBRARY_BOOKS_PER_PAGE], [LIBRARY_BOOKS_PER_PAGE]"
// This does though
var/sql = "SELECT id, author, title, category, ckey, flagged FROM [format_table_name("library")] [searchquery] LIMIT :lowerlimit, :upperlimit"
sql_params["lowerlimit"] = text2num((page_num - 1) * LIBRARY_BOOKS_PER_PAGE)
sql_params["upperlimit"] = LIBRARY_BOOKS_PER_PAGE
// Pagination
var/DBQuery/_query = GLOB.dbcon.NewQuery(sql)
_query.Execute()
if(_query.ErrorMsg())
log_world(_query.ErrorMsg())
var/datum/db_query/select_query = SSdbcore.NewQuery(sql, sql_params)
if(!select_query.warn_execute())
qdel(select_query)
return
var/list/results = list()
while(_query.NextRow())
while(select_query.NextRow())
var/datum/cachedbook/CB = new()
CB.LoadFromRow(list(
"id" =_query.item[1],
"author" =_query.item[2],
"title" =_query.item[3],
"category"=_query.item[4],
"ckey" =_query.item[5],
"flagged" =text2num(_query.item[6])
"id" =select_query.item[1],
"author" =select_query.item[2],
"title" =select_query.item[3],
"category"=select_query.item[4],
"ckey" =select_query.item[5],
"flagged" =text2num(select_query.item[6])
))
results += CB
qdel(select_query)
return results
/obj/machinery/computer/library/proc/get_num_results()
var/sql = "SELECT COUNT(*) FROM [format_table_name("library")]"
var/sql = "SELECT COUNT(id) FROM [format_table_name("library")]"
var/DBQuery/_query = GLOB.dbcon.NewQuery(sql)
_query.Execute()
while(_query.NextRow())
return text2num(_query.item[1])
var/datum/db_query/count_query = SSdbcore.NewQuery(sql)
if(!count_query.warn_execute())
qdel(count_query)
return
while(count_query.NextRow())
var/value = text2num(count_query.item[1])
qdel(count_query)
return value
qdel(count_query)
return 0
/obj/machinery/computer/library/proc/get_pagelist()
+39 -29
View File
@@ -91,7 +91,7 @@
<A href='?src=[UID()];switchscreen=0'>(Return to main menu)</A><BR>"}
if(4)
dat += "<h3>External Archive</h3>"
if(!GLOB.dbcon.IsConnected())
if(!SSdbcore.IsConnected())
dat += "<font color=red><b>ERROR</b>: Unable to contact External Archive. Please contact your system administrator for assistance.</font>"
else
num_results = src.get_num_results()
@@ -262,11 +262,13 @@
var/datum/cachedbook/target = getBookByID(href_list["del"]) // Sanitized in getBookByID
var/ans = alert(usr, "Are you sure you wish to delete \"[target.title]\", by [target.author]? This cannot be undone.", "Library System", "Yes", "No")
if(ans=="Yes")
var/DBQuery/query = GLOB.dbcon.NewQuery("DELETE FROM [format_table_name("library")] WHERE id=[target.id]")
var/response = query.Execute()
if(!response)
to_chat(usr, query.ErrorMsg())
var/datum/db_query/query = SSdbcore.NewQuery("DELETE FROM [format_table_name("library")] WHERE id=:id", list(
"id" = text2num(target.id)
))
if(!query.warn_execute())
qdel(query)
return
qdel(query)
log_admin("LIBRARY: [key_name(usr)] has deleted \"[target.title]\", by [target.author] ([target.ckey])!")
message_admins("[key_name_admin(usr)] has deleted \"[target.title]\", by [target.author] ([target.ckey])!")
src.updateUsrDialog()
@@ -278,22 +280,25 @@
var/tckey = ckey(href_list["delbyckey"])
var/ans = alert(usr,"Are you sure you wish to delete all books by [tckey]? This cannot be undone.", "Library System", "Yes", "No")
if(ans=="Yes")
var/DBQuery/query = GLOB.dbcon.NewQuery("DELETE FROM [format_table_name("library")] WHERE ckey='[sanitizeSQL(tckey)]'")
var/response = query.Execute()
if(!response)
to_chat(usr, query.ErrorMsg())
var/datum/db_query/query = SSdbcore.NewQuery("DELETE FROM [format_table_name("library")] WHERE ckey=:ckey", list(
"ckey" = tckey
))
if(!query.warn_execute())
qdel(query)
return
var/affected=query.RowsAffected()
if(affected==0)
if(query.affected == 0)
to_chat(usr, "<span class='danger'>Unable to find any matching rows.</span>")
qdel(query)
return
log_admin("LIBRARY: [key_name(usr)] has deleted [affected] books written by [tckey]!")
message_admins("[key_name_admin(usr)] has deleted [affected] books written by [tckey]!")
qdel(query)
log_admin("LIBRARY: [key_name(usr)] has deleted [query.affected] books written by [tckey]!")
message_admins("[key_name_admin(usr)] has deleted [query.affected] books written by [tckey]!")
src.updateUsrDialog()
return
if(href_list["flag"])
if(!GLOB.dbcon.IsConnected())
if(!SSdbcore.IsConnected())
alert("Connection to Archive has been severed. Aborting.")
return
var/id = href_list["flag"]
@@ -378,21 +383,26 @@
if(scanner.cache)
var/choice = input("Are you certain you wish to upload this title to the Archive?") in list("Confirm", "Abort")
if(choice == "Confirm")
establish_db_connection()
if(!GLOB.dbcon.IsConnected())
if(!SSdbcore.IsConnected())
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/DBQuery/query = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("library")] (author, title, content, category, ckey, flagged) VALUES ('[sqlauthor]', '[sqltitle]', '[sqlcontent]', '[sqlcategory]', '[ckey(usr.key)]', 0)")
var/response = query.Execute()
if(!response)
to_chat(usr, query.ErrorMsg())
else
log_admin("[usr.name]/[usr.key] has uploaded the book titled [scanner.cache.name], [length(scanner.cache.dat)] characters in length")
message_admins("[key_name_admin(usr)] has uploaded the book titled [scanner.cache.name], [length(scanner.cache.dat)] characters in length")
var/datum/db_query/query = SSdbcore.NewQuery({"
INSERT INTO [format_table_name("library")] (author, title, content, category, ckey, flagged)
VALUES (:author, :title, :content, :category, :ckey, 0)"}, list(
"author" = scanner.cache.author,
"title" = scanner.cache.name,
"content" = scanner.cache.dat,
"category" = upload_category,
"ckey" = usr.ckey
))
if(!query.warn_execute())
qdel(query)
return
qdel(query)
log_admin("[usr.name]/[usr.key] has uploaded the book titled [scanner.cache.name], [length(scanner.cache.dat)] characters in length")
message_admins("[key_name_admin(usr)] has uploaded the book titled [scanner.cache.name], [length(scanner.cache.dat)] characters in length")
if(href_list["id"])
if(href_list["id"]=="-1")
@@ -400,7 +410,7 @@
if(!href_list["id"])
return
if(!GLOB.dbcon.IsConnected())
if(!SSdbcore.IsConnected())
alert("Connection to Archive has been severed. Aborting.")
return
@@ -423,7 +433,7 @@
if(!href_list["manual"]) return
var/bookid = href_list["manual"]
if(!GLOB.dbcon.IsConnected())
if(!SSdbcore.IsConnected())
alert("Connection to Archive has been severed. Aborting.")
return
+2 -3
View File
@@ -26,8 +26,7 @@
<A href='?src=[UID()];setauthor=1'>Filter by Author: [query.author]</A><br />
<A href='?src=[UID()];search=1'>\[Start Search\]</A><br />"}
if(1)
establish_db_connection()
if(!GLOB.dbcon.IsConnected())
if(!SSdbcore.IsConnected())
dat += "<font color=red><b>ERROR</b>: Unable to contact External Archive. Please contact your system administrator for assistance.</font><br />"
else if(num_results == 0)
dat += "<em>No results found.</em>"
@@ -113,7 +112,7 @@
screenstate = 0
if(href_list["flag"])
if(!GLOB.dbcon.IsConnected())
if(!SSdbcore.IsConnected())
alert("Connection to Archive has been severed. Aborting.")
return
var/id = href_list["flag"]
+19 -24
View File
@@ -44,18 +44,6 @@ GLOBAL_LIST_INIT(library_section_names, list("Any", "Fiction", "Non-Fiction", "A
var/category
var/title
/datum/library_query/proc/toSQL()
var/list/where = list()
if(author || title || category)
if(author)
where.Add("author LIKE '%[sanitizeSQL(author)]%'")
if(category)
where.Add("category = '[sanitizeSQL(category)]'")
if(title)
where.Add("title LIKE '%[sanitizeSQL(title)]%'")
return " WHERE " + jointext(where, " AND ")
return ""
// So we can have catalogs of books that are programmatic, and ones that aren't.
/datum/library_catalog
var/list/cached_books = list()
@@ -90,11 +78,13 @@ GLOBAL_LIST_INIT(library_section_names, list("Any", "Fiction", "Non-Fiction", "A
books_flagged_this_round["[id]"] = 1
message_admins("[key_name_admin(user)] has flagged book #[id] as inappropriate.")
var/sqlid = text2num(id)
if(!sqlid)
var/datum/db_query/query = SSdbcore.NewQuery("UPDATE [format_table_name("library")] SET flagged = flagged + 1 WHERE id=:id", list(
"id" = text2num(id)
))
if(!query.warn_execute())
qdel(query)
return
var/DBQuery/query = GLOB.dbcon.NewQuery("UPDATE [format_table_name("library")] SET flagged = flagged + 1 WHERE id=[sqlid]")
query.Execute()
qdel(query)
/datum/library_catalog/proc/rmBookByID(mob/user, id)
if("[id]" in cached_books)
@@ -103,21 +93,24 @@ GLOBAL_LIST_INIT(library_section_names, list("Any", "Fiction", "Non-Fiction", "A
to_chat(user, "<span class='danger'>That book cannot be removed from the system, as it does not actually exist in the database.</span>")
return
var/sqlid = text2num(id)
if(!sqlid)
var/datum/db_query/query = SSdbcore.NewQuery("DELETE FROM [format_table_name("library")] WHERE id=:id", list(
"id" = text2num(id)
))
if(!query.warn_execute())
qdel(query)
return
var/DBQuery/query = GLOB.dbcon.NewQuery("DELETE FROM [format_table_name("library")] WHERE id=[sqlid]")
query.Execute()
qdel(query)
/datum/library_catalog/proc/getBookByID(id)
if("[id]" in cached_books)
return cached_books["[id]"]
var/sqlid = text2num(id)
if(!sqlid)
var/datum/db_query/query = SSdbcore.NewQuery("SELECT id, author, title, category, content, ckey, flagged FROM [format_table_name("library")] WHERE id=:id", list(
"id" = text2num(id)
))
if(!query.warn_execute())
qdel(query)
return
var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT id, author, title, category, content, ckey, flagged FROM [format_table_name("library")] WHERE id=[sqlid]")
query.Execute()
var/list/results=list()
while(query.NextRow())
@@ -133,7 +126,9 @@ GLOBAL_LIST_INIT(library_section_names, list("Any", "Fiction", "Non-Fiction", "A
))
results += CB
cached_books["[id]"]=CB
qdel(query)
return CB
qdel(query)
return results
/** Scanner **/
+18 -7
View File
@@ -36,11 +36,12 @@
create_random_books(book_count, src, FALSE, category)
update_icon()
// why is this a global proc
/proc/create_random_books(amount = 2, location, fail_loud = FALSE, category = null)
. = list()
if(!isnum(amount) || amount<1)
return
if(!GLOB.dbcon.IsConnected())
if(!SSdbcore.IsConnected())
if(fail_loud || prob(5))
var/obj/item/paper/P = new(location)
P.info = "There once was a book from Nantucket<br>But the database failed us, so f*$! it.<br>I tried to be good to you<br>Now this is an I.O.U<br>If you're feeling entitled, well, stuff it!<br><br><font color='gray'>~</font>"
@@ -48,17 +49,27 @@
return
if(prob(25))
category = null
var/c = category? " AND category='[sanitizeSQL(category)]'" :""
var/DBQuery/query_get_random_books = GLOB.dbcon.NewQuery("SELECT * FROM [format_table_name("library")] WHERE (isnull(flagged) OR flagged = 0)[c] GROUP BY title ORDER BY rand() LIMIT [amount];")
query_get_random_books.Execute()
var/c = ""
var/list/sql_params = list()
if(category)
c = " AND category=:category"
sql_params["category"] = category
sql_params["amount"] = amount
var/datum/db_query/query_get_random_books = SSdbcore.NewQuery("SELECT author, title, content FROM [format_table_name("library")] WHERE (isnull(flagged) OR flagged = 0)[c] GROUP BY title ORDER BY rand() LIMIT :amount", sql_params)
if(!query_get_random_books.warn_execute())
qdel(query_get_random_books)
return
while(query_get_random_books.NextRow())
var/obj/item/book/B = new(location)
. += B
B.author = query_get_random_books.item[2]
B.title = query_get_random_books.item[3]
B.dat = query_get_random_books.item[4]
B.author = query_get_random_books.item[1]
B.title = query_get_random_books.item[2]
B.dat = query_get_random_books.item[3]
B.name = "Book: [B.title]"
B.icon_state= "book[rand(1,8)]"
qdel(query_get_random_books)
/obj/structure/bookcase/random/fiction
name = "bookcase (Fiction)"
-16
View File
@@ -26,22 +26,6 @@
new_player_panel()
spawn(30)
// Annoy the player with polls.
establish_db_connection()
if(GLOB.dbcon.IsConnected() && client && client.can_vote())
var/isadmin = 0
if(client && client.holder)
isadmin = 1
var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT id FROM [format_table_name("poll_question")] WHERE [(isadmin ? "" : "adminonly = false AND")] Now() BETWEEN starttime AND endtime AND id NOT IN (SELECT pollid FROM [format_table_name("poll_vote")] WHERE ckey = \"[ckey]\") AND id NOT IN (SELECT pollid FROM [format_table_name("poll_textreply")] WHERE ckey = \"[ckey]\")")
query.Execute()
var/newpoll = 0
while(query.NextRow())
newpoll = 1
break
if(newpoll)
client.handle_player_polling()
if(ckey in GLOB.deadmins)
verbs += /client/proc/readmin
spawn(40)
+24 -29
View File
@@ -31,17 +31,25 @@
tos_consent = TRUE
return TRUE
establish_db_connection()
if(!GLOB.dbcon.IsConnected())
if(!SSdbcore.IsConnected())
tos_consent = TRUE
return TRUE
var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT * FROM [format_table_name("privacy")] WHERE ckey='[src.ckey]' AND consent=1")
query.Execute()
var/datum/db_query/query = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("privacy")] WHERE ckey=:ckey AND consent=1", list(
"ckey" = ckey
))
if(!query.warn_execute())
qdel(query)
// If our query failed, just assume yes
tos_consent = TRUE
return TRUE
while(query.NextRow())
qdel(query)
tos_consent = TRUE
return TRUE
qdel(query)
privacy_consent()
return FALSE
@@ -85,25 +93,6 @@
if(GLOB.join_tos)
output += "<p><a href='byond://?src=[UID()];tos=1'>Terms of Service</A></p>"
if(!IsGuestKey(src.key))
establish_db_connection()
if(GLOB.dbcon.IsConnected() && client.can_vote())
var/isadmin = 0
if(src.client && src.client.holder)
isadmin = 1
var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT id FROM [format_table_name("poll_question")] WHERE [(isadmin ? "" : "adminonly = false AND")] Now() BETWEEN starttime AND endtime AND id NOT IN (SELECT pollid FROM [format_table_name("poll_vote")] WHERE ckey = \"[ckey]\") AND id NOT IN (SELECT pollid FROM [format_table_name("poll_textreply")] WHERE ckey = \"[ckey]\")")
query.Execute()
var/newpoll = 0
while(query.NextRow())
newpoll = 1
break
if(newpoll)
output += "<p><b><a href='byond://?showpoll=1'>Show Player Polls</A> (NEW!)</b></p>"
else
output += "<p><a href='byond://?showpoll=1'>Show Player Polls</A></p>"
output += "</center>"
var/datum/browser/popup = new(src, "playersetup", "<div align='center'>New Player Options</div>", 240, 330)
@@ -151,18 +140,24 @@
return FALSE
if(href_list["consent_signed"])
var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss")
var/DBQuery/query = GLOB.dbcon.NewQuery("REPLACE INTO [format_table_name("privacy")] (ckey, datetime, consent) VALUES ('[ckey]', '[sqltime]', 1)")
query.Execute()
var/datum/db_query/query = SSdbcore.NewQuery("REPLACE INTO [format_table_name("privacy")] (ckey, datetime, consent) VALUES (:ckey, Now(), 1)", list(
"ckey" = ckey
))
// If the query fails we dont want them permenantly stuck on being unable to accept TOS
query.warn_execute()
qdel(query)
src << browse(null, "window=privacy_consent")
tos_consent = 1
new_player_panel_proc()
if(href_list["consent_rejected"])
tos_consent = 0
to_chat(usr, "<span class='warning'>You must consent to the terms of service before you can join!</span>")
var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss")
var/DBQuery/query = GLOB.dbcon.NewQuery("REPLACE INTO [format_table_name("privacy")] (ckey, datetime, consent) VALUES ('[ckey]', '[sqltime]', 0)")
query.Execute()
var/datum/db_query/query = SSdbcore.NewQuery("REPLACE INTO [format_table_name("privacy")] (ckey, datetime, consent) VALUES (:ckey, Now(), 0)", list(
"ckey" = ckey
))
// If the query fails we dont want them permenantly stuck on being unable to accept TOS
query.warn_execute()
qdel(query)
if(href_list["show_preferences"])
client.prefs.ShowChoices(src)
-661
View File
@@ -1,661 +0,0 @@
/datum/polloption
var/optionid
var/optiontext
/client/verb/polls_verb()
set name = "Show Player Polls"
set category = "OOC"
handle_player_polling()
/client/proc/can_vote()
return istext(player_age) || player_age >= 30
/client/proc/handle_player_polling()
establish_db_connection()
if(GLOB.dbcon.IsConnected())
var/isadmin = 0
if(holder)
isadmin = 1
var/DBQuery/select_query = GLOB.dbcon.NewQuery("SELECT id, question, (id IN (SELECT pollid FROM [format_table_name("poll_vote")] WHERE ckey = '[ckey]') OR id IN (SELECT pollid FROM [format_table_name("poll_textreply")] WHERE ckey = '[ckey]')) AS voted FROM [format_table_name("poll_question")] WHERE [(isadmin ? "" : "adminonly = false AND")] Now() BETWEEN starttime AND endtime")
select_query.Execute()
var/output = "<div align='center'><B>Player polls</B>"
if(check_rights(R_SERVER))
output += "(<a href='?createpollwindow=1'>Create new poll</a>)"
output +="<hr>"
output += "<table>"
var/color1 = "#ececec"
var/color2 = "#e2e2e2"
var/i = 0
output += "<tr><th>Active Polls</th></tr>"
while(select_query.NextRow())
var/pollid = select_query.item[1]
var/pollquestion = select_query.item[2]
var/voted = text2num(select_query.item[3])
output += "<tr bgcolor='[(i % 2 == 1) ? color1 : color2 ]'><td><a href=\"byond://?pollid=[pollid]\"><b>[pollquestion]</b></a></td></tr>"
if(can_vote() && !voted)
output += "<tr><td>[poll_player(pollid, 1)]</tr></td>"
i++
// Show expired polls. Non admins can view admin polls at this stage
// (just like tgstation's web interface so don't complain)
// (Also why was there no ingame interface? tg not having an ingame
// interface is a pain in the neck because it means downstreams have to roll their own)
select_query = GLOB.dbcon.NewQuery("SELECT id, question FROM [format_table_name("poll_question")] WHERE Now() > endtime ORDER BY id DESC")
select_query.Execute()
output += "<tr><th>Expired Polls</th></tr>"
while(select_query.NextRow())
var/pollid = select_query.item[1]
var/pollquestion = select_query.item[2]
output += "<tr bgcolor='[(i % 2 == 1) ? color1 : color2]'><td><a href=\"byond://?pollresults=[pollid]\"><b>[pollquestion]</b></a></td></tr>"
output += "</table>"
src << browse(output,"window=playerpolllist;size=500x300")
/client/proc/poll_results(var/pollid = -1)
if(pollid == -1)
return
establish_db_connection()
if(!GLOB.dbcon.IsConnected())
return
var/DBQuery/select_query = GLOB.dbcon.NewQuery("SELECT polltype, question, adminonly, multiplechoiceoptions, starttime, endtime FROM [format_table_name("poll_question")] WHERE id = [pollid] AND endtime < Now()")
select_query.Execute()
var/question = ""
var/polltype = ""
var/adminonly = 0
var/multiplechoiceoptions = 0
var/starttime = ""
var/endtime = ""
var/found = 0
while(select_query.NextRow())
polltype = select_query.item[1]
question = select_query.item[2]
adminonly = text2num(select_query.item[3])
multiplechoiceoptions = text2num(select_query.item[4])
starttime = select_query.item[5]
endtime = select_query.item[6]
found = 1
break
if(!found)
to_chat(src, "<span class='warning'>Poll question details not found. (Maybe the poll isn't expired yet?)</span>")
return
if(polltype == POLLTYPE_MULTI)
question += " (Choose up to [multiplechoiceoptions] options)"
if(adminonly)
question = "(<font color='#997700'>Admin only poll</font>) " + question
var/output = "<!DOCTYPE html><html><body>"
if(polltype == POLLTYPE_MULTI || polltype == POLLTYPE_OPTION)
select_query = GLOB.dbcon.NewQuery("SELECT text, percentagecalc, (SELECT COUNT(optionid) FROM [format_table_name("poll_vote")] WHERE optionid = poll_option.id GROUP BY optionid) AS votecount FROM [format_table_name("poll_option")] WHERE pollid = [pollid]")
select_query.Execute()
var/list/options = list()
var/total_votes = 1
var/total_percent_votes = 1
var/max_votes = 1
while(select_query.NextRow())
var/text = select_query.item[1]
var/percentagecalc = select_query.item[2]
var/votecount = text2num(select_query.item[3])
if(percentagecalc)
total_percent_votes += votecount
total_votes += votecount
if(votecount > max_votes)
max_votes = votecount
options[++options.len] = list(text, percentagecalc, votecount)
// fuck ie.
output += {"
<table width='900' align='center' bgcolor='#eeffee' cellspacing='0' cellpadding='4'>
<tr bgcolor='#ddffdd'>
<th colspan='4' align='center'>[question]<br><font size='1'><b>[starttime] - [endtime]</b></font></th>
</tr>
<tr bgcolor='#ddffdd'>
<th colspan='4' align='center'><div style='width:700px;position:relative'>"}
var/list/colors = list("#66c2a5", "#fc8d62", "#8da0cb", "#e78ac3", "#a6d854", "#ffd92f", "#e5c494", "#b3b3b3")
var/color_index = 0
for(var/list/option in options)
var/bar_width = option[3] * 700 / total_votes
var/percentage = option[2] ? "[round(option[3] * 100 / total_percent_votes)]%" : "N/A"
color_index++
if(color_index > colors.len)
color_index = 1
output += "<div style='width:[bar_width]px;height:[5]px;background-color:[colors[color_index]];float:left' title='[option[1]] ([percentage])'></div>"
output += "</div><br><font size='2'><b>(Hover over the colored bar to read description)</b></font></tr>"
for(var/list/option in options)
var/bar_width = option[3] * 390 / max_votes
var/percentage = option[2] ? "[round(option[3] * 100 / total_percent_votes)]%" : "N/A"
output += "<tr><td width='300' align='right'>[option[1]]</td>"
output += "<td width='100' align='center'><b>[option[3]]</b></td>"
output += "<td width='100' align='center'><b>[percentage]</b></td>"
output += "<td width='400' align='left'><div style='width:[bar_width]px;height:10px;display:inline-block;background-color:#08b000'></div></td>"
output += "</table>"
if(polltype == POLLTYPE_RATING)
output += {"
<table width='900' align='center' bgcolor='#eeffee' cellspacing='0' cellpadding='4'>
<tr bgcolor='#ddffdd'>
<th colspan='4' align='center'>[question]<br><font size='1'><b>[starttime] - [endtime]</b></font></th>
</tr>"}
select_query = GLOB.dbcon.NewQuery("SELECT id, text, (SELECT AVG(rating) FROM [format_table_name("poll_vote")] WHERE optionid = poll_option.id AND rating != 'abstain') AS avgrating, (SELECT COUNT(rating) FROM [format_table_name("poll_vote")] WHERE optionid = poll_option.id AND rating != 'abstain') AS countvotes, minval, maxval FROM [format_table_name("poll_option")] WHERE pollid = [pollid]")
select_query.Execute()
while(select_query.NextRow())
output += {"
<tr>
<td align='right' width='300'>[select_query.item[2]]</th>
<td align='center' width='100'><b>N = [select_query.item[4]]</b></th>
<td align='center' width='100'><b>AVG = [select_query.item[3]]</b></th>
<td align='left' width='400'><table width='400 style='table-layout: fixed'>"}
var/optionid = select_query.item[1]
var/totalvotes = text2num(select_query.item[4])
var/minval = text2num(select_query.item[5])
var/maxval = text2num(select_query.item[6])
var/maxvote = 1
var/list/votecounts = list()
for(var/I in minval to maxval)
var/DBQuery/rating_query = GLOB.dbcon.NewQuery("SELECT COUNT(rating) AS countrating FROM [format_table_name("poll_vote")] WHERE optionid = [optionid] AND rating = [I] GROUP BY rating")
rating_query.Execute()
var/votecount = 0
while(rating_query.NextRow())
votecount = text2num(rating_query.item[1])
votecounts["[I]"] = votecount
if(votecount > maxvote)
maxvote = votecount
for(var/I in minval to maxval)
var/votecount = votecounts["[I]"]
var/bar_width = votecount * 200 / maxvote
output += {"
<tr>
<td align='center' width='50'><b>[I]</b></td>
<td align='center' width='50'>[votecount]</td>
<td align='center' width='75'>([votecount / totalvotes]%)</td>
<td width='200'><div style='width:[bar_width]px;height:10px;display:inline-block;background-color:#08b000'></div></td>
</tr>"}
output += "</table></td></tr>"
output += "</table>"
if(polltype == POLLTYPE_TEXT)
select_query = GLOB.dbcon.NewQuery("SELECT replytext, COUNT(replytext) AS countresponse, GROUP_CONCAT(DISTINCT ckey SEPARATOR ', ') as ckeys FROM [format_table_name("poll_textreply")] WHERE pollid = [pollid] GROUP BY replytext ORDER BY countresponse DESC")
select_query.Execute()
output += {"
<table width='900' align='center' bgcolor='#eeffee' cellspacing='0' cellpadding='4'>
<tr bgcolor='#ddffdd'>
<th colspan='2' align='center'>[question]<br><font size='1'><b>[starttime] - [endtime]</b></font></th>
</tr>"}
while(select_query.NextRow())
var/replytext = select_query.item[1]
var/countresponse = select_query.item[2]
var/ckeys = select_query.item[3]
output += {"
<tr>
<td>[ckeys] ([countresponse] player\s) responded with:</td>
<td style='border:1px solid #888888'>[replytext]</td>
</tr>"}
output += "</table>"
output += "</body></html>"
src << browse(output,"window=pollresults;size=950x500")
/client/proc/poll_player(var/pollid = -1, var/inline = 0)
if(pollid == -1) return
establish_db_connection()
if(GLOB.dbcon.IsConnected())
var/DBQuery/select_query = GLOB.dbcon.NewQuery("SELECT starttime, endtime, question, polltype, multiplechoiceoptions FROM [format_table_name("poll_question")] WHERE id = [pollid] AND Now() BETWEEN starttime AND endtime [holder ? "AND adminonly = 0" : ""]")
select_query.Execute()
var/pollstarttime = ""
var/pollendtime = ""
var/pollquestion = ""
var/polltype = ""
var/found = 0
var/multiplechoiceoptions = 0
var/canvote = can_vote()
while(select_query.NextRow())
pollstarttime = select_query.item[1]
pollendtime = select_query.item[2]
pollquestion = select_query.item[3]
polltype = select_query.item[4]
found = 1
break
if(!found)
to_chat(usr, "<span class='warning'>Poll question details not found. (Maybe you do not have access?)</span>")
return
switch(polltype)
//Polls that have enumerated options
if(POLLTYPE_OPTION)
var/DBQuery/voted_query = GLOB.dbcon.NewQuery("SELECT optionid FROM [format_table_name("poll_vote")] WHERE pollid = [pollid] AND ckey = '[ckey]'")
voted_query.Execute()
var/voted = 0 // If the can't vote then consider them voted
var/votedoptionid = 0
while(voted_query.NextRow())
votedoptionid = text2num(voted_query.item[1])
voted = 1
break
var/list/datum/polloption/options = list()
var/DBQuery/options_query = GLOB.dbcon.NewQuery("SELECT id, text FROM [format_table_name("poll_option")] WHERE pollid = [pollid]")
options_query.Execute()
while(options_query.NextRow())
var/datum/polloption/PO = new()
PO.optionid = text2num(options_query.item[1])
PO.optiontext = options_query.item[2]
options += PO
var/output
if(!inline)
output += "<div align='center'><B>Player poll</B>"
output +="<hr>"
output += "<b>Question: [pollquestion]</b><br>"
output += "<font size='2'>Poll runs from <b>[pollstarttime]</b> until <b>[pollendtime]</b></font><p>"
if(canvote && !voted) //Only make this a form if we have not voted yet
output += "<form name='cardcomp' action='byond://' method='get'>"
output += "<input type='hidden' name='votepollid' value='[pollid]'>"
output += "<input type='hidden' name='votetype' value='OPTION'>"
output += "<table><tr><td>"
for(var/datum/polloption/O in options)
if(O.optionid && O.optiontext)
if(voted || !canvote)
if(votedoptionid == O.optionid)
output += "<b>[O.optiontext]</b><br>"
else
output += "[O.optiontext]<br>"
else
output += "<input type='radio' name='voteoptionid' value='[O.optionid]'> [O.optiontext]<br>"
output += "</td></tr></table>"
if(canvote && !voted) //Only make this a form if we have not voted yet
output += "<p><input type='submit' value='Vote'>"
output += "</form>"
output += "</div>"
if(inline)
return output
else
src << browse(output,"window=playerpoll;size=500x250")
//Polls with a text input
if(POLLTYPE_TEXT)
var/DBQuery/voted_query = GLOB.dbcon.NewQuery("SELECT replytext FROM [format_table_name("poll_textreply")] WHERE pollid = [pollid] AND ckey = '[ckey]'")
voted_query.Execute()
var/voted = 0
var/vote_text = ""
while(voted_query.NextRow())
vote_text = voted_query.item[1]
voted = 1
break
var/output
if(!inline)
output += "<div align='center'><B>Player poll</B>"
output +="<hr>"
output += "<b>Question: [pollquestion]</b><br>"
output += "<font size='2'>Feedback gathering runs from <b>[pollstarttime]</b> until <b>[pollendtime]</b></font><p>"
if(canvote && !voted) //Only make this a form if we have not voted yet
output += "<form name='cardcomp' action='byond://' method='get'>"
output += "<input type='hidden' name='votepollid' value='[pollid]'>"
output += "<input type='hidden' name='votetype' value='TEXT'>"
output += "<font size='2'>Please provide feedback below. You can use any letters of the English alphabet, numbers and the symbols: . , ! ? : ; -</font><br>"
output += "<textarea name='replytext' cols='50' rows='14'></textarea>"
output += "<p><input type='submit' value='Submit'>"
output += "</form>"
output += "<form name='cardcomp' action='byond://' method='get'>"
output += "<input type='hidden' name='votepollid' value='[pollid]'>"
output += "<input type='hidden' name='votetype' value='TEXT'>"
output += "<input type='hidden' name='replytext' value='ABSTAIN'>"
output += "<input type='submit' value='Abstain'>"
output += "</form>"
else
output += "[vote_text]"
if(inline)
return output
else
src << browse(output,"window=playerpoll;size=500x500")
//Polls with a text input
if(POLLTYPE_RATING)
var/DBQuery/voted_query = GLOB.dbcon.NewQuery("SELECT o.text, v.rating FROM [format_table_name("poll_option")] o, erro_poll_vote v WHERE o.pollid = [pollid] AND v.ckey = '[ckey]' AND o.id = v.optionid")
voted_query.Execute()
var/output
if(!inline)
output += "<div align='center'><B>Player poll</B>"
output +="<hr>"
output += "<b>Question: [pollquestion]</b><br>"
output += "<font size='2'>Poll runs from <b>[pollstarttime]</b> until <b>[pollendtime]</b></font><p>"
var/voted = 0
while(voted_query.NextRow())
voted = 1
var/optiontext = voted_query.item[1]
var/rating = voted_query.item[2]
output += "<br><b>[optiontext] - [rating]</b>"
if(canvote && !voted) //Only make this a form if we have not voted yet
output += "<form name='cardcomp' action='byond://' method='get'>"
output += "<input type='hidden' name='votepollid' value='[pollid]'>"
output += "<input type='hidden' name='votetype' value='NUMVAL'>"
var/minid = 999999
var/maxid = 0
var/DBQuery/option_query = GLOB.dbcon.NewQuery("SELECT id, text, minval, maxval, descmin, descmid, descmax FROM [format_table_name("poll_option")] WHERE pollid = [pollid]")
option_query.Execute()
while(option_query.NextRow())
var/optionid = text2num(option_query.item[1])
var/optiontext = option_query.item[2]
var/minvalue = text2num(option_query.item[3])
var/maxvalue = text2num(option_query.item[4])
var/descmin = option_query.item[5]
var/descmid = option_query.item[6]
var/descmax = option_query.item[7]
if(optionid < minid)
minid = optionid
if(optionid > maxid)
maxid = optionid
var/midvalue = round( (maxvalue + minvalue) / 2)
if(isnull(minvalue) || isnull(maxvalue) || (minvalue == maxvalue))
continue
output += "<br>[optiontext]: <select name='o[optionid]'>"
output += "<option value='abstain'>abstain</option>"
for(var/j = minvalue; j <= maxvalue; j++)
if(j == minvalue && descmin)
output += "<option value='[j]'>[j] ([descmin])</option>"
else if(j == midvalue && descmid)
output += "<option value='[j]'>[j] ([descmid])</option>"
else if(j == maxvalue && descmax)
output += "<option value='[j]'>[j] ([descmax])</option>"
else
output += "<option value='[j]'>[j]</option>"
output += "</select>"
output += "<input type='hidden' name='minid' value='[minid]'>"
output += "<input type='hidden' name='maxid' value='[maxid]'>"
output += "<p><input type='submit' value='Submit'>"
output += "</form>"
if(inline)
return output
else
src << browse(output,"window=playerpoll;size=500x500")
if(POLLTYPE_MULTI)
var/DBQuery/voted_query = GLOB.dbcon.NewQuery("SELECT optionid FROM [format_table_name("poll_vote")] WHERE pollid = [pollid] AND ckey = '[ckey]'")
voted_query.Execute()
var/list/votedfor = list()
var/voted = 0
while(voted_query.NextRow())
votedfor.Add(text2num(voted_query.item[1]))
voted = 1
var/list/datum/polloption/options = list()
var/maxoptionid = 0
var/minoptionid = 0
var/DBQuery/options_query = GLOB.dbcon.NewQuery("SELECT id, text FROM [format_table_name("poll_option")] WHERE pollid = [pollid]")
options_query.Execute()
while(options_query.NextRow())
var/datum/polloption/PO = new()
PO.optionid = text2num(options_query.item[1])
PO.optiontext = options_query.item[2]
if(PO.optionid > maxoptionid)
maxoptionid = PO.optionid
if(PO.optionid < minoptionid || !minoptionid)
minoptionid = PO.optionid
options += PO
if(select_query.item[5])
multiplechoiceoptions = text2num(select_query.item[5])
var/output
if(!inline)
output += "<div align='center'><B>Player poll</B>"
output +="<hr>"
output += "<b>Question: [pollquestion]</b><br>You can select up to [multiplechoiceoptions] options. If you select more, the first [multiplechoiceoptions] will be saved.<br>"
output += "<font size='2'>Poll runs from <b>[pollstarttime]</b> until <b>[pollendtime]</b></font><p>"
if(canvote && !voted) //Only make this a form if we have not voted yet
output += "<form name='cardcomp' action='byond://' method='get'>"
output += "<input type='hidden' name='votepollid' value='[pollid]'>"
output += "<input type='hidden' name='votetype' value='MULTICHOICE'>"
output += "<input type='hidden' name='maxoptionid' value='[maxoptionid]'>"
output += "<input type='hidden' name='minoptionid' value='[minoptionid]'>"
output += "<table><tr><td>"
for(var/datum/polloption/O in options)
if(O.optionid && O.optiontext)
if(canvote && voted)
if(O.optionid in votedfor)
output += "<b>[O.optiontext]</b><br>"
else
output += "[O.optiontext]<br>"
else
output += "<input type='checkbox' name='option_[O.optionid]' value='[O.optionid]'> [O.optiontext]<br>"
output += "</td></tr></table>"
if(canvote && !voted) //Only make this a form if we have not voted yet
output += "<p><input type='submit' value='Vote'>"
output += "</form>"
output += "</div>"
if(inline)
return output
else
src << browse(output,"window=playerpoll;size=600x250")
return
/client/proc/vote_on_poll(var/pollid = -1, var/optionid = -1, var/multichoice = 0)
if(pollid == -1 || optionid == -1)
return
if(!isnum(pollid) || !isnum(optionid))
return
establish_db_connection()
if(GLOB.dbcon.IsConnected())
var/DBQuery/select_query = GLOB.dbcon.NewQuery("SELECT starttime, endtime, question, polltype, multiplechoiceoptions FROM [format_table_name("poll_question")] WHERE id = [pollid] AND Now() BETWEEN starttime AND endtime [holder ? "AND adminonly = 0" : ""]")
select_query.Execute()
var/validpoll = 0
var/multiplechoiceoptions = 0
while(select_query.NextRow())
if(select_query.item[4] != POLLTYPE_OPTION && select_query.item[4] != POLLTYPE_MULTI)
return
validpoll = 1
if(select_query.item[5])
multiplechoiceoptions = text2num(select_query.item[5])
break
if(!validpoll)
to_chat(usr, "<span class='warning'>Poll is not valid.</span>")
return
var/DBQuery/select_query2 = GLOB.dbcon.NewQuery("SELECT id FROM [format_table_name("poll_option")] WHERE id = [optionid] AND pollid = [pollid]")
select_query2.Execute()
var/validoption = 0
while(select_query2.NextRow())
validoption = 1
break
if(!validoption)
to_chat(usr, "<span class='warning'>Poll option is not valid.</span>")
return
var/alreadyvoted = 0
var/DBQuery/voted_query = GLOB.dbcon.NewQuery("SELECT id FROM [format_table_name("poll_vote")] WHERE pollid = [pollid] AND ckey = '[ckey]'")
voted_query.Execute()
while(voted_query.NextRow())
alreadyvoted += 1
if(!multichoice)
break
if(!multichoice && alreadyvoted)
to_chat(usr, "<span class='warning'>You already voted in this poll.</span>")
return
if(multichoice && (alreadyvoted >= multiplechoiceoptions))
to_chat(usr, "<span class='warning'>You already have more than [multiplechoiceoptions] logged votes on this poll. Enough is enough. Contact the database admin if this is an error.</span>")
return
var/adminrank = "Player"
if(usr && usr.client && usr.client.holder)
adminrank = usr.client.holder.rank
var/DBQuery/insert_query = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("poll_vote")] (id ,datetime ,pollid ,optionid ,ckey ,ip ,adminrank) VALUES (null, Now(), [pollid], [optionid], '[ckey]', '[usr.client.address]', '[adminrank]')")
insert_query.Execute()
to_chat(usr, "<span class='notice'>Vote successful.</span>")
usr << browse(null,"window=playerpoll")
/client/proc/log_text_poll_reply(var/pollid = -1, var/replytext = "")
if(pollid == -1 || replytext == "")
return
if(!isnum(pollid) || !istext(replytext))
return
establish_db_connection()
if(GLOB.dbcon.IsConnected())
var/DBQuery/select_query = GLOB.dbcon.NewQuery("SELECT starttime, endtime, question, polltype FROM [format_table_name("poll_question")] WHERE id = [pollid] AND Now() BETWEEN starttime AND endtime [holder ? "AND adminonly = 0" : ""]")
select_query.Execute()
var/validpoll = 0
while(select_query.NextRow())
if(select_query.item[4] != POLLTYPE_TEXT)
return
validpoll = 1
break
if(!validpoll)
to_chat(usr, "<span class='warning'>Poll is not valid.</span>")
return
var/alreadyvoted = 0
var/DBQuery/voted_query = GLOB.dbcon.NewQuery("SELECT id FROM [format_table_name("poll_textreply")] WHERE pollid = [pollid] AND ckey = '[ckey]'")
voted_query.Execute()
while(voted_query.NextRow())
alreadyvoted = 1
break
if(alreadyvoted)
to_chat(usr, "<span class='warning'>You already sent your feedback for this poll.</span>")
return
var/adminrank = "Player"
if(usr && usr.client && usr.client.holder)
adminrank = usr.client.holder.rank
replytext = replacetext(replytext, "%BR%", "")
replytext = replacetext(replytext, "\n", "%BR%")
var/text_pass = reject_bad_text(replytext,8000)
replytext = replacetext(replytext, "%BR%", "<BR>")
if(!text_pass)
to_chat(usr, "The text you entered was blank, contained illegal characters or was too long. Please correct the text and submit again.")
return
var/DBQuery/insert_query = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("poll_textreply")] (id ,datetime ,pollid ,ckey ,ip ,replytext ,adminrank) VALUES (null, Now(), [pollid], '[ckey]', '[usr.client.address]', '[replytext]', '[adminrank]')")
insert_query.Execute()
to_chat(usr, "<span class='notice'>Feedback logging successful.</span>")
usr << browse(null,"window=playerpoll")
/client/proc/vote_on_numval_poll(var/pollid = -1, var/optionid = -1, var/rating = null)
if(pollid == -1 || optionid == -1)
return
if(!isnum(pollid) || !isnum(optionid))
return
establish_db_connection()
if(GLOB.dbcon.IsConnected())
var/DBQuery/select_query = GLOB.dbcon.NewQuery("SELECT starttime, endtime, question, polltype FROM [format_table_name("poll_question")] WHERE id = [pollid] AND Now() BETWEEN starttime AND endtime [holder ? "AND adminonly = 0" : ""]")
select_query.Execute()
var/validpoll = 0
while(select_query.NextRow())
if(select_query.item[4] != POLLTYPE_RATING)
return
validpoll = 1
break
if(!validpoll)
to_chat(usr, "<span class='warning'>Poll is not valid.</span>")
return
var/DBQuery/select_query2 = GLOB.dbcon.NewQuery("SELECT id FROM [format_table_name("poll_option")] WHERE id = [optionid] AND pollid = [pollid]")
select_query2.Execute()
var/validoption = 0
while(select_query2.NextRow())
validoption = 1
break
if(!validoption)
to_chat(usr, "<span class='warning'>Poll option is not valid.</span>")
return
var/alreadyvoted = 0
var/DBQuery/voted_query = GLOB.dbcon.NewQuery("SELECT id FROM [format_table_name("poll_vote")] WHERE optionid = [optionid] AND ckey = '[ckey]'")
voted_query.Execute()
while(voted_query.NextRow())
alreadyvoted = 1
break
if(alreadyvoted)
to_chat(usr, "<span class='warning'>You already voted in this poll.</span>")
return
var/adminrank = "Player"
if(usr && usr.client && usr.client.holder)
adminrank = usr.client.holder.rank
var/DBQuery/insert_query = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("poll_vote")] (id ,datetime ,pollid ,optionid ,ckey ,ip ,adminrank, rating) VALUES (null, Now(), [pollid], [optionid], '[ckey]', '[usr.client.address]', '[adminrank]', [(isnull(rating)) ? "null" : rating])")
insert_query.Execute()
to_chat(usr, "<span class='notice'>Vote successful.</span>")
usr << browse(null,"window=playerpoll")
+22 -21
View File
@@ -315,23 +315,36 @@ GLOBAL_DATUM(blackbox, /obj/machinery/blackbox_recorder)
if(!feedback) return
round_end_data_gathering() //round_end time logging and some other data processing
establish_db_connection()
if(!GLOB.dbcon.IsConnected()) return
if(!SSdbcore.IsConnected())
return
var/round_id
var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT MAX(round_id) AS round_id FROM [format_table_name("feedback")]")
query.Execute()
while(query.NextRow())
round_id = query.item[1]
var/datum/db_query/query_roundid = SSdbcore.NewQuery("SELECT MAX(round_id) AS round_id FROM [format_table_name("feedback")]")
if(!query_roundid.warn_execute())
qdel(query_roundid)
return
while(query_roundid.NextRow())
round_id = query_roundid.item[1]
if(!isnum(round_id))
round_id = text2num(round_id)
round_id++
qdel(query_roundid)
for(var/datum/feedback_variable/FV in feedback)
var/sql = "INSERT INTO [format_table_name("feedback")] VALUES (null, Now(), [round_id], \"[FV.get_variable()]\", [FV.get_value()], \"[FV.get_details()]\")"
var/DBQuery/query_insert = GLOB.dbcon.NewQuery(sql)
query_insert.Execute()
var/sql = "INSERT INTO [format_table_name("feedback")] VALUES (null, Now(), :rid, :var, :val, :details)"
var/datum/db_query/query_insert = SSdbcore.NewQuery(sql, list(
"rid" = text2num(round_id),
"var" = FV.get_variable(),
"val" = FV.get_value(),
"details" = FV.get_details()
))
if(!query_insert.warn_execute())
qdel(query_insert)
return
qdel(query_insert)
/obj/machinery/blackbox_recorder/vv_edit_var(var_name, var_value)
return FALSE // don't fuck with the stupid blackbox shit
@@ -345,8 +358,6 @@ GLOBAL_DATUM(blackbox, /obj/machinery/blackbox_recorder)
return
if(!GLOB.blackbox) return
variable = sanitizeSQL(variable)
var/datum/feedback_variable/FV = GLOB.blackbox.find_feedback_datum(variable)
if(!FV) return
@@ -361,8 +372,6 @@ GLOBAL_DATUM(blackbox, /obj/machinery/blackbox_recorder)
return
if(!GLOB.blackbox) return
variable = sanitizeSQL(variable)
var/datum/feedback_variable/FV = GLOB.blackbox.find_feedback_datum(variable)
if(!FV) return
@@ -377,8 +386,6 @@ GLOBAL_DATUM(blackbox, /obj/machinery/blackbox_recorder)
return
if(!GLOB.blackbox) return
variable = sanitizeSQL(variable)
var/datum/feedback_variable/FV = GLOB.blackbox.find_feedback_datum(variable)
if(!FV) return
@@ -393,9 +400,6 @@ GLOBAL_DATUM(blackbox, /obj/machinery/blackbox_recorder)
return
if(!GLOB.blackbox) return
variable = sanitizeSQL(variable)
details = sanitizeSQL(details)
var/datum/feedback_variable/FV = GLOB.blackbox.find_feedback_datum(variable)
if(!FV) return
@@ -410,9 +414,6 @@ GLOBAL_DATUM(blackbox, /obj/machinery/blackbox_recorder)
return
if(!GLOB.blackbox) return
variable = sanitizeSQL(variable)
details = sanitizeSQL(details)
var/datum/feedback_variable/FV = GLOB.blackbox.find_feedback_datum(variable)
if(!FV) return
+3
View File
@@ -39,4 +39,7 @@
if(example_db_version != SQL_VERSION)
Fail("SQL version error: Game is running V[SQL_VERSION] but config/example/dbconfig.txt is V[example_db_version].")
if(SSdbcore.total_errors > 0)
Fail("SQL errors occured on startup. Please fix them.")