1 #include "rar.hpp"
2 
3 static bool match(const wchar *pattern,const wchar *string,bool ForceCase);
4 static int mwcsicompc(const wchar *Str1,const wchar *Str2,bool ForceCase);
5 static int mwcsnicompc(const wchar *Str1,const wchar *Str2,size_t N,bool ForceCase);
6 
touppercw(uint ch,bool ForceCase)7 inline uint touppercw(uint ch,bool ForceCase)
8 {
9   if (ForceCase)
10     return ch;
11 #if defined(_UNIX)
12   return ch;
13 #else
14   return toupperw(ch);
15 #endif
16 }
17 
18 
CmpName(const wchar * Wildcard,const wchar * Name,int CmpMode)19 bool CmpName(const wchar *Wildcard,const wchar *Name,int CmpMode)
20 {
21   bool ForceCase=(CmpMode&MATCH_FORCECASESENSITIVE)!=0;
22 
23   CmpMode&=MATCH_MODEMASK;
24 
25   if (CmpMode!=MATCH_NAMES)
26   {
27     size_t WildLength=wcslen(Wildcard);
28     if (CmpMode!=MATCH_EXACT && CmpMode!=MATCH_EXACTPATH && CmpMode!=MATCH_ALLWILD &&
29         mwcsnicompc(Wildcard,Name,WildLength,ForceCase)==0)
30     {
31       // For all modes except MATCH_NAMES, MATCH_EXACT, MATCH_EXACTPATH, MATCH_ALLWILD,
32       // "path1" mask must match "path1\path2\filename.ext" and "path1" names.
33       wchar NextCh=Name[WildLength];
34       if (NextCh==L'\\' || NextCh==L'/' || NextCh==0)
35         return(true);
36     }
37 
38     // Nothing more to compare for MATCH_SUBPATHONLY.
39     if (CmpMode==MATCH_SUBPATHONLY)
40       return(false);
41 
42     wchar Path1[NM],Path2[NM];
43     GetFilePath(Wildcard,Path1,ASIZE(Path1));
44     GetFilePath(Name,Path2,ASIZE(Path2));
45 
46     if ((CmpMode==MATCH_EXACT || CmpMode==MATCH_EXACTPATH) &&
47         mwcsicompc(Path1,Path2,ForceCase)!=0)
48       return(false);
49     if (CmpMode==MATCH_ALLWILD)
50       return match(Wildcard,Name,ForceCase);
51     if (CmpMode==MATCH_SUBPATH || CmpMode==MATCH_WILDSUBPATH)
52       if (IsWildcard(Path1))
53         return(match(Wildcard,Name,ForceCase));
54       else
55         if (CmpMode==MATCH_SUBPATH || IsWildcard(Wildcard))
56         {
57           if (*Path1 && mwcsnicompc(Path1,Path2,wcslen(Path1),ForceCase)!=0)
58             return(false);
59         }
60         else
61           if (mwcsicompc(Path1,Path2,ForceCase)!=0)
62             return(false);
63   }
64   wchar *Name1=PointToName(Wildcard);
65   wchar *Name2=PointToName(Name);
66 
67   // Always return false for RAR temporary files to exclude them
68   // from archiving operations.
69 //  if (mwcsnicompc(L"__rar_",Name2,6,false)==0)
70 //    return(false);
71 
72   if (CmpMode==MATCH_EXACT)
73     return(mwcsicompc(Name1,Name2,ForceCase)==0);
74 
75   return(match(Name1,Name2,ForceCase));
76 }
77 
78 
match(const wchar * pattern,const wchar * string,bool ForceCase)79 bool match(const wchar *pattern,const wchar *string,bool ForceCase)
80 {
81   for (;; ++string)
82   {
83     wchar stringc=touppercw(*string,ForceCase);
84     wchar patternc=touppercw(*pattern++,ForceCase);
85     switch (patternc)
86     {
87       case 0:
88         return(stringc==0);
89       case '?':
90         if (stringc == 0)
91           return(false);
92         break;
93       case '*':
94         if (*pattern==0)
95           return(true);
96         if (*pattern=='.')
97         {
98           if (pattern[1]=='*' && pattern[2]==0)
99             return(true);
100           const wchar *dot=wcschr(string,'.');
101           if (pattern[1]==0)
102             return (dot==NULL || dot[1]==0);
103           if (dot!=NULL)
104           {
105             string=dot;
106             if (wcspbrk(pattern,L"*?")==NULL && wcschr(string+1,'.')==NULL)
107               return(mwcsicompc(pattern+1,string+1,ForceCase)==0);
108           }
109         }
110 
111         while (*string)
112           if (match(pattern,string++,ForceCase))
113             return(true);
114         return(false);
115       default:
116         if (patternc != stringc)
117         {
118           // Allow "name." mask match "name" and "name.\" match "name\".
119           if (patternc=='.' && (stringc==0 || stringc=='\\' || stringc=='.'))
120             return(match(pattern,string,ForceCase));
121           else
122             return(false);
123         }
124         break;
125     }
126   }
127 }
128 
129 
mwcsicompc(const wchar * Str1,const wchar * Str2,bool ForceCase)130 int mwcsicompc(const wchar *Str1,const wchar *Str2,bool ForceCase)
131 {
132   if (ForceCase)
133     return wcscmp(Str1,Str2);
134   return wcsicompc(Str1,Str2);
135 }
136 
137 
mwcsnicompc(const wchar * Str1,const wchar * Str2,size_t N,bool ForceCase)138 int mwcsnicompc(const wchar *Str1,const wchar *Str2,size_t N,bool ForceCase)
139 {
140   if (ForceCase)
141     return wcsncmp(Str1,Str2,N);
142 #if defined(_UNIX)
143   return wcsncmp(Str1,Str2,N);
144 #else
145   return wcsnicomp(Str1,Str2,N);
146 #endif
147 }
148