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 &&
29 mwcsnicompc(Wildcard,Name,WildLength,ForceCase)==0)
30 {
31 // For all modes except MATCH_NAMES, MATCH_EXACT and MATCH_EXACTPATH
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_SUBPATH || CmpMode==MATCH_WILDSUBPATH)
50 if (IsWildcard(Path1))
51 return(match(Wildcard,Name,ForceCase));
52 else
53 if (CmpMode==MATCH_SUBPATH || IsWildcard(Wildcard))
54 {
55 if (*Path1 && mwcsnicompc(Path1,Path2,wcslen(Path1),ForceCase)!=0)
56 return(false);
57 }
58 else
59 if (mwcsicompc(Path1,Path2,ForceCase)!=0)
60 return(false);
61 }
62 wchar *Name1=PointToName(Wildcard);
63 wchar *Name2=PointToName(Name);
64
65 // Always return false for RAR temporary files to exclude them
66 // from archiving operations.
67 if (mwcsnicompc(L"__rar_",Name2,6,false)==0)
68 return(false);
69
70 if (CmpMode==MATCH_EXACT)
71 return(mwcsicompc(Name1,Name2,ForceCase)==0);
72
73 return(match(Name1,Name2,ForceCase));
74 }
75
76
match(const wchar * pattern,const wchar * string,bool ForceCase)77 bool match(const wchar *pattern,const wchar *string,bool ForceCase)
78 {
79 for (;; ++string)
80 {
81 wchar stringc=touppercw(*string,ForceCase);
82 wchar patternc=touppercw(*pattern++,ForceCase);
83 switch (patternc)
84 {
85 case 0:
86 return(stringc==0);
87 case '?':
88 if (stringc == 0)
89 return(false);
90 break;
91 case '*':
92 if (*pattern==0)
93 return(true);
94 if (*pattern=='.')
95 {
96 if (pattern[1]=='*' && pattern[2]==0)
97 return(true);
98 const wchar *dot=wcschr(string,'.');
99 if (pattern[1]==0)
100 return (dot==NULL || dot[1]==0);
101 if (dot!=NULL)
102 {
103 string=dot;
104 if (wcspbrk(pattern,L"*?")==NULL && wcschr(string+1,'.')==NULL)
105 return(mwcsicompc(pattern+1,string+1,ForceCase)==0);
106 }
107 }
108
109 while (*string)
110 if (match(pattern,string++,ForceCase))
111 return(true);
112 return(false);
113 default:
114 if (patternc != stringc)
115 {
116 // Allow "name." mask match "name" and "name.\" match "name\".
117 if (patternc=='.' && (stringc==0 || stringc=='\\' || stringc=='.'))
118 return(match(pattern,string,ForceCase));
119 else
120 return(false);
121 }
122 break;
123 }
124 }
125 }
126
127
mwcsicompc(const wchar * Str1,const wchar * Str2,bool ForceCase)128 int mwcsicompc(const wchar *Str1,const wchar *Str2,bool ForceCase)
129 {
130 if (ForceCase)
131 return(wcscmp(Str1,Str2));
132 return(wcsicompc(Str1,Str2));
133 }
134
135
mwcsnicompc(const wchar * Str1,const wchar * Str2,size_t N,bool ForceCase)136 int mwcsnicompc(const wchar *Str1,const wchar *Str2,size_t N,bool ForceCase)
137 {
138 if (ForceCase)
139 return(wcsncmp(Str1,Str2,N));
140 #if defined(_UNIX)
141 return(wcsncmp(Str1,Str2,N));
142 #else
143 return(wcsnicomp(Str1,Str2,N));
144 #endif
145 }
146