Merge pull request #4011 from fritsch/vdpau-settings
[vuplus_xbmc] / lib / UnrarXLib / archive.cpp
1 #include "rar.hpp"
2
3 #ifndef SHELL_EXT
4 #include "arccmt.cpp"
5 #endif
6
7
8 Archive::Archive(RAROptions *InitCmd)
9 {
10   Cmd=InitCmd==NULL ? &DummyCmd:InitCmd;
11   OpenShared=Cmd->OpenShared;
12   OldFormat=false;
13   Solid=false;
14   Volume=false;
15   MainComment=false;
16   Locked=false;
17   Signed=false;
18   NotFirstVolume=false;
19   SFXSize=0;
20   LatestTime.Reset();
21   Protected=false;
22   Encrypted=false;
23   BrokenFileHeader=false;
24   LastReadBlock=0;
25
26   CurBlockPos=0;
27   NextBlockPos=0;
28
29   RecoveryPos=SIZEOF_MARKHEAD;
30   RecoverySectors=-1;
31
32   memset(&NewMhd,0,sizeof(NewMhd));
33   NewMhd.HeadType=MAIN_HEAD;
34   NewMhd.HeadSize=SIZEOF_NEWMHD;
35   HeaderCRC=0;
36   VolWrite=0;
37   AddingFilesSize=0;
38   AddingHeadersSize=0;
39 #if !defined(SHELL_EXT) && !defined(NOCRYPT)
40   *HeadersSalt=0;
41   *SubDataSalt=0;
42 #endif
43   *FirstVolumeName=0;
44   *FirstVolumeNameW=0;
45
46   Splitting=false;
47   NewArchive=false;
48
49   SilentOpen=false;
50 }
51
52
53 #ifndef SHELL_EXT
54 void Archive::CheckArc(bool EnableBroken)
55 {
56   if (!IsArchive(EnableBroken))
57   {
58     Log(FileName,St(MBadArc),FileName);
59     ErrHandler.Exit(FATAL_ERROR);
60   }
61 }
62 #endif
63
64
65 #if !defined(SHELL_EXT) && !defined(SFX_MODULE)
66 void Archive::CheckOpen(char *Name,wchar *NameW)
67 {
68   TOpen(Name,NameW);
69   CheckArc(false);
70 }
71 #endif
72
73
74 bool Archive::WCheckOpen(char *Name,wchar *NameW)
75 {
76   if (!WOpen(Name,NameW))
77     return(false);
78   if (!IsArchive(false))
79   {
80 #ifndef SHELL_EXT
81     Log(FileName,St(MNotRAR),FileName);
82 #endif
83     Close();
84     return(false);
85   }
86   return(true);
87 }
88
89
90 bool Archive::IsSignature(byte *D)
91 {
92   bool Valid=false;
93   if (D[0]==0x52)
94   {
95 #ifndef SFX_MODULE
96     if (D[1]==0x45 && D[2]==0x7e && D[3]==0x5e)
97     {
98       OldFormat=true;
99       Valid=true;
100     }
101     else
102 #endif
103     {
104       if (D[1]==0x61 && D[2]==0x72 && D[3]==0x21 && D[4]==0x1a && D[5]==0x07 && D[6]==0x00)
105       {
106         OldFormat=false;
107         Valid=true;
108       }
109     }
110   }
111   return(Valid);
112 }
113
114
115 bool Archive::IsArchive(bool EnableBroken)
116 {
117   Encrypted=false;
118 #ifndef SFX_MODULE
119   if (IsDevice())
120   {
121 #ifndef SHELL_EXT
122     Log(FileName,St(MInvalidName),FileName);
123 #endif
124     return(false);
125   }
126 #endif
127   if (Read(MarkHead.Mark,SIZEOF_MARKHEAD)!=SIZEOF_MARKHEAD)
128     return(false);
129     
130   SFXSize=0;
131   if (IsSignature(MarkHead.Mark))
132   {
133     if (OldFormat)
134       Seek(0,SEEK_SET);
135   }
136   else
137   {
138     Array<char> Buffer(0x80000);
139     long CurPos=int64to32(Tell());
140     int ReadSize=Read(&Buffer[0],Buffer.Size()-16);
141     for (int I=0;I<ReadSize;I++)
142       if (Buffer[I]==0x52 && IsSignature((byte *)&Buffer[I]))
143       {
144         if (OldFormat && I>0 && CurPos<28 && ReadSize>31)
145         {
146           char *D=&Buffer[28-CurPos];
147           if (D[0]!=0x52 || D[1]!=0x53 || D[2]!=0x46 || D[3]!=0x58)
148             continue;
149         }
150         SFXSize=CurPos+I;
151         Seek(SFXSize,SEEK_SET);
152         if (!OldFormat)
153           Read(MarkHead.Mark,SIZEOF_MARKHEAD);
154         break;
155       }
156     if (SFXSize==0)
157       return(false);
158   }
159   ReadHeader();
160   SeekToNext();
161 #ifndef SFX_MODULE
162   if (OldFormat)
163   {
164     NewMhd.Flags=OldMhd.Flags & 0x3f;
165     NewMhd.HeadSize=OldMhd.HeadSize;
166   }
167   else
168 #endif
169   {
170     if (HeaderCRC!=NewMhd.HeadCRC)
171     {
172 #ifndef SHELL_EXT
173       Log(FileName,St(MLogMainHead));
174 #endif
175       Alarm();
176       if (!EnableBroken)
177         return(false);
178     }
179   }
180   Volume=(NewMhd.Flags & MHD_VOLUME);
181   Solid=(NewMhd.Flags & MHD_SOLID)!=0;
182   MainComment=(NewMhd.Flags & MHD_COMMENT)!=0;
183   Locked=(NewMhd.Flags & MHD_LOCK)!=0;
184   Signed=(NewMhd.PosAV!=0);
185   Protected=(NewMhd.Flags & MHD_PROTECT)!=0;
186   Encrypted=(NewMhd.Flags & MHD_PASSWORD)!=0;
187
188 #ifdef RARDLL
189   SilentOpen=true;
190 #endif
191   if (!SilentOpen || !Encrypted)
192   {
193     SaveFilePos SavePos(*this);
194     Int64 SaveCurBlockPos=CurBlockPos,SaveNextBlockPos=NextBlockPos;
195
196     NotFirstVolume=false;
197     while (ReadHeader())
198     {
199       int HeaderType=GetHeaderType();
200       if (HeaderType==NEWSUB_HEAD)
201       {
202         if (SubHead.CmpName(SUBHEAD_TYPE_CMT))
203           MainComment=true;
204         if ((SubHead.Flags & LHD_SPLIT_BEFORE) ||
205             (Volume && (NewMhd.Flags & MHD_FIRSTVOLUME)==0))
206           NotFirstVolume=true;
207       }
208       else
209       {
210         if ((HeaderType==FILE_HEAD && ((NewLhd.Flags & LHD_SPLIT_BEFORE)!=0)) ||
211             (Volume && NewLhd.UnpVer>=29 && (NewMhd.Flags & MHD_FIRSTVOLUME)==0))
212           NotFirstVolume=true;
213         break;
214       }
215       SeekToNext();
216     }
217     CurBlockPos=SaveCurBlockPos;
218     NextBlockPos=SaveNextBlockPos;
219   }
220   return(true);
221 }
222
223
224
225
226 void Archive::SeekToNext()
227 {
228   Seek(NextBlockPos,SEEK_SET);
229 }
230
231
232 #ifndef SFX_MODULE
233 int Archive::GetRecoverySize(bool Required)
234 {
235   if (!Protected)
236     return(0);
237   if (RecoverySectors!=-1 || !Required)
238     return(RecoverySectors);
239   SaveFilePos SavePos(*this);
240   Seek(SFXSize,SEEK_SET);
241   SearchSubBlock(SUBHEAD_TYPE_RR);
242   return(RecoverySectors);
243 }
244 #endif
245
246