unrarsrc  6.1.7
About: unrar extracts, views and tests the contents of archives created with the RAR archiver.
  Fossies Dox: unrarsrc-6.1.7.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

archive.cpp
Go to the documentation of this file.
1#include "rar.hpp"
2
3#include "arccmt.cpp"
4
5
7{
8 Cmd=NULL; // Just in case we'll have an exception in 'new' below.
9
10 DummyCmd=(InitCmd==NULL);
11 Cmd=DummyCmd ? (new RAROptions):InitCmd;
12
15 Solid=false;
16 Volume=false;
17 MainComment=false;
18 Locked=false;
19 Signed=false;
20 FirstVolume=false;
21 NewNumbering=false;
22 SFXSize=0;
24 Protected=false;
25 Encrypted=false;
27 BrokenHeader=false;
29
32
33
34 memset(&MainHead,0,sizeof(MainHead));
35 memset(&CryptHead,0,sizeof(CryptHead));
36 memset(&EndArcHead,0,sizeof(EndArcHead));
37
38 VolNumber=0;
39 VolWrite=0;
43
44 Splitting=false;
45 NewArchive=false;
46
47 SilentOpen=false;
48
49#ifdef USE_QOPEN
50 ProhibitQOpen=false;
51#endif
52
53}
54
55
57{
58 if (DummyCmd)
59 delete Cmd;
60}
61
62
63void Archive::CheckArc(bool EnableBroken)
64{
65 if (!IsArchive(EnableBroken))
66 {
67 // If FailedHeaderDecryption is set, we already reported that archive
68 // password is incorrect.
72 }
73}
74
75
76#if !defined(SFX_MODULE)
77void Archive::CheckOpen(const wchar *Name)
78{
79 TOpen(Name);
80 CheckArc(false);
81}
82#endif
83
84
85bool Archive::WCheckOpen(const wchar *Name)
86{
87 if (!WOpen(Name))
88 return false;
89 if (!IsArchive(false))
90 {
92 Close();
93 return false;
94 }
95 return true;
96}
97
98
99RARFORMAT Archive::IsSignature(const byte *D,size_t Size)
100{
102 if (Size>=1 && D[0]==0x52)
103#ifndef SFX_MODULE
104 if (Size>=4 && D[1]==0x45 && D[2]==0x7e && D[3]==0x5e)
105 Type=RARFMT14;
106 else
107#endif
108 if (Size>=7 && D[1]==0x61 && D[2]==0x72 && D[3]==0x21 && D[4]==0x1a && D[5]==0x07)
109 {
110 // We check the last signature byte, so we can return a sensible
111 // warning in case we'll want to change the archive format
112 // sometimes in the future.
113 if (D[6]==0)
114 Type=RARFMT15;
115 else
116 if (D[6]==1)
117 Type=RARFMT50;
118 else
119 if (D[6]>1 && D[6]<5)
120 Type=RARFMT_FUTURE;
121 }
122 return Type;
123}
124
125
126bool Archive::IsArchive(bool EnableBroken)
127{
128 Encrypted=false;
129 BrokenHeader=false; // Might be left from previous volume.
130
131#ifndef SFX_MODULE
132 if (IsDevice())
133 {
135 return false;
136 }
137#endif
139 return false;
140 SFXSize=0;
141
142 RARFORMAT Type;
144 {
145 Format=Type;
146 if (Format==RARFMT14)
147 Seek(Tell()-SIZEOF_MARKHEAD3,SEEK_SET);
148 }
149 else
150 {
151 Array<char> Buffer(MAXSFXSIZE);
152 long CurPos=(long)Tell();
153 int ReadSize=Read(&Buffer[0],Buffer.Size()-16);
154 for (int I=0;I<ReadSize;I++)
155 if (Buffer[I]==0x52 && (Type=IsSignature((byte *)&Buffer[I],ReadSize-I))!=RARFMT_NONE)
156 {
157 Format=Type;
158 if (Format==RARFMT14 && I>0 && CurPos<28 && ReadSize>31)
159 {
160 char *D=&Buffer[28-CurPos];
161 if (D[0]!=0x52 || D[1]!=0x53 || D[2]!=0x46 || D[3]!=0x58)
162 continue;
163 }
164 SFXSize=CurPos+I;
165 Seek(SFXSize,SEEK_SET);
168 break;
169 }
170 if (SFXSize==0)
171 return false;
172 }
174 {
176 return false;
177 }
178 if (Format==RARFMT50) // RAR 5.0 signature is by one byte longer.
179 {
181 return false;
183 }
184 else
186
187#ifdef RARDLL
188 // If callback function is not set, we cannot get the password,
189 // so we skip the initial header processing for encrypted header archive.
190 // It leads to skipped archive comment, but the rest of archive data
191 // is processed correctly.
192 if (Cmd->Callback==NULL)
193 SilentOpen=true;
194#endif
195
196 bool HeadersLeft; // Any headers left to read.
197 bool StartFound=false; // Main or encryption headers found.
198 // Skip the archive encryption header if any and read the main header.
199 while ((HeadersLeft=(ReadHeader()!=0))==true) // Additional parentheses to silence Clang.
200 {
201 SeekToNext();
202
204 // In RAR 5.0 we need to quit after reading HEAD_CRYPT if we wish to
205 // avoid the password prompt.
206 StartFound=Type==HEAD_MAIN || SilentOpen && Type==HEAD_CRYPT;
207 if (StartFound)
208 break;
209 }
210
211
212 // We should not do it for EnableBroken or we'll get 'not RAR archive'
213 // messages when extracting encrypted archives with wrong password.
214 if (FailedHeaderDecryption && !EnableBroken)
215 return false;
216
217 if (BrokenHeader || !StartFound) // Main archive header is corrupt or missing.
218 {
219 if (!FailedHeaderDecryption) // If not reported a wrong password already.
221 if (!EnableBroken)
222 return false;
223 }
224
226
227 // If we process non-encrypted archive or can request a password,
228 // we set 'first volume' flag based on file attributes below.
229 // It is necessary for RAR 2.x archives, which did not have 'first volume'
230 // flag in main header. Also for all RAR formats we need to scan until
231 // first file header to set "comment" flag when reading service header.
232 // Unless we are in silent mode, we need to know about presence of comment
233 // immediately after IsArchive call.
234 if (HeadersLeft && (!SilentOpen || !Encrypted) && IsSeekable())
235 {
236 int64 SavePos=Tell();
237 int64 SaveCurBlockPos=CurBlockPos,SaveNextBlockPos=NextBlockPos;
238 HEADER_TYPE SaveCurHeaderType=CurHeaderType;
239
240 while (ReadHeader()!=0)
241 {
242 HEADER_TYPE HeaderType=GetHeaderType();
243 if (HeaderType==HEAD_SERVICE)
244 {
245 // If we have a split service headers, it surely indicates non-first
246 // volume. But not split service header does not guarantee the first
247 // volume, because we can have split file after non-split archive
248 // comment. So we do not quit from loop here.
250 }
251 else
252 if (HeaderType==HEAD_FILE)
253 {
255 break;
256 }
257 else
258 if (HeaderType==HEAD_ENDARC) // Might happen if archive contains only a split service header.
259 break;
260 SeekToNext();
261 }
262 CurBlockPos=SaveCurBlockPos;
263 NextBlockPos=SaveNextBlockPos;
264 CurHeaderType=SaveCurHeaderType;
265 Seek(SavePos,SEEK_SET);
266 }
267 if (!Volume || FirstVolume)
269
270 return true;
271}
272
273
274
275
277{
278 Seek(NextBlockPos,SEEK_SET);
279}
280
281
282
283
284
285
286// Calculate the block size including encryption fields and padding if any.
288{
289 if (Encrypted)
290 {
291 Size = ALIGN_VALUE(Size, CRYPT_BLOCK_SIZE); // Align to encryption block size.
292 if (Format == RARFMT50)
293 Size += SIZE_INITV;
294 else
295 Size += SIZE_SALT30;
296 }
297 return uint(Size);
298}
299
300
301
302
303#ifdef USE_QOPEN
304bool Archive::Open(const wchar *Name,uint Mode)
305{
306 // Important if we reuse Archive object and it has virtual QOpen
307 // file position not matching real. For example, for 'l -v volname'.
308 QOpen.Unload();
309
310 return File::Open(Name,Mode);
311}
312
313
314int Archive::Read(void *Data,size_t Size)
315{
316 size_t Result;
317 if (QOpen.Read(Data,Size,Result))
318 return (int)Result;
319 return File::Read(Data,Size);
320}
321
322
323void Archive::Seek(int64 Offset,int Method)
324{
325 if (!QOpen.Seek(Offset,Method))
326 File::Seek(Offset,Method);
327}
328
329
331{
332 int64 QPos;
333 if (QOpen.Tell(&QPos))
334 return QPos;
335 return File::Tell();
336}
337#endif
338
RARFORMAT
Definition: archive.hpp:13
@ RARFMT_FUTURE
Definition: archive.hpp:13
@ RARFMT50
Definition: archive.hpp:13
@ RARFMT15
Definition: archive.hpp:13
@ RARFMT_NONE
Definition: archive.hpp:13
@ RARFMT14
Definition: archive.hpp:13
ErrorHandler ErrHandler
RAROptions * Cmd
Definition: archive.hpp:48
wchar FirstVolumeName[NM]
Definition: archive.hpp:144
size_t ReadHeader()
Definition: arcread.cpp:3
uint64 AddingFilesSize
Definition: archive.hpp:139
void CheckOpen(const wchar *Name)
Definition: archive.cpp:77
bool Signed
Definition: archive.hpp:122
bool DummyCmd
Definition: archive.hpp:47
bool Encrypted
Definition: archive.hpp:126
bool BrokenHeader
Definition: archive.hpp:128
~Archive()
Definition: archive.cpp:56
bool FirstVolume
Definition: archive.hpp:123
bool FailedHeaderDecryption
Definition: archive.hpp:129
HEADER_TYPE GetHeaderType()
Definition: archive.hpp:85
bool SilentOpen
Definition: archive.hpp:55
uint VolNumber
Definition: archive.hpp:137
bool Protected
Definition: archive.hpp:125
MarkHeader MarkHead
Definition: archive.hpp:101
int LastReadBlock
Definition: archive.hpp:52
bool IsArchive(bool EnableBroken)
Definition: archive.cpp:126
int64 VolWrite
Definition: archive.hpp:138
EndArcHeader EndArcHead
Definition: archive.hpp:105
bool Locked
Definition: archive.hpp:121
static RARFORMAT IsSignature(const byte *D, size_t Size)
Definition: archive.cpp:99
void SeekToNext()
Definition: archive.cpp:276
bool Solid
Definition: archive.hpp:118
HEADER_TYPE CurHeaderType
Definition: archive.hpp:53
FileHeader FileHead
Definition: archive.hpp:104
bool MainComment
Definition: archive.hpp:120
RARFORMAT Format
Definition: archive.hpp:117
uint FullHeaderSize(size_t Size)
Definition: archive.cpp:287
uint64 AddingHeadersSize
Definition: archive.hpp:140
int64 NextBlockPos
Definition: archive.hpp:115
size_t SFXSize
Definition: archive.hpp:127
Archive(RAROptions *InitCmd=NULL)
Definition: archive.cpp:6
FileHeader SubHead
Definition: archive.hpp:107
bool Splitting
Definition: archive.hpp:135
MainHeader MainHead
Definition: archive.hpp:102
RarTime LatestTime
Definition: archive.hpp:51
bool WCheckOpen(const wchar *Name)
Definition: archive.cpp:85
int64 CurBlockPos
Definition: archive.hpp:114
bool NewNumbering
Definition: archive.hpp:124
CryptHeader CryptHead
Definition: archive.hpp:103
void CheckArc(bool EnableBroken)
Definition: archive.cpp:63
bool NewArchive
Definition: archive.hpp:142
bool Volume
Definition: archive.hpp:119
Definition: array.hpp:7
size_t Size()
Definition: array.hpp:94
void Exit(RAR_EXIT ExitCode)
Definition: errhnd.cpp:236
virtual void Seek(int64 Offset, int Method)
Definition: file.cpp:514
virtual int Read(void *Data, size_t Size)
Definition: file.cpp:374
bool IsSeekable()
Definition: file.hpp:127
bool OpenShared
Definition: file.hpp:86
bool IsDevice()
Definition: file.cpp:760
virtual bool Open(const wchar *Name, uint Mode=FMF_READ)
Definition: file.cpp:48
virtual int64 Tell()
Definition: file.cpp:576
wchar FileName[NM]
Definition: file.hpp:88
virtual bool Close()
Definition: file.cpp:241
bool WOpen(const wchar *Name)
Definition: file.cpp:167
void TOpen(const wchar *Name)
Definition: file.cpp:159
bool OpenShared
Definition: options.hpp:164
void Reset()
Definition: timefn.hpp:57
#define SIZE_SALT30
Definition: crypt.hpp:10
#define SIZE_INITV
Definition: crypt.hpp:11
#define CRYPT_BLOCK_SIZE
Definition: crypt.hpp:15
@ RARX_FATAL
Definition: errhnd.hpp:8
#define SIZEOF_MARKHEAD5
Definition: headers5.hpp:4
HEADER_TYPE
Definition: headers.hpp:74
@ HEAD_FILE
Definition: headers.hpp:76
@ HEAD_CRYPT
Definition: headers.hpp:77
@ HEAD_SERVICE
Definition: headers.hpp:76
@ HEAD_MAIN
Definition: headers.hpp:76
@ HEAD_ENDARC
Definition: headers.hpp:77
#define SIZEOF_MARKHEAD3
Definition: headers.hpp:4
#define MAXSFXSIZE
Definition: rardefs.hpp:16
#define ASIZE(x)
Definition: rardefs.hpp:10
#define ALIGN_VALUE(v, a)
Definition: rardefs.hpp:29
wchar_t wchar
Definition: rartypes.hpp:13
int64_t int64
Definition: rartypes.hpp:12
unsigned int uint
Definition: rartypes.hpp:8
void wcsncpyz(wchar *dest, const wchar *src, size_t maxlen)
Definition: strfn.cpp:275
bool SplitBefore
Definition: headers.hpp:200
bool CommentInHeader
Definition: headers.hpp:164
byte Mark[8]
Definition: headers.hpp:131
uint HeadSize
Definition: headers.hpp:134
void uiMsg(UIMESSAGE_CODE Code)
Definition: ui.hpp:148
@ UIERROR_NEWRARFORMAT
Definition: ui.hpp:30
@ UIERROR_MHEADERBROKEN
Definition: ui.hpp:18
@ UIERROR_BADARCHIVE
Definition: ui.hpp:29
@ UIERROR_INVALIDNAME
Definition: ui.hpp:29