forbidden dirs: allow wildcard patterns
authorRudolf Polzer <divVerent@xonotic.org>
Fri, 1 Jul 2011 09:27:15 +0000 (11:27 +0200)
committerRudolf Polzer <divVerent@xonotic.org>
Fri, 1 Jul 2011 09:27:15 +0000 (11:27 +0200)
Makefile
include/filematch.h [new file with mode: 0644]
libs/filematch.c [new file with mode: 0644]
plugins/vfspk3/vfs.cpp
tools/quake3/common/vfs.c

index 44460a7..ecb5fb6 100644 (file)
--- 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 (file)
index 0000000..f801809
--- /dev/null
@@ -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 (file)
index 0000000..f3e3ea4
--- /dev/null
@@ -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
+}
index b47942b..8890edd 100644 (file)
@@ -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)
index 86a749c..ef2fad8 100644 (file)
@@ -46,6 +46,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <sys/stat.h>
 
 #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)