Add file functions that uses the engine file API (#740)

This provides a safer and more secure alternative to the standard C file API.
This commit is contained in:
smallmodel authored and GitHub committed 2025-06-07 23:54:31 +02:00
1 parent 50fdc70025
commit 9ec3c68d64
2 files changed
+338

No files matched your search

+308
View File
@@ -2072,6 +2072,51 @@ Event EV_ScriptThread_IsBot
"Returns 1 if the client is a bot, 0 otherwise. Will return 0 if the entity is not a client.",
EV_RETURN
);
Event EV_ScriptThread_FS_ReadContent
(
"fs_read_content",
EV_DEFAULT,
"s",
"fileName",
"Reads and returns the whole file content.",
EV_RETURN
);
Event EV_ScriptThread_FS_WriteContent
(
"fs_write_content",
EV_DEFAULT,
"sS",
"fileName content",
"Write the specified content to a file (replaces the existing file).",
EV_NORMAL
);
Event EV_ScriptThread_FS_OpenRead
(
"fs_open_read",
EV_DEFAULT,
"s",
"fileName",
"Opens the specified file for reading. Returns an FSFile object.",
EV_RETURN
);
Event EV_ScriptThread_FS_OpenWrite
(
"fs_open_write",
EV_DEFAULT,
"s",
"fileName",
"Opens the specified file for writing. Returns an FSFile object.",
EV_RETURN
);
Event EV_ScriptThread_FS_OpenAppend
(
"fs_open_append",
EV_DEFAULT,
"s",
"fileName",
"Opens the specified file for appending. Returns an FSFile object.",
EV_RETURN
);
CLASS_DECLARATION(Listener, ScriptThread, NULL) {
{&EV_ScriptThread_GetCvar, &ScriptThread::Getcvar },
@@ -2303,6 +2348,11 @@ CLASS_DECLARATION(Listener, ScriptThread, NULL) {
{&EV_ScriptThread_VisionGetNaked, &ScriptThread::VisionGetNaked },
{&EV_ScriptThread_VisionSetNaked, &ScriptThread::VisionSetNaked },
{&EV_ScriptThread_IsBot, &ScriptThread::IsPlayerBot },
{&EV_ScriptThread_FS_ReadContent, &ScriptThread::FS_ReadContent },
{&EV_ScriptThread_FS_WriteContent, &ScriptThread::FS_WriteContent },
{&EV_ScriptThread_FS_OpenRead, &ScriptThread::FS_OpenRead },
{&EV_ScriptThread_FS_OpenWrite, &ScriptThread::FS_OpenWrite },
{&EV_ScriptThread_FS_OpenAppend, &ScriptThread::FS_OpenAppend },
{NULL, NULL }
};
@@ -5437,6 +5487,8 @@ void ScriptThread::FileOpen(Event *ev)
FILE *f = NULL;
char buf[16] = {0};
ScriptDeprecatedAltMethod("fs_open_*");
numArgs = ev->NumArgs();
if (numArgs != 2) {
@@ -5477,6 +5529,8 @@ void ScriptThread::FileClose(Event *ev)
FILE *f = NULL;
char buf[16] = {0};
ScriptDeprecatedAltMethod("FSFile->close");
numArgs = ev->NumArgs();
if (numArgs != 1) {
@@ -5508,6 +5562,8 @@ void ScriptThread::FileEof(Event *ev)
int ret = 0;
FILE *f = NULL;
ScriptDeprecatedAltMethod("FSFile->seek() and FSFile->tell()");
numArgs = ev->NumArgs();
if (numArgs != 1) {
@@ -5535,6 +5591,8 @@ void ScriptThread::FileSeek(Event *ev)
int ret = 0;
FILE *f = NULL;
ScriptDeprecatedAltMethod("FSFile->seek");
numArgs = ev->NumArgs();
if (numArgs != 3) {
@@ -5572,6 +5630,8 @@ void ScriptThread::FileTell(Event *ev)
long int ret = 0;
FILE *f = NULL;
ScriptDeprecatedAltMethod("FSFile->tell");
numArgs = ev->NumArgs();
if (numArgs != 1) {
@@ -5597,6 +5657,8 @@ void ScriptThread::FileRewind(Event *ev)
long int ret = 0;
FILE *f = NULL;
ScriptDeprecatedAltMethod("FSFile->seek");
numArgs = ev->NumArgs();
if (numArgs != 1) {
@@ -5621,6 +5683,8 @@ void ScriptThread::FilePutc(Event *ev)
FILE *f = NULL;
int c = 0;
ScriptDeprecatedAltMethod("FSFile->write");
numArgs = ev->NumArgs();
if (numArgs != 2) {
@@ -5649,6 +5713,8 @@ void ScriptThread::FilePuts(Event *ev)
FILE *f = NULL;
str c;
ScriptDeprecatedAltMethod("FSFile->write");
numArgs = ev->NumArgs();
if (numArgs != 2) {
@@ -5676,6 +5742,8 @@ void ScriptThread::FileGetc(Event *ev)
int ret = 0;
FILE *f = NULL;
ScriptDeprecatedAltMethod("FSFile->read");
numArgs = ev->NumArgs();
if (numArgs != 1) {
@@ -5703,6 +5771,8 @@ void ScriptThread::FileGets(Event *ev)
char *c = NULL;
char *buff = NULL;
ScriptDeprecatedAltMethod("FSFile->read");
numArgs = ev->NumArgs();
if (numArgs != 2) {
@@ -5752,6 +5822,8 @@ void ScriptThread::FileError(Event *ev)
int ret = 0;
FILE *f = NULL;
ScriptDeprecated("ferror");
numArgs = ev->NumArgs();
if (numArgs != 1) {
@@ -5777,6 +5849,8 @@ void ScriptThread::FileFlush(Event *ev)
int ret = 0;
FILE *f = NULL;
ScriptDeprecatedAltMethod("FSFile->flush");
numArgs = ev->NumArgs();
if (numArgs != 1) {
@@ -5801,6 +5875,8 @@ void ScriptThread::FileExists(Event *ev)
FILE *f = 0;
str filename;
ScriptDeprecatedAltMethod("fs_open_read");
numArgs = ev->NumArgs();
if (numArgs != 1) {
@@ -5832,6 +5908,8 @@ void ScriptThread::FileReadAll(Event *ev)
size_t size = 0;
size_t sizeRead = 0;
ScriptDeprecatedAltMethod("fs_read_content");
numArgs = ev->NumArgs();
if (numArgs != 1) {
@@ -5873,6 +5951,8 @@ void ScriptThread::FileSaveAll(Event *ev)
size_t sizeWrite = 0;
str text;
ScriptDeprecatedAltMethod("fs_write_content");
numArgs = ev->NumArgs();
if (numArgs != 2) {
@@ -7228,6 +7308,72 @@ void ScriptThread::IsPlayerBot(Event *ev)
ev->AddInteger(1);
}
void ScriptThread::FS_ReadContent(Event *ev) {
void *buffer;
size_t length;
const str path = ev->GetString(1);
if ((length = gi.FS_ReadFile(path, &buffer, qtrue)) == -1) {
ev->AddNil();
return;
}
// FIXME: Only text is supported (not binary)
ev->AddString((char*)buffer);
gi.FS_FreeFile(buffer);
}
void ScriptThread::FS_WriteContent(Event *ev) {
const str path = ev->GetString(1);
const str content = ev->GetString(2);
gi.FS_WriteFile(path, content, content.length());
}
void ScriptThread::FS_OpenRead(Event *ev) {
FSFile *file;
fileHandle_t f;
const str path = ev->GetString(1);
if (gi.FS_FOpenFile(path, &f, qtrue, qtrue) == -1) {
ev->AddNil();
return;
}
file = new FSFile(f);
ev->AddListener(file);
}
void ScriptThread::FS_OpenWrite(Event *ev) {
FSFile *file;
fileHandle_t f;
const str path = ev->GetString(1);
if ((f = gi.FS_FOpenFileWrite(path)) == -1) {
ev->AddNil();
return;
}
file = new FSFile(f);
ev->AddListener(file);
}
void ScriptThread::FS_OpenAppend(Event *ev) {
FSFile *file;
fileHandle_t f;
const str path = ev->GetString(1);
if ((f = gi.FS_FOpenFileAppend(path)) == -1) {
ev->AddNil();
return;
}
file = new FSFile(f);
ev->AddListener(file);
}
CLASS_DECLARATION(Listener, OSFile, NULL) {
{NULL, NULL}
};
@@ -7251,3 +7397,165 @@ void *OSFile::getOSFile() const
{
return file;
}
Event EV_FSFile_Close
(
"close",
EV_DEFAULT,
NULL,
NULL,
"Closes the file.",
EV_NORMAL
);
Event EV_FSFile_Flush
(
"flush",
EV_DEFAULT,
NULL,
NULL,
"Flush to disk.",
EV_NORMAL
);
Event EV_FSFile_Read
(
"read",
EV_DEFAULT,
"i",
"length",
"Reads n characters from file.",
EV_RETURN
);
Event EV_FSFile_Write
(
"write",
EV_DEFAULT,
"si",
"buffer length",
"Writes n characters from file.",
EV_NORMAL
);
Event EV_FSFile_Seek
(
"seek",
EV_DEFAULT,
"ii",
"offset origin",
"Seeks to the specified offset.\n"
"0 = From current\n"
"1 = From end\n"
"2 = Set\n",
EV_NORMAL
);
Event EV_FSFile_Tell
(
"tell",
EV_DEFAULT,
NULL,
NULL,
"Returns the specified offset.",
EV_RETURN
);
CLASS_DECLARATION(Listener, FSFile, NULL) {
{&EV_FSFile_Close, &FSFile::CloseEvent},
{&EV_FSFile_Flush, &FSFile::FlushEvent},
{&EV_FSFile_Read, &FSFile::ReadEvent },
{&EV_FSFile_Write, &FSFile::WriteEvent},
{&EV_FSFile_Seek, &FSFile::SeekEvent },
{&EV_FSFile_Tell, &FSFile::TellEvent },
{NULL, NULL }
};
FSFile::FSFile()
{
handle = -1;
}
FSFile::FSFile(fileHandle_t inFile)
: handle(inFile)
{}
FSFile::~FSFile()
{
if (handle != -1) {
gi.FS_FCloseFile(handle);
}
}
fileHandle_t FSFile::getHandle() const
{
return handle;
}
void FSFile::CloseEvent(Event *ev)
{
delete this;
}
void FSFile::FlushEvent(Event *ev)
{
if (handle == -1) {
return;
}
gi.FS_Flush(handle);
}
void FSFile::ReadEvent(Event *ev)
{
const int length = ev->GetInteger(1);
if (handle == -1) {
return;
}
char *buffer = new char[length + 1];
const size_t readlen = gi.FS_Read(buffer, length, handle);
buffer[readlen] = 0;
ev->AddString(buffer);
delete[] buffer;
}
void FSFile::WriteEvent(Event *ev)
{
const str buffer = ev->GetString(1);
const int length = ev->GetInteger(2);
if (handle == -1) {
return;
}
gi.FS_Write(buffer, length, handle);
}
void FSFile::SeekEvent(Event *ev)
{
const long offset = ev->GetInteger(1);
const int origin = ev->GetInteger(2);
if (handle == -1) {
return;
}
gi.FS_Seek(handle, offset, origin);
}
void FSFile::TellEvent(Event *ev)
{
long offset;
if (handle == -1) {
return;
}
offset = gi.FS_Tell(handle);
ev->AddInteger(offset);
}