mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-05-17 20:30:46 +01:00
e0aabe5914
* talon uniform
* Talon update
* Update talon_v2.dmm
Playing
* Talon fix and a new Slogan!
* talon fax
* For admins set up talon company fax
+ paperworks can use [talogo]
* Add FAX word
* Talon seal addation
* Fix and Updating the Talon map
Regarding the Talon map, I brought it to the appearance of the Rogue Star. So that players on both servers feel as little strange as possible when playing on the same ship, even on different servers.
* Update talon_v2.dmm
bluespace
* Fixup maps in TGM format
a89e3f1f87: maps/offmap_vr/talon/talon_v2.dmm
Automatically commited by: tools\mapmerge2\fixup.py
* Update talon_v2.dm
* Update talon_v2.dm
* sprite fix
* Forgot to add a fix
Fix for stamp and logo for correct work
* Delete custom_items.txt
accidentally add that in PR, now rempve that
797 lines
28 KiB
Plaintext
797 lines
28 KiB
Plaintext
/*
|
|
* Holds procs designed to help with filtering text
|
|
* Contains groups:
|
|
* SQL sanitization
|
|
* Text sanitization
|
|
* Text searches
|
|
* Text modification
|
|
* Misc
|
|
*/
|
|
|
|
GLOBAL_LIST_INIT(alphabet_upper, list("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"))
|
|
|
|
/*
|
|
* SQL sanitization
|
|
*/
|
|
|
|
// Run all strings to be used in an SQL query through this proc first to properly escape out injection attempts.
|
|
/proc/sanitizeSQL(var/t as text)
|
|
//var/sqltext = dbcon.Quote(t);
|
|
//return copytext(sqltext, 2, length(sqltext));//Quote() adds quotes around input, we already do that
|
|
return t
|
|
|
|
/proc/format_table_name(table as text)
|
|
//return CONFIG_GET(string/feedback_tableprefix) + table
|
|
return table // We don't implement tableprefix
|
|
|
|
/*
|
|
* Text sanitization
|
|
*/
|
|
// Can be used almost the same way as normal input for text
|
|
/proc/clean_input(Message, Title, Default, mob/user)
|
|
var/txt = input(user, Message, Title, Default) as text | null
|
|
if(txt)
|
|
return html_encode(txt)
|
|
|
|
//Simply removes < and > and limits the length of the message
|
|
/proc/strip_html_simple(var/t,var/limit=MAX_MESSAGE_LEN)
|
|
var/list/strip_chars = list("<",">")
|
|
t = copytext(t,1,limit)
|
|
for(var/char in strip_chars)
|
|
var/index = findtext(t, char)
|
|
while(index)
|
|
t = copytext(t, 1, index) + copytext(t, index+1)
|
|
index = findtext(t, char)
|
|
return t
|
|
|
|
//Runs byond's sanitization proc along-side strip_html_simple
|
|
//I believe strip_html_simple() is required to run first to prevent '<' from displaying as '<' that html_encode() would cause
|
|
/proc/adminscrub(var/t,var/limit=MAX_MESSAGE_LEN)
|
|
return copytext((html_encode(strip_html_simple(t))),1,limit)
|
|
|
|
//Used for preprocessing entered text
|
|
/proc/sanitize(var/input, var/max_length = MAX_MESSAGE_LEN, var/encode = 1, var/trim = 1, var/extra = 1)
|
|
if(!input)
|
|
return
|
|
|
|
if(max_length)
|
|
input = copytext(input,1,max_length)
|
|
|
|
if(extra)
|
|
input = replacetext(input, new/regex("^\[\\n\]+|\[\\n\]+$", "g"), "")// strip leading and trailing new lines
|
|
var/temp_input = replace_characters(input, list("\n"=" ","\t"=" "))//one character is replaced by two
|
|
if(length(input) < (length(temp_input) - 18))//18 is the number of linebreaks allowed per message
|
|
input = replace_characters(temp_input,list(" "=" "))//replace again, this time the double spaces with single ones
|
|
|
|
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.
|
|
//It is important to avoid double-encode text, it can "break" quotes and some other characters.
|
|
//Also, keep in mind that escaped characters don't work in the interface (window titles, lower left corner of the main window, etc.)
|
|
input = html_encode(input)
|
|
else
|
|
//If not need encode text, simply remove < and >
|
|
//note: we can also remove here byond formatting codes: 0xFF + next byte
|
|
input = replace_characters(input, list("<"=" ", ">"=" "))
|
|
|
|
if(trim)
|
|
//Maybe, we need trim text twice? Here and before copytext?
|
|
input = trim(input)
|
|
|
|
return input
|
|
|
|
//Run sanitize(), but remove <, >, " first to prevent displaying them as > < &34; in some places, after html_encode().
|
|
//Best used for sanitize object names, window titles.
|
|
//If you have a problem with sanitize() in chat, when quotes and >, < are displayed as html entites -
|
|
//this is a problem of double-encode(when & becomes &), use sanitize() with encode=0, but not the sanitizeSafe()!
|
|
/proc/sanitizeSafe(var/input, var/max_length = MAX_MESSAGE_LEN, var/encode = 1, var/trim = 1, var/extra = 1)
|
|
return sanitize(replace_characters(input, list(">"=" ","<"=" ", "\""="'")), max_length, encode, trim, extra)
|
|
|
|
//Filters out undesirable characters from names
|
|
/proc/sanitizeName(var/input, var/max_length = MAX_NAME_LEN, var/allow_numbers = 0)
|
|
if(!input || length(input) > max_length)
|
|
return //Rejects the input if it is null or if it is longer then the max length allowed
|
|
|
|
var/number_of_alphanumeric = 0
|
|
var/last_char_group = 0
|
|
var/output = ""
|
|
|
|
for(var/i=1, i<=length(input), i++)
|
|
var/ascii_char = text2ascii(input,i)
|
|
switch(ascii_char)
|
|
// A .. Z
|
|
if(65 to 90) //Uppercase Letters
|
|
output += ascii2text(ascii_char)
|
|
number_of_alphanumeric++
|
|
last_char_group = 4
|
|
|
|
// a .. z
|
|
if(97 to 122) //Lowercase Letters
|
|
if(last_char_group<2) output += ascii2text(ascii_char-32) //Force uppercase first character
|
|
else output += ascii2text(ascii_char)
|
|
number_of_alphanumeric++
|
|
last_char_group = 4
|
|
|
|
// 0 .. 9
|
|
if(48 to 57) //Numbers
|
|
if(!allow_numbers) continue // If allow_numbers is 0, then don't do this.
|
|
output += ascii2text(ascii_char)
|
|
number_of_alphanumeric++
|
|
last_char_group = 3
|
|
|
|
// ' - .
|
|
if(39,45,46) //Common name punctuation
|
|
if(!last_char_group) continue
|
|
output += ascii2text(ascii_char)
|
|
last_char_group = 2
|
|
|
|
// ~ | @ : # $ % & * +
|
|
if(126,124,64,58,35,36,37,38,42,43) //Other symbols that we'll allow (mainly for AI)
|
|
if(!last_char_group) continue //suppress at start of string
|
|
if(!allow_numbers) continue
|
|
output += ascii2text(ascii_char)
|
|
last_char_group = 2
|
|
|
|
//Space
|
|
if(32)
|
|
if(last_char_group <= 1) continue //suppress double-spaces and spaces at start of string
|
|
output += ascii2text(ascii_char)
|
|
last_char_group = 1
|
|
else
|
|
return
|
|
|
|
if(number_of_alphanumeric < 2) return //protects against tiny names like "A" and also names like "' ' ' ' ' ' ' '"
|
|
|
|
if(last_char_group == 1)
|
|
output = copytext(output,1,length(output)) //removes the last character (in this case a space)
|
|
|
|
for(var/bad_name in list("space","floor","wall","r-wall","monkey","unknown","inactive ai","plating")) //prevents these common metagamey names
|
|
if(cmptext(output,bad_name)) return //(not case sensitive)
|
|
|
|
return output
|
|
|
|
/**
|
|
* Returns the text if properly formatted, or null else.
|
|
*
|
|
* Things considered improper:
|
|
* * Larger than max_length.
|
|
* * Presence of non-ASCII characters if asci_only is set to TRUE.
|
|
* * Only whitespaces, tabs and/or line breaks in the text.
|
|
* * Presence of the <, >, \ and / characters.
|
|
* * Presence of ASCII special control characters (horizontal tab and new line not included).
|
|
* */
|
|
/proc/reject_bad_text(text, max_length = 512, ascii_only = TRUE)
|
|
if(ascii_only)
|
|
if(length(text) > max_length)
|
|
return null
|
|
var/static/regex/non_ascii = regex(@"[^\x20-\x7E\t\n]")
|
|
if(non_ascii.Find(text))
|
|
return null
|
|
else if(length_char(text) > max_length)
|
|
return null
|
|
var/static/regex/non_whitespace = regex(@"\S")
|
|
if(!non_whitespace.Find(text))
|
|
return null
|
|
var/static/regex/bad_chars = regex(@"[\\<>/\x00-\x08\x11-\x1F]")
|
|
if(bad_chars.Find(text))
|
|
return null
|
|
return text
|
|
|
|
|
|
//Old variant. Haven't dared to replace in some places.
|
|
/proc/sanitize_old(var/t,var/list/repl_chars = list("\n"="#","\t"="#"))
|
|
return html_encode(replace_characters(t,repl_chars))
|
|
|
|
|
|
//Removes a few problematic characters
|
|
/proc/sanitize_simple(t,list/repl_chars = list("\n"="#","\t"="#"))
|
|
for(var/char in repl_chars)
|
|
var/index = findtext(t, char)
|
|
while(index)
|
|
t = copytext(t, 1, index) + repl_chars[char] + copytext(t, index + length(char))
|
|
index = findtext(t, char, index + length(char))
|
|
return t
|
|
|
|
/proc/sanitize_filename(t)
|
|
return sanitize_simple(t, list("\n"="", "\t"="", "/"="", "\\"="", "?"="", "%"="", "*"="", ":"="", "|"="", "\""="", "<"="", ">"=""))
|
|
|
|
/*
|
|
* Text searches
|
|
*/
|
|
|
|
//Checks the beginning of a string for a specified sub-string
|
|
//Returns the position of the substring or 0 if it was not found
|
|
/proc/dd_hasprefix(text, prefix)
|
|
var/start = 1
|
|
var/end = length(prefix) + 1
|
|
return findtext(text, prefix, start, end)
|
|
|
|
//Checks the beginning of a string for a specified sub-string. This proc is case sensitive
|
|
//Returns the position of the substring or 0 if it was not found
|
|
/proc/dd_hasprefix_case(text, prefix)
|
|
var/start = 1
|
|
var/end = length(prefix) + 1
|
|
return findtextEx(text, prefix, start, end)
|
|
|
|
//Checks the end of a string for a specified substring.
|
|
//Returns the position of the substring or 0 if it was not found
|
|
/proc/dd_hassuffix(text, suffix)
|
|
var/start = length(text) - length(suffix)
|
|
if(start)
|
|
return findtext(text, suffix, start, null)
|
|
return
|
|
|
|
//Checks the end of a string for a specified substring. This proc is case sensitive
|
|
//Returns the position of the substring or 0 if it was not found
|
|
/proc/dd_hassuffix_case(text, suffix)
|
|
var/start = length(text) - length(suffix)
|
|
if(start)
|
|
return findtextEx(text, suffix, start, null)
|
|
|
|
/*
|
|
* Text modification
|
|
*/
|
|
/proc/replace_characters(var/t,var/list/repl_chars)
|
|
for(var/char in repl_chars)
|
|
t = replacetext(t, char, repl_chars[char])
|
|
return t
|
|
|
|
//Adds 'u' number of zeros ahead of the text 't'
|
|
/proc/add_zero(t, u)
|
|
while (length(t) < u)
|
|
t = "0[t]"
|
|
return t
|
|
|
|
//Adds 'u' number of spaces ahead of the text 't'
|
|
/proc/add_lspace(t, u)
|
|
while(length(t) < u)
|
|
t = " [t]"
|
|
return t
|
|
|
|
//Adds 'u' number of spaces behind the text 't'
|
|
/proc/add_tspace(t, u)
|
|
while(length(t) < u)
|
|
t = "[t] "
|
|
return t
|
|
|
|
//Returns a string with reserved characters and spaces before the first letter removed
|
|
/proc/trim_left(text)
|
|
for (var/i = 1 to length(text))
|
|
if (text2ascii(text, i) > 32)
|
|
return copytext(text, i)
|
|
return ""
|
|
|
|
//Returns a string with reserved characters and spaces after the last letter removed
|
|
/proc/trim_right(text)
|
|
for (var/i = length(text), i > 0, i--)
|
|
if (text2ascii(text, i) > 32)
|
|
return copytext(text, 1, i + 1)
|
|
return ""
|
|
|
|
//Returns a string with reserved characters and spaces before the first word and after the last word removed.
|
|
/proc/trim(text)
|
|
return trim_left(trim_right(text))
|
|
|
|
//Returns a string with the first element of the string capitalized.
|
|
/proc/capitalize(var/t as text)
|
|
return uppertext(copytext(t, 1, 2)) + copytext(t, 2)
|
|
|
|
//Returns a unicode string with the first element of the string capitalized.
|
|
/proc/capitalize_utf(var/t as text)
|
|
return uppertext(copytext_char(t, 1, 2)) + copytext_char(t, 2)
|
|
|
|
//This proc strips html properly, remove < > and all text between
|
|
//for complete text sanitizing should be used sanitize()
|
|
/proc/strip_html_properly(var/input)
|
|
if(!input)
|
|
return
|
|
var/opentag = 1 //These store the position of < and > respectively.
|
|
var/closetag = 1
|
|
while(1)
|
|
opentag = findtext(input, "<")
|
|
closetag = findtext(input, ">")
|
|
if(closetag && opentag)
|
|
if(closetag < opentag)
|
|
input = copytext(input, (closetag + 1))
|
|
else
|
|
input = copytext(input, 1, opentag) + copytext(input, (closetag + 1))
|
|
else if(closetag || opentag)
|
|
if(opentag)
|
|
input = copytext(input, 1, opentag)
|
|
else
|
|
input = copytext(input, (closetag + 1))
|
|
else
|
|
break
|
|
|
|
return input
|
|
|
|
//This proc fills in all spaces with the "replace" var (* by default) with whatever
|
|
//is in the other string at the same spot (assuming it is not a replace char).
|
|
//This is used for fingerprints
|
|
/proc/stringmerge(var/text,var/compare,replace = "*")
|
|
var/newtext = text
|
|
if(length(text) != length(compare))
|
|
return 0
|
|
for(var/i = 1, i < length(text), i++)
|
|
var/a = copytext(text,i,i+1)
|
|
var/b = copytext(compare,i,i+1)
|
|
//if it isn't both the same letter, or if they are both the replacement character
|
|
//(no way to know what it was supposed to be)
|
|
if(a != b)
|
|
if(a == replace) //if A is the replacement char
|
|
newtext = copytext(newtext,1,i) + b + copytext(newtext, i+1)
|
|
else if(b == replace) //if B is the replacement char
|
|
newtext = copytext(newtext,1,i) + a + copytext(newtext, i+1)
|
|
else //The lists disagree, Uh-oh!
|
|
return 0
|
|
return newtext
|
|
|
|
//This proc returns the number of chars of the string that is the character
|
|
//This is used for detective work to determine fingerprint completion.
|
|
/proc/stringpercent(var/text,character = "*")
|
|
if(!text || !character)
|
|
return 0
|
|
var/count = 0
|
|
for(var/i = 1, i <= length(text), i++)
|
|
var/a = copytext(text,i,i+1)
|
|
if(a == character)
|
|
count++
|
|
return count
|
|
|
|
/proc/reverse_text(var/text = "")
|
|
var/new_text = ""
|
|
for(var/i = length(text); i > 0; i--)
|
|
new_text += copytext(text, i, i+1)
|
|
return new_text
|
|
|
|
//Used in preferences' SetFlavorText and human's set_flavor verb
|
|
//Previews a string of len or less length
|
|
/proc/TextPreview(var/string,var/len=40)
|
|
if(length(string) <= len)
|
|
if(!length(string))
|
|
return "\[...\]"
|
|
else
|
|
return string
|
|
else
|
|
return "[copytext_preserve_html(string, 1, len - 3)]..."
|
|
|
|
//alternative copytext() for encoded text, doesn't break html entities (" and other)
|
|
/proc/copytext_preserve_html(var/text, var/first, var/last)
|
|
return html_encode(copytext(html_decode(text), first, last))
|
|
|
|
//For generating neat chat tag-images
|
|
//The icon var could be local in the proc, but it's a waste of resources
|
|
// to always create it and then throw it out.
|
|
GLOBAL_VAR_INIT(text_tag_icons, 'icons/chattags.dmi')
|
|
GLOBAL_LIST_EMPTY(text_tag_cache)
|
|
|
|
/proc/create_text_tag(var/tagname, var/tagdesc = tagname, var/client/C = null)
|
|
if(!(C && C.prefs?.read_preference(/datum/preference/toggle/chat_tags)))
|
|
return tagdesc
|
|
if(!GLOB.text_tag_cache[tagname])
|
|
var/datum/asset/spritesheet_batched/chatassets = get_asset_datum(/datum/asset/spritesheet_batched/chat)
|
|
GLOB.text_tag_cache[tagname] = chatassets.icon_tag(tagname)
|
|
if(!C.tgui_panel.is_ready() || C.tgui_panel.oldchat)
|
|
return "<IMG src='\ref[GLOB.text_tag_icons]' class='text_tag' iconstate='[tagname]'" + (tagdesc ? " alt='[tagdesc]'" : "") + ">"
|
|
return GLOB.text_tag_cache[tagname]
|
|
|
|
/proc/create_text_tag_old(var/tagname, var/tagdesc = tagname, var/client/C = null)
|
|
if(!(C && C.prefs?.read_preference(/datum/preference/toggle/chat_tags)))
|
|
return tagdesc
|
|
return "<IMG src='\ref[GLOB.text_tag_icons]' class='text_tag' iconstate='[tagname]'" + (tagdesc ? " alt='[tagdesc]'" : "") + ">"
|
|
|
|
/proc/contains_az09(var/input)
|
|
for(var/i=1, i<=length(input), i++)
|
|
var/ascii_char = text2ascii(input,i)
|
|
switch(ascii_char)
|
|
// A .. Z
|
|
if(65 to 90) //Uppercase Letters
|
|
return 1
|
|
// a .. z
|
|
if(97 to 122) //Lowercase Letters
|
|
return 1
|
|
|
|
// 0 .. 9
|
|
if(48 to 57) //Numbers
|
|
return 1
|
|
return 0
|
|
|
|
/**
|
|
* Strip out the special beyond characters for \proper and \improper
|
|
* from text that will be sent to the browser.
|
|
*/
|
|
/proc/strip_improper(text)
|
|
return replacetext(replacetext(text, "\proper", ""), "\improper", "")
|
|
|
|
/proc/pencode2html(t)
|
|
t = replacetext(t, "\n", "<BR>")
|
|
t = replacetext(t, "\[center\]", "<center>")
|
|
t = replacetext(t, "\[/center\]", "</center>")
|
|
t = replacetext(t, "\[br\]", "<BR>")
|
|
t = replacetext(t, "\[b\]", "<B>")
|
|
t = replacetext(t, "\[/b\]", "</B>")
|
|
t = replacetext(t, "\[i\]", "<I>")
|
|
t = replacetext(t, "\[/i\]", "</I>")
|
|
t = replacetext(t, "\[u\]", "<U>")
|
|
t = replacetext(t, "\[/u\]", "</U>")
|
|
t = replacetext(t, "\[time\]", "[stationtime2text()]")
|
|
t = replacetext(t, "\[date\]", "[stationdate2text()]")
|
|
t = replacetext(t, "\[large\]", "<font size=\"4\">")
|
|
t = replacetext(t, "\[/large\]", "</font>")
|
|
t = replacetext(t, "\[field\]", "<span class=\"paper_field\"></span>")
|
|
t = replacetext(t, "\[h1\]", "<H1>")
|
|
t = replacetext(t, "\[/h1\]", "</H1>")
|
|
t = replacetext(t, "\[h2\]", "<H2>")
|
|
t = replacetext(t, "\[/h2\]", "</H2>")
|
|
t = replacetext(t, "\[h3\]", "<H3>")
|
|
t = replacetext(t, "\[/h3\]", "</H3>")
|
|
t = replacetext(t, "\[*\]", "<li>")
|
|
t = replacetext(t, "\[hr\]", "<HR>")
|
|
t = replacetext(t, "\[small\]", "<font size = \"1\">")
|
|
t = replacetext(t, "\[/small\]", "</font>")
|
|
t = replacetext(t, "\[list\]", "<ul>")
|
|
t = replacetext(t, "\[/list\]", "</ul>")
|
|
t = replacetext(t, "\[table\]", "<table border=1 cellspacing=0 cellpadding=3 style='border: 1px solid black;'>")
|
|
t = replacetext(t, "\[/table\]", "</td></tr></table>")
|
|
t = replacetext(t, "\[grid\]", "<table>")
|
|
t = replacetext(t, "\[/grid\]", "</td></tr></table>")
|
|
t = replacetext(t, "\[row\]", "</td><tr>")
|
|
t = replacetext(t, "\[cell\]", "<td>")
|
|
t = replacetext(t, "\[logo\]", "<img src=\ref['html/images/ntlogo.png']")
|
|
t = replacetext(t, "\[talogo\]", "<img src=\ref['html/images/talonlogo.png']>")
|
|
t = replacetext(t, "\[redlogo\]", "<img src=\ref['html/images/redntlogo.png']>")
|
|
t = replacetext(t, "\[sglogo\]", "<img src=\ref['html/images/sglogo.png']")
|
|
t = replacetext(t, "\[editorbr\]", "")
|
|
return t
|
|
|
|
//pencode translation to html for tags exclusive to digital files (currently email, nanoword, report editor fields,
|
|
//modular scanner data and txt file printing) and prints from them
|
|
/proc/digitalPencode2html(var/text)
|
|
text = replacetext(text, "\[pre\]", "<pre>")
|
|
text = replacetext(text, "\[/pre\]", "</pre>")
|
|
text = replacetext(text, "\[fontred\]", "<font color=\"red\">") //</font> to pass html tag integrity unit test
|
|
text = replacetext(text, "\[fontblue\]", "<font color=\"blue\">")//</font> to pass html tag integrity unit test
|
|
text = replacetext(text, "\[fontgreen\]", "<font color=\"green\">")
|
|
text = replacetext(text, "\[/font\]", "</font>")
|
|
text = replacetext(text, "\[redacted\]", "<span class=\"redacted\">R E D A C T E D</span>")
|
|
return pencode2html(text)
|
|
|
|
//Will kill most formatting; not recommended.
|
|
/proc/html2pencode(t)
|
|
t = replacetext(t, "<pre>", "\[pre\]")
|
|
t = replacetext(t, "</pre>", "\[/pre\]")
|
|
t = replacetext(t, "<font color=\"red\">", "\[fontred\]")//</font> to pass html tag integrity unit test
|
|
t = replacetext(t, "<font color=\"blue\">", "\[fontblue\]")//</font> to pass html tag integrity unit test
|
|
t = replacetext(t, "<font color=\"green\">", "\[fontgreen\]")
|
|
t = replacetext(t, "</font>", "\[/font\]")
|
|
t = replacetext(t, "<BR>", "\[br\]")
|
|
t = replacetext(t, "<br>", "\[br\]")
|
|
t = replacetext(t, "<B>", "\[b\]")
|
|
t = replacetext(t, "</B>", "\[/b\]")
|
|
t = replacetext(t, "<I>", "\[i\]")
|
|
t = replacetext(t, "</I>", "\[/i\]")
|
|
t = replacetext(t, "<U>", "\[u\]")
|
|
t = replacetext(t, "</U>", "\[/u\]")
|
|
t = replacetext(t, "<center>", "\[center\]")
|
|
t = replacetext(t, "</center>", "\[/center\]")
|
|
t = replacetext(t, "<H1>", "\[h1\]")
|
|
t = replacetext(t, "</H1>", "\[/h1\]")
|
|
t = replacetext(t, "<H2>", "\[h2\]")
|
|
t = replacetext(t, "</H2>", "\[/h2\]")
|
|
t = replacetext(t, "<H3>", "\[h3\]")
|
|
t = replacetext(t, "</H3>", "\[/h3\]")
|
|
t = replacetext(t, "<li>", "\[*\]")
|
|
t = replacetext(t, "<HR>", "\[hr\]")
|
|
t = replacetext(t, "<ul>", "\[list\]")
|
|
t = replacetext(t, "</ul>", "\[/list\]")
|
|
t = replacetext(t, "<table>", "\[grid\]")
|
|
t = replacetext(t, "</table>", "\[/grid\]")
|
|
t = replacetext(t, "<tr>", "\[row\]")
|
|
t = replacetext(t, "<td>", "\[cell\]")
|
|
t = replacetext(t, "<img src=\ref['html/images/ntlogo.png']>", "\[logo\]")
|
|
t = replacetext(t, "<img src=\ref['html/images/redntlogo.png']>", "\[redlogo\]")
|
|
t = replacetext(t, "<img src=\ref['html/images/talonlogo.png']>", "\[talogo\]")
|
|
t = replacetext(t, "<img src=\ref['html/images/sglogo.png']>", "\[sglogo\]")
|
|
t = replacetext(t, "<span class=\"paper_field\"></span>", "\[field\]")
|
|
t = replacetext(t, "<span class=\"redacted\">R E D A C T E D</span>", "\[redacted\]")
|
|
t = strip_html_properly(t)
|
|
return t
|
|
|
|
// Random password generator
|
|
/proc/GenerateKey()
|
|
//Feel free to move to Helpers.
|
|
var/newKey
|
|
newKey += pick("the", "if", "of", "as", "in", "a", "you", "from", "to", "an", "too", "little", "snow", "dead", "drunk", "rosebud", "duck", "al", "le")
|
|
newKey += pick("diamond", "beer", "mushroom", "assistant", "clown", "captain", "twinkie", "security", "nuke", "small", "big", "escape", "yellow", "gloves", "monkey", "engine", "nuclear", "ai")
|
|
newKey += pick("1", "2", "3", "4", "5", "6", "7", "8", "9", "0")
|
|
return newKey
|
|
|
|
//Used for applying byonds text macros to strings that are loaded at runtime
|
|
/proc/apply_text_macros(string)
|
|
var/next_backslash = findtext(string, "\\")
|
|
if(!next_backslash)
|
|
return string
|
|
|
|
var/leng = length(string)
|
|
|
|
var/next_space = findtext(string, " ", next_backslash + 1)
|
|
if(!next_space)
|
|
next_space = leng - next_backslash
|
|
|
|
if(!next_space) //trailing bs
|
|
return string
|
|
|
|
var/base = next_backslash == 1 ? "" : copytext(string, 1, next_backslash)
|
|
var/macro = lowertext(copytext(string, next_backslash + 1, next_space))
|
|
var/rest = next_backslash > leng ? "" : copytext(string, next_space + 1)
|
|
|
|
//See http://www.byond.com/docs/ref/info.html#/DM/text/macros
|
|
switch(macro)
|
|
//prefixes/agnostic
|
|
if("the")
|
|
rest = text("\the []", rest)
|
|
if("a")
|
|
rest = text("\a []", rest)
|
|
if("an")
|
|
rest = text("\an []", rest)
|
|
if("proper")
|
|
rest = text("\proper []", rest)
|
|
if("improper")
|
|
rest = text("\improper []", rest)
|
|
if("roman")
|
|
rest = text("\roman []", rest)
|
|
//postfixes
|
|
if("th")
|
|
base = text("[]\th", rest)
|
|
if("s")
|
|
base = text("[]\s", rest)
|
|
if("he")
|
|
base = text("[]\he", rest)
|
|
if("she")
|
|
base = text("[]\she", rest)
|
|
if("his")
|
|
base = text("[]\his", rest)
|
|
if("himself")
|
|
base = text("[]\himself", rest)
|
|
if("herself")
|
|
base = text("[]\herself", rest)
|
|
if("hers")
|
|
base = text("[]\hers", rest)
|
|
|
|
. = base
|
|
if(rest)
|
|
. += .(rest)
|
|
|
|
|
|
#define gender2text(gender) capitalize(gender)
|
|
|
|
/**
|
|
* Used to get a properly sanitized input. Returns null if cancel is pressed.
|
|
*
|
|
* Arguments
|
|
** user - Target of the input prompt.
|
|
** message - The text inside of the prompt.
|
|
** title - The window title of the prompt.
|
|
** max_length - If you intend to impose a length limit - default is 1024.
|
|
** no_trim - Prevents the input from being trimmed if you intend to parse newlines or whitespace.
|
|
*/
|
|
/proc/stripped_input(mob/user, message = "", title = "", default = "", max_length=MAX_MESSAGE_LEN, no_trim=FALSE)
|
|
var/user_input = input(user, message, title, default) as text|null
|
|
if(isnull(user_input)) // User pressed cancel
|
|
return
|
|
if(no_trim)
|
|
return copytext_char(html_encode(user_input), 1, max_length)
|
|
else
|
|
return trim(html_encode(user_input), max_length) //trim is "outside" because html_encode can expand single symbols into multiple symbols (such as turning < into <)
|
|
|
|
/**
|
|
* Used to get a properly sanitized input in a larger box. Works very similarly to stripped_input.
|
|
*
|
|
* Arguments
|
|
** user - Target of the input prompt.
|
|
** message - The text inside of the prompt.
|
|
** title - The window title of the prompt.
|
|
** max_length - If you intend to impose a length limit - default is 1024.
|
|
** no_trim - Prevents the input from being trimmed if you intend to parse newlines or whitespace.
|
|
*/
|
|
/proc/stripped_multiline_input(mob/user, message = "", title = "", default = "", max_length=MAX_MESSAGE_LEN, no_trim=FALSE)
|
|
var/user_input = input(user, message, title, default) as message|null
|
|
if(isnull(user_input)) // User pressed cancel
|
|
return
|
|
if(no_trim)
|
|
return copytext_char(html_encode(user_input), 1, max_length)
|
|
else
|
|
return trim(html_encode(user_input), max_length)
|
|
|
|
#define NO_CHARS_DETECTED 0
|
|
#define SPACES_DETECTED 1
|
|
#define SYMBOLS_DETECTED 2
|
|
#define NUMBERS_DETECTED 3
|
|
#define LETTERS_DETECTED 4
|
|
|
|
/**
|
|
* Filters out undesirable characters from names.
|
|
*
|
|
* * strict - return null immediately instead of filtering out
|
|
* * allow_numbers - allows numbers and common special characters - used for silicon/other weird things names
|
|
* * cap_after_symbols - words like Bob's will be capitalized to Bob'S by default. False is good for titles.
|
|
*/
|
|
/proc/reject_bad_name(t_in, allow_numbers = FALSE, max_length = MAX_NAME_LEN, ascii_only = TRUE, strict = FALSE, cap_after_symbols = TRUE)
|
|
if(!t_in)
|
|
return //Rejects the input if it is null
|
|
|
|
var/number_of_alphanumeric = 0
|
|
var/last_char_group = NO_CHARS_DETECTED
|
|
var/t_out = ""
|
|
var/t_len = length(t_in)
|
|
var/charcount = 0
|
|
var/char = ""
|
|
|
|
// This is a sanity short circuit, if the users name is three times the maximum allowable length of name
|
|
// We bail out on trying to process the name at all, as it could be a bug or malicious input and we don't
|
|
// Want to iterate all of it.
|
|
if(t_len > 3 * MAX_NAME_LEN)
|
|
return
|
|
for(var/i = 1, i <= t_len, i += length(char))
|
|
char = t_in[i]
|
|
switch(text2ascii(char))
|
|
|
|
// A .. Z
|
|
if(65 to 90) //Uppercase Letters
|
|
number_of_alphanumeric++
|
|
last_char_group = LETTERS_DETECTED
|
|
|
|
// a .. z
|
|
if(97 to 122) //Lowercase Letters
|
|
if(last_char_group == NO_CHARS_DETECTED || last_char_group == SPACES_DETECTED || cap_after_symbols && last_char_group == SYMBOLS_DETECTED) //start of a word
|
|
char = uppertext(char)
|
|
number_of_alphanumeric++
|
|
last_char_group = LETTERS_DETECTED
|
|
|
|
// 0 .. 9
|
|
if(48 to 57) //Numbers
|
|
if(!allow_numbers) //allow name to start with number if AI/Borg
|
|
if(strict)
|
|
return
|
|
continue
|
|
number_of_alphanumeric++
|
|
last_char_group = NUMBERS_DETECTED
|
|
// ' - .
|
|
if(39,45,46) //Common name punctuation
|
|
if(last_char_group == NO_CHARS_DETECTED)
|
|
if(strict)
|
|
return
|
|
continue
|
|
last_char_group = SYMBOLS_DETECTED
|
|
|
|
// ~ | @ : # $ % & * +
|
|
if(126,124,64,58,35,36,37,38,42,43) //Other symbols that we'll allow (mainly for AI)
|
|
if(last_char_group == NO_CHARS_DETECTED || !allow_numbers) //suppress at start of string
|
|
if(strict)
|
|
return
|
|
continue
|
|
last_char_group = SYMBOLS_DETECTED
|
|
|
|
//Space
|
|
if(32)
|
|
if(last_char_group == NO_CHARS_DETECTED || last_char_group == SPACES_DETECTED) //suppress double-spaces and spaces at start of string
|
|
if(strict)
|
|
return
|
|
continue
|
|
last_char_group = SPACES_DETECTED
|
|
|
|
if(127 to INFINITY)
|
|
if(ascii_only)
|
|
if(strict)
|
|
return
|
|
continue
|
|
last_char_group = SYMBOLS_DETECTED //for now, we'll treat all non-ascii characters like symbols even though most are letters
|
|
|
|
else
|
|
continue
|
|
t_out += char
|
|
charcount++
|
|
if(charcount >= max_length)
|
|
break
|
|
|
|
if(number_of_alphanumeric < 2)
|
|
return //protects against tiny names like "A" and also names like "' ' ' ' ' ' ' '"
|
|
|
|
if(last_char_group == SPACES_DETECTED)
|
|
t_out = copytext_char(t_out, 1, -1) //removes the last character (in this case a space)
|
|
|
|
//if(!filter_name_ic(t_out)) FIXME
|
|
// return
|
|
|
|
return t_out
|
|
|
|
#undef NO_CHARS_DETECTED
|
|
#undef SPACES_DETECTED
|
|
#undef NUMBERS_DETECTED
|
|
#undef LETTERS_DETECTED
|
|
|
|
//Adds 'char' ahead of 'text' until there are 'count' characters total
|
|
/proc/add_leading(text, count, char = " ")
|
|
text = "[text]"
|
|
var/charcount = count - length_char(text)
|
|
var/list/chars_to_add[max(charcount + 1, 0)]
|
|
return jointext(chars_to_add, char) + text
|
|
|
|
//Adds 'char' behind 'text' until there are 'count' characters total
|
|
/proc/add_trailing(text, count, char = " ")
|
|
text = "[text]"
|
|
var/charcount = count - length_char(text)
|
|
var/list/chars_to_add[max(charcount + 1, 0)]
|
|
return text + jointext(chars_to_add, char)
|
|
|
|
//Readds quotes and apostrophes to HTML-encoded strings
|
|
/proc/readd_quotes(var/t)
|
|
var/list/repl_chars = list(""" = "\"","'" = "'")
|
|
for(var/char in repl_chars)
|
|
var/index = findtext(t, char)
|
|
while(index)
|
|
t = copytext(t, 1, index) + repl_chars[char] + copytext(t, index+5)
|
|
index = findtext(t, char)
|
|
return t
|
|
|
|
// Rips out paper HTML but tries to keep it semi-readable.
|
|
/proc/paper_html_to_plaintext(paper_text)
|
|
paper_text = replacetext(paper_text, "<hr>", "-----")
|
|
paper_text = replacetext(paper_text, "<li>", "- ") // This makes ordered lists turn into unordered but fixing that is too much effort.
|
|
paper_text = replacetext(paper_text, "</li>", "\n")
|
|
paper_text = replacetext(paper_text, "<p>", "\n")
|
|
paper_text = replacetext(paper_text, "<br>", "\n")
|
|
paper_text = strip_html_properly(paper_text) // Get rid of everything else entirely.
|
|
return paper_text
|
|
|
|
//json decode that will return null on parse error instead of runtiming.
|
|
/proc/safe_json_decode(data)
|
|
try
|
|
return json_decode(data)
|
|
catch
|
|
return null
|
|
|
|
/// Removes all non-alphanumerics from the text, keep in mind this can lead to id conflicts
|
|
/proc/sanitize_css_class_name(name)
|
|
var/static/regex/regex = new(@"[^a-zA-Z0-9]","g")
|
|
return replacetext(name, regex, "")
|
|
|
|
/// Returns TRUE if the input_text ends with the ending
|
|
/proc/endswith(input_text, ending)
|
|
var/input_length = LAZYLEN(ending)
|
|
return !!findtext(input_text, ending, -input_length)
|
|
|
|
/// Returns TRUE if the input_text starts with any of the beginnings
|
|
/proc/starts_with_any(input_text, list/beginnings)
|
|
for(var/beginning in beginnings)
|
|
if(!!findtext(input_text, beginning, 1, LAZYLEN(beginning)+1))
|
|
return TRUE
|
|
return FALSE
|
|
|
|
//finds the first occurrence of one of the characters from needles argument inside haystack
|
|
//it may appear this can be optimised, but it really can't. findtext() is so much faster than anything you can do in byondcode.
|
|
//stupid byond :(
|
|
/proc/findchar(haystack, needles, start=1, end=0)
|
|
var/temp
|
|
var/len = length(needles)
|
|
for(var/i=1, i<=len, i++)
|
|
temp = findtextEx(haystack, ascii2text(text2ascii(needles,i)), start, end) //Note: ascii2text(text2ascii) is faster than copytext()
|
|
if(temp) end = temp
|
|
return end
|
|
|
|
/// Converts a semver string into a list of numbers
|
|
/proc/semver_to_list(semver_string)
|
|
var/static/regex/semver_regex = regex(@"(\d+)\.(\d+)\.(\d+)", "")
|
|
if(!semver_regex.Find(semver_string))
|
|
return null
|
|
|
|
return list(
|
|
text2num(semver_regex.group[1]),
|
|
text2num(semver_regex.group[2]),
|
|
text2num(semver_regex.group[3]),
|
|
)
|
|
|
|
///Properly format a string of text by using replacetext()
|
|
/proc/format_text(text)
|
|
return replacetext(replacetext(text,"\proper ",""),"\improper ","")
|