Skip to content

Commit

Permalink
Change lua FileSystem.MakeUserDataDirectory to FileSytem.MakeDirector…
Browse files Browse the repository at this point in the history
…y and have it take a URI

This checks the uri sceme to be sure we can modify it, so only "user://" is valid.
  • Loading branch information
JonBooth78 committed Oct 9, 2023
1 parent 027a952 commit 53b4c38
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 23 deletions.
4 changes: 2 additions & 2 deletions data/meta/FileSystem.lua
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ function FileSystem.ReadDirectory(root, path) end
---@return string The joined path elements
function FileSystem.JoinPath( ... ) end

---@param dir_name string The name of the folder to create in the user directory
---@param dir_name string The name of the folder to create
---@return boolean Success
function FileSystem.MakeUserDataDirectory( dir_name ) end
function FileSystem.MakeDirectory( dir_name ) end

--- Wrapper for our patched io.open that ensures files are opened inside the sandbox.
--- Prefer using this to io.open
Expand Down
60 changes: 39 additions & 21 deletions src/lua/LuaFileSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,51 +12,58 @@
class ParsedFilePath
{
public:
ParsedFilePath(lua_State* l, const char* luaPath);
ParsedFilePath(lua_State *l, const char *luaPath);

// Probably not needed as if it isn't valid we'll already fail.
bool IsValid() const { return m_fs != nullptr; }

bool ValidateWritePermission(lua_State* l) const;
FileSystem::FileSource& GetFileSource() const { return *m_fs; }
// The FileSourceFS structure allows us to write, so to grab one
// we validate that we can and error if we can't and return null
// otherewise we return the FileSourceFS.
FileSystem::FileSourceFS* ValidateWritePermission(lua_State *l) const;
FileSystem::FileSource& GetFileSource() const { return *m_fs; }
const std::string_view& GetRelativePath() const { return m_fs_path; }

std::string CalculateAbsolutePath(lua_State* l) const;
private:
std::string_view m_luaPath;
std::string_view m_scheme;
std::string_view m_fs_path;
FileSystem::FileSource* m_fs;
std::string_view m_luaPath;
std::string_view m_scheme;
std::string_view m_fs_path;
FileSystem::FileSource *m_fs;
FileSystem::FileSourceFS *m_writeableFS;
};

ParsedFilePath::ParsedFilePath(lua_State* l, const char* luaPath)
ParsedFilePath::ParsedFilePath(lua_State *l, const char *luaPath)
: m_luaPath(luaPath)
{
if (starts_with_ci(m_luaPath, "user://"))
{
m_fs = &FileSystem::userFiles;
m_writeableFS = &FileSystem::userFiles;
m_scheme = m_luaPath.substr(0, 7);// strlen("user://"));
}
else if (starts_with_ci(m_luaPath, "data://"))
{
m_fs = &FileSystem::gameDataFiles;
m_writeableFS = nullptr;
m_scheme = m_luaPath.substr(0, 7);// strlen("data://"));
}
else
{
luaL_error(l, "'%s' does not have a valid scheme, must be user:// or data://", luaPath);
m_writeableFS = nullptr;
m_fs = nullptr;
return;
}
m_fs_path = m_luaPath;
m_fs_path.remove_prefix(m_scheme.length());
}

bool ParsedFilePath::ValidateWritePermission(lua_State* l) const
FileSystem::FileSourceFS* ParsedFilePath::ValidateWritePermission(lua_State *l) const
{
if (m_fs == &FileSystem::userFiles)
if (m_writeableFS != nullptr)
{
return true;
return m_writeableFS;
}
luaL_error(l, "'%s' does not support file operations that modify it, only things in the user folder do", m_luaPath.data());
return false;
Expand Down Expand Up @@ -85,7 +92,7 @@ void LuaFileSystem::register_raw_io_open_function(lua_CFunction open)
int LuaFileSystem::l_patched_io_open(lua_State* L)
{
ParsedFilePath path = ParsedFilePath(L, lua_tostring(L, 1));
const char* root_cstr = lua_tostring(L, 2);
const char *root_cstr = lua_tostring(L, 2);
for (const char* c = root_cstr; *c != 0; ++c )
{
if (*c != 'r')
Expand Down Expand Up @@ -118,7 +125,7 @@ int LuaFileSystem::l_patched_io_open(lua_State* L)

FileSystem::FileSource* get_filesytem_for_root(LuaFileSystem::Root root)
{
FileSystem::FileSource* fs = nullptr;
FileSystem::FileSource *fs = nullptr;
switch (root) {
case LuaFileSystem::ROOT_USER:
fs = &FileSystem::userFiles;
Expand Down Expand Up @@ -257,9 +264,9 @@ static int l_filesystem_join_path(lua_State *l)


/*
* Function: MakeUserDataDirectory
* Function: MakeDirectory
*
* > local path = FileSystem.MakeUserDataDirectory( dir_name )
* > local success = FileSystem.MakeDirectory( dir_name )
*
* Creating the given directory if it's missing, returning a boolean
* indicating success
Expand All @@ -272,20 +279,31 @@ static int l_filesystem_join_path(lua_State *l)
*
* experimental
*/
static int l_filesystem_make_user_directory(lua_State* l)
static int l_filesystem_make_directory(lua_State *l)
{
const char* path_cstr = luaL_checkstring(l, 1);
try {
std::string dir = luaL_checkstring(l, 1);
ParsedFilePath path = ParsedFilePath(l, path_cstr);

FileSystem::userFiles.MakeDirectory(dir);
FileSystem::FileSourceFS* fs = path.ValidateWritePermission(l);
if (!fs) // Probably not needed, we already errored out.
{
return 0;
}

// shame these methods can't take a string_view.
std::string rel_path = std::string(path.GetRelativePath());
// At the moment, anything with a filesourceFS is also writeable, so the write permission test
// above also validates this...
fs->MakeDirectory(rel_path);

FileSystem::FileInfo f = FileSystem::userFiles.Lookup(dir);
FileSystem::FileInfo f = fs->Lookup(rel_path);

lua_pushboolean(l, f.IsDir());
return 1;
}
catch (const std::invalid_argument&) {
luaL_error(l, "unable to create directory the argument is invalid");
luaL_error(l, "unable to create directory '%s' the argument is invalid", path_cstr);
lua_pushboolean(l, 0);
return 1;
}
Expand All @@ -300,7 +318,7 @@ void LuaFileSystem::Register()
static const luaL_Reg l_methods[] = {
{ "ReadDirectory", l_filesystem_read_dir },
{ "JoinPath", l_filesystem_join_path },
{ "MakeUserDataDirectory", l_filesystem_make_user_directory },
{ "MakeDirectory", l_filesystem_make_directory },
{ "Open", l_patched_io_open },
{ 0, 0 }
};
Expand Down

0 comments on commit 53b4c38

Please sign in to comment.