diff --git a/code/__defines/admin.dm b/code/__defines/admin.dm index 84e0656c97..0e8730bae8 100644 --- a/code/__defines/admin.dm +++ b/code/__defines/admin.dm @@ -46,26 +46,26 @@ #define SMITE_SPONTANEOUSCOMBUSTION "Spontaneous Combustion" #define SMITE_LIGHTNINGBOLT "Lightning Bolt" -#define ADMIN_QUE(user) "(?)" -#define ADMIN_FLW(user) "(FLW)" -#define ADMIN_PP(user) "(PP)" -#define ADMIN_VV(atom) "(VV)" -#define ADMIN_SM(user) "(SM)" -#define ADMIN_TP(user) "(TP)" -#define ADMIN_BSA(user) "(BSA)" -#define ADMIN_KICK(user) "(KICK)" -#define ADMIN_CENTCOM_REPLY(user) "(RPLY)" -#define ADMIN_SYNDICATE_REPLY(user) "(RPLY)" -#define ADMIN_SC(user) "(SC)" -#define ADMIN_SMITE(user) "(SMITE)" +#define ADMIN_QUE(user) "(?)" +#define ADMIN_FLW(user) "(FLW)" +#define ADMIN_PP(user) "(PP)" +#define ADMIN_VV(atom) "(VV)" +#define ADMIN_SM(user) "(SM)" +#define ADMIN_TP(user) "(TP)" +#define ADMIN_BSA(user) "(BSA)" +#define ADMIN_KICK(user) "(KICK)" +#define ADMIN_CENTCOM_REPLY(user) "(RPLY)" +#define ADMIN_SYNDICATE_REPLY(user) "(RPLY)" +#define ADMIN_SC(user) "(SC)" +#define ADMIN_SMITE(user) "(SMITE)" #define ADMIN_LOOKUP(user) "[key_name_admin(user)][ADMIN_QUE(user)]" #define ADMIN_LOOKUPFLW(user) "[key_name_admin(user)][ADMIN_QUE(user)] [ADMIN_FLW(user)]" #define ADMIN_FULLMONTY_NONAME(user) "[ADMIN_QUE(user)] [ADMIN_PP(user)] [ADMIN_VV(user)] [ADMIN_SM(user)] [ADMIN_FLW(user)] [ADMIN_TP(user)]" #define ADMIN_FULLMONTY(user) "[key_name_admin(user)] [ADMIN_FULLMONTY_NONAME(user)]" -#define ADMIN_JMP(src) "(JMP)" +#define ADMIN_JMP(src) "(JMP)" #define COORD(src) "[src ? "([src.x],[src.y],[src.z])" : "nonexistent location"]" #define ADMIN_COORDJMP(src) "[src ? "[COORD(src)] [ADMIN_JMP(src)]" : "nonexistent location"]" #define AHELP_ACTIVE 1 #define AHELP_CLOSED 2 -#define AHELP_RESOLVED 3 \ No newline at end of file +#define AHELP_RESOLVED 3 diff --git a/code/__defines/procpath.dm b/code/__defines/procpath.dm new file mode 100644 index 0000000000..e58a2a48b2 --- /dev/null +++ b/code/__defines/procpath.dm @@ -0,0 +1,25 @@ +/// Represents a proc or verb path. +/// +/// Despite having no DM-defined static type, proc paths have some variables, +/// listed below. These are not modifiable, but for a given procpath P, +/// `new P(null, "Name", "Desc")` can be used to create a new procpath with the +/// same code but new `name` and `desc` values. The other variables cannot be +/// changed in this way. +/// +/// This type exists only to act as an annotation, providing reasonable static +/// typing for procpaths. Previously, types like `/atom/verb` were used, with +/// the `name` and `desc` vars of `/atom` thus being accessible. Proc and verb +/// paths will fail `istype` and `ispath` checks against `/procpath`. +/procpath + // Although these variables are effectively const, if they are marked const + // below, their accesses are optimized away. + /// A text string of the verb's name. + var/name as text + /// The verb's help text or description. + var/desc as text + /// The category or tab the verb will appear in. + var/category as text + /// Only clients/mobs with `see_invisibility` higher can use the verb. + var/invisibility as num + /// Whether or not the verb appears in statpanel and commandbar when you press space + var/hidden as num diff --git a/code/_helpers/files.dm b/code/_helpers/files.dm index d6603e4275..9468becf8b 100644 --- a/code/_helpers/files.dm +++ b/code/_helpers/files.dm @@ -58,3 +58,18 @@ fileaccess_timer = world.time + FTPDELAY return 0 #undef FTPDELAY + +/// Returns the md5 of a file at a given path. +/proc/md5filepath(path) + . = md5(file(path)) + +/// Save file as an external file then md5 it. +/// Used because md5ing files stored in the rsc sometimes gives incorrect md5 results. +/proc/md5asfile(file) + var/static/notch = 0 + // its importaint this code can handle md5filepath sleeping instead of hard blocking, if it's converted to use rust_g. + var/filename = "tmp/md5asfile.[world.realtime].[world.timeofday].[world.time].[world.tick_usage].[notch]" + notch = WRAP(notch+1, 0, 2**15) + fcopy(file, filename) + . = md5filepath(filename) + fdel(filename) diff --git a/code/modules/admin/NewBan.dm b/code/modules/admin/NewBan.dm index 15d29eb1f0..22e8d9a4b2 100644 --- a/code/modules/admin/NewBan.dm +++ b/code/modules/admin/NewBan.dm @@ -186,7 +186,7 @@ var/savefile/Banlist if(!expiry) expiry = "Removal Pending" else expiry = "Permaban" - dat += text("(U)(E) Key: [key]ComputerID: [id]IP: [ip] [expiry](By: [by])(Reason: [reason])") + dat += text("(U)(E) Key: [key]ComputerID: [id]IP: [ip] [expiry](By: [by])(Reason: [reason])") dat += "" dat = "
Bans: (U) = Unban , (E) = Edit Ban - ([count] Bans)
[dat]" @@ -227,4 +227,3 @@ var/savefile/Banlist Banlist.cd = "/base" for (var/A in Banlist.dir) RemoveBan(A) - diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 31773e10b4..30acc8dd3a 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -43,12 +43,12 @@ var/global/floorIsLava = 0 body += "Options panel for [M]" if(M.client) body += " played by [M.client] " - body += "\[[M.client.holder ? M.client.holder.rank : "Player"]\]" + body += "\[[M.client.holder ? M.client.holder.rank : "Player"]\]" if(istype(M, /mob/new_player)) body += " Hasn't Entered Game " else - body += " \[Heal\] " + body += " \[Heal\] " if(M.client) body += "
First connection: [M.client.player_age] days ago" @@ -57,41 +57,41 @@ var/global/floorIsLava = 0 body += {"

\[ - VV - - TP - - PM - - SM - + VV - + TP - + PM - + SM - [admin_jump_link(M, src)]\]
Mob type: [M.type]
Inactivity time: [M.client ? "[M.client.inactivity/600] minutes" : "Logged out"]

- Kick | - Warn | - Ban | - Jobban | - Notes + Kick | + Warn | + Ban | + Jobban | + Notes "} if(M.client) - body += "| Prison | " - body += "\ Send back to Lobby | " + body += "| Prison | " + body += "\ Send back to Lobby | " var/muted = M.client.prefs.muted body += {"
Mute: - \[IC | - OOC | - PRAY | - ADMINHELP | - DEADCHAT\] - (toggle all) + \[IC | + OOC | + PRAY | + ADMINHELP | + DEADCHAT\] + (toggle all) "} body += {"

- Jump to | - Get | - Send To + Jump to | + Get | + Send To

- [check_rights(R_ADMIN|R_MOD|R_EVENT,0) ? "Traitor panel | " : "" ] - Narrate to | - Subtle message + [check_rights(R_ADMIN|R_MOD|R_EVENT,0) ? "Traitor panel | " : "" ] + Narrate to | + Subtle message "} if (M.client) @@ -104,30 +104,30 @@ var/global/floorIsLava = 0 if(issmall(M)) body += "Monkeyized | " else - body += "Monkeyize | " + body += "Monkeyize | " //Corgi if(iscorgi(M)) body += "Corgized | " else - body += "Corgize | " + body += "Corgize | " //AI / Cyborg if(isAI(M)) body += "Is an AI " else if(ishuman(M)) - body += {"Make AI | - Make Robot | - Make Alien + body += {"Make AI | + Make Robot | + Make Alien "} //Simple Animals if(isanimal(M)) - body += "Re-Animalize | " + body += "Re-Animalize | " else - body += "Animalize | " + body += "Animalize | " - body += "Respawn | " + body += "Respawn | " // DNA2 - Admin Hax if(M.dna && iscarbon(M)) @@ -142,7 +142,7 @@ var/global/floorIsLava = 0 if(bname) var/bstate=M.dna.GetSEState(block) var/bcolor="[(bstate)?"#006600":"#ff0000"]" - body += "[bname][block]" + body += "[bname][block]" else body += "[block]" body+="" @@ -150,45 +150,45 @@ var/global/floorIsLava = 0 body += {"

Rudimentary transformation:
These transformations only create a new mob type and copy stuff over. They do not take into account MMIs and similar mob-specific things. The buttons in 'Transformations' are preferred, when possible.

- Observer | - \[ Xenos: Larva - Drone - Hunter - Sentinel - Queen \] | - \[ Crew: Human - Unathi - Tajaran - Skrell \] | \[ - Nymph - Diona \] | - \[ slime: Baby, - Adult \] - Monkey | - Cyborg | - Cat | - Runtime | - Corgi | - Ian | - Crab | - Coffee | - \[ Construct: Armoured , - Builder , - Wraith \] - Shade + Observer | + \[ Xenos: Larva + Drone + Hunter + Sentinel + Queen \] | + \[ Crew: Human + Unathi + Tajaran + Skrell \] | \[ + Nymph + Diona \] | + \[ slime: Baby, + Adult \] + Monkey | + Cyborg | + Cat | + Runtime | + Corgi | + Ian | + Crab | + Coffee | + \[ Construct: Armoured , + Builder , + Wraith \] + Shade
"} body += {"

Other actions:
- Forcesay + Forcesay "} if (M.client) body += {" | - Thunderdome 1 | - Thunderdome 2 | - Thunderdome Admin | - Thunderdome Observer | + Thunderdome 1 | + Thunderdome 2 | + Thunderdome Admin | + Thunderdome Observer | "} // language toggles body += "

Languages:
" @@ -199,9 +199,9 @@ var/global/floorIsLava = 0 if(!f) body += " | " else f = 0 if(L in M.languages) - body += "[k]" + body += "[k]" else - body += "[k]" + body += "[k]" body += {"
@@ -527,7 +527,7 @@ var/global/floorIsLava = 0 var/r = t if( findtext(r,"##") ) r = copytext( r, 1, findtext(r,"##") )//removes the description - dat += text("") + dat += text("") dat += "
[t] (unban)
[t] (unban)
" usr << browse(dat, "window=ban;size=400x400") @@ -536,20 +536,20 @@ var/global/floorIsLava = 0 var/dat = {"
Game Panel

\n - Change Game Mode
+ Change Game Mode
"} if(master_mode == "secret") - dat += "(Force Secret Mode)
" + dat += "(Force Secret Mode)
" dat += {"
- Create Object
- Quick Create Object
- Create Turf
- Create Mob
-
Edit Airflow Settings
- Edit Phoron Settings
- Choose a default ZAS setting
+ Create Object
+ Quick Create Object
+ Create Turf
+ Create Mob
+
Edit Airflow Settings
+ Edit Phoron Settings
+ Choose a default ZAS setting
"} usr << browse(dat, "window=admin2;size=210x280") @@ -563,7 +563,7 @@ var/global/floorIsLava = 0 for(var/datum/admin_secret_category/category in admin_secrets.categories) if(!category.can_view(usr)) continue - dat += "[category.name] " + dat += "[category.name] " dat += "
" // If a category is selected, print its description and then options @@ -574,7 +574,7 @@ var/global/floorIsLava = 0 for(var/datum/admin_secret_item/item in active_category.items) if(!item.can_view(usr)) continue - dat += "[item.name()]
" + dat += "[item.name()]
" dat += "
" var/datum/browser/popup = new(usr, "secrets", "Secrets", 500, 500) diff --git a/code/modules/admin/admin_report.dm b/code/modules/admin/admin_report.dm index bc1adbcfdc..e0af36c9c8 100644 --- a/code/modules/admin/admin_report.dm +++ b/code/modules/admin/admin_report.dm @@ -107,9 +107,9 @@ world/New() output += "Offense:[N.body]
" output += "Occured at [time2text(N.date,"MM/DD hh:mm:ss")]
" output += "authored by [N.author]
" - output += " Flag as Handled" + output += " Flag as Handled" if(src.key == N.author) - output += " Edit" + output += " Edit" output += "
" output += "
" else @@ -149,7 +149,7 @@ world/New() for(var/datum/admin_report/N in reports) if(N.ID == ID) found = N - if(!found) + if(!found) to_chat(src, "* An error occured, sorry.") found.done = 1 @@ -171,7 +171,7 @@ world/New() for(var/datum/admin_report/N in reports) if(N.ID == ID) found = N - if(!found) + if(!found) to_chat(src, "* An error occured, sorry.") var/body = tgui_input_text(src.mob, "Enter a body for the news", "Body", multiline = TRUE, prevent_enter = TRUE) diff --git a/code/modules/admin/holder2.dm b/code/modules/admin/holder2.dm index cff69baffc..46544a0809 100644 --- a/code/modules/admin/holder2.dm +++ b/code/modules/admin/holder2.dm @@ -1,3 +1,6 @@ +GLOBAL_VAR_INIT(href_token, GenerateToken()) +GLOBAL_PROTECT(href_token) + var/list/admin_datums = list() /datum/admins @@ -13,6 +16,8 @@ var/list/admin_datums = list() var/datum/feed_channel/admincaster_feed_channel = new /datum/feed_channel var/admincaster_signature //What you'll sign the newsfeeds as + var/href_token + /datum/admins/New(initial_rank = "Temporary Admin", initial_rights = 0, ckey) if(!ckey) @@ -20,6 +25,7 @@ var/list/admin_datums = list() qdel(src) return admincaster_signature = "[using_map.company_name] Officer #[rand(0,9)][rand(0,9)][rand(0,9)]" + href_token = GenerateToken() rank = initial_rank rights = initial_rights admin_datums[ckey] = src @@ -126,4 +132,26 @@ NOTE: It checks usr by default. Supply the "user" argument if you wish to check if(rights_required && !(rights_required & subject.holder.rights)) return 0 return 1 - return 0 \ No newline at end of file + return 0 + +/proc/GenerateToken() + . = "" + for(var/I in 1 to 32) + . += "[rand(10)]" + +/proc/RawHrefToken(forceGlobal = FALSE) + var/tok = GLOB.href_token + if(!forceGlobal && usr) + var/client/C = usr.client + if(!C) + CRASH("No client for HrefToken()!") + var/datum/admins/holder = C.holder + if(holder) + tok = holder.href_token + return tok + +/proc/HrefToken(forceGlobal = FALSE) + return "admin_token=[RawHrefToken(forceGlobal)]" + +/proc/HrefTokenFormField(forceGlobal = FALSE) + return "" diff --git a/code/modules/admin/newbanjob.dm b/code/modules/admin/newbanjob.dm index c7180d0a49..e743bb6bc2 100644 --- a/code/modules/admin/newbanjob.dm +++ b/code/modules/admin/newbanjob.dm @@ -211,7 +211,7 @@ var/savefile/Banlistjob for (var/A in Banlistjob.dir) count++ Banlistjob.cd = "/base/[A]" - dat += text("(U) Key: [Banlistjob["key"]] Rank: [Banlistjob["rank"]] ([Banlistjob["temp"] ? "[GetBanExpjob(Banlistjob["minutes"]) ? GetBanExpjob(Banlistjob["minutes"]) : "Removal pending" ]" : "Permaban"])(By: [Banlistjob["bannedby"]])(Reason: [Banlistjob["reason"]])") + dat += text("(U) Key: [Banlistjob["key"]] Rank: [Banlistjob["rank"]] ([Banlistjob["temp"] ? "[GetBanExpjob(Banlistjob["minutes"]) ? GetBanExpjob(Banlistjob["minutes"]) : "Removal pending" ]" : "Permaban"])(By: [Banlistjob["bannedby"]])(Reason: [Banlistjob["reason"]])") dat += "" dat = "
Bans: (U) = Unban , - ([count] Bans)
[dat]" diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 0ddf3441f7..d5545f1ad6 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -1,3 +1,19 @@ +/datum/admins/proc/CheckAdminHref(href, href_list) + var/auth = href_list["admin_token"] + . = auth && (auth == href_token || auth == GLOB.href_token) + if(.) + return + var/msg = !auth ? "no" : "a bad" + message_admins("[key_name_admin(usr)] clicked an href with [msg] authorization key!") + + var/debug_admin_hrefs = TRUE // Remove once everything is converted over + if(debug_admin_hrefs) + message_admins("Debug mode enabled, call not blocked. Please ask your coders to review this round's logs.") + log_world("UAH: [href]") + return TRUE + + log_admin("[key_name(usr)] clicked an href with [msg] authorization key! [href]") + /datum/admins/Topic(href, href_list) ..() @@ -6,6 +22,9 @@ message_admins("[usr.key] has attempted to override the admin panel!") return + if(!CheckAdminHref(href, href_list)) + return + if(ticker.mode && ticker.mode.check_antagonists_topic(href, href_list)) check_antagonists() return diff --git a/vorestation.dme b/vorestation.dme index d2e071e791..ce20b2d070 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -78,6 +78,7 @@ #include "code\__defines\plants.dm" #include "code\__defines\preferences.dm" #include "code\__defines\process_scheduler.dm" +#include "code\__defines\procpath.dm" #include "code\__defines\qdel.dm" #include "code\__defines\research.dm" #include "code\__defines\roguemining_vr.dm"