use same path validation process for fgcommands "load", "save",
"loadxml", ans "savexml" as is used for io.open(). This is still Nasal based for now. See $FG_ROOT/Nasal/io.nas.
This commit is contained in:
parent
ce7f695ea2
commit
76a13e689d
4 changed files with 74 additions and 24 deletions
|
@ -320,16 +320,23 @@ do_resume (const SGPropertyNode * arg)
|
|||
static bool
|
||||
do_load (const SGPropertyNode * arg)
|
||||
{
|
||||
const string &file = arg->getStringValue("file", "fgfs.sav");
|
||||
ifstream input(file.c_str());
|
||||
if (input.good() && fgLoadFlight(input)) {
|
||||
input.close();
|
||||
SG_LOG(SG_INPUT, SG_INFO, "Restored flight from " << file);
|
||||
return true;
|
||||
} else {
|
||||
SG_LOG(SG_INPUT, SG_WARN, "Cannot load flight from " << file);
|
||||
return false;
|
||||
}
|
||||
const string &file = arg->getStringValue("file", "fgfs.sav");
|
||||
|
||||
if (!fgValidatePath(file.c_str(), false)) {
|
||||
SG_LOG(SG_IO, SG_ALERT, "load: reading '" << file << "' denied "
|
||||
"(unauthorized access)");
|
||||
return false;
|
||||
}
|
||||
|
||||
ifstream input(file.c_str());
|
||||
if (input.good() && fgLoadFlight(input)) {
|
||||
input.close();
|
||||
SG_LOG(SG_INPUT, SG_INFO, "Restored flight from " << file);
|
||||
return true;
|
||||
} else {
|
||||
SG_LOG(SG_INPUT, SG_WARN, "Cannot load flight from " << file);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -342,18 +349,25 @@ do_load (const SGPropertyNode * arg)
|
|||
static bool
|
||||
do_save (const SGPropertyNode * arg)
|
||||
{
|
||||
const string &file = arg->getStringValue("file", "fgfs.sav");
|
||||
bool write_all = arg->getBoolValue("write-all", false);
|
||||
SG_LOG(SG_INPUT, SG_INFO, "Saving flight");
|
||||
ofstream output(file.c_str());
|
||||
if (output.good() && fgSaveFlight(output, write_all)) {
|
||||
output.close();
|
||||
SG_LOG(SG_INPUT, SG_INFO, "Saved flight to " << file);
|
||||
return true;
|
||||
} else {
|
||||
SG_LOG(SG_INPUT, SG_ALERT, "Cannot save flight to " << file);
|
||||
return false;
|
||||
}
|
||||
const string &file = arg->getStringValue("file", "fgfs.sav");
|
||||
|
||||
if (!fgValidatePath(file.c_str(), false)) {
|
||||
SG_LOG(SG_IO, SG_ALERT, "save: reading '" << file << "' denied "
|
||||
"(unauthorized access)");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool write_all = arg->getBoolValue("write-all", false);
|
||||
SG_LOG(SG_INPUT, SG_INFO, "Saving flight");
|
||||
ofstream output(file.c_str());
|
||||
if (output.good() && fgSaveFlight(output, write_all)) {
|
||||
output.close();
|
||||
SG_LOG(SG_INPUT, SG_INFO, "Saved flight to " << file);
|
||||
return true;
|
||||
} else {
|
||||
SG_LOG(SG_INPUT, SG_ALERT, "Cannot save flight to " << file);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1336,6 +1350,12 @@ do_load_xml_to_proptree(const SGPropertyNode * arg)
|
|||
if (file.extension() != "xml")
|
||||
file.concat(".xml");
|
||||
|
||||
if (!fgValidatePath(file.c_str(), false)) {
|
||||
SG_LOG(SG_IO, SG_ALERT, "loadxml: reading '" << file.str() << "' denied "
|
||||
"(unauthorized access)");
|
||||
return false;
|
||||
}
|
||||
|
||||
SGPropertyNode *targetnode;
|
||||
if (arg->hasValue("targetnode"))
|
||||
targetnode = fgGetNode(arg->getStringValue("targetnode"), true);
|
||||
|
@ -1349,7 +1369,7 @@ do_load_xml_to_proptree(const SGPropertyNode * arg)
|
|||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1376,6 +1396,12 @@ do_save_xml_from_proptree(const SGPropertyNode * arg)
|
|||
if (file.extension() != "xml")
|
||||
file.concat(".xml");
|
||||
|
||||
if (!fgValidatePath(file.c_str(), true)) {
|
||||
SG_LOG(SG_IO, SG_ALERT, "savexml: writing to '" << file.str() << "' denied "
|
||||
"(unauthorized access)");
|
||||
return false;
|
||||
}
|
||||
|
||||
SGPropertyNode *sourcenode;
|
||||
if (arg->hasValue("sourcenode"))
|
||||
sourcenode = fgGetNode(arg->getStringValue("sourcenode"), true);
|
||||
|
|
|
@ -81,6 +81,7 @@
|
|||
#include "renderer.hxx"
|
||||
#include "splash.hxx"
|
||||
#include "main.hxx"
|
||||
#include "util.hxx"
|
||||
|
||||
|
||||
static double real_delta_time_sec = 0.0;
|
||||
|
@ -984,6 +985,7 @@ bool fgMainInit( int argc, char **argv ) {
|
|||
string_list *col = new string_list;
|
||||
globals->set_channel_options_list( col );
|
||||
|
||||
fgValidatePath("", false); // initialize static variables
|
||||
upper_case_property("/sim/presets/airport-id");
|
||||
upper_case_property("/sim/presets/runway");
|
||||
upper_case_property("/sim/tower/airport-id");
|
||||
|
|
|
@ -147,7 +147,7 @@ fgGetLowPass (double current, double target, double timeratio)
|
|||
|
||||
|
||||
string
|
||||
fgUnescape(const char *s)
|
||||
fgUnescape (const char *s)
|
||||
{
|
||||
string r;
|
||||
while (*s) {
|
||||
|
@ -197,5 +197,19 @@ fgUnescape(const char *s)
|
|||
return r;
|
||||
}
|
||||
|
||||
|
||||
const char *fgValidatePath (const char *str, bool write)
|
||||
{
|
||||
static SGPropertyNode_ptr r, w;
|
||||
if (!r) {
|
||||
r = fgGetNode("/sim/paths/validate/read", true);
|
||||
w = fgGetNode("/sim/paths/validate/write", true);
|
||||
}
|
||||
SGPropertyNode *prop = write ? w : r;
|
||||
prop->setStringValue(str);
|
||||
const char *result = prop->getStringValue();
|
||||
return result[0] ? result : 0;
|
||||
}
|
||||
|
||||
// end of util.cxx
|
||||
|
||||
|
|
|
@ -83,4 +83,12 @@ extern double fgGetLowPass (double current, double target, double timeratio);
|
|||
extern std::string fgUnescape (const char *str);
|
||||
|
||||
|
||||
/**
|
||||
* Validation listener interface for io.nas, used by fgcommands.
|
||||
* @param path Path to be validated
|
||||
* @param write True for write operations and false for read operations.
|
||||
* @return The validated path on success or 0 if access denied.
|
||||
*/
|
||||
extern const char *fgValidatePath (const char *path, bool write);
|
||||
|
||||
#endif // __UTIL_HXX
|
||||
|
|
Loading…
Add table
Reference in a new issue