From 06338d2a956280f852e6807e718754bf22d04dd4 Mon Sep 17 00:00:00 2001
From: Varlaisvea <125837828+Varlaisvea@users.noreply.github.com>
Date: Sun, 28 May 2023 20:06:15 +0100
Subject: [PATCH] Updates text sanitization (#9082)
---
code/_helpers/text.dm | 3 ++
code/datums/uplink/announcements.dm | 4 +--
code/game/machinery/requests_console.dm | 5 ++--
code/game/objects/items/devices/uplink.dm | 28 +++++++++----------
.../preference_setup/antagonism/01_basic.dm | 6 ++--
.../preference_setup/general/05_background.dm | 14 +++++-----
code/modules/emotes/emote_mob.dm | 2 +-
code/modules/paperwork/handlabeler.dm | 4 +--
8 files changed, 35 insertions(+), 31 deletions(-)
diff --git a/code/_helpers/text.dm b/code/_helpers/text.dm
index f0c60ef734..3ef005f891 100644
--- a/code/_helpers/text.dm
+++ b/code/_helpers/text.dm
@@ -54,6 +54,9 @@
if(extra)
input = replace_characters(input, list("\n"=" ","\t"=" "))
+ input = html_decode(input) //this prevents double-encoding, but does nothing if it's not encoded already.
+ //For sending text to HTML UIs (eg browse() ), ensure encode = 1.
+
if(encode)
// The below \ escapes have a space inserted to attempt to enable CI auto-checking of span class usage. Please do not remove the space.
//In addition to processing html, html_encode removes byond formatting codes like "\ red", "\ i" and other.
diff --git a/code/datums/uplink/announcements.dm b/code/datums/uplink/announcements.dm
index 3d5ec18feb..ef35df734d 100644
--- a/code/datums/uplink/announcements.dm
+++ b/code/datums/uplink/announcements.dm
@@ -16,10 +16,10 @@
item_cost = 20
/datum/uplink_item/abstract/announcements/fake_centcom/extra_args(var/mob/user)
- var/title = sanitize(input("Enter your announcement title.", "Announcement Title") as null|text)
+ var/title = html_decode(sanitize(input("Enter your announcement title.", "Announcement Title") as null|text))
if(!title)
return
- var/message = sanitize(input("Enter your announcement message.", "Announcement Title") as null|text)
+ var/message = html_decode(sanitize(input("Enter your announcement message.", "Announcement Title") as message|null, extra = 0))
if(!message)
return
return list("title" = title, "message" = message)
diff --git a/code/game/machinery/requests_console.dm b/code/game/machinery/requests_console.dm
index a0c6af6921..829ced7d49 100644
--- a/code/game/machinery/requests_console.dm
+++ b/code/game/machinery/requests_console.dm
@@ -152,7 +152,7 @@ var/global/list/obj/machinery/requests_console/allConsoles = list()
reset_message(1)
if(href_list["writeAnnouncement"])
- var/new_message = sanitize(input("Write your message:", "Awaiting Input", ""))
+ var/new_message = sanitize(input("Write your message:", "Awaiting Input", "") as message|null, extra = 0) //Lets you write longer announcements.
if(new_message)
message = new_message
else
@@ -204,13 +204,14 @@ var/global/list/obj/machinery/requests_console/allConsoles = list()
if(computer_deconstruction_screwdriver(user, O))
return
if(istype(O, /obj/item/multitool))
- var/input = sanitize(input(usr, "What Department ID would you like to give this request console?", "Multitool-Request Console Interface", department))
+ var/input = html_decode(sanitize(input(usr, "What Department ID would you like to give this request console?", "Multitool-Request Console Interface", department)))
if(!input)
to_chat(usr, "No input found. Please hang up and try your call again.")
return
department = input
announcement.title = "[department] announcement"
announcement.newscast = 1
+ announcementConsole = 1 //2023-03-20, fixes deconstruction breaking announcement function
name = "[department] Requests Console"
allConsoles += src
diff --git a/code/game/objects/items/devices/uplink.dm b/code/game/objects/items/devices/uplink.dm
index e518cfdf95..458338ecb7 100644
--- a/code/game/objects/items/devices/uplink.dm
+++ b/code/game/objects/items/devices/uplink.dm
@@ -135,22 +135,22 @@
data["exploit"] = list() // Setting this to equal L.fields passes it's variables that are lists as reference instead of value.
// We trade off being able to automatically add shit for more control over what gets passed to json
// and if it's sanitized for html.
- data["exploit"]["nanoui_exploit_record"] = html_encode(L.fields["exploit_record"]) // Change stuff into html
- data["exploit"]["nanoui_exploit_record"] = replacetext(data["exploit"]["nanoui_exploit_record"], "\n", "
") // change line breaks into
- data["exploit"]["name"] = html_encode(L.fields["name"])
- data["exploit"]["sex"] = html_encode(L.fields["sex"])
- data["exploit"]["age"] = html_encode(L.fields["age"])
- data["exploit"]["species"] = html_encode(L.fields["species"])
- data["exploit"]["rank"] = html_encode(L.fields["rank"])
- data["exploit"]["home_system"] = html_encode(L.fields["home_system"])
- data["exploit"]["citizenship"] = html_encode(L.fields["citizenship"])
- data["exploit"]["faction"] = html_encode(L.fields["faction"])
- data["exploit"]["religion"] = html_encode(L.fields["religion"])
- data["exploit"]["fingerprint"] = html_encode(L.fields["fingerprint"])
+ data["exploit"]["nanoui_exploit_record"] = html_decode(L.fields["exploit_record"]) // This is all sanitized and encoded when it's entered.
+// data["exploit"]["nanoui_exploit_record"] = replacetext(data["exploit"]["nanoui_exploit_record"], "\n", "
") // We want to keep line breaks, though.
+ data["exploit"]["name"] = html_decode(L.fields["name"])
+ data["exploit"]["sex"] = html_decode(L.fields["sex"])
+ data["exploit"]["age"] = html_decode(L.fields["age"])
+ data["exploit"]["species"] = html_decode(L.fields["species"])
+ data["exploit"]["rank"] = html_decode(L.fields["rank"])
+ data["exploit"]["home_system"] = html_decode(L.fields["home_system"])
+ data["exploit"]["citizenship"] = html_decode(L.fields["citizenship"])
+ data["exploit"]["faction"] = html_decode(L.fields["faction"])
+ data["exploit"]["religion"] = html_decode(L.fields["religion"])
+ data["exploit"]["fingerprint"] = html_decode(L.fields["fingerprint"])
if(L.fields["antagvis"] == ANTAG_KNOWN || (faction == L.fields["antagfac"] && (L.fields["antagvis"] == ANTAG_SHARED)))
- data["exploit"]["antagfaction"] = html_encode(L.fields["antagfac"])
+ data["exploit"]["antagfaction"] = html_decode(L.fields["antagfac"])
else
- data["exploit"]["antagfaction"] = html_encode("None")
+ data["exploit"]["antagfaction"] = html_decode("None")
break
else
var/list/permanentData = list()
diff --git a/code/modules/client/preference_setup/antagonism/01_basic.dm b/code/modules/client/preference_setup/antagonism/01_basic.dm
index e0a60b6313..83b40f5e82 100644
--- a/code/modules/client/preference_setup/antagonism/01_basic.dm
+++ b/code/modules/client/preference_setup/antagonism/01_basic.dm
@@ -44,11 +44,11 @@ var/global/list/uplink_locations = list("PDA", "Headset", "None")
return TOPIC_REFRESH
if(href_list["exploitable_record"])
- var/exploitmsg = sanitize(input(user,"Set exploitable information about you here.","Exploitable Information", html_decode(pref.exploit_record)) as message|null, MAX_RECORD_LENGTH, extra = 0)
+ var/exploitmsg = html_decode(sanitizeSafe(input(user,"Set exploitable information about you here.","Exploitable Information", html_decode(pref.exploit_record)) as message|null, MAX_RECORD_LENGTH, extra = 0))
if(!isnull(exploitmsg) && !jobban_isbanned(user, "Records") && CanUseTopic(user))
pref.exploit_record = exploitmsg
return TOPIC_REFRESH
-
+
if(href_list["antagfaction"])
var/choice = input(user, "Please choose an antagonistic faction to work for.", "Character Preference", pref.antag_faction) as null|anything in antag_faction_choices + list("None","Other")
if(!choice || !CanUseTopic(user))
@@ -60,7 +60,7 @@ var/global/list/uplink_locations = list("PDA", "Headset", "None")
else
pref.antag_faction = choice
return TOPIC_REFRESH
-
+
if(href_list["antagvis"])
var/choice = input(user, "Please choose an antagonistic visibility level.", "Character Preference", pref.antag_vis) as null|anything in antag_visiblity_choices
if(!choice || !CanUseTopic(user))
diff --git a/code/modules/client/preference_setup/general/05_background.dm b/code/modules/client/preference_setup/general/05_background.dm
index 079cedca93..d8a47b7d33 100644
--- a/code/modules/client/preference_setup/general/05_background.dm
+++ b/code/modules/client/preference_setup/general/05_background.dm
@@ -107,27 +107,27 @@
if(!choice || !CanUseTopic(user))
return TOPIC_NOACTION
if(choice == "Other")
- var/raw_choice = sanitize(input(user, "Please enter a religon.", "Character Preference") as text|null, MAX_NAME_LEN)
+ var/raw_choice = sanitize(input(user, "Please enter a religion.", "Character Preference") as text|null, MAX_NAME_LEN)
if(raw_choice)
pref.religion = sanitize(raw_choice)
else
pref.religion = choice
return TOPIC_REFRESH
- else if(href_list["set_medical_records"])
- var/new_medical = sanitize(input(user,"Enter medical information here.","Character Preference", html_decode(pref.med_record)) as message|null, MAX_RECORD_LENGTH, extra = 0)
+ else if(href_list["set_medical_records"]) //2023-03-18, we're using sanitizeSafe() in order to remove <> entirely, allowing us to safely decode it on the pref screen
+ var/new_medical = html_decode(sanitizeSafe(input(user,"Enter medical information here.","Character Preference", html_decode(pref.med_record)) as message|null, MAX_RECORD_LENGTH, extra = 0))
if(!isnull(new_medical) && !jobban_isbanned(user, "Records") && CanUseTopic(user))
pref.med_record = new_medical
return TOPIC_REFRESH
- else if(href_list["set_general_records"])
- var/new_general = sanitize(input(user,"Enter employment information here.","Character Preference", html_decode(pref.gen_record)) as message|null, MAX_RECORD_LENGTH, extra = 0)
+ else if(href_list["set_general_records"]) //2023-03-20, this allows people to use apostrophes in their records!
+ var/new_general = html_decode(sanitizeSafe(input(user,"Enter employment information here.","Character Preference", html_decode(pref.gen_record)) as message|null, MAX_RECORD_LENGTH, extra = 0))
if(!isnull(new_general) && !jobban_isbanned(user, "Records") && CanUseTopic(user))
pref.gen_record = new_general
return TOPIC_REFRESH
- else if(href_list["set_security_records"])
- var/sec_medical = sanitize(input(user,"Enter security information here.","Character Preference", html_decode(pref.sec_record)) as message|null, MAX_RECORD_LENGTH, extra = 0)
+ else if(href_list["set_security_records"]) //Note that html exploits still won't work here because we removed <> earlier.
+ var/sec_medical = html_decode(sanitizeSafe(input(user,"Enter security information here.","Character Preference", html_decode(pref.sec_record)) as message|null, MAX_RECORD_LENGTH, extra = 0))
if(!isnull(sec_medical) && !jobban_isbanned(user, "Records") && CanUseTopic(user))
pref.sec_record = sec_medical
return TOPIC_REFRESH
diff --git a/code/modules/emotes/emote_mob.dm b/code/modules/emotes/emote_mob.dm
index c2a38f01cf..3be55945ee 100644
--- a/code/modules/emotes/emote_mob.dm
+++ b/code/modules/emotes/emote_mob.dm
@@ -152,7 +152,7 @@
to_chat(src, "You are unable to emote.")
return
- message = sanitize(message, encode = FALSE) // This is getting double-encoded somewhere along the line.
+ message = html_decode(sanitize(message))
if(!message)
return
diff --git a/code/modules/paperwork/handlabeler.dm b/code/modules/paperwork/handlabeler.dm
index 0162fa479f..649a926fe2 100644
--- a/code/modules/paperwork/handlabeler.dm
+++ b/code/modules/paperwork/handlabeler.dm
@@ -72,8 +72,8 @@
icon_state = "labeler[mode]"
if(mode)
to_chat(user, SPAN_NOTICE("You turn on \the [src]."))
- //Now let them chose the text.
- var/str = sanitizeSafe(input(user,"Label text?","Set label",""), MAX_NAME_LEN)
+ //Now let them choose the text.
+ var/str = html_decode(sanitizeSafe(input(user,"Label text?","Set label",""), MAX_NAME_LEN))
if(!str || !length(str))
to_chat(user, SPAN_WARNING("Invalid text."))
return