1 #include "rar.hpp"
2 
3 #ifndef SHELL_EXT
4 #include "arccmt.cpp"
5 #endif
6 
7 
Archive(RAROptions * InitCmd)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   FailedHeaderDecryption=false;
24   BrokenFileHeader=false;
25   LastReadBlock=0;
26 
27   CurBlockPos=0;
28   NextBlockPos=0;
29 
30   RecoveryPos=SIZEOF_MARKHEAD;
31   RecoverySectors=-1;
32 
33   memset(&NewMhd,0,sizeof(NewMhd));
34   NewMhd.HeadType=MAIN_HEAD;
35   NewMhd.HeadSize=SIZEOF_NEWMHD;
36   HeaderCRC=0;
37   VolWrite=0;
38   AddingFilesSize=0;
39   AddingHeadersSize=0;
40 #if !defined(SHELL_EXT) && !defined(RAR_NOCRYPT)
41   *HeadersSalt=0;
42   *SubDataSalt=0;
43 #endif
44   *FirstVolumeName=0;
45   *FirstVolumeNameW=0;
46 
47   Splitting=false;
48   NewArchive=false;
49 
50   SilentOpen=false;
51 
52 }
53 
54 
55 #ifndef SHELL_EXT
CheckArc(bool EnableBroken)56 void Archive::CheckArc(bool EnableBroken)
57 {
58   if (!IsArchive(EnableBroken))
59   {
60     Log(FileName,St(MBadArc),FileName);
61     ErrHandler.Exit(FATAL_ERROR);
62   }
63 }
64 #endif
65 
66 
67 #if !defined(SHELL_EXT) && !defined(SFX_MODULE)
CheckOpen(const char * Name,const wchar * NameW)68 void Archive::CheckOpen(const char *Name,const wchar *NameW)
69 {
70   TOpen(Name,NameW);
71   CheckArc(false);
72 }
73 #endif
74 
75 
WCheckOpen(const char * Name,const wchar * NameW)76 bool Archive::WCheckOpen(const char *Name,const wchar *NameW)
77 {
78   if (!WOpen(Name,NameW))
79     return(false);
80   if (!IsArchive(false))
81   {
82 #ifndef SHELL_EXT
83     Log(FileName,St(MNotRAR),FileName);
84 #endif
85     Close();
86     return(false);
87   }
88   return(true);
89 }
90 
91 
IsSignature(byte * D)92 bool Archive::IsSignature(byte *D)
93 {
94   bool Valid=false;
95   if (D[0]==0x52)
96 #ifndef SFX_MODULE
97     if (D[1]==0x45 && D[2]==0x7e && D[3]==0x5e)
98     {
99       OldFormat=true;
100       Valid=true;
101     }
102     else
103 #endif
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   return(Valid);
110 }
111 
112 
IsArchive(bool EnableBroken)113 bool Archive::IsArchive(bool EnableBroken)
114 {
115   Encrypted=false;
116 #ifndef SFX_MODULE
117   if (IsDevice())
118   {
119 #ifndef SHELL_EXT
120     Log(FileName,St(MInvalidName),FileName);
121 #endif
122     return(false);
123   }
124 #endif
125   if (Read(MarkHead.Mark,SIZEOF_MARKHEAD)!=SIZEOF_MARKHEAD)
126     return(false);
127   SFXSize=0;
128   if (IsSignature(MarkHead.Mark))
129   {
130     if (OldFormat)
131       Seek(0,SEEK_SET);
132   }
133   else
134   {
135     Array<char> Buffer(MAXSFXSIZE);
136     long CurPos=(long)Tell();
137     int ReadSize=Read(&Buffer[0],Buffer.Size()-16);
138     for (int I=0;I<ReadSize;I++)
139       if (Buffer[I]==0x52 && IsSignature((byte *)&Buffer[I]))
140       {
141         if (OldFormat && I>0 && CurPos<28 && ReadSize>31)
142         {
143           char *D=&Buffer[28-CurPos];
144           if (D[0]!=0x52 || D[1]!=0x53 || D[2]!=0x46 || D[3]!=0x58)
145             continue;
146         }
147         SFXSize=CurPos+I;
148         Seek(SFXSize,SEEK_SET);
149         if (!OldFormat)
150           Read(MarkHead.Mark,SIZEOF_MARKHEAD);
151         break;
152       }
153     if (SFXSize==0)
154       return(false);
155   }
156   ReadHeader();
157   SeekToNext();
158 #ifndef SFX_MODULE
159   if (OldFormat)
160   {
161     NewMhd.Flags=OldMhd.Flags & 0x3f;
162     NewMhd.HeadSize=OldMhd.HeadSize;
163   }
164   else
165 #endif
166   {
167     if (HeaderCRC!=NewMhd.HeadCRC)
168     {
169 #ifndef SHELL_EXT
170       Log(FileName,St(MLogMainHead));
171 #endif
172       Alarm();
173       if (!EnableBroken)
174         return(false);
175     }
176   }
177   Volume=(NewMhd.Flags & MHD_VOLUME);
178   Solid=(NewMhd.Flags & MHD_SOLID)!=0;
179   MainComment=(NewMhd.Flags & MHD_COMMENT)!=0;
180   Locked=(NewMhd.Flags & MHD_LOCK)!=0;
181   Signed=(NewMhd.PosAV!=0);
182   Protected=(NewMhd.Flags & MHD_PROTECT)!=0;
183   Encrypted=(NewMhd.Flags & MHD_PASSWORD)!=0;
184 
185   if (NewMhd.EncryptVer>UNP_VER)
186   {
187 #ifdef RARDLL
188     Cmd->DllError=ERAR_UNKNOWN_FORMAT;
189 #else
190     ErrHandler.SetErrorCode(WARNING);
191   #if !defined(SILENT) && !defined(SFX_MODULE)
192       Log(FileName,St(MUnknownMeth),FileName);
193       Log(FileName,St(MVerRequired),NewMhd.EncryptVer/10,NewMhd.EncryptVer%10);
194   #endif
195 #endif
196     return(false);
197   }
198 #ifdef RARDLL
199   // If callback function is not set, we cannot get the password,
200   // so we skip the initial header processing for encrypted header archive.
201   // It leads to skipped archive comment, but the rest of archive data
202   // is processed correctly.
203   if (Cmd->Callback==NULL)
204     SilentOpen=true;
205 #endif
206 
207   // If not encrypted, we'll check it below.
208   NotFirstVolume=Encrypted && (NewMhd.Flags & MHD_FIRSTVOLUME)==0;
209 
210   if (!SilentOpen || !Encrypted)
211   {
212     SaveFilePos SavePos(*this);
213     int64 SaveCurBlockPos=CurBlockPos,SaveNextBlockPos=NextBlockPos;
214 
215     NotFirstVolume=false;
216     while (ReadHeader()!=0)
217     {
218       int HeaderType=GetHeaderType();
219       if (HeaderType==NEWSUB_HEAD)
220       {
221         if (SubHead.CmpName(SUBHEAD_TYPE_CMT))
222           MainComment=true;
223         if ((SubHead.Flags & LHD_SPLIT_BEFORE) ||
224             Volume && (NewMhd.Flags & MHD_FIRSTVOLUME)==0)
225           NotFirstVolume=true;
226       }
227       else
228       {
229         if (HeaderType==FILE_HEAD && ((NewLhd.Flags & LHD_SPLIT_BEFORE)!=0 ||
230             Volume && NewLhd.UnpVer>=29 && (NewMhd.Flags & MHD_FIRSTVOLUME)==0))
231           NotFirstVolume=true;
232         break;
233       }
234       SeekToNext();
235     }
236     CurBlockPos=SaveCurBlockPos;
237     NextBlockPos=SaveNextBlockPos;
238   }
239   if (!Volume || !NotFirstVolume)
240   {
241     strcpy(FirstVolumeName,FileName);
242     wcscpy(FirstVolumeNameW,FileNameW);
243   }
244 
245   return(true);
246 }
247 
248 
249 
250 
SeekToNext()251 void Archive::SeekToNext()
252 {
253   Seek(NextBlockPos,SEEK_SET);
254 }
255 
256 
257 #ifndef SFX_MODULE
GetRecoverySize(bool Required)258 int Archive::GetRecoverySize(bool Required)
259 {
260   if (!Protected)
261     return(0);
262   if (RecoverySectors!=-1 || !Required)
263     return(RecoverySectors);
264   SaveFilePos SavePos(*this);
265   Seek(SFXSize,SEEK_SET);
266   SearchSubBlock(SUBHEAD_TYPE_RR);
267   return(RecoverySectors);
268 }
269 #endif
270 
271 
272 
273 
274