67
68
// If FailedHeaderDecryption is set, we already reported that archive
68
69
// password is incorrect.
69
70
if (!FailedHeaderDecryption)
71
Log(FileName,St(MBadArc),FileName);
71
uiMsg(UIERROR_BADARCHIVE,FileName);
73
72
ErrHandler.Exit(RARX_FATAL);
131
128
bool Archive::IsArchive(bool EnableBroken)
138
// Important if we reuse Archive object and it has virtual QOpen
139
// file position not matching real. For example, for 'l -v volname'.
131
BrokenHeader=false; // Might be left from previous volume.
142
133
#ifndef SFX_MODULE
146
Log(FileName,St(MInvalidName),FileName);
136
uiMsg(UIERROR_INVALIDNAME,FileName,FileName);
151
140
if (Read(MarkHead.Mark,SIZEOF_MARKHEAD3)!=SIZEOF_MARKHEAD3)
201
188
MarkHead.HeadSize=SIZEOF_MARKHEAD3;
191
// If callback function is not set, we cannot get the password,
192
// so we skip the initial header processing for encrypted header archive.
193
// It leads to skipped archive comment, but the rest of archive data
194
// is processed correctly.
195
if (Cmd->Callback==NULL)
203
199
// Skip the archive encryption header if any and read the main header.
204
while (ReadHeader()!=0 && GetHeaderType()!=HEAD_MAIN)
200
while (ReadHeader()!=0)
202
HEADER_TYPE Type=GetHeaderType();
203
// In RAR 5.0 we need to quit after reading HEAD_CRYPT if we wish to
204
// avoid the password prompt.
205
if (Type==HEAD_MAIN || SilentOpen && Type==HEAD_CRYPT)
207
210
// This check allows to make RS based recovery even if password is incorrect.
208
211
// But we should not do it for EnableBroken or we'll get 'not RAR archive'
217
if (BrokenHeader) // Main archive header is corrupt.
217
Log(FileName,St(MMainHeaderBroken));
219
uiMsg(UIERROR_MHEADERBROKEN,FileName);
219
220
if (!EnableBroken)
224
if (MainHead.EncryptVer>VER_UNPACK)
227
Cmd->DllError=ERAR_UNKNOWN_FORMAT;
229
ErrHandler.SetErrorCode(RARX_WARNING);
230
#if !defined(SILENT) && !defined(SFX_MODULE)
231
Log(FileName,St(MUnknownMeth),FileName);
232
Log(FileName,St(MVerRequired),MainHead.EncryptVer/10,MainHead.EncryptVer%10);
240
// If callback function is not set, we cannot get the password,
241
// so we skip the initial header processing for encrypted header archive.
242
// It leads to skipped archive comment, but the rest of archive data
243
// is processed correctly.
244
if (Cmd->Callback==NULL)
248
224
MainComment=MainHead.CommentInHeader;
251
if (MainHead.Locator && MainHead.QOpenOffset>0 && Cmd->QOpenMode!=QOPEN_NONE)
253
QOpen.Init(this,false);
254
QOpen.Load(MainHead.QOpenOffset);
258
226
// If we process non-encrypted archive or can request a password,
259
227
// we set 'first volume' flag based on file attributes below.
260
228
// It is necessary for RAR 2.x archives, which did not have 'first volume'
261
// flag in main header.
229
// flag in main header. Also for all RAR formats we need to scan until
230
// first file header to set "comment" flag when reading service header.
231
// Unless we are in silent mode, we need to know about presence of comment
232
// immediately after IsArchive call.
262
233
if (!SilentOpen || !Encrypted)
264
235
SaveFilePos SavePos(*this);
265
236
int64 SaveCurBlockPos=CurBlockPos,SaveNextBlockPos=NextBlockPos;
237
HEADER_TYPE SaveCurHeaderType=CurHeaderType;
267
239
while (ReadHeader()!=0)
269
241
HEADER_TYPE HeaderType=GetHeaderType();
270
242
if (HeaderType==HEAD_SERVICE)
272
if (SubHead.CmpName(SUBHEAD_TYPE_CMT))
274
FirstVolume=!SubHead.SplitBefore;
243
FirstVolume=Volume && !SubHead.SplitBefore;
278
FirstVolume=HeaderType==HEAD_FILE && !FileHead.SplitBefore;
245
if (HeaderType==HEAD_FILE)
247
FirstVolume=Volume && !FileHead.SplitBefore;
283
252
CurBlockPos=SaveCurBlockPos;
284
253
NextBlockPos=SaveNextBlockPos;
254
CurHeaderType=SaveCurHeaderType;
286
256
if (!Volume || FirstVolume)
287
257
wcscpy(FirstVolumeName,FileName);
293
bool Archive::Open(const wchar *Name,uint Mode)
295
// Important if we reuse Archive object and it has virtual QOpen
296
// file position not matching real. For example, for 'l -v volname'.
299
return File::Open(Name,Mode);
323
303
int Archive::Read(void *Data,size_t Size)