mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-17 05:03:28 +00:00
I have been trying to load Tram station to show Lemon the smoother tram for a few hours now only to find out someone broke things big time. I'm adding a sanitize_filepath proc to fix the flunky. For those ignorant about the issue: Someone has recently modified the procs in the string_list file so they'd sanitize filenames, as a security precaution. Unfortunately, it turns out these procs are also used with filepaths as argument, which use the / as a delimiter between nodes. Because the SANITIZE_FILENAME macro also purges delimiters (it's supposed to be used on filenames, not paths), this meant file paths were not being loaded correctly. Basically, it has broken map rotation, tcg and wound strings. At least the server hasn't been updated yet. Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
118 lines
3.8 KiB
Plaintext
118 lines
3.8 KiB
Plaintext
/**
|
|
* For FTP requests. (i.e. downloading runtime logs.)
|
|
*
|
|
* However it'd be ok to use for accessing attack logs and such too, which are even laggier.
|
|
*/
|
|
GLOBAL_VAR_INIT(fileaccess_timer, 0)
|
|
|
|
/client/proc/browse_files(root_type=BROWSE_ROOT_ALL_LOGS, max_iterations=10, list/valid_extensions=list("txt","log","htm", "html"))
|
|
// wow why was this ever a parameter
|
|
var/root = "data/logs/"
|
|
switch(root_type)
|
|
if(BROWSE_ROOT_ALL_LOGS)
|
|
root = "data/logs/"
|
|
if(BROWSE_ROOT_CURRENT_LOGS)
|
|
root = "[GLOB.log_directory]/"
|
|
var/path = root
|
|
|
|
for(var/i=0, i<max_iterations, i++)
|
|
var/list/choices = flist(path)
|
|
if(path != root)
|
|
choices.Insert(1,"/")
|
|
|
|
var/choice = input(src,"Choose a file to access:","Download",null) as null|anything in sort_list(choices)
|
|
switch(choice)
|
|
if(null)
|
|
return
|
|
if("/")
|
|
path = root
|
|
continue
|
|
path += choice
|
|
|
|
if(copytext_char(path, -1) != "/") //didn't choose a directory, no need to iterate again
|
|
break
|
|
var/extensions
|
|
for(var/i in valid_extensions)
|
|
if(extensions)
|
|
extensions += "|"
|
|
extensions += "[i]"
|
|
var/regex/valid_ext = new("\\.([extensions])$", "i")
|
|
if( !fexists(path) || !(valid_ext.Find(path)) )
|
|
to_chat(src, "<font color='red'>Error: browse_files(): File not found/Invalid file([path]).</font>")
|
|
return
|
|
|
|
return path
|
|
|
|
#define FTPDELAY 200 //200 tick delay to discourage spam
|
|
#define ADMIN_FTPDELAY_MODIFIER 0.5 //Admins get to spam files faster since we ~trust~ them!
|
|
/* This proc is a failsafe to prevent spamming of file requests.
|
|
It is just a timer that only permits a download every [FTPDELAY] ticks.
|
|
This can be changed by modifying FTPDELAY's value above.
|
|
|
|
PLEASE USE RESPONSIBLY, Some log files can reach sizes of 4MB! */
|
|
/client/proc/file_spam_check()
|
|
var/time_to_wait = GLOB.fileaccess_timer - world.time
|
|
if(time_to_wait > 0)
|
|
to_chat(src, "<font color='red'>Error: file_spam_check(): Spam. Please wait [DisplayTimeText(time_to_wait)].</font>")
|
|
return TRUE
|
|
var/delay = FTPDELAY
|
|
if(holder)
|
|
delay *= ADMIN_FTPDELAY_MODIFIER
|
|
GLOB.fileaccess_timer = world.time + delay
|
|
return FALSE
|
|
#undef FTPDELAY
|
|
#undef ADMIN_FTPDELAY_MODIFIER
|
|
|
|
/proc/pathwalk(path)
|
|
var/list/jobs = list(path)
|
|
var/list/filenames = list()
|
|
|
|
while(jobs.len)
|
|
var/current_dir = pop(jobs)
|
|
var/list/new_filenames = flist(current_dir)
|
|
for(var/new_filename in new_filenames)
|
|
// if filename ends in / it is a directory, append to currdir
|
|
if(findtext(new_filename, "/", -1))
|
|
jobs += current_dir + new_filename
|
|
else
|
|
filenames += current_dir + new_filename
|
|
return filenames
|
|
|
|
/proc/pathflatten(path)
|
|
return replacetext(path, "/", "_")
|
|
|
|
/// 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)
|
|
|
|
/**
|
|
* Sanitizes the name of each node in the path.
|
|
*
|
|
* Im case you are wondering when to use this proc and when to use SANITIZE_FILENAME,
|
|
*
|
|
* You use SANITIZE_FILENAME to sanitize the name of a file [e.g. example.txt]
|
|
*
|
|
* You use sanitize_filepath sanitize the path of a file [e.g. root/node/example.txt]
|
|
*
|
|
* If you use SANITIZE_FILENAME to sanitize a file path things will break.
|
|
*/
|
|
/proc/sanitize_filepath(path)
|
|
. = ""
|
|
var/delimiter = "/" //Very much intentionally hardcoded
|
|
var/list/all_nodes = splittext(path, delimiter)
|
|
for(var/node in all_nodes)
|
|
if(.)
|
|
. += delimiter // Add the delimiter before each successive node.
|
|
. += SANITIZE_FILENAME(node)
|