[IO]: Use filesystem api (#860)

This commit is contained in:
Edo 2023-03-21 18:06:48 +00:00 committed by GitHub
parent 9ff7dd81f5
commit 61173b3d9b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 48 additions and 50 deletions

View File

@ -4,17 +4,19 @@
namespace Components::GSC namespace Components::GSC
{ {
const char* IO::QueryStrings[] = { R"(..)", R"(../)", R"(..\)" }; const char* IO::ForbiddenStrings[] = { R"(..)", R"(../)", R"(..\)" };
std::filesystem::path IO::Path;
void IO::AddScriptFunctions() void IO::AddScriptFunctions()
{ {
Script::AddFunction("FileWrite", [] // gsc: FileWrite(<filepath>, <string>, <mode>) Script::AddFunction("FileWrite", [] // gsc: FileWrite(<filepath>, <string>, <mode>)
{ {
const auto* path = Game::Scr_GetString(0); const auto* filepath = Game::Scr_GetString(0);
auto* text = Game::Scr_GetString(1); auto* text = Game::Scr_GetString(1);
auto* mode = Game::Scr_GetString(2); auto* mode = Game::Scr_GetString(2);
if (!path) if (!filepath)
{ {
Game::Scr_ParamError(0, "FileWrite: filepath is not defined!"); Game::Scr_ParamError(0, "FileWrite: filepath is not defined!");
return; return;
@ -26,9 +28,9 @@ namespace Components::GSC
return; return;
} }
for (std::size_t i = 0; i < ARRAYSIZE(QueryStrings); ++i) for (std::size_t i = 0; i < std::extent_v<decltype(ForbiddenStrings)>; ++i)
{ {
if (std::strstr(path, QueryStrings[i]) != nullptr) if (std::strstr(filepath, ForbiddenStrings[i]) != nullptr)
{ {
Logger::PrintError(Game::CON_CHANNEL_ERROR, "FileWrite: directory traversal is not allowed!\n"); Logger::PrintError(Game::CON_CHANNEL_ERROR, "FileWrite: directory traversal is not allowed!\n");
return; return;
@ -41,102 +43,91 @@ namespace Components::GSC
mode = "write"; mode = "write";
} }
const auto* scriptData = Utils::String::VA("%s/%s", "scriptdata", path); const auto append = mode == "append"s;
const auto scriptData = Path / "scriptdata"s / filepath;
if (mode == "write"s) Utils::IO::WriteFile(scriptData.string(), text, append);
{
FileSystem::FileWriter(scriptData).write(text);
}
else if (mode == "append"s)
{
FileSystem::FileWriter(scriptData, true).write(text);
}
}); });
Script::AddFunction("FileRead", [] // gsc: FileRead(<filepath>) Script::AddFunction("FileRead", [] // gsc: FileRead(<filepath>)
{ {
const auto* path = Game::Scr_GetString(0); const auto* filepath = Game::Scr_GetString(0);
if (!filepath)
if (!path)
{ {
Game::Scr_ParamError(0, "FileRead: filepath is not defined!"); Game::Scr_ParamError(0, "FileRead: filepath is not defined!");
return; return;
} }
for (std::size_t i = 0; i < ARRAYSIZE(QueryStrings); ++i) for (std::size_t i = 0; i < std::extent_v<decltype(ForbiddenStrings)>; ++i)
{ {
if (std::strstr(path, QueryStrings[i]) != nullptr) if (std::strstr(filepath, ForbiddenStrings[i]) != nullptr)
{ {
Logger::PrintError(Game::CON_CHANNEL_ERROR, "FileRead: directory traversal is not allowed!\n"); Logger::PrintError(Game::CON_CHANNEL_ERROR, "FileRead: directory traversal is not allowed!\n");
return; return;
} }
} }
const auto* scriptData = Utils::String::VA("%s/%s", "scriptdata", path); const auto scriptData = Path / "scriptdata"s / filepath;
const auto file = FileSystem::FileReader(scriptData); std::string file;
if (!file.exists()) if (!Utils::IO::ReadFile(scriptData.string(), &file))
{ {
Logger::PrintError(Game::CON_CHANNEL_ERROR, "FileRead: file '{}' not found!\n", scriptData); Logger::PrintError(Game::CON_CHANNEL_ERROR, "FileRead: file '{}' not found!\n", scriptData.string());
return; return;
} }
auto buffer = file.getBuffer(); file = file.substr(0, 1024 - 1); // 1024 is the max string size for the SL system
buffer = buffer.substr(0, 1024 - 1); // 1024 is the max string size for the SL system Game::Scr_AddString(file.data());
Game::Scr_AddString(buffer.data());
}); });
Script::AddFunction("FileExists", [] // gsc: FileExists(<filepath>) Script::AddFunction("FileExists", [] // gsc: FileExists(<filepath>)
{ {
const auto* path = Game::Scr_GetString(0); const auto* filepath = Game::Scr_GetString(0);
if (!filepath)
if (!path)
{ {
Game::Scr_ParamError(0, "FileExists: filepath is not defined!"); Game::Scr_ParamError(0, "FileExists: filepath is not defined!");
return; return;
} }
for (std::size_t i = 0; i < ARRAYSIZE(QueryStrings); ++i) for (std::size_t i = 0; i < std::extent_v<decltype(ForbiddenStrings)>; ++i)
{ {
if (std::strstr(path, QueryStrings[i]) != nullptr) if (std::strstr(filepath, ForbiddenStrings[i]) != nullptr)
{ {
Logger::PrintError(Game::CON_CHANNEL_ERROR, "FileExists: directory traversal is not allowed!\n"); Logger::PrintError(Game::CON_CHANNEL_ERROR, "FileExists: directory traversal is not allowed!\n");
return; return;
} }
} }
const auto* scriptData = Utils::String::VA("%s/%s", "scriptdata", path); const auto scriptData = Path / "scriptdata"s / filepath;
Game::Scr_AddBool(FileSystem::FileReader(scriptData).exists()); Game::Scr_AddBool(Utils::IO::FileExists(scriptData.string()));
}); });
Script::AddFunction("FileRemove", [] // gsc: FileRemove(<filepath>) Script::AddFunction("FileRemove", [] // gsc: FileRemove(<filepath>)
{ {
const auto* path = Game::Scr_GetString(0); const auto* filepath = Game::Scr_GetString(0);
if (!filepath)
if (!path)
{ {
Game::Scr_ParamError(0, "FileRemove: filepath is not defined!"); Game::Scr_ParamError(0, "FileRemove: filepath is not defined!");
return; return;
} }
for (std::size_t i = 0; i < ARRAYSIZE(QueryStrings); ++i) for (std::size_t i = 0; i < std::extent_v<decltype(ForbiddenStrings)>; ++i)
{ {
if (std::strstr(path, QueryStrings[i]) != nullptr) if (std::strstr(filepath, ForbiddenStrings[i]) != nullptr)
{ {
Logger::Print("FileRemove: directory traversal is not allowed!\n"); Logger::Print("FileRemove: directory traversal is not allowed!\n");
return; return;
} }
} }
const auto p = "scriptdata"s / std::filesystem::path(path); const auto scriptData = Path / "scriptdata"s / filepath;
const auto folder = p.parent_path().string(); Game::Scr_AddInt(Utils::IO::RemoveFile(scriptData.string()));
const auto file = p.filename().string();
Game::Scr_AddInt(FileSystem::_DeleteFile(folder, file));
}); });
} }
IO::IO() IO::IO()
{ {
Path = "userraw"s;
AddScriptFunctions(); AddScriptFunctions();
} }
} }

View File

@ -8,7 +8,9 @@ namespace Components::GSC
IO(); IO();
private: private:
static const char* QueryStrings[]; static const char* ForbiddenStrings[];
static std::filesystem::path Path;
static void AddScriptFunctions(); static void AddScriptFunctions();
}; };

View File

@ -72,16 +72,20 @@ namespace Components::GSC
const auto* op = Game::Scr_GetString(1); const auto* op = Game::Scr_GetString(1);
const auto b = GetInt64Arg(2, true); const auto b = GetInt64Arg(2, true);
if (const auto itr = Operations.find(op); itr != Operations.end())
{ {
Game::Scr_AddString(Utils::String::VA("%lld", itr->second(a, b))); if (const auto itr = Operations.find(op); itr != Operations.end())
return; {
Game::Scr_AddString(Utils::String::VA("%lld", itr->second(a, b)));
return;
}
} }
if (const auto itr = Comparisons.find(op); itr != Comparisons.end())
{ {
Game::Scr_AddBool(itr->second(a, b)); if (const auto itr = Comparisons.find(op); itr != Comparisons.end())
return; {
Game::Scr_AddBool(itr->second(a, b));
return;
}
} }
Game::Scr_ParamError(1, "Invalid int64 operation"); Game::Scr_ParamError(1, "Invalid int64 operation");

View File

@ -46,6 +46,7 @@
#include <type_traits> #include <type_traits>
#include <map> #include <map>
#include <set> #include <set>
#include <type_traits>
#include <unordered_map> #include <unordered_map>
#include <unordered_set> #include <unordered_set>