Add SB_MULTISEARCH flag for search_begin.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5782 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2020-10-27 02:56:18 +00:00
parent 3008072807
commit 5d4f66cffd
3 changed files with 66 additions and 13 deletions

View File

@ -2671,9 +2671,55 @@ void FS_FreeFile(void *file)
BZ_Free(file);
}
//handle->EnumerateFiles on each a:b:c part of the given matches string.
static qboolean FS_EnumerateFilesEach(searchpathfuncs_t *handle, char *matches, int (QDECL *func)(const char *fname, qofs_t fsize, time_t mtime, void *parm, searchpathfuncs_t *spath), void *parm)
{
char cleanpath[MAX_QPATH];
const char *match;
char *sep;
for (; matches; matches = sep)
{
sep = strchr(matches, ':');
if (sep)
{
*sep = 0;
match = FS_GetCleanPath(matches, true, cleanpath, sizeof(cleanpath));
*sep++ = ':';
}
else
match = FS_GetCleanPath(matches, true, cleanpath, sizeof(cleanpath));
searchpathfuncs_t *COM_EnumerateFilesPackage (const char *match, const char *package, unsigned int flags, int (QDECL *func)(const char *, qofs_t, time_t mtime, void *, searchpathfuncs_t*), void *parm)
{ //special version that takes an explicit package name to search inside.
if (match && *match)
if (!handle->EnumerateFiles(handle, match, func, parm))
return false;
}
return true;
}
static int FS_EnumerateFilesEachSys (const char *syspath, char *matches, int (*func)(const char *, qofs_t, time_t modtime, void *, searchpathfuncs_t *), void *parm, searchpathfuncs_t *spath)
{
char cleanpath[MAX_QPATH];
const char *match;
char *sep;
for (; matches; matches = sep)
{
sep = strchr(matches, ':');
if (sep)
{
*sep = 0;
match = FS_GetCleanPath(matches, true, cleanpath, sizeof(cleanpath));
*sep++ = ':';
}
else
match = FS_GetCleanPath(matches, true, cleanpath, sizeof(cleanpath));
if (!Sys_EnumerateFiles(syspath, match, func, parm, spath))
return false;
}
return true;
}
searchpathfuncs_t *COM_EnumerateFilesPackage (char *matches, const char *package, unsigned int flags, int (QDECL *func)(const char *, qofs_t, time_t mtime, void *, searchpathfuncs_t*), void *parm)
{ //special version of COM_EnumerateFiles that takes an explicit package name to search inside.
//additionally accepts multiple patterns (separated by : chsrs)
searchpathfuncs_t *handle;
searchpath_t *search;
const char *sp;
@ -2696,8 +2742,8 @@ searchpathfuncs_t *COM_EnumerateFilesPackage (const char *match, const char *pac
continue; //ignore this package
}
foundpackage = true;
// is the element a pak file?
if (!search->handle->EnumerateFiles(search->handle, match, func, parm))
if (!FS_EnumerateFilesEach(search->handle, matches, func, parm))
break;
}
@ -2733,7 +2779,7 @@ searchpathfuncs_t *COM_EnumerateFilesPackage (const char *match, const char *pac
}
if (handle)
handle->EnumerateFiles(handle, match, func, parm);
FS_EnumerateFilesEach(handle, matches, func, parm);
return handle; //caller can use this for context, but is expected to tidy it up too.
}
else
@ -2744,11 +2790,11 @@ searchpathfuncs_t *COM_EnumerateFilesPackage (const char *match, const char *pac
if (com_homepathenabled)
{
Q_snprintfz(syspath, sizeof(syspath), "%s%s", com_homepath, package);
Sys_EnumerateFiles(syspath, match, func, parm, NULL);
FS_EnumerateFilesEachSys(syspath, matches, func, parm, NULL);
}
Q_snprintfz(syspath, sizeof(syspath), "%s%s", com_gamepath, package);
Sys_EnumerateFiles(syspath, match, func, parm, NULL);
FS_EnumerateFilesEachSys(syspath, matches, func, parm, NULL);
}
}
return NULL;

View File

@ -3037,12 +3037,13 @@ void QCBUILTIN PF_whichpack (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo
enum
{
QCSEARCH_INSENSITIVE = 1u<<0, //for dp, we're always insensitive you prick.
// QCSEARCH_INSENSITIVE = 1u<<0, //for dp, we're always insensitive you prick.
QCSEARCH_FULLPACKAGE = 1u<<1, //package names include gamedir prefix etc.
QCSEARCH_ALLOWDUPES = 1u<<2, //don't filter out dupes, allowing entries hidden by later packages to be shown.
QCSEARCH_FORCESEARCH = 1u<<3, //force the search to succeed even if the gamedir/package is not active.
QCSEARCH_MULTISEARCH = 1u<<4, //to avoid possible string manipulation exploits?
};
searchpathfuncs_t *COM_EnumerateFilesPackage (const char *match, const char *package, unsigned int flags, int (QDECL *func)(const char *, qofs_t, time_t mtime, void *, searchpathfuncs_t*), void *parm);
searchpathfuncs_t *COM_EnumerateFilesPackage (char *matches, const char *package, unsigned int flags, int (QDECL *func)(const char *, qofs_t, time_t mtime, void *, searchpathfuncs_t*), void *parm);
typedef struct prvmsearch_s {
pubprogfuncs_t *fromprogs; //share across menu/server
@ -3142,7 +3143,7 @@ static int QDECL search_enumerate(const char *name, qofs_t fsize, time_t mtime,
return true;
}
//float search_begin(string pattern, float caseinsensitive, float quiet) = #74;
//float search_begin(string pattern, float flags, float quiet) = #74;
void QCBUILTIN PF_search_begin (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ //< 0 for error, >= 0 for handle.
//error includes bad search patterns, but not no files
@ -3153,7 +3154,7 @@ void QCBUILTIN PF_search_begin (pubprogfuncs_t *prinst, struct globalvars_s *pr_
prvmsearch_t *s;
size_t j;
if (!*pattern || (*pattern == '.' && pattern[1] == '.') || *pattern == '/' || *pattern == '\\' || strchr(pattern, ':'))
if (!*pattern || (*pattern == '.' && pattern[1] == '.') || *pattern == '/' || *pattern == '\\' || (!(flags&QCSEARCH_MULTISEARCH)&&strchr(pattern, ':')))
{
PF_Warningf(prinst, "PF_search_begin: bad search pattern \"%s\"\n", pattern);
G_FLOAT(OFS_RETURN) = -1;
@ -3183,7 +3184,7 @@ void QCBUILTIN PF_search_begin (pubprogfuncs_t *prinst, struct globalvars_s *pr_
s->fsflags |= WP_FORCE;
Q_strncpyz(s->searchinfo.purepath, package?package:"", sizeof(s->searchinfo.purepath));
s->searchinfo.handle = COM_EnumerateFilesPackage(pattern, package?s->searchinfo.purepath:NULL, s->fsflags, search_enumerate, s);
s->searchinfo.handle = COM_EnumerateFilesPackage(s->pattern, package?s->searchinfo.purepath:NULL, s->fsflags, search_enumerate, s);
G_FLOAT(OFS_RETURN) = j;
}

View File

@ -10628,7 +10628,13 @@ static BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"cvar_string", PF_Fixme, 0, 0, 0, 71, D("string(string name)", "Returns the value of a cvar, as a string.")},
{"crash", PF_Fixme, 0, 0, 0, 72, D("void()", "Demonstrates that no program is bug free.")},
{"stackdump", PF_Fixme, 0, 0, 0, 73, D("void()", "Prints out the QC's stack, for console-based error reports.")},
{"search_begin", PF_Fixme, 0, 0, 0, 74, "searchhandle(string pattern, enumflags:float{SB_CASEINSENSITIVE=1<<0,SB_FULLPACKAGEPATH=1<<1,SB_ALLOWDUPES=1<<2,SB_FORCESEARCH=1<<3} flags, float quiet, optional string package)"},
{"search_begin", PF_Fixme, 0, 0, 0, 74, "searchhandle(string pattern, enumflags:float{"
"SB_CASEINSENSITIVE=1<<0,"
"SB_FULLPACKAGEPATH=1<<1,"
"SB_ALLOWDUPES=1<<2,"
"SB_FORCESEARCH=1<<3"
"SB_MULTISEARCH=1<<4"
"} flags, float quiet, optional string package)"},
{"search_end", PF_Fixme, 0, 0, 0, 75, "void(searchhandle handle)"},
{"search_getsize", PF_Fixme, 0, 0, 0, 76, "float(searchhandle handle)"},
{"search_getfilename",PF_Fixme, 0, 0, 0, 77, "string(searchhandle handle, float num)"},