• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Common/Wildcard.cpp
2 
3 #include "StdAfx.h"
4 
5 #include "Wildcard.h"
6 
7 extern
8 bool g_CaseSensitive;
9 bool g_CaseSensitive =
10   #ifdef _WIN32
11     false;
12   #elif defined (__APPLE__)
13     #ifdef TARGET_OS_IPHONE
14       true;
15     #else
16       false;
17     #endif
18   #else
19     true;
20   #endif
21 
22 
IsPath1PrefixedByPath2(const wchar_t * s1,const wchar_t * s2)23 bool IsPath1PrefixedByPath2(const wchar_t *s1, const wchar_t *s2)
24 {
25   if (g_CaseSensitive)
26     return IsString1PrefixedByString2(s1, s2);
27   return IsString1PrefixedByString2_NoCase(s1, s2);
28 }
29 
30 // #include <stdio.h>
31 
32 /*
33 static int MyStringCompare_PathLinux(const wchar_t *s1, const wchar_t *s2) throw()
34 {
35   for (;;)
36   {
37     wchar_t c1 = *s1++;
38     wchar_t c2 = *s2++;
39     if (c1 != c2)
40     {
41       if (c1 == 0) return -1;
42       if (c2 == 0) return 1;
43       if (c1 == '/') c1 = 0;
44       if (c2 == '/') c2 = 0;
45       if (c1 < c2) return -1;
46       if (c1 > c2) return 1;
47       continue;
48     }
49     if (c1 == 0) return 0;
50   }
51 }
52 */
53 
MyStringCompare_Path(const wchar_t * s1,const wchar_t * s2)54 static int MyStringCompare_Path(const wchar_t *s1, const wchar_t *s2) throw()
55 {
56   for (;;)
57   {
58     wchar_t c1 = *s1++;
59     wchar_t c2 = *s2++;
60     if (c1 != c2)
61     {
62       if (c1 == 0) return -1;
63       if (c2 == 0) return 1;
64       if (IS_PATH_SEPAR(c1)) c1 = 0;
65       if (IS_PATH_SEPAR(c2)) c2 = 0;
66       if (c1 < c2) return -1;
67       if (c1 > c2) return 1;
68       continue;
69     }
70     if (c1 == 0) return 0;
71   }
72 }
73 
MyStringCompareNoCase_Path(const wchar_t * s1,const wchar_t * s2)74 static int MyStringCompareNoCase_Path(const wchar_t *s1, const wchar_t *s2) throw()
75 {
76   for (;;)
77   {
78     wchar_t c1 = *s1++;
79     wchar_t c2 = *s2++;
80     if (c1 != c2)
81     {
82       if (c1 == 0) return -1;
83       if (c2 == 0) return 1;
84       if (IS_PATH_SEPAR(c1)) c1 = 0;
85       if (IS_PATH_SEPAR(c2)) c2 = 0;
86       c1 = MyCharUpper(c1);
87       c2 = MyCharUpper(c2);
88       if (c1 < c2) return -1;
89       if (c1 > c2) return 1;
90       continue;
91     }
92     if (c1 == 0) return 0;
93   }
94 }
95 
CompareFileNames(const wchar_t * s1,const wchar_t * s2)96 int CompareFileNames(const wchar_t *s1, const wchar_t *s2) STRING_UNICODE_THROW
97 {
98   /*
99   printf("\nCompareFileNames");
100   printf("\n S1: %ls", s1);
101   printf("\n S2: %ls", s2);
102   printf("\n");
103   */
104   // 21.07 : we parse PATH_SEPARATOR so: 0 < PATH_SEPARATOR < 1
105   if (g_CaseSensitive)
106     return MyStringCompare_Path(s1, s2);
107   return MyStringCompareNoCase_Path(s1, s2);
108 }
109 
110 #ifndef USE_UNICODE_FSTRING
CompareFileNames(const char * s1,const char * s2)111 int CompareFileNames(const char *s1, const char *s2)
112 {
113   const UString u1 = fs2us(s1);
114   const UString u2 = fs2us(s2);
115   return CompareFileNames(u1, u2);
116 }
117 #endif
118 
119 // -----------------------------------------
120 // this function compares name with mask
121 // ? - any char
122 // * - any char or empty
123 
EnhancedMaskTest(const wchar_t * mask,const wchar_t * name)124 static bool EnhancedMaskTest(const wchar_t *mask, const wchar_t *name)
125 {
126   for (;;)
127   {
128     const wchar_t m = *mask;
129     const wchar_t c = *name;
130     if (m == 0)
131       return (c == 0);
132     if (m == '*')
133     {
134       if (EnhancedMaskTest(mask + 1, name))
135         return true;
136       if (c == 0)
137         return false;
138     }
139     else
140     {
141       if (m == '?')
142       {
143         if (c == 0)
144           return false;
145       }
146       else if (m != c)
147         if (g_CaseSensitive || MyCharUpper(m) != MyCharUpper(c))
148           return false;
149       mask++;
150     }
151     name++;
152   }
153 }
154 
155 // --------------------------------------------------
156 // Splits path to strings
157 
SplitPathToParts(const UString & path,UStringVector & pathParts)158 void SplitPathToParts(const UString &path, UStringVector &pathParts)
159 {
160   pathParts.Clear();
161   unsigned len = path.Len();
162   if (len == 0)
163     return;
164   UString name;
165   unsigned prev = 0;
166   for (unsigned i = 0; i < len; i++)
167     if (IsPathSepar(path[i]))
168     {
169       name.SetFrom(path.Ptr(prev), i - prev);
170       pathParts.Add(name);
171       prev = i + 1;
172     }
173   name.SetFrom(path.Ptr(prev), len - prev);
174   pathParts.Add(name);
175 }
176 
SplitPathToParts_2(const UString & path,UString & dirPrefix,UString & name)177 void SplitPathToParts_2(const UString &path, UString &dirPrefix, UString &name)
178 {
179   const wchar_t *start = path;
180   const wchar_t *p = start + path.Len();
181   for (; p != start; p--)
182     if (IsPathSepar(*(p - 1)))
183       break;
184   dirPrefix.SetFrom(path, (unsigned)(p - start));
185   name = p;
186 }
187 
SplitPathToParts_Smart(const UString & path,UString & dirPrefix,UString & name)188 void SplitPathToParts_Smart(const UString &path, UString &dirPrefix, UString &name)
189 {
190   const wchar_t *start = path;
191   const wchar_t *p = start + path.Len();
192   if (p != start)
193   {
194     if (IsPathSepar(*(p - 1)))
195       p--;
196     for (; p != start; p--)
197       if (IsPathSepar(*(p - 1)))
198         break;
199   }
200   dirPrefix.SetFrom(path, (unsigned)(p - start));
201   name = p;
202 }
203 
204 /*
205 UString ExtractDirPrefixFromPath(const UString &path)
206 {
207   return path.Left(path.ReverseFind_PathSepar() + 1));
208 }
209 */
210 
ExtractFileNameFromPath(const UString & path)211 UString ExtractFileNameFromPath(const UString &path)
212 {
213   return UString(path.Ptr((unsigned)(path.ReverseFind_PathSepar() + 1)));
214 }
215 
216 
DoesWildcardMatchName(const UString & mask,const UString & name)217 bool DoesWildcardMatchName(const UString &mask, const UString &name)
218 {
219   return EnhancedMaskTest(mask, name);
220 }
221 
DoesNameContainWildcard(const UString & path)222 bool DoesNameContainWildcard(const UString &path)
223 {
224   for (unsigned i = 0; i < path.Len(); i++)
225   {
226     wchar_t c = path[i];
227     if (c == '*' || c == '?')
228       return true;
229   }
230   return false;
231 }
232 
233 
234 // ----------------------------------------------------------'
235 // NWildcard
236 
237 namespace NWildcard {
238 
239 /*
240 
241 M = MaskParts.Size();
242 N = TestNameParts.Size();
243 
244                            File                          Dir
245 ForFile     rec   M<=N  [N-M, N)                          -
246 !ForDir  nonrec   M=N   [0, M)                            -
247 
248 ForDir      rec   M<N   [0, M) ... [N-M-1, N-1)  same as ForBoth-File
249 !ForFile nonrec         [0, M)                   same as ForBoth-File
250 
251 ForFile     rec   m<=N  [0, M) ... [N-M, N)      same as ForBoth-File
252 ForDir   nonrec         [0, M)                   same as ForBoth-File
253 
254 */
255 
AreAllAllowed() const256 bool CItem::AreAllAllowed() const
257 {
258   return ForFile && ForDir && WildcardMatching && PathParts.Size() == 1 && PathParts.Front() == L"*";
259 }
260 
CheckPath(const UStringVector & pathParts,bool isFile) const261 bool CItem::CheckPath(const UStringVector &pathParts, bool isFile) const
262 {
263   if (!isFile && !ForDir)
264     return false;
265 
266   /*
267   if (PathParts.IsEmpty())
268   {
269     // PathParts.IsEmpty() means all items (universal wildcard)
270     if (!isFile)
271       return true;
272     if (pathParts.Size() <= 1)
273       return ForFile;
274     return (ForDir || Recursive && ForFile);
275   }
276   */
277 
278   int delta = (int)pathParts.Size() - (int)PathParts.Size();
279   if (delta < 0)
280     return false;
281   int start = 0;
282   int finish = 0;
283 
284   if (isFile)
285   {
286     if (!ForDir)
287     {
288       if (Recursive)
289         start = delta;
290       else if (delta !=0)
291         return false;
292     }
293     if (!ForFile && delta == 0)
294       return false;
295   }
296 
297   if (Recursive)
298   {
299     finish = delta;
300     if (isFile && !ForFile)
301       finish = delta - 1;
302   }
303 
304   for (int d = start; d <= finish; d++)
305   {
306     unsigned i;
307     for (i = 0; i < PathParts.Size(); i++)
308     {
309       if (WildcardMatching)
310       {
311         if (!DoesWildcardMatchName(PathParts[i], pathParts[i + (unsigned)d]))
312           break;
313       }
314       else
315       {
316         if (CompareFileNames(PathParts[i], pathParts[i + (unsigned)d]) != 0)
317           break;
318       }
319     }
320     if (i == PathParts.Size())
321       return true;
322   }
323   return false;
324 }
325 
AreAllAllowed() const326 bool CCensorNode::AreAllAllowed() const
327 {
328   if (!Name.IsEmpty() ||
329       !SubNodes.IsEmpty() ||
330       !ExcludeItems.IsEmpty() ||
331       IncludeItems.Size() != 1)
332     return false;
333   return IncludeItems.Front().AreAllAllowed();
334 }
335 
FindSubNode(const UString & name) const336 int CCensorNode::FindSubNode(const UString &name) const
337 {
338   FOR_VECTOR (i, SubNodes)
339     if (CompareFileNames(SubNodes[i].Name, name) == 0)
340       return (int)i;
341   return -1;
342 }
343 
AddItemSimple(bool include,CItem & item)344 void CCensorNode::AddItemSimple(bool include, CItem &item)
345 {
346   CObjectVector<CItem> &items = include ? IncludeItems : ExcludeItems;
347   items.Add(item);
348 }
349 
AddItem(bool include,CItem & item,int ignoreWildcardIndex)350 void CCensorNode::AddItem(bool include, CItem &item, int ignoreWildcardIndex)
351 {
352   if (item.PathParts.Size() <= 1)
353   {
354     if (item.PathParts.Size() != 0 && item.WildcardMatching)
355     {
356       if (!DoesNameContainWildcard(item.PathParts.Front()))
357         item.WildcardMatching = false;
358     }
359     AddItemSimple(include, item);
360     return;
361   }
362 
363   const UString &front = item.PathParts.Front();
364 
365   // WIN32 doesn't support wildcards in file names
366   if (item.WildcardMatching
367       && ignoreWildcardIndex != 0
368       && DoesNameContainWildcard(front))
369   {
370     AddItemSimple(include, item);
371     return;
372   }
373   CCensorNode &subNode = Find_SubNode_Or_Add_New(front);
374   item.PathParts.Delete(0);
375   subNode.AddItem(include, item, ignoreWildcardIndex - 1);
376 }
377 
378 /*
379 void CCensorNode::AddItem(bool include, const UString &path, const CCensorPathProps &props)
380 {
381   CItem item;
382   SplitPathToParts(path, item.PathParts);
383   item.Recursive = props.Recursive;
384   item.ForFile = props.ForFile;
385   item.ForDir = props.ForDir;
386   item.WildcardMatching = props.WildcardMatching;
387   AddItem(include, item);
388 }
389 */
390 
NeedCheckSubDirs() const391 bool CCensorNode::NeedCheckSubDirs() const
392 {
393   FOR_VECTOR (i, IncludeItems)
394   {
395     const CItem &item = IncludeItems[i];
396     if (item.Recursive || item.PathParts.Size() > 1)
397       return true;
398   }
399   return false;
400 }
401 
AreThereIncludeItems() const402 bool CCensorNode::AreThereIncludeItems() const
403 {
404   if (IncludeItems.Size() > 0)
405     return true;
406   FOR_VECTOR (i, SubNodes)
407     if (SubNodes[i].AreThereIncludeItems())
408       return true;
409   return false;
410 }
411 
CheckPathCurrent(bool include,const UStringVector & pathParts,bool isFile) const412 bool CCensorNode::CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const
413 {
414   const CObjectVector<CItem> &items = include ? IncludeItems : ExcludeItems;
415   FOR_VECTOR (i, items)
416     if (items[i].CheckPath(pathParts, isFile))
417       return true;
418   return false;
419 }
420 
CheckPathVect(const UStringVector & pathParts,bool isFile,bool & include) const421 bool CCensorNode::CheckPathVect(const UStringVector &pathParts, bool isFile, bool &include) const
422 {
423   if (CheckPathCurrent(false, pathParts, isFile))
424   {
425     include = false;
426     return true;
427   }
428   if (pathParts.Size() > 1)
429   {
430     int index = FindSubNode(pathParts.Front());
431     if (index >= 0)
432     {
433       UStringVector pathParts2 = pathParts;
434       pathParts2.Delete(0);
435       if (SubNodes[(unsigned)index].CheckPathVect(pathParts2, isFile, include))
436         return true;
437     }
438   }
439   bool finded = CheckPathCurrent(true, pathParts, isFile);
440   include = finded; // if (!finded), then (true) is allowed also
441   return finded;
442 }
443 
444 /*
445 bool CCensorNode::CheckPath2(bool isAltStream, const UString &path, bool isFile, bool &include) const
446 {
447   UStringVector pathParts;
448   SplitPathToParts(path, pathParts);
449   if (CheckPathVect(pathParts, isFile, include))
450   {
451     if (!include || !isAltStream)
452       return true;
453   }
454   if (isAltStream && !pathParts.IsEmpty())
455   {
456     UString &back = pathParts.Back();
457     int pos = back.Find(L':');
458     if (pos > 0)
459     {
460       back.DeleteFrom(pos);
461       return CheckPathVect(pathParts, isFile, include);
462     }
463   }
464   return false;
465 }
466 
467 bool CCensorNode::CheckPath(bool isAltStream, const UString &path, bool isFile) const
468 {
469   bool include;
470   if (CheckPath2(isAltStream, path, isFile, include))
471     return include;
472   return false;
473 }
474 */
475 
CheckPathToRoot_Change(bool include,UStringVector & pathParts,bool isFile) const476 bool CCensorNode::CheckPathToRoot_Change(bool include, UStringVector &pathParts, bool isFile) const
477 {
478   if (CheckPathCurrent(include, pathParts, isFile))
479     return true;
480   if (!Parent)
481     return false;
482   pathParts.Insert(0, Name);
483   return Parent->CheckPathToRoot_Change(include, pathParts, isFile);
484 }
485 
CheckPathToRoot(bool include,const UStringVector & pathParts,bool isFile) const486 bool CCensorNode::CheckPathToRoot(bool include, const UStringVector &pathParts, bool isFile) const
487 {
488   if (CheckPathCurrent(include, pathParts, isFile))
489     return true;
490   if (!Parent)
491     return false;
492   UStringVector pathParts2;
493   pathParts2.Add(Name);
494   pathParts2 += pathParts;
495   return Parent->CheckPathToRoot_Change(include, pathParts2, isFile);
496 }
497 
498 /*
499 bool CCensorNode::CheckPathToRoot(bool include, const UString &path, bool isFile) const
500 {
501   UStringVector pathParts;
502   SplitPathToParts(path, pathParts);
503   return CheckPathToRoot(include, pathParts, isFile);
504 }
505 */
506 
ExtendExclude(const CCensorNode & fromNodes)507 void CCensorNode::ExtendExclude(const CCensorNode &fromNodes)
508 {
509   ExcludeItems += fromNodes.ExcludeItems;
510   FOR_VECTOR (i, fromNodes.SubNodes)
511   {
512     const CCensorNode &node = fromNodes.SubNodes[i];
513     Find_SubNode_Or_Add_New(node.Name).ExtendExclude(node);
514   }
515 }
516 
FindPairForPrefix(const UString & prefix) const517 int CCensor::FindPairForPrefix(const UString &prefix) const
518 {
519   FOR_VECTOR (i, Pairs)
520     if (CompareFileNames(Pairs[i].Prefix, prefix) == 0)
521       return (int)i;
522   return -1;
523 }
524 
525 #ifdef _WIN32
526 
IsDriveColonName(const wchar_t * s)527 bool IsDriveColonName(const wchar_t *s)
528 {
529   unsigned c = s[0];
530   c |= 0x20;
531   c -= 'a';
532   return c <= (unsigned)('z' - 'a') && s[1] == ':' && s[2] == 0;
533 }
534 
GetNumPrefixParts_if_DrivePath(UStringVector & pathParts)535 unsigned GetNumPrefixParts_if_DrivePath(UStringVector &pathParts)
536 {
537   if (pathParts.IsEmpty())
538     return 0;
539 
540   unsigned testIndex = 0;
541   if (pathParts[0].IsEmpty())
542   {
543     if (pathParts.Size() < 4
544         || !pathParts[1].IsEmpty()
545         || pathParts[2] != L"?")
546       return 0;
547     testIndex = 3;
548   }
549   if (NWildcard::IsDriveColonName(pathParts[testIndex]))
550     return testIndex + 1;
551   return 0;
552 }
553 
554 #endif
555 
GetNumPrefixParts(const UStringVector & pathParts)556 static unsigned GetNumPrefixParts(const UStringVector &pathParts)
557 {
558   if (pathParts.IsEmpty())
559     return 0;
560 
561   /* empty last part could be removed already from (pathParts),
562      if there was tail path separator (slash) in original full path string. */
563 
564   #ifdef _WIN32
565 
566   if (IsDriveColonName(pathParts[0]))
567     return 1;
568   if (!pathParts[0].IsEmpty())
569     return 0;
570 
571   if (pathParts.Size() == 1)
572     return 1;
573   if (!pathParts[1].IsEmpty())
574     return 1;
575   if (pathParts.Size() == 2)
576     return 2;
577   if (pathParts[2] == L".")
578     return 3;
579 
580   unsigned networkParts = 2;
581   if (pathParts[2] == L"?")
582   {
583     if (pathParts.Size() == 3)
584       return 3;
585     if (IsDriveColonName(pathParts[3]))
586       return 4;
587     if (!pathParts[3].IsEqualTo_Ascii_NoCase("UNC"))
588       return 3;
589     networkParts = 4;
590   }
591 
592   networkParts +=
593       // 2; // server/share
594       1; // server
595   if (pathParts.Size() <= networkParts)
596     return pathParts.Size();
597   return networkParts;
598 
599   #else
600 
601   return pathParts[0].IsEmpty() ? 1 : 0;
602 
603   #endif
604 }
605 
AddItem(ECensorPathMode pathMode,bool include,const UString & path,const CCensorPathProps & props)606 void CCensor::AddItem(ECensorPathMode pathMode, bool include, const UString &path,
607     const CCensorPathProps &props)
608 {
609   if (path.IsEmpty())
610     throw "Empty file path";
611 
612   UStringVector pathParts;
613   SplitPathToParts(path, pathParts);
614 
615   CCensorPathProps props2 = props;
616 
617   bool forFile = true;
618   bool forDir = true;
619   const UString &back = pathParts.Back();
620   if (back.IsEmpty())
621   {
622     // we have tail path separator. So it's directory.
623     // we delete tail path separator here even for "\" and "c:\"
624     forFile = false;
625     pathParts.DeleteBack();
626   }
627   else
628   {
629     if (props.MarkMode == kMark_StrictFile
630         || (props.MarkMode == kMark_StrictFile_IfWildcard
631             && DoesNameContainWildcard(back)))
632       forDir = false;
633   }
634 
635 
636   UString prefix;
637 
638   int ignoreWildcardIndex = -1;
639 
640   // #ifdef _WIN32
641   // we ignore "?" wildcard in "\\?\" prefix.
642   if (pathParts.Size() >= 3
643       && pathParts[0].IsEmpty()
644       && pathParts[1].IsEmpty()
645       && pathParts[2] == L"?")
646     ignoreWildcardIndex = 2;
647   // #endif
648 
649   if (pathMode != k_AbsPath)
650   {
651     // detection of the number of Skip Parts for prefix
652     ignoreWildcardIndex = -1;
653 
654     const unsigned numPrefixParts = GetNumPrefixParts(pathParts);
655     unsigned numSkipParts = numPrefixParts;
656 
657     if (pathMode != k_FullPath)
658     {
659       // if absolute path, then all parts before last part will be in prefix
660       if (numPrefixParts != 0 && pathParts.Size() > numPrefixParts)
661         numSkipParts = pathParts.Size() - 1;
662     }
663     {
664       int dotsIndex = -1;
665       for (unsigned i = numPrefixParts; i < pathParts.Size(); i++)
666       {
667         const UString &part = pathParts[i];
668         if (part == L".." || part == L".")
669           dotsIndex = (int)i;
670       }
671 
672       if (dotsIndex >= 0)
673       {
674         if (dotsIndex == (int)pathParts.Size() - 1)
675           numSkipParts = pathParts.Size();
676         else
677           numSkipParts = pathParts.Size() - 1;
678       }
679     }
680 
681     // we split (pathParts) to (prefix) and (pathParts).
682     for (unsigned i = 0; i < numSkipParts; i++)
683     {
684       {
685         const UString &front = pathParts.Front();
686         // WIN32 doesn't support wildcards in file names
687         if (props.WildcardMatching)
688           if (i >= numPrefixParts && DoesNameContainWildcard(front))
689             break;
690         prefix += front;
691         prefix.Add_PathSepar();
692       }
693       pathParts.Delete(0);
694     }
695   }
696 
697   int index = FindPairForPrefix(prefix);
698   if (index < 0)
699   {
700     index = (int)Pairs.Size();
701     Pairs.AddNew().Prefix = prefix;
702   }
703 
704   if (pathMode != k_AbsPath)
705   {
706     if (pathParts.IsEmpty() || (pathParts.Size() == 1 && pathParts[0].IsEmpty()))
707     {
708       // we create universal item, if we skip all parts as prefix (like \ or L:\ )
709       pathParts.Clear();
710       pathParts.Add(UString("*"));
711       forFile = true;
712       forDir = true;
713       props2.WildcardMatching = true;
714       props2.Recursive = false;
715     }
716   }
717 
718   /*
719   // not possible now
720   if (!forDir && !forFile)
721   {
722     UString s ("file path was blocked for files and directories: ");
723     s += path;
724     throw s;
725     // return; // for debug : ignore item (don't create Item)
726   }
727   */
728 
729   CItem item;
730   item.PathParts = pathParts;
731   item.ForDir = forDir;
732   item.ForFile = forFile;
733   item.Recursive = props2.Recursive;
734   item.WildcardMatching = props2.WildcardMatching;
735   Pairs[(unsigned)index].Head.AddItem(include, item, ignoreWildcardIndex);
736 }
737 
738 /*
739 bool CCensor::CheckPath(bool isAltStream, const UString &path, bool isFile) const
740 {
741   bool finded = false;
742   FOR_VECTOR (i, Pairs)
743   {
744     bool include;
745     if (Pairs[i].Head.CheckPath2(isAltStream, path, isFile, include))
746     {
747       if (!include)
748         return false;
749       finded = true;
750     }
751   }
752   return finded;
753 }
754 */
755 
ExtendExclude()756 void CCensor::ExtendExclude()
757 {
758   unsigned i;
759   for (i = 0; i < Pairs.Size(); i++)
760     if (Pairs[i].Prefix.IsEmpty())
761       break;
762   if (i == Pairs.Size())
763     return;
764   unsigned index = i;
765   for (i = 0; i < Pairs.Size(); i++)
766     if (index != i)
767       Pairs[i].Head.ExtendExclude(Pairs[index].Head);
768 }
769 
AddPathsToCensor(ECensorPathMode censorPathMode)770 void CCensor::AddPathsToCensor(ECensorPathMode censorPathMode)
771 {
772   FOR_VECTOR(i, CensorPaths)
773   {
774     const CCensorPath &cp = CensorPaths[i];
775     AddItem(censorPathMode, cp.Include, cp.Path, cp.Props);
776   }
777   CensorPaths.Clear();
778 }
779 
AddPreItem(bool include,const UString & path,const CCensorPathProps & props)780 void CCensor::AddPreItem(bool include, const UString &path, const CCensorPathProps &props)
781 {
782   CCensorPath &cp = CensorPaths.AddNew();
783   cp.Path = path;
784   cp.Include = include;
785   cp.Props = props;
786 }
787 
788 }
789