stockpiles: Restrict characters in filenames when saving

Previously, it was possible to save outside of the stocksettings
directory or fail to save in a nonexistent subdirectory (e.g. when
a stockpile name had slashes in it).

Resolves #621
develop
lethosor 2015-07-29 14:17:14 -04:00
parent 4e45cc5bbb
commit a90f3c3d67
2 changed files with 46 additions and 8 deletions

@ -96,6 +96,48 @@ function tablify(iterableObject)
return t return t
end end
local filename_invalid_regex = '[^A-Za-z0-9 ._-]'
function valid_filename(filename)
return not filename:match(filename_invalid_regex)
end
function sanitize_filename(filename)
local ret = ''
for i = 1, #filename do
local ch = filename:sub(i, i)
if valid_filename(ch) then
ret = ret .. ch
else
ret = ret .. '-'
end
end
return ret
end
FilenameInputBox = defclass(FilenameInputBox, dlg.InputBox)
function FilenameInputBox:onInput(keys)
if not valid_filename(string.char(keys._STRING or 0)) and not keys.STRING_A000 then
keys._STRING = nil
end
FilenameInputBox.super.onInput(self, keys)
end
function showFilenameInputPrompt(title, text, tcolor, input, min_width)
FilenameInputBox{
frame_title = title,
text = text,
text_pen = tcolor,
input = input,
frame_width = min_width,
on_input = script.mkresume(true),
on_cancel = script.mkresume(false),
on_close = script.qresume(nil)
}:show()
return script.wait()
end
function load_settings() function load_settings()
init() init()
local path = get_path() local path = get_path()
@ -132,16 +174,16 @@ function save_settings(stockpile)
if #suggested == 0 then if #suggested == 0 then
suggested = 'Stock1' suggested = 'Stock1'
end end
suggested = sanitize_filename(suggested)
local path = get_path() local path = get_path()
local sok,filename = script.showInputPrompt('Stockpile Settings', 'Enter stockpile name', COLOR_WHITE, suggested) local sok,filename = showFilenameInputPrompt('Stockpile Settings', 'Enter filename', COLOR_WHITE, suggested)
if sok then if sok then
if filename == nil or filename == '' then if filename == nil or filename == '' or not valid_filename(filename) then
script.showMessage('Stockpile Settings', 'Invalid File Name', COLOR_RED) script.showMessage('Stockpile Settings', 'Invalid File Name', COLOR_RED)
else else
if not dfhack.filesystem.exists(path) then if not dfhack.filesystem.exists(path) then
dfhack.filesystem.mkdir(path) dfhack.filesystem.mkdir(path)
end end
print("saving...", path..'/'..filename)
stockpiles_save(path..'/'..filename) stockpiles_save(path..'/'..filename)
end end
end end

@ -246,7 +246,7 @@ static command_result savestock ( color_ostream &out, vector <string> & paramete
if ( !is_dfstockfile ( file ) ) file += ".dfstock"; if ( !is_dfstockfile ( file ) ) file += ".dfstock";
if ( !cereal.serialize_to_file ( file ) ) if ( !cereal.serialize_to_file ( file ) )
{ {
out.printerr ( "serialize failed\n" ); out.printerr ( "could not save to %s\n", file.c_str() );
return CR_FAILURE; return CR_FAILURE;
} }
return CR_OK; return CR_OK;
@ -510,11 +510,9 @@ static int stockpiles_list_settings ( lua_State *L )
static void stockpiles_load ( color_ostream &out, std::string filename ) static void stockpiles_load ( color_ostream &out, std::string filename )
{ {
out << "stockpiles_load " << filename << " ";
std::vector<std::string> params; std::vector<std::string> params;
params.push_back ( filename ); params.push_back ( filename );
command_result r = loadstock ( out, params ); command_result r = loadstock ( out, params );
out << " result = "<< r << endl;
if ( r != CR_OK ) if ( r != CR_OK )
show_message_box ( "Stockpile Settings Error", "Couldn't load. Does the folder exist?", true ); show_message_box ( "Stockpile Settings Error", "Couldn't load. Does the folder exist?", true );
} }
@ -522,11 +520,9 @@ static void stockpiles_load ( color_ostream &out, std::string filename )
static void stockpiles_save ( color_ostream &out, std::string filename ) static void stockpiles_save ( color_ostream &out, std::string filename )
{ {
out << "stockpiles_save " << filename << " ";
std::vector<std::string> params; std::vector<std::string> params;
params.push_back ( filename ); params.push_back ( filename );
command_result r = savestock ( out, params ); command_result r = savestock ( out, params );
out << " result = "<< r << endl;
if ( r != CR_OK ) if ( r != CR_OK )
show_message_box ( "Stockpile Settings Error", "Couldn't save. Does the folder exist?", true ); show_message_box ( "Stockpile Settings Error", "Couldn't save. Does the folder exist?", true );
} }