mirror of
https://github.com/vgstation-coders/vgstation13.git
synced 2025-12-10 18:32:03 +00:00
>tried to make the comments less confusing. >Removed the procs for rebuilding the lists (they weren't meant to be used and half were broken anyway). >added a directory. It maps ckey to client like so directory[ckey] = client. It could be used for PMs, banning, and various other admin tools rather than using \ref[] >var/list/admins is now a list of clients whom are admins. >var/list/admin_datums is what var/list/admins used to be. A map from ckey -> admin datum Most of this is so I can add modular admin ranks in a non-horrendous way and fix some existing issues. >var/list/client_list is now var/list/clients (laziness sorry) >removed some needless loops and stuff. git-svn-id: http://tgstation13.googlecode.com/svn/trunk@4951 316c924e-a436-60f5-8080-3fe189b3f50e
192 lines
6.2 KiB
Plaintext
192 lines
6.2 KiB
Plaintext
////////////
|
|
//SECURITY//
|
|
////////////
|
|
#define TOPIC_SPAM_DELAY 4 //4 ticks is about 3/10ths of a second
|
|
#define UPLOAD_LIMIT 1048576 //Restricts client uploads to the server to 1MB //Could probably do with being lower.
|
|
#define MIN_CLIENT_VERSION 0 //Just an ambiguously low version for now, I don't want to suddenly stop people playing.
|
|
//I would just like the code ready should it ever need to be used.
|
|
/*
|
|
When somebody clicks a link in game, this Topic is called first.
|
|
It does the stuff in this proc and then is redirected to the Topic() proc for the src=[0xWhatever]
|
|
(if specified in the link). ie locate(hsrc).Topic()
|
|
|
|
Such links can be spoofed.
|
|
|
|
Because of this certain things MUST be considered whenever adding a Topic() for something:
|
|
- Can it be fed harmful values which could cause runtimes?
|
|
- Is the Topic call an admin-only thing?
|
|
- If so, does it have checks to see if the person who called it (usr.client) is an admin?
|
|
- Are the processes being called by Topic() particularly laggy?
|
|
- If so, is there any protection against somebody spam-clicking a link?
|
|
If you have any questions about this stuff feel free to ask. ~Carn
|
|
*/
|
|
/client/Topic(href, href_list, hsrc)
|
|
if(!usr || usr != mob) //stops us calling Topic for somebody else's client. Also helps prevent usr=null
|
|
return
|
|
|
|
//Reduces spamming of links by dropping calls that happen during the delay period
|
|
if(next_allowed_topic_time > world.time)
|
|
return
|
|
next_allowed_topic_time = world.time + TOPIC_SPAM_DELAY
|
|
|
|
//search the href for script injection
|
|
if( findtext(href,"<script",1,0) )
|
|
world.log << "Attempted use of scripts within a topic call, by [src]"
|
|
message_admins("Attempted use of scripts within a topic call, by [src]")
|
|
//del(usr)
|
|
return
|
|
|
|
//Admin PM
|
|
if(href_list["priv_msg"])
|
|
var/client/C = locate(href_list["priv_msg"])
|
|
if(ismob(C)) //Old stuff can feed-in mobs instead of clients
|
|
var/mob/M = C
|
|
C = M.client
|
|
cmd_admin_pm(C,null)
|
|
return
|
|
|
|
//Logs all hrefs
|
|
if(config && config.log_hrefs && href_logfile)
|
|
href_logfile << "<small>[time2text(world.timeofday,"hh:mm")] [src] (usr:[usr])</small> || [href]<br>"
|
|
|
|
if(view_var_Topic(href,href_list,hsrc)) //Until viewvars can be rewritten as datum/admins/Topic()
|
|
return
|
|
|
|
..() //redirect to [locate(hsrc)]/Topic()
|
|
|
|
/client/proc/handle_spam_prevention(var/message, var/mute_type)
|
|
if(config.automute_on && !holder && src.last_message == message)
|
|
src.last_message_count++
|
|
if(src.last_message_count >= SPAM_TRIGGER_AUTOMUTE)
|
|
src << "\red You have exceeded the spam filter limit for identical messages. An auto-mute was applied."
|
|
cmd_admin_mute(src.mob, mute_type, 1)
|
|
return 1
|
|
if(src.last_message_count >= SPAM_TRIGGER_WARNING)
|
|
src << "\red You are nearing the spam filter limit for identical messages."
|
|
return 0
|
|
else
|
|
last_message = message
|
|
src.last_message_count = 0
|
|
return 0
|
|
|
|
//This stops files larger than UPLOAD_LIMIT being sent from client to server via input(), client.Import() etc.
|
|
/client/AllowUpload(filename, filelength)
|
|
if(filelength > UPLOAD_LIMIT)
|
|
src << "<font color='red'>Error: AllowUpload(): File Upload too large. Upload Limit: [UPLOAD_LIMIT/1024]KiB.</font>"
|
|
return 0
|
|
/* //Don't need this at the moment. But it's here if it's needed later.
|
|
//Helps prevent multiple files being uploaded at once. Or right after eachother.
|
|
var/time_to_wait = fileaccess_timer - world.time
|
|
if(time_to_wait > 0)
|
|
src << "<font color='red'>Error: AllowUpload(): Spam prevention. Please wait [round(time_to_wait/10)] seconds.</font>"
|
|
return 0
|
|
fileaccess_timer = world.time + FTPDELAY */
|
|
return 1
|
|
|
|
|
|
///////////
|
|
//CONNECT//
|
|
///////////
|
|
/client/New(TopicData)
|
|
TopicData = null //Prevent calls to client.Topic from connect
|
|
|
|
if(connection != "seeker") //Invalid connection type.
|
|
return null
|
|
if(byond_version < MIN_CLIENT_VERSION) //Out of date client.
|
|
return null
|
|
|
|
clients += src
|
|
directory[ckey] = src
|
|
|
|
//Admin Authorisation
|
|
holder = admin_datums[ckey]
|
|
if(holder)
|
|
admins += src
|
|
holder.owner = src
|
|
holder.state = null
|
|
|
|
. = ..() //calls mob.Login()
|
|
|
|
if( (world.address == address || !address) && !host )
|
|
host = key
|
|
world.update_status()
|
|
|
|
if(holder)
|
|
admin_memo_show()
|
|
|
|
log_client_to_db()
|
|
|
|
|
|
//////////////
|
|
//DISCONNECT//
|
|
//////////////
|
|
/client/Del()
|
|
if(holder)
|
|
holder.state = null
|
|
holder.owner = null
|
|
admins -= src
|
|
directory -= ckey
|
|
clients -= src
|
|
return ..()
|
|
|
|
|
|
|
|
/client/proc/log_client_to_db()
|
|
|
|
if ( IsGuestKey(src.key) )
|
|
return
|
|
|
|
var/user = sqlfdbklogin
|
|
var/pass = sqlfdbkpass
|
|
var/db = sqlfdbkdb
|
|
var/address = sqladdress
|
|
var/port = sqlport
|
|
|
|
var/DBConnection/dbcon = new()
|
|
|
|
dbcon.Connect("dbi:mysql:[db]:[address]:[port]","[user]","[pass]")
|
|
if(!dbcon.IsConnected())
|
|
return
|
|
|
|
var/sql_ckey = sql_sanitize_text(src.ckey)
|
|
|
|
var/DBQuery/query = dbcon.NewQuery("SELECT id FROM erro_player WHERE ckey = '[sql_ckey]'")
|
|
query.Execute()
|
|
var/sql_id = 0
|
|
while(query.NextRow())
|
|
sql_id = query.item[1]
|
|
break
|
|
|
|
//Just the standard check to see if it's actually a number
|
|
if(sql_id)
|
|
if(istext(sql_id))
|
|
sql_id = text2num(sql_id)
|
|
if(!isnum(sql_id))
|
|
return
|
|
|
|
var/admin_rank = "Player"
|
|
if(src.holder)
|
|
admin_rank = src.holder.rank
|
|
|
|
var/sql_ip = sql_sanitize_text(src.address)
|
|
var/sql_computerid = sql_sanitize_text(src.computer_id)
|
|
var/sql_admin_rank = sql_sanitize_text(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 = dbcon.NewQuery("UPDATE erro_player SET lastseen = Now(), ip = '[sql_ip]', computerid = '[sql_computerid]', lastadminrank = '[sql_admin_rank]' WHERE id = [sql_id]")
|
|
query_update.Execute()
|
|
else
|
|
//New player!! Need to insert all the stuff
|
|
|
|
var/DBQuery/query_insert = dbcon.NewQuery("INSERT INTO erro_player (id, ckey, firstseen, lastseen, ip, computerid, lastadminrank) VALUES (null, '[sql_ckey]', Now(), Now(), '[sql_ip]', '[sql_computerid]', '[sql_admin_rank]')")
|
|
query_insert.Execute()
|
|
|
|
dbcon.Disconnect()
|
|
|
|
#undef TOPIC_SPAM_DELAY
|
|
#undef UPLOAD_LIMIT
|
|
#undef MIN_CLIENT_VERSION
|