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