1370b324cSopenharmony_ci// Common/Wildcard.cpp
2370b324cSopenharmony_ci
3370b324cSopenharmony_ci#include "StdAfx.h"
4370b324cSopenharmony_ci
5370b324cSopenharmony_ci#include "Wildcard.h"
6370b324cSopenharmony_ci
7370b324cSopenharmony_ciextern
8370b324cSopenharmony_cibool g_CaseSensitive;
9370b324cSopenharmony_cibool g_CaseSensitive =
10370b324cSopenharmony_ci  #ifdef _WIN32
11370b324cSopenharmony_ci    false;
12370b324cSopenharmony_ci  #elif defined (__APPLE__)
13370b324cSopenharmony_ci    #ifdef TARGET_OS_IPHONE
14370b324cSopenharmony_ci      true;
15370b324cSopenharmony_ci    #else
16370b324cSopenharmony_ci      false;
17370b324cSopenharmony_ci    #endif
18370b324cSopenharmony_ci  #else
19370b324cSopenharmony_ci    true;
20370b324cSopenharmony_ci  #endif
21370b324cSopenharmony_ci
22370b324cSopenharmony_ci
23370b324cSopenharmony_cibool IsPath1PrefixedByPath2(const wchar_t *s1, const wchar_t *s2)
24370b324cSopenharmony_ci{
25370b324cSopenharmony_ci  if (g_CaseSensitive)
26370b324cSopenharmony_ci    return IsString1PrefixedByString2(s1, s2);
27370b324cSopenharmony_ci  return IsString1PrefixedByString2_NoCase(s1, s2);
28370b324cSopenharmony_ci}
29370b324cSopenharmony_ci
30370b324cSopenharmony_ci// #include <stdio.h>
31370b324cSopenharmony_ci
32370b324cSopenharmony_ci/*
33370b324cSopenharmony_cistatic int MyStringCompare_PathLinux(const wchar_t *s1, const wchar_t *s2) throw()
34370b324cSopenharmony_ci{
35370b324cSopenharmony_ci  for (;;)
36370b324cSopenharmony_ci  {
37370b324cSopenharmony_ci    wchar_t c1 = *s1++;
38370b324cSopenharmony_ci    wchar_t c2 = *s2++;
39370b324cSopenharmony_ci    if (c1 != c2)
40370b324cSopenharmony_ci    {
41370b324cSopenharmony_ci      if (c1 == 0) return -1;
42370b324cSopenharmony_ci      if (c2 == 0) return 1;
43370b324cSopenharmony_ci      if (c1 == '/') c1 = 0;
44370b324cSopenharmony_ci      if (c2 == '/') c2 = 0;
45370b324cSopenharmony_ci      if (c1 < c2) return -1;
46370b324cSopenharmony_ci      if (c1 > c2) return 1;
47370b324cSopenharmony_ci      continue;
48370b324cSopenharmony_ci    }
49370b324cSopenharmony_ci    if (c1 == 0) return 0;
50370b324cSopenharmony_ci  }
51370b324cSopenharmony_ci}
52370b324cSopenharmony_ci*/
53370b324cSopenharmony_ci
54370b324cSopenharmony_cistatic int MyStringCompare_Path(const wchar_t *s1, const wchar_t *s2) throw()
55370b324cSopenharmony_ci{
56370b324cSopenharmony_ci  for (;;)
57370b324cSopenharmony_ci  {
58370b324cSopenharmony_ci    wchar_t c1 = *s1++;
59370b324cSopenharmony_ci    wchar_t c2 = *s2++;
60370b324cSopenharmony_ci    if (c1 != c2)
61370b324cSopenharmony_ci    {
62370b324cSopenharmony_ci      if (c1 == 0) return -1;
63370b324cSopenharmony_ci      if (c2 == 0) return 1;
64370b324cSopenharmony_ci      if (IS_PATH_SEPAR(c1)) c1 = 0;
65370b324cSopenharmony_ci      if (IS_PATH_SEPAR(c2)) c2 = 0;
66370b324cSopenharmony_ci      if (c1 < c2) return -1;
67370b324cSopenharmony_ci      if (c1 > c2) return 1;
68370b324cSopenharmony_ci      continue;
69370b324cSopenharmony_ci    }
70370b324cSopenharmony_ci    if (c1 == 0) return 0;
71370b324cSopenharmony_ci  }
72370b324cSopenharmony_ci}
73370b324cSopenharmony_ci
74370b324cSopenharmony_cistatic int MyStringCompareNoCase_Path(const wchar_t *s1, const wchar_t *s2) throw()
75370b324cSopenharmony_ci{
76370b324cSopenharmony_ci  for (;;)
77370b324cSopenharmony_ci  {
78370b324cSopenharmony_ci    wchar_t c1 = *s1++;
79370b324cSopenharmony_ci    wchar_t c2 = *s2++;
80370b324cSopenharmony_ci    if (c1 != c2)
81370b324cSopenharmony_ci    {
82370b324cSopenharmony_ci      if (c1 == 0) return -1;
83370b324cSopenharmony_ci      if (c2 == 0) return 1;
84370b324cSopenharmony_ci      if (IS_PATH_SEPAR(c1)) c1 = 0;
85370b324cSopenharmony_ci      if (IS_PATH_SEPAR(c2)) c2 = 0;
86370b324cSopenharmony_ci      c1 = MyCharUpper(c1);
87370b324cSopenharmony_ci      c2 = MyCharUpper(c2);
88370b324cSopenharmony_ci      if (c1 < c2) return -1;
89370b324cSopenharmony_ci      if (c1 > c2) return 1;
90370b324cSopenharmony_ci      continue;
91370b324cSopenharmony_ci    }
92370b324cSopenharmony_ci    if (c1 == 0) return 0;
93370b324cSopenharmony_ci  }
94370b324cSopenharmony_ci}
95370b324cSopenharmony_ci
96370b324cSopenharmony_ciint CompareFileNames(const wchar_t *s1, const wchar_t *s2) STRING_UNICODE_THROW
97370b324cSopenharmony_ci{
98370b324cSopenharmony_ci  /*
99370b324cSopenharmony_ci  printf("\nCompareFileNames");
100370b324cSopenharmony_ci  printf("\n S1: %ls", s1);
101370b324cSopenharmony_ci  printf("\n S2: %ls", s2);
102370b324cSopenharmony_ci  printf("\n");
103370b324cSopenharmony_ci  */
104370b324cSopenharmony_ci  // 21.07 : we parse PATH_SEPARATOR so: 0 < PATH_SEPARATOR < 1
105370b324cSopenharmony_ci  if (g_CaseSensitive)
106370b324cSopenharmony_ci    return MyStringCompare_Path(s1, s2);
107370b324cSopenharmony_ci  return MyStringCompareNoCase_Path(s1, s2);
108370b324cSopenharmony_ci}
109370b324cSopenharmony_ci
110370b324cSopenharmony_ci#ifndef USE_UNICODE_FSTRING
111370b324cSopenharmony_ciint CompareFileNames(const char *s1, const char *s2)
112370b324cSopenharmony_ci{
113370b324cSopenharmony_ci  const UString u1 = fs2us(s1);
114370b324cSopenharmony_ci  const UString u2 = fs2us(s2);
115370b324cSopenharmony_ci  return CompareFileNames(u1, u2);
116370b324cSopenharmony_ci}
117370b324cSopenharmony_ci#endif
118370b324cSopenharmony_ci
119370b324cSopenharmony_ci// -----------------------------------------
120370b324cSopenharmony_ci// this function compares name with mask
121370b324cSopenharmony_ci// ? - any char
122370b324cSopenharmony_ci// * - any char or empty
123370b324cSopenharmony_ci
124370b324cSopenharmony_cistatic bool EnhancedMaskTest(const wchar_t *mask, const wchar_t *name)
125370b324cSopenharmony_ci{
126370b324cSopenharmony_ci  for (;;)
127370b324cSopenharmony_ci  {
128370b324cSopenharmony_ci    const wchar_t m = *mask;
129370b324cSopenharmony_ci    const wchar_t c = *name;
130370b324cSopenharmony_ci    if (m == 0)
131370b324cSopenharmony_ci      return (c == 0);
132370b324cSopenharmony_ci    if (m == '*')
133370b324cSopenharmony_ci    {
134370b324cSopenharmony_ci      if (EnhancedMaskTest(mask + 1, name))
135370b324cSopenharmony_ci        return true;
136370b324cSopenharmony_ci      if (c == 0)
137370b324cSopenharmony_ci        return false;
138370b324cSopenharmony_ci    }
139370b324cSopenharmony_ci    else
140370b324cSopenharmony_ci    {
141370b324cSopenharmony_ci      if (m == '?')
142370b324cSopenharmony_ci      {
143370b324cSopenharmony_ci        if (c == 0)
144370b324cSopenharmony_ci          return false;
145370b324cSopenharmony_ci      }
146370b324cSopenharmony_ci      else if (m != c)
147370b324cSopenharmony_ci        if (g_CaseSensitive || MyCharUpper(m) != MyCharUpper(c))
148370b324cSopenharmony_ci          return false;
149370b324cSopenharmony_ci      mask++;
150370b324cSopenharmony_ci    }
151370b324cSopenharmony_ci    name++;
152370b324cSopenharmony_ci  }
153370b324cSopenharmony_ci}
154370b324cSopenharmony_ci
155370b324cSopenharmony_ci// --------------------------------------------------
156370b324cSopenharmony_ci// Splits path to strings
157370b324cSopenharmony_ci
158370b324cSopenharmony_civoid SplitPathToParts(const UString &path, UStringVector &pathParts)
159370b324cSopenharmony_ci{
160370b324cSopenharmony_ci  pathParts.Clear();
161370b324cSopenharmony_ci  unsigned len = path.Len();
162370b324cSopenharmony_ci  if (len == 0)
163370b324cSopenharmony_ci    return;
164370b324cSopenharmony_ci  UString name;
165370b324cSopenharmony_ci  unsigned prev = 0;
166370b324cSopenharmony_ci  for (unsigned i = 0; i < len; i++)
167370b324cSopenharmony_ci    if (IsPathSepar(path[i]))
168370b324cSopenharmony_ci    {
169370b324cSopenharmony_ci      name.SetFrom(path.Ptr(prev), i - prev);
170370b324cSopenharmony_ci      pathParts.Add(name);
171370b324cSopenharmony_ci      prev = i + 1;
172370b324cSopenharmony_ci    }
173370b324cSopenharmony_ci  name.SetFrom(path.Ptr(prev), len - prev);
174370b324cSopenharmony_ci  pathParts.Add(name);
175370b324cSopenharmony_ci}
176370b324cSopenharmony_ci
177370b324cSopenharmony_civoid SplitPathToParts_2(const UString &path, UString &dirPrefix, UString &name)
178370b324cSopenharmony_ci{
179370b324cSopenharmony_ci  const wchar_t *start = path;
180370b324cSopenharmony_ci  const wchar_t *p = start + path.Len();
181370b324cSopenharmony_ci  for (; p != start; p--)
182370b324cSopenharmony_ci    if (IsPathSepar(*(p - 1)))
183370b324cSopenharmony_ci      break;
184370b324cSopenharmony_ci  dirPrefix.SetFrom(path, (unsigned)(p - start));
185370b324cSopenharmony_ci  name = p;
186370b324cSopenharmony_ci}
187370b324cSopenharmony_ci
188370b324cSopenharmony_civoid SplitPathToParts_Smart(const UString &path, UString &dirPrefix, UString &name)
189370b324cSopenharmony_ci{
190370b324cSopenharmony_ci  const wchar_t *start = path;
191370b324cSopenharmony_ci  const wchar_t *p = start + path.Len();
192370b324cSopenharmony_ci  if (p != start)
193370b324cSopenharmony_ci  {
194370b324cSopenharmony_ci    if (IsPathSepar(*(p - 1)))
195370b324cSopenharmony_ci      p--;
196370b324cSopenharmony_ci    for (; p != start; p--)
197370b324cSopenharmony_ci      if (IsPathSepar(*(p - 1)))
198370b324cSopenharmony_ci        break;
199370b324cSopenharmony_ci  }
200370b324cSopenharmony_ci  dirPrefix.SetFrom(path, (unsigned)(p - start));
201370b324cSopenharmony_ci  name = p;
202370b324cSopenharmony_ci}
203370b324cSopenharmony_ci
204370b324cSopenharmony_ci/*
205370b324cSopenharmony_ciUString ExtractDirPrefixFromPath(const UString &path)
206370b324cSopenharmony_ci{
207370b324cSopenharmony_ci  return path.Left(path.ReverseFind_PathSepar() + 1));
208370b324cSopenharmony_ci}
209370b324cSopenharmony_ci*/
210370b324cSopenharmony_ci
211370b324cSopenharmony_ciUString ExtractFileNameFromPath(const UString &path)
212370b324cSopenharmony_ci{
213370b324cSopenharmony_ci  return UString(path.Ptr((unsigned)(path.ReverseFind_PathSepar() + 1)));
214370b324cSopenharmony_ci}
215370b324cSopenharmony_ci
216370b324cSopenharmony_ci
217370b324cSopenharmony_cibool DoesWildcardMatchName(const UString &mask, const UString &name)
218370b324cSopenharmony_ci{
219370b324cSopenharmony_ci  return EnhancedMaskTest(mask, name);
220370b324cSopenharmony_ci}
221370b324cSopenharmony_ci
222370b324cSopenharmony_cibool DoesNameContainWildcard(const UString &path)
223370b324cSopenharmony_ci{
224370b324cSopenharmony_ci  for (unsigned i = 0; i < path.Len(); i++)
225370b324cSopenharmony_ci  {
226370b324cSopenharmony_ci    wchar_t c = path[i];
227370b324cSopenharmony_ci    if (c == '*' || c == '?')
228370b324cSopenharmony_ci      return true;
229370b324cSopenharmony_ci  }
230370b324cSopenharmony_ci  return false;
231370b324cSopenharmony_ci}
232370b324cSopenharmony_ci
233370b324cSopenharmony_ci
234370b324cSopenharmony_ci// ----------------------------------------------------------'
235370b324cSopenharmony_ci// NWildcard
236370b324cSopenharmony_ci
237370b324cSopenharmony_cinamespace NWildcard {
238370b324cSopenharmony_ci
239370b324cSopenharmony_ci/*
240370b324cSopenharmony_ci
241370b324cSopenharmony_ciM = MaskParts.Size();
242370b324cSopenharmony_ciN = TestNameParts.Size();
243370b324cSopenharmony_ci
244370b324cSopenharmony_ci                           File                          Dir
245370b324cSopenharmony_ciForFile     rec   M<=N  [N-M, N)                          -
246370b324cSopenharmony_ci!ForDir  nonrec   M=N   [0, M)                            -
247370b324cSopenharmony_ci
248370b324cSopenharmony_ciForDir      rec   M<N   [0, M) ... [N-M-1, N-1)  same as ForBoth-File
249370b324cSopenharmony_ci!ForFile nonrec         [0, M)                   same as ForBoth-File
250370b324cSopenharmony_ci
251370b324cSopenharmony_ciForFile     rec   m<=N  [0, M) ... [N-M, N)      same as ForBoth-File
252370b324cSopenharmony_ciForDir   nonrec         [0, M)                   same as ForBoth-File
253370b324cSopenharmony_ci
254370b324cSopenharmony_ci*/
255370b324cSopenharmony_ci
256370b324cSopenharmony_cibool CItem::AreAllAllowed() const
257370b324cSopenharmony_ci{
258370b324cSopenharmony_ci  return ForFile && ForDir && WildcardMatching && PathParts.Size() == 1 && PathParts.Front() == L"*";
259370b324cSopenharmony_ci}
260370b324cSopenharmony_ci
261370b324cSopenharmony_cibool CItem::CheckPath(const UStringVector &pathParts, bool isFile) const
262370b324cSopenharmony_ci{
263370b324cSopenharmony_ci  if (!isFile && !ForDir)
264370b324cSopenharmony_ci    return false;
265370b324cSopenharmony_ci
266370b324cSopenharmony_ci  /*
267370b324cSopenharmony_ci  if (PathParts.IsEmpty())
268370b324cSopenharmony_ci  {
269370b324cSopenharmony_ci    // PathParts.IsEmpty() means all items (universal wildcard)
270370b324cSopenharmony_ci    if (!isFile)
271370b324cSopenharmony_ci      return true;
272370b324cSopenharmony_ci    if (pathParts.Size() <= 1)
273370b324cSopenharmony_ci      return ForFile;
274370b324cSopenharmony_ci    return (ForDir || Recursive && ForFile);
275370b324cSopenharmony_ci  }
276370b324cSopenharmony_ci  */
277370b324cSopenharmony_ci
278370b324cSopenharmony_ci  int delta = (int)pathParts.Size() - (int)PathParts.Size();
279370b324cSopenharmony_ci  if (delta < 0)
280370b324cSopenharmony_ci    return false;
281370b324cSopenharmony_ci  int start = 0;
282370b324cSopenharmony_ci  int finish = 0;
283370b324cSopenharmony_ci
284370b324cSopenharmony_ci  if (isFile)
285370b324cSopenharmony_ci  {
286370b324cSopenharmony_ci    if (!ForDir)
287370b324cSopenharmony_ci    {
288370b324cSopenharmony_ci      if (Recursive)
289370b324cSopenharmony_ci        start = delta;
290370b324cSopenharmony_ci      else if (delta !=0)
291370b324cSopenharmony_ci        return false;
292370b324cSopenharmony_ci    }
293370b324cSopenharmony_ci    if (!ForFile && delta == 0)
294370b324cSopenharmony_ci      return false;
295370b324cSopenharmony_ci  }
296370b324cSopenharmony_ci
297370b324cSopenharmony_ci  if (Recursive)
298370b324cSopenharmony_ci  {
299370b324cSopenharmony_ci    finish = delta;
300370b324cSopenharmony_ci    if (isFile && !ForFile)
301370b324cSopenharmony_ci      finish = delta - 1;
302370b324cSopenharmony_ci  }
303370b324cSopenharmony_ci
304370b324cSopenharmony_ci  for (int d = start; d <= finish; d++)
305370b324cSopenharmony_ci  {
306370b324cSopenharmony_ci    unsigned i;
307370b324cSopenharmony_ci    for (i = 0; i < PathParts.Size(); i++)
308370b324cSopenharmony_ci    {
309370b324cSopenharmony_ci      if (WildcardMatching)
310370b324cSopenharmony_ci      {
311370b324cSopenharmony_ci        if (!DoesWildcardMatchName(PathParts[i], pathParts[i + (unsigned)d]))
312370b324cSopenharmony_ci          break;
313370b324cSopenharmony_ci      }
314370b324cSopenharmony_ci      else
315370b324cSopenharmony_ci      {
316370b324cSopenharmony_ci        if (CompareFileNames(PathParts[i], pathParts[i + (unsigned)d]) != 0)
317370b324cSopenharmony_ci          break;
318370b324cSopenharmony_ci      }
319370b324cSopenharmony_ci    }
320370b324cSopenharmony_ci    if (i == PathParts.Size())
321370b324cSopenharmony_ci      return true;
322370b324cSopenharmony_ci  }
323370b324cSopenharmony_ci  return false;
324370b324cSopenharmony_ci}
325370b324cSopenharmony_ci
326370b324cSopenharmony_cibool CCensorNode::AreAllAllowed() const
327370b324cSopenharmony_ci{
328370b324cSopenharmony_ci  if (!Name.IsEmpty() ||
329370b324cSopenharmony_ci      !SubNodes.IsEmpty() ||
330370b324cSopenharmony_ci      !ExcludeItems.IsEmpty() ||
331370b324cSopenharmony_ci      IncludeItems.Size() != 1)
332370b324cSopenharmony_ci    return false;
333370b324cSopenharmony_ci  return IncludeItems.Front().AreAllAllowed();
334370b324cSopenharmony_ci}
335370b324cSopenharmony_ci
336370b324cSopenharmony_ciint CCensorNode::FindSubNode(const UString &name) const
337370b324cSopenharmony_ci{
338370b324cSopenharmony_ci  FOR_VECTOR (i, SubNodes)
339370b324cSopenharmony_ci    if (CompareFileNames(SubNodes[i].Name, name) == 0)
340370b324cSopenharmony_ci      return (int)i;
341370b324cSopenharmony_ci  return -1;
342370b324cSopenharmony_ci}
343370b324cSopenharmony_ci
344370b324cSopenharmony_civoid CCensorNode::AddItemSimple(bool include, CItem &item)
345370b324cSopenharmony_ci{
346370b324cSopenharmony_ci  CObjectVector<CItem> &items = include ? IncludeItems : ExcludeItems;
347370b324cSopenharmony_ci  items.Add(item);
348370b324cSopenharmony_ci}
349370b324cSopenharmony_ci
350370b324cSopenharmony_civoid CCensorNode::AddItem(bool include, CItem &item, int ignoreWildcardIndex)
351370b324cSopenharmony_ci{
352370b324cSopenharmony_ci  if (item.PathParts.Size() <= 1)
353370b324cSopenharmony_ci  {
354370b324cSopenharmony_ci    if (item.PathParts.Size() != 0 && item.WildcardMatching)
355370b324cSopenharmony_ci    {
356370b324cSopenharmony_ci      if (!DoesNameContainWildcard(item.PathParts.Front()))
357370b324cSopenharmony_ci        item.WildcardMatching = false;
358370b324cSopenharmony_ci    }
359370b324cSopenharmony_ci    AddItemSimple(include, item);
360370b324cSopenharmony_ci    return;
361370b324cSopenharmony_ci  }
362370b324cSopenharmony_ci
363370b324cSopenharmony_ci  const UString &front = item.PathParts.Front();
364370b324cSopenharmony_ci
365370b324cSopenharmony_ci  // WIN32 doesn't support wildcards in file names
366370b324cSopenharmony_ci  if (item.WildcardMatching
367370b324cSopenharmony_ci      && ignoreWildcardIndex != 0
368370b324cSopenharmony_ci      && DoesNameContainWildcard(front))
369370b324cSopenharmony_ci  {
370370b324cSopenharmony_ci    AddItemSimple(include, item);
371370b324cSopenharmony_ci    return;
372370b324cSopenharmony_ci  }
373370b324cSopenharmony_ci  CCensorNode &subNode = Find_SubNode_Or_Add_New(front);
374370b324cSopenharmony_ci  item.PathParts.Delete(0);
375370b324cSopenharmony_ci  subNode.AddItem(include, item, ignoreWildcardIndex - 1);
376370b324cSopenharmony_ci}
377370b324cSopenharmony_ci
378370b324cSopenharmony_ci/*
379370b324cSopenharmony_civoid CCensorNode::AddItem(bool include, const UString &path, const CCensorPathProps &props)
380370b324cSopenharmony_ci{
381370b324cSopenharmony_ci  CItem item;
382370b324cSopenharmony_ci  SplitPathToParts(path, item.PathParts);
383370b324cSopenharmony_ci  item.Recursive = props.Recursive;
384370b324cSopenharmony_ci  item.ForFile = props.ForFile;
385370b324cSopenharmony_ci  item.ForDir = props.ForDir;
386370b324cSopenharmony_ci  item.WildcardMatching = props.WildcardMatching;
387370b324cSopenharmony_ci  AddItem(include, item);
388370b324cSopenharmony_ci}
389370b324cSopenharmony_ci*/
390370b324cSopenharmony_ci
391370b324cSopenharmony_cibool CCensorNode::NeedCheckSubDirs() const
392370b324cSopenharmony_ci{
393370b324cSopenharmony_ci  FOR_VECTOR (i, IncludeItems)
394370b324cSopenharmony_ci  {
395370b324cSopenharmony_ci    const CItem &item = IncludeItems[i];
396370b324cSopenharmony_ci    if (item.Recursive || item.PathParts.Size() > 1)
397370b324cSopenharmony_ci      return true;
398370b324cSopenharmony_ci  }
399370b324cSopenharmony_ci  return false;
400370b324cSopenharmony_ci}
401370b324cSopenharmony_ci
402370b324cSopenharmony_cibool CCensorNode::AreThereIncludeItems() const
403370b324cSopenharmony_ci{
404370b324cSopenharmony_ci  if (IncludeItems.Size() > 0)
405370b324cSopenharmony_ci    return true;
406370b324cSopenharmony_ci  FOR_VECTOR (i, SubNodes)
407370b324cSopenharmony_ci    if (SubNodes[i].AreThereIncludeItems())
408370b324cSopenharmony_ci      return true;
409370b324cSopenharmony_ci  return false;
410370b324cSopenharmony_ci}
411370b324cSopenharmony_ci
412370b324cSopenharmony_cibool CCensorNode::CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const
413370b324cSopenharmony_ci{
414370b324cSopenharmony_ci  const CObjectVector<CItem> &items = include ? IncludeItems : ExcludeItems;
415370b324cSopenharmony_ci  FOR_VECTOR (i, items)
416370b324cSopenharmony_ci    if (items[i].CheckPath(pathParts, isFile))
417370b324cSopenharmony_ci      return true;
418370b324cSopenharmony_ci  return false;
419370b324cSopenharmony_ci}
420370b324cSopenharmony_ci
421370b324cSopenharmony_cibool CCensorNode::CheckPathVect(const UStringVector &pathParts, bool isFile, bool &include) const
422370b324cSopenharmony_ci{
423370b324cSopenharmony_ci  if (CheckPathCurrent(false, pathParts, isFile))
424370b324cSopenharmony_ci  {
425370b324cSopenharmony_ci    include = false;
426370b324cSopenharmony_ci    return true;
427370b324cSopenharmony_ci  }
428370b324cSopenharmony_ci  if (pathParts.Size() > 1)
429370b324cSopenharmony_ci  {
430370b324cSopenharmony_ci    int index = FindSubNode(pathParts.Front());
431370b324cSopenharmony_ci    if (index >= 0)
432370b324cSopenharmony_ci    {
433370b324cSopenharmony_ci      UStringVector pathParts2 = pathParts;
434370b324cSopenharmony_ci      pathParts2.Delete(0);
435370b324cSopenharmony_ci      if (SubNodes[(unsigned)index].CheckPathVect(pathParts2, isFile, include))
436370b324cSopenharmony_ci        return true;
437370b324cSopenharmony_ci    }
438370b324cSopenharmony_ci  }
439370b324cSopenharmony_ci  bool finded = CheckPathCurrent(true, pathParts, isFile);
440370b324cSopenharmony_ci  include = finded; // if (!finded), then (true) is allowed also
441370b324cSopenharmony_ci  return finded;
442370b324cSopenharmony_ci}
443370b324cSopenharmony_ci
444370b324cSopenharmony_ci/*
445370b324cSopenharmony_cibool CCensorNode::CheckPath2(bool isAltStream, const UString &path, bool isFile, bool &include) const
446370b324cSopenharmony_ci{
447370b324cSopenharmony_ci  UStringVector pathParts;
448370b324cSopenharmony_ci  SplitPathToParts(path, pathParts);
449370b324cSopenharmony_ci  if (CheckPathVect(pathParts, isFile, include))
450370b324cSopenharmony_ci  {
451370b324cSopenharmony_ci    if (!include || !isAltStream)
452370b324cSopenharmony_ci      return true;
453370b324cSopenharmony_ci  }
454370b324cSopenharmony_ci  if (isAltStream && !pathParts.IsEmpty())
455370b324cSopenharmony_ci  {
456370b324cSopenharmony_ci    UString &back = pathParts.Back();
457370b324cSopenharmony_ci    int pos = back.Find(L':');
458370b324cSopenharmony_ci    if (pos > 0)
459370b324cSopenharmony_ci    {
460370b324cSopenharmony_ci      back.DeleteFrom(pos);
461370b324cSopenharmony_ci      return CheckPathVect(pathParts, isFile, include);
462370b324cSopenharmony_ci    }
463370b324cSopenharmony_ci  }
464370b324cSopenharmony_ci  return false;
465370b324cSopenharmony_ci}
466370b324cSopenharmony_ci
467370b324cSopenharmony_cibool CCensorNode::CheckPath(bool isAltStream, const UString &path, bool isFile) const
468370b324cSopenharmony_ci{
469370b324cSopenharmony_ci  bool include;
470370b324cSopenharmony_ci  if (CheckPath2(isAltStream, path, isFile, include))
471370b324cSopenharmony_ci    return include;
472370b324cSopenharmony_ci  return false;
473370b324cSopenharmony_ci}
474370b324cSopenharmony_ci*/
475370b324cSopenharmony_ci
476370b324cSopenharmony_cibool CCensorNode::CheckPathToRoot_Change(bool include, UStringVector &pathParts, bool isFile) const
477370b324cSopenharmony_ci{
478370b324cSopenharmony_ci  if (CheckPathCurrent(include, pathParts, isFile))
479370b324cSopenharmony_ci    return true;
480370b324cSopenharmony_ci  if (!Parent)
481370b324cSopenharmony_ci    return false;
482370b324cSopenharmony_ci  pathParts.Insert(0, Name);
483370b324cSopenharmony_ci  return Parent->CheckPathToRoot_Change(include, pathParts, isFile);
484370b324cSopenharmony_ci}
485370b324cSopenharmony_ci
486370b324cSopenharmony_cibool CCensorNode::CheckPathToRoot(bool include, const UStringVector &pathParts, bool isFile) const
487370b324cSopenharmony_ci{
488370b324cSopenharmony_ci  if (CheckPathCurrent(include, pathParts, isFile))
489370b324cSopenharmony_ci    return true;
490370b324cSopenharmony_ci  if (!Parent)
491370b324cSopenharmony_ci    return false;
492370b324cSopenharmony_ci  UStringVector pathParts2;
493370b324cSopenharmony_ci  pathParts2.Add(Name);
494370b324cSopenharmony_ci  pathParts2 += pathParts;
495370b324cSopenharmony_ci  return Parent->CheckPathToRoot_Change(include, pathParts2, isFile);
496370b324cSopenharmony_ci}
497370b324cSopenharmony_ci
498370b324cSopenharmony_ci/*
499370b324cSopenharmony_cibool CCensorNode::CheckPathToRoot(bool include, const UString &path, bool isFile) const
500370b324cSopenharmony_ci{
501370b324cSopenharmony_ci  UStringVector pathParts;
502370b324cSopenharmony_ci  SplitPathToParts(path, pathParts);
503370b324cSopenharmony_ci  return CheckPathToRoot(include, pathParts, isFile);
504370b324cSopenharmony_ci}
505370b324cSopenharmony_ci*/
506370b324cSopenharmony_ci
507370b324cSopenharmony_civoid CCensorNode::ExtendExclude(const CCensorNode &fromNodes)
508370b324cSopenharmony_ci{
509370b324cSopenharmony_ci  ExcludeItems += fromNodes.ExcludeItems;
510370b324cSopenharmony_ci  FOR_VECTOR (i, fromNodes.SubNodes)
511370b324cSopenharmony_ci  {
512370b324cSopenharmony_ci    const CCensorNode &node = fromNodes.SubNodes[i];
513370b324cSopenharmony_ci    Find_SubNode_Or_Add_New(node.Name).ExtendExclude(node);
514370b324cSopenharmony_ci  }
515370b324cSopenharmony_ci}
516370b324cSopenharmony_ci
517370b324cSopenharmony_ciint CCensor::FindPairForPrefix(const UString &prefix) const
518370b324cSopenharmony_ci{
519370b324cSopenharmony_ci  FOR_VECTOR (i, Pairs)
520370b324cSopenharmony_ci    if (CompareFileNames(Pairs[i].Prefix, prefix) == 0)
521370b324cSopenharmony_ci      return (int)i;
522370b324cSopenharmony_ci  return -1;
523370b324cSopenharmony_ci}
524370b324cSopenharmony_ci
525370b324cSopenharmony_ci#ifdef _WIN32
526370b324cSopenharmony_ci
527370b324cSopenharmony_cibool IsDriveColonName(const wchar_t *s)
528370b324cSopenharmony_ci{
529370b324cSopenharmony_ci  unsigned c = s[0];
530370b324cSopenharmony_ci  c |= 0x20;
531370b324cSopenharmony_ci  c -= 'a';
532370b324cSopenharmony_ci  return c <= (unsigned)('z' - 'a') && s[1] == ':' && s[2] == 0;
533370b324cSopenharmony_ci}
534370b324cSopenharmony_ci
535370b324cSopenharmony_ciunsigned GetNumPrefixParts_if_DrivePath(UStringVector &pathParts)
536370b324cSopenharmony_ci{
537370b324cSopenharmony_ci  if (pathParts.IsEmpty())
538370b324cSopenharmony_ci    return 0;
539370b324cSopenharmony_ci
540370b324cSopenharmony_ci  unsigned testIndex = 0;
541370b324cSopenharmony_ci  if (pathParts[0].IsEmpty())
542370b324cSopenharmony_ci  {
543370b324cSopenharmony_ci    if (pathParts.Size() < 4
544370b324cSopenharmony_ci        || !pathParts[1].IsEmpty()
545370b324cSopenharmony_ci        || pathParts[2] != L"?")
546370b324cSopenharmony_ci      return 0;
547370b324cSopenharmony_ci    testIndex = 3;
548370b324cSopenharmony_ci  }
549370b324cSopenharmony_ci  if (NWildcard::IsDriveColonName(pathParts[testIndex]))
550370b324cSopenharmony_ci    return testIndex + 1;
551370b324cSopenharmony_ci  return 0;
552370b324cSopenharmony_ci}
553370b324cSopenharmony_ci
554370b324cSopenharmony_ci#endif
555370b324cSopenharmony_ci
556370b324cSopenharmony_cistatic unsigned GetNumPrefixParts(const UStringVector &pathParts)
557370b324cSopenharmony_ci{
558370b324cSopenharmony_ci  if (pathParts.IsEmpty())
559370b324cSopenharmony_ci    return 0;
560370b324cSopenharmony_ci
561370b324cSopenharmony_ci  /* empty last part could be removed already from (pathParts),
562370b324cSopenharmony_ci     if there was tail path separator (slash) in original full path string. */
563370b324cSopenharmony_ci
564370b324cSopenharmony_ci  #ifdef _WIN32
565370b324cSopenharmony_ci
566370b324cSopenharmony_ci  if (IsDriveColonName(pathParts[0]))
567370b324cSopenharmony_ci    return 1;
568370b324cSopenharmony_ci  if (!pathParts[0].IsEmpty())
569370b324cSopenharmony_ci    return 0;
570370b324cSopenharmony_ci
571370b324cSopenharmony_ci  if (pathParts.Size() == 1)
572370b324cSopenharmony_ci    return 1;
573370b324cSopenharmony_ci  if (!pathParts[1].IsEmpty())
574370b324cSopenharmony_ci    return 1;
575370b324cSopenharmony_ci  if (pathParts.Size() == 2)
576370b324cSopenharmony_ci    return 2;
577370b324cSopenharmony_ci  if (pathParts[2] == L".")
578370b324cSopenharmony_ci    return 3;
579370b324cSopenharmony_ci
580370b324cSopenharmony_ci  unsigned networkParts = 2;
581370b324cSopenharmony_ci  if (pathParts[2] == L"?")
582370b324cSopenharmony_ci  {
583370b324cSopenharmony_ci    if (pathParts.Size() == 3)
584370b324cSopenharmony_ci      return 3;
585370b324cSopenharmony_ci    if (IsDriveColonName(pathParts[3]))
586370b324cSopenharmony_ci      return 4;
587370b324cSopenharmony_ci    if (!pathParts[3].IsEqualTo_Ascii_NoCase("UNC"))
588370b324cSopenharmony_ci      return 3;
589370b324cSopenharmony_ci    networkParts = 4;
590370b324cSopenharmony_ci  }
591370b324cSopenharmony_ci
592370b324cSopenharmony_ci  networkParts +=
593370b324cSopenharmony_ci      // 2; // server/share
594370b324cSopenharmony_ci      1; // server
595370b324cSopenharmony_ci  if (pathParts.Size() <= networkParts)
596370b324cSopenharmony_ci    return pathParts.Size();
597370b324cSopenharmony_ci  return networkParts;
598370b324cSopenharmony_ci
599370b324cSopenharmony_ci  #else
600370b324cSopenharmony_ci
601370b324cSopenharmony_ci  return pathParts[0].IsEmpty() ? 1 : 0;
602370b324cSopenharmony_ci
603370b324cSopenharmony_ci  #endif
604370b324cSopenharmony_ci}
605370b324cSopenharmony_ci
606370b324cSopenharmony_civoid CCensor::AddItem(ECensorPathMode pathMode, bool include, const UString &path,
607370b324cSopenharmony_ci    const CCensorPathProps &props)
608370b324cSopenharmony_ci{
609370b324cSopenharmony_ci  if (path.IsEmpty())
610370b324cSopenharmony_ci    throw "Empty file path";
611370b324cSopenharmony_ci
612370b324cSopenharmony_ci  UStringVector pathParts;
613370b324cSopenharmony_ci  SplitPathToParts(path, pathParts);
614370b324cSopenharmony_ci
615370b324cSopenharmony_ci  CCensorPathProps props2 = props;
616370b324cSopenharmony_ci
617370b324cSopenharmony_ci  bool forFile = true;
618370b324cSopenharmony_ci  bool forDir = true;
619370b324cSopenharmony_ci  const UString &back = pathParts.Back();
620370b324cSopenharmony_ci  if (back.IsEmpty())
621370b324cSopenharmony_ci  {
622370b324cSopenharmony_ci    // we have tail path separator. So it's directory.
623370b324cSopenharmony_ci    // we delete tail path separator here even for "\" and "c:\"
624370b324cSopenharmony_ci    forFile = false;
625370b324cSopenharmony_ci    pathParts.DeleteBack();
626370b324cSopenharmony_ci  }
627370b324cSopenharmony_ci  else
628370b324cSopenharmony_ci  {
629370b324cSopenharmony_ci    if (props.MarkMode == kMark_StrictFile
630370b324cSopenharmony_ci        || (props.MarkMode == kMark_StrictFile_IfWildcard
631370b324cSopenharmony_ci            && DoesNameContainWildcard(back)))
632370b324cSopenharmony_ci      forDir = false;
633370b324cSopenharmony_ci  }
634370b324cSopenharmony_ci
635370b324cSopenharmony_ci
636370b324cSopenharmony_ci  UString prefix;
637370b324cSopenharmony_ci
638370b324cSopenharmony_ci  int ignoreWildcardIndex = -1;
639370b324cSopenharmony_ci
640370b324cSopenharmony_ci  // #ifdef _WIN32
641370b324cSopenharmony_ci  // we ignore "?" wildcard in "\\?\" prefix.
642370b324cSopenharmony_ci  if (pathParts.Size() >= 3
643370b324cSopenharmony_ci      && pathParts[0].IsEmpty()
644370b324cSopenharmony_ci      && pathParts[1].IsEmpty()
645370b324cSopenharmony_ci      && pathParts[2] == L"?")
646370b324cSopenharmony_ci    ignoreWildcardIndex = 2;
647370b324cSopenharmony_ci  // #endif
648370b324cSopenharmony_ci
649370b324cSopenharmony_ci  if (pathMode != k_AbsPath)
650370b324cSopenharmony_ci  {
651370b324cSopenharmony_ci    // detection of the number of Skip Parts for prefix
652370b324cSopenharmony_ci    ignoreWildcardIndex = -1;
653370b324cSopenharmony_ci
654370b324cSopenharmony_ci    const unsigned numPrefixParts = GetNumPrefixParts(pathParts);
655370b324cSopenharmony_ci    unsigned numSkipParts = numPrefixParts;
656370b324cSopenharmony_ci
657370b324cSopenharmony_ci    if (pathMode != k_FullPath)
658370b324cSopenharmony_ci    {
659370b324cSopenharmony_ci      // if absolute path, then all parts before last part will be in prefix
660370b324cSopenharmony_ci      if (numPrefixParts != 0 && pathParts.Size() > numPrefixParts)
661370b324cSopenharmony_ci        numSkipParts = pathParts.Size() - 1;
662370b324cSopenharmony_ci    }
663370b324cSopenharmony_ci    {
664370b324cSopenharmony_ci      int dotsIndex = -1;
665370b324cSopenharmony_ci      for (unsigned i = numPrefixParts; i < pathParts.Size(); i++)
666370b324cSopenharmony_ci      {
667370b324cSopenharmony_ci        const UString &part = pathParts[i];
668370b324cSopenharmony_ci        if (part == L".." || part == L".")
669370b324cSopenharmony_ci          dotsIndex = (int)i;
670370b324cSopenharmony_ci      }
671370b324cSopenharmony_ci
672370b324cSopenharmony_ci      if (dotsIndex >= 0)
673370b324cSopenharmony_ci      {
674370b324cSopenharmony_ci        if (dotsIndex == (int)pathParts.Size() - 1)
675370b324cSopenharmony_ci          numSkipParts = pathParts.Size();
676370b324cSopenharmony_ci        else
677370b324cSopenharmony_ci          numSkipParts = pathParts.Size() - 1;
678370b324cSopenharmony_ci      }
679370b324cSopenharmony_ci    }
680370b324cSopenharmony_ci
681370b324cSopenharmony_ci    // we split (pathParts) to (prefix) and (pathParts).
682370b324cSopenharmony_ci    for (unsigned i = 0; i < numSkipParts; i++)
683370b324cSopenharmony_ci    {
684370b324cSopenharmony_ci      {
685370b324cSopenharmony_ci        const UString &front = pathParts.Front();
686370b324cSopenharmony_ci        // WIN32 doesn't support wildcards in file names
687370b324cSopenharmony_ci        if (props.WildcardMatching)
688370b324cSopenharmony_ci          if (i >= numPrefixParts && DoesNameContainWildcard(front))
689370b324cSopenharmony_ci            break;
690370b324cSopenharmony_ci        prefix += front;
691370b324cSopenharmony_ci        prefix.Add_PathSepar();
692370b324cSopenharmony_ci      }
693370b324cSopenharmony_ci      pathParts.Delete(0);
694370b324cSopenharmony_ci    }
695370b324cSopenharmony_ci  }
696370b324cSopenharmony_ci
697370b324cSopenharmony_ci  int index = FindPairForPrefix(prefix);
698370b324cSopenharmony_ci  if (index < 0)
699370b324cSopenharmony_ci  {
700370b324cSopenharmony_ci    index = (int)Pairs.Size();
701370b324cSopenharmony_ci    Pairs.AddNew().Prefix = prefix;
702370b324cSopenharmony_ci  }
703370b324cSopenharmony_ci
704370b324cSopenharmony_ci  if (pathMode != k_AbsPath)
705370b324cSopenharmony_ci  {
706370b324cSopenharmony_ci    if (pathParts.IsEmpty() || (pathParts.Size() == 1 && pathParts[0].IsEmpty()))
707370b324cSopenharmony_ci    {
708370b324cSopenharmony_ci      // we create universal item, if we skip all parts as prefix (like \ or L:\ )
709370b324cSopenharmony_ci      pathParts.Clear();
710370b324cSopenharmony_ci      pathParts.Add(UString("*"));
711370b324cSopenharmony_ci      forFile = true;
712370b324cSopenharmony_ci      forDir = true;
713370b324cSopenharmony_ci      props2.WildcardMatching = true;
714370b324cSopenharmony_ci      props2.Recursive = false;
715370b324cSopenharmony_ci    }
716370b324cSopenharmony_ci  }
717370b324cSopenharmony_ci
718370b324cSopenharmony_ci  /*
719370b324cSopenharmony_ci  // not possible now
720370b324cSopenharmony_ci  if (!forDir && !forFile)
721370b324cSopenharmony_ci  {
722370b324cSopenharmony_ci    UString s ("file path was blocked for files and directories: ");
723370b324cSopenharmony_ci    s += path;
724370b324cSopenharmony_ci    throw s;
725370b324cSopenharmony_ci    // return; // for debug : ignore item (don't create Item)
726370b324cSopenharmony_ci  }
727370b324cSopenharmony_ci  */
728370b324cSopenharmony_ci
729370b324cSopenharmony_ci  CItem item;
730370b324cSopenharmony_ci  item.PathParts = pathParts;
731370b324cSopenharmony_ci  item.ForDir = forDir;
732370b324cSopenharmony_ci  item.ForFile = forFile;
733370b324cSopenharmony_ci  item.Recursive = props2.Recursive;
734370b324cSopenharmony_ci  item.WildcardMatching = props2.WildcardMatching;
735370b324cSopenharmony_ci  Pairs[(unsigned)index].Head.AddItem(include, item, ignoreWildcardIndex);
736370b324cSopenharmony_ci}
737370b324cSopenharmony_ci
738370b324cSopenharmony_ci/*
739370b324cSopenharmony_cibool CCensor::CheckPath(bool isAltStream, const UString &path, bool isFile) const
740370b324cSopenharmony_ci{
741370b324cSopenharmony_ci  bool finded = false;
742370b324cSopenharmony_ci  FOR_VECTOR (i, Pairs)
743370b324cSopenharmony_ci  {
744370b324cSopenharmony_ci    bool include;
745370b324cSopenharmony_ci    if (Pairs[i].Head.CheckPath2(isAltStream, path, isFile, include))
746370b324cSopenharmony_ci    {
747370b324cSopenharmony_ci      if (!include)
748370b324cSopenharmony_ci        return false;
749370b324cSopenharmony_ci      finded = true;
750370b324cSopenharmony_ci    }
751370b324cSopenharmony_ci  }
752370b324cSopenharmony_ci  return finded;
753370b324cSopenharmony_ci}
754370b324cSopenharmony_ci*/
755370b324cSopenharmony_ci
756370b324cSopenharmony_civoid CCensor::ExtendExclude()
757370b324cSopenharmony_ci{
758370b324cSopenharmony_ci  unsigned i;
759370b324cSopenharmony_ci  for (i = 0; i < Pairs.Size(); i++)
760370b324cSopenharmony_ci    if (Pairs[i].Prefix.IsEmpty())
761370b324cSopenharmony_ci      break;
762370b324cSopenharmony_ci  if (i == Pairs.Size())
763370b324cSopenharmony_ci    return;
764370b324cSopenharmony_ci  unsigned index = i;
765370b324cSopenharmony_ci  for (i = 0; i < Pairs.Size(); i++)
766370b324cSopenharmony_ci    if (index != i)
767370b324cSopenharmony_ci      Pairs[i].Head.ExtendExclude(Pairs[index].Head);
768370b324cSopenharmony_ci}
769370b324cSopenharmony_ci
770370b324cSopenharmony_civoid CCensor::AddPathsToCensor(ECensorPathMode censorPathMode)
771370b324cSopenharmony_ci{
772370b324cSopenharmony_ci  FOR_VECTOR(i, CensorPaths)
773370b324cSopenharmony_ci  {
774370b324cSopenharmony_ci    const CCensorPath &cp = CensorPaths[i];
775370b324cSopenharmony_ci    AddItem(censorPathMode, cp.Include, cp.Path, cp.Props);
776370b324cSopenharmony_ci  }
777370b324cSopenharmony_ci  CensorPaths.Clear();
778370b324cSopenharmony_ci}
779370b324cSopenharmony_ci
780370b324cSopenharmony_civoid CCensor::AddPreItem(bool include, const UString &path, const CCensorPathProps &props)
781370b324cSopenharmony_ci{
782370b324cSopenharmony_ci  CCensorPath &cp = CensorPaths.AddNew();
783370b324cSopenharmony_ci  cp.Path = path;
784370b324cSopenharmony_ci  cp.Include = include;
785370b324cSopenharmony_ci  cp.Props = props;
786370b324cSopenharmony_ci}
787370b324cSopenharmony_ci
788370b324cSopenharmony_ci}
789