Merge pull request #4852 from FernetMenta/aefixes
[vuplus_xbmc] / lib / UnrarXLib / scantree.cpp
1 #include "rar.hpp"
2
3 ScanTree::ScanTree(StringList *FileMasks,int Recurse,bool GetLinks,int GetDirs)
4 {
5   ScanTree::FileMasks=FileMasks;
6   ScanTree::Recurse=Recurse;
7   ScanTree::GetLinks=GetLinks;
8   ScanTree::GetDirs=GetDirs;
9
10   SetAllMaskDepth=0;
11   *CurMask=0;
12   *CurMaskW=0;
13   memset(FindStack,0,sizeof(FindStack));
14   Depth=0;
15   Errors=0;
16   FastFindFile=false;
17   *ErrArcName=0;
18   Cmd=NULL;
19 }
20
21
22 ScanTree::~ScanTree()
23 {
24   for (int I=Depth;I>=0;I--)
25     if (FindStack[I]!=NULL)
26       delete FindStack[I];
27 }
28
29
30 int ScanTree::GetNext(FindData *FindData)
31 {
32   if (Depth<0)
33     return(SCAN_DONE);
34
35   int FindCode;
36   while (1)
37   {
38     if ((*CurMask==0 || (FastFindFile && Depth==0)) && !PrepareMasks())
39       return(SCAN_DONE);
40     FindCode=FindProc(FindData);
41     if (FindCode==SCAN_ERROR)
42     {
43       Errors++;
44       continue;
45     }
46     if (FindCode==SCAN_NEXT)
47       continue;
48     if (FindCode==SCAN_SUCCESS && FindData->IsDir && GetDirs==SCAN_SKIPDIRS)
49       continue;
50     if (FindCode==SCAN_DONE && PrepareMasks())
51       continue;
52     break;
53   }
54   return(FindCode);
55 }
56
57
58 bool ScanTree::PrepareMasks()
59 {
60   if (!FileMasks->GetString(CurMask,CurMaskW,sizeof(CurMask)))
61     return(false);
62 #ifdef _WIN_32
63   UnixSlashToDos(CurMask);
64 #endif
65   char *Name=PointToName(CurMask);
66   if (*Name==0)
67     strcat(CurMask,MASKALL);
68   if (Name[0]=='.' && (Name[1]==0 || (Name[1]=='.' && Name[2]==0)))
69   {
70     AddEndSlash(CurMask);
71     strcat(CurMask,MASKALL);
72   }
73   SpecPathLength=Name-CurMask;
74 //  if (SpecPathLength>1)
75 //    SpecPathLength--;
76
77   bool WideName=(*CurMaskW!=0);
78
79   if (WideName)
80   {
81     wchar *NameW=PointToName(CurMaskW);
82     if (*NameW==0)
83       strcatw(CurMaskW,MASKALLW);
84     if (NameW[0]=='.' && (NameW[1]==0 || (NameW[1]=='.' && NameW[2]==0)))
85     {
86       AddEndSlash(CurMaskW);
87       strcatw(CurMaskW,MASKALLW);
88     }
89     SpecPathLengthW=NameW-CurMaskW;
90   }
91   else
92   {
93     wchar WideMask[NM];
94     CharToWide(CurMask,WideMask);
95     SpecPathLengthW=PointToName(WideMask)-WideMask;
96   }
97   Depth=0;
98
99   strcpy(OrigCurMask,CurMask);
100   strcpyw(OrigCurMaskW,CurMaskW);
101
102   return(true);
103 }
104
105
106 int ScanTree::FindProc(FindData *FindData)
107 {
108   if (*CurMask==0)
109     return(SCAN_NEXT);
110   FastFindFile=false;
111   if (FindStack[Depth]==NULL)
112   {
113     bool Wildcards=IsWildcard(CurMask,CurMaskW);
114     bool FindCode=!Wildcards && FindFile::FastFind(CurMask,CurMaskW,FindData,GetLinks);
115     bool IsDir=FindCode && FindData->IsDir;
116     bool SearchAll=!IsDir && (Depth>0 || Recurse==RECURSE_ALWAYS || (Wildcards && Recurse==RECURSE_WILDCARDS));
117     if (Depth==0)
118       SearchAllInRoot=SearchAll;
119     if (SearchAll || Wildcards)
120     {
121       FindStack[Depth]=new FindFile;
122       char SearchMask[NM];
123       strcpy(SearchMask,CurMask);
124       if (SearchAll)
125         strcpy(PointToName(SearchMask),MASKALL);
126       FindStack[Depth]->SetMask(SearchMask);
127       if (*CurMaskW)
128       {
129         wchar SearchMaskW[NM];
130         strcpyw(SearchMaskW,CurMaskW);
131         if (SearchAll)
132           strcpyw(PointToName(SearchMaskW),MASKALLW);
133         FindStack[Depth]->SetMaskW(SearchMaskW);
134       }
135     }
136     else
137     {
138       FastFindFile=true;
139       if (!FindCode)
140       {
141         if (Cmd!=NULL && Cmd->ExclCheck(CurMask,true))
142           return(SCAN_NEXT);
143         ErrHandler.OpenErrorMsg(ErrArcName,CurMask);
144         return(FindData->Error ? SCAN_ERROR:SCAN_NEXT);
145       }
146     }
147   }
148
149   if (!FastFindFile && !FindStack[Depth]->Next(FindData,GetLinks))
150   {
151     bool Error=FindData->Error;
152
153 #ifdef _WIN_32
154     if (Error && strstr(CurMask,"System Volume Information\\")!=NULL)
155       Error=false;
156 #endif
157
158     if (Cmd!=NULL && Cmd->ExclCheck(CurMask,true))
159       Error=false;
160
161 #ifndef SILENT
162     if (Error)
163     {
164       Log(NULL,St(MScanError),CurMask);
165     }
166 #endif
167
168     char DirName[NM];
169     wchar DirNameW[NM];
170     *DirName=0;
171     *DirNameW=0;
172
173     delete FindStack[Depth];
174     FindStack[Depth--]=NULL;
175     while (Depth>=0 && FindStack[Depth]==NULL)
176       Depth--;
177     if (Depth < 0)
178     {
179       if (Error)
180         Errors++;
181       return(SCAN_DONE);
182     }
183     char *Slash=strrchrd(CurMask,CPATHDIVIDER);
184     if (Slash!=NULL)
185     {
186       char Mask[NM];
187       strcpy(Mask,Slash);
188       if (Depth<SetAllMaskDepth)
189         strcpy(Mask+1,PointToName(OrigCurMask));
190       *Slash=0;
191       strcpy(DirName,CurMask);
192       char *PrevSlash=strrchrd(CurMask,CPATHDIVIDER);
193       if (PrevSlash==NULL)
194         strcpy(CurMask,Mask+1);
195       else
196         strcpy(PrevSlash,Mask);
197     }
198
199     if (*CurMaskW!=0)
200     {
201       wchar *Slash=strrchrw(CurMaskW,CPATHDIVIDER);
202       if (Slash!=NULL)
203       {
204         wchar Mask[NM];
205         strcpyw(Mask,Slash);
206         *Slash=0;
207         strcpyw(DirNameW,CurMaskW);
208         wchar *PrevSlash=strrchrw(CurMaskW,CPATHDIVIDER);
209         if (PrevSlash==NULL)
210           strcpyw(CurMaskW,Mask+1);
211         else
212           strcpyw(PrevSlash,Mask);
213       }
214 #ifndef _WIN_CE
215       if (LowAscii(CurMaskW))
216         *CurMaskW=0;
217 #endif
218     }
219     if (GetDirs==SCAN_GETDIRSTWICE &&
220         FindFile::FastFind(DirName,DirNameW,FindData,GetLinks) && FindData->IsDir)
221       return(Error ? SCAN_ERROR:SCAN_SUCCESS);
222     return(Error ? SCAN_ERROR:SCAN_NEXT);
223   }
224
225   if (FindData->IsDir)
226   {
227     if (!FastFindFile && Depth==0 && !SearchAllInRoot)
228       return(GetDirs==SCAN_GETCURDIRS ? SCAN_SUCCESS:SCAN_NEXT);
229
230 //    if (GetDirs==SCAN_GETCURDIRS && Depth==0 && !SearchAllInRoot)
231 //      return(SCAN_SUCCESS);
232
233     char Mask[NM];
234     bool MaskAll=FastFindFile;
235
236     strcpy(Mask,MaskAll ? MASKALL:PointToName(CurMask));
237     strcpy(CurMask,FindData->Name);
238
239     if (strlen(CurMask)+strlen(Mask)+1>=NM || Depth>=MAXSCANDEPTH-1)
240     {
241 #ifndef SILENT
242       Log(NULL,"\n%s%c%s",CurMask,CPATHDIVIDER,Mask);
243       Log(NULL,St(MPathTooLong));
244 #endif
245       return(SCAN_ERROR);
246     }
247
248     AddEndSlash(CurMask);
249     strcat(CurMask,Mask);
250
251     if (*CurMaskW && *FindData->NameW==0)
252       CharToWide(FindData->Name,FindData->NameW);
253     if (*FindData->NameW!=0)
254     {
255       wchar Mask[NM];
256       if (FastFindFile)
257         strcpyw(Mask,MASKALLW);
258       else
259         if (*CurMaskW)
260           strcpyw(Mask,PointToName(CurMaskW));
261         else
262           CharToWide(PointToName(CurMask),Mask);
263       strcpyw(CurMaskW,FindData->NameW);
264       AddEndSlash(CurMaskW);
265       strcatw(CurMaskW,Mask);
266     }
267     Depth++;
268     if (MaskAll)
269       SetAllMaskDepth=Depth;
270   }
271   if (!FastFindFile && !CmpName(CurMask,FindData->Name,MATCH_NAMES))
272     return(SCAN_NEXT);
273   return(SCAN_SUCCESS);
274 }