//////////// //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,"[time2text(world.timeofday,"hh:mm")] [src] (usr:[usr]) || [href]
" 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 << "Error: AllowUpload(): File Upload too large. Upload Limit: [UPLOAD_LIMIT/1024]KiB." 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 << "Error: AllowUpload(): Spam prevention. Please wait [round(time_to_wait/10)] seconds." return 0 fileaccess_timer = world.time + FTPDELAY */ return 1 /////////// //CONNECT// /////////// /client/New() //Connection-Type and client byond_version checking if( connection != "seeker" || (byond_version < MIN_CLIENT_VERSION)) //Out of date or wrong connection type. Update your client!! del(src) return if(IsGuestKey(key)) alert(src,"Baystation12 doesn't allow guest accounts to play. Please go to http://www.byond.com/ and register for a key.","Guest","OK") del(src) return client_list += src if ( (world.address == address || !address) && !host ) host = key world.update_status() ..() //calls mob.Login() //makejson() if(custom_event_msg && custom_event_msg != "") src << "

Custom Event

" src << "

A custom event is taking place. OOC Info:

" src << "[html_encode(custom_event_msg)]" src << "
" //Admin Authorisation var/datum/admins/Admin_Obj = admins[ckey] if(istype(Admin_Obj)) admin_list += src holder = Admin_Obj holder.owner = src holder.state = null ..() //calls mob.Login() if(holder) admin_memo_show() log_client_to_db() ////////////// //DISCONNECT// ////////////// /client/Del() if(holder) holder.state = null admin_list -= src client_list -= 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