From c75ae4296b59dbdc836355dcf8478bc097b32ebd Mon Sep 17 00:00:00 2001 From: Rudolf Polzer Date: Fri, 1 Jul 2011 11:27:15 +0200 Subject: [PATCH] forbidden dirs: allow wildcard patterns --- Makefile | 6 ++++ include/filematch.h | 7 ++++ libs/filematch.c | 68 +++++++++++++++++++++++++++++++++++++++ plugins/vfspk3/vfs.cpp | 5 +-- tools/quake3/common/vfs.c | 6 ++-- 5 files changed, 88 insertions(+), 4 deletions(-) create mode 100644 include/filematch.h create mode 100644 libs/filematch.c diff --git a/Makefile b/Makefile index 44460a7..ecb5fb6 100644 --- a/Makefile +++ b/Makefile @@ -506,6 +506,7 @@ $(INSTALLDIR)/q3map2.$(EXE): \ tools/quake3/q3map2/vis.o \ tools/quake3/q3map2/writebsp.o \ libddslib.$(A) \ + libfilematch.$(A) \ libjpeg6.$(A) \ libl_net.$(A) \ libmathlib.$(A) \ @@ -693,6 +694,7 @@ $(INSTALLDIR)/radiant.$(EXE): \ radiant/xmlstuff.o \ radiant/xywindow.o \ libcmdlib.$(A) \ + libfilematch.$(A) \ libgtkutil.$(A) \ libl_net.$(A) \ libmathlib.$(A) \ @@ -700,6 +702,10 @@ $(INSTALLDIR)/radiant.$(EXE): \ libxmllib.$(A) \ $(if $(findstring $(OS),Win32),icons/radiant.o,) \ +libfilematch.$(A): CPPFLAGS_EXTRA := -Ilibs +libfilematch.$(A): \ + libs/filematch.o \ + libcmdlib.$(A): CPPFLAGS_EXTRA := -Ilibs libcmdlib.$(A): \ libs/cmdlib/cmdlib.o \ diff --git a/include/filematch.h b/include/filematch.h new file mode 100644 index 0000000..f801809 --- /dev/null +++ b/include/filematch.h @@ -0,0 +1,7 @@ +#if !defined(INCLUDED_FILEMATCH_H) +#define INCLUDED_FILEMATCH_H + +int matchpattern(const char *in, const char *pattern, int caseinsensitive); +int matchpattern_with_separator(const char *in, const char *pattern, int caseinsensitive, const char *separators, int wildcard_least_one); + +#endif diff --git a/libs/filematch.c b/libs/filematch.c new file mode 100644 index 0000000..f3e3ea4 --- /dev/null +++ b/libs/filematch.c @@ -0,0 +1,68 @@ +#include "matchpattern.h" + +// LordHavoc: some portable directory listing code I wrote for lmp2pcx, now used in darkplaces to load id1/*.pak and such... + +int matchpattern(const char *in, const char *pattern, int caseinsensitive) +{ + return matchpattern_with_separator(in, pattern, caseinsensitive, "/\\:", false); +} + +// wildcard_least_one: if true * matches 1 or more characters +// if false * matches 0 or more characters +int matchpattern_with_separator(const char *in, const char *pattern, int caseinsensitive, const char *separators, int wildcard_least_one) +{ + int c1, c2; + while (*pattern) + { + switch (*pattern) + { + case 0: + return 1; // end of pattern + case '?': // match any single character + if (*in == 0 || strchr(separators, *in)) + return 0; // no match + in++; + pattern++; + break; + case '*': // match anything until following string + if(wildcard_least_one) + { + if (*in == 0 || strchr(separators, *in)) + return 0; // no match + in++; + } + pattern++; + while (*in) + { + if (strchr(separators, *in)) + break; + // see if pattern matches at this offset + if (matchpattern_with_separator(in, pattern, caseinsensitive, separators, wildcard_least_one)) + return 1; + // nope, advance to next offset + in++; + } + break; + default: + if (*in != *pattern) + { + if (!caseinsensitive) + return 0; // no match + c1 = *in; + if (c1 >= 'A' && c1 <= 'Z') + c1 += 'a' - 'A'; + c2 = *pattern; + if (c2 >= 'A' && c2 <= 'Z') + c2 += 'a' - 'A'; + if (c1 != c2) + return 0; // no match + } + in++; + pattern++; + break; + } + } + if (*in) + return 0; // reached end of pattern but not end of input + return 1; // success +} diff --git a/plugins/vfspk3/vfs.cpp b/plugins/vfspk3/vfs.cpp index b47942b..8890edd 100644 --- a/plugins/vfspk3/vfs.cpp +++ b/plugins/vfspk3/vfs.cpp @@ -315,8 +315,9 @@ void InitDirectory(const char* directory, ArchiveModules& archiveModules) for(j = 0; j < g_numForbiddenDirs; ++j) { - if(!string_compare_nocase_upper(directory, g_strForbiddenDirs[j]) - || (string_length(directory) > string_length(g_strForbiddenDirs[j]) && directory[string_length(directory) - string_length(g_strForbiddenDirs[j]) - 1] == '/' && !string_compare_nocase_upper(directory + string_length(directory) - string_length(g_strForbiddenDirs[j]), g_strForbiddenDirs[j]))) + const char *p = strrchr(directory, '/'); + p = (p ? (p+1) : path); + if(matchpattern(p, g_strForbiddenDirs[j], TRUE)) break; } if(j < g_numForbiddenDirs) diff --git a/tools/quake3/common/vfs.c b/tools/quake3/common/vfs.c index 86a749c..ef2fad8 100644 --- a/tools/quake3/common/vfs.c +++ b/tools/quake3/common/vfs.c @@ -46,6 +46,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "cmdlib.h" +#include "filematch.h" #include "mathlib.h" #include "inout.h" #include "vfs.h" @@ -160,8 +161,9 @@ void vfsInitDirectory (const char *path) for(j = 0; j < g_numForbiddenDirs; ++j) { - if(!Q_stricmp(path, g_strForbiddenDirs[j]) - || (strlen(path) > strlen(g_strForbiddenDirs[j]) && path[strlen(path) - strlen(g_strForbiddenDirs[j]) - 1] == '/' && !Q_stricmp(path + strlen(path) - strlen(g_strForbiddenDirs[j]), g_strForbiddenDirs[j]))) + const char *p = strrchr(path, '/'); + p = (p ? (p+1) : path); + if(matchpattern(p, g_strForbiddenDirs[j], TRUE)) break; } if(j < g_numForbiddenDirs) -- 2.39.2