1
by Chris Anderson
Import upstream version 3.3.6 |
1 |
#include "rar.hpp" |
2 |
||
1.2.4
by Martin Meredith
Import upstream version 3.9.3 |
3 |
size_t Archive::SearchBlock(int BlockType) |
1
by Chris Anderson
Import upstream version 3.3.6 |
4 |
{
|
1.2.4
by Martin Meredith
Import upstream version 3.9.3 |
5 |
size_t Size,Count=0; |
1
by Chris Anderson
Import upstream version 3.3.6 |
6 |
while ((Size=ReadHeader())!=0 && |
7 |
(BlockType==ENDARC_HEAD || GetHeaderType()!=ENDARC_HEAD)) |
|
8 |
{
|
|
9 |
if ((++Count & 127)==0) |
|
10 |
Wait(); |
|
11 |
if (GetHeaderType()==BlockType) |
|
12 |
return(Size); |
|
13 |
SeekToNext(); |
|
14 |
}
|
|
15 |
return(0); |
|
16 |
}
|
|
17 |
||
18 |
||
1.2.4
by Martin Meredith
Import upstream version 3.9.3 |
19 |
size_t Archive::SearchSubBlock(const char *Type) |
1
by Chris Anderson
Import upstream version 3.3.6 |
20 |
{
|
1.2.4
by Martin Meredith
Import upstream version 3.9.3 |
21 |
size_t Size; |
1.1.1
by Chris Anderson
Import upstream version 3.4.3 |
22 |
while ((Size=ReadHeader())!=0 && GetHeaderType()!=ENDARC_HEAD) |
1
by Chris Anderson
Import upstream version 3.3.6 |
23 |
{
|
24 |
if (GetHeaderType()==NEWSUB_HEAD && SubHead.CmpName(Type)) |
|
25 |
return(Size); |
|
26 |
SeekToNext(); |
|
27 |
}
|
|
28 |
return(0); |
|
29 |
}
|
|
30 |
||
31 |
||
1.2.6
by Martin Meredith
Import upstream version 3.9.6 |
32 |
void Archive::UnexpEndArcMsg() |
33 |
{
|
|
34 |
int64 ArcSize=FileLength(); |
|
35 |
if (CurBlockPos>ArcSize || NextBlockPos>ArcSize) |
|
36 |
{
|
|
37 |
#ifndef SHELL_EXT
|
|
38 |
Log(FileName,St(MLogUnexpEOF)); |
|
39 |
#endif
|
|
1.2.13
by Nick Andrik
Import upstream version 4.2.4 |
40 |
ErrHandler.SetErrorCode(RARX_WARNING); |
1.2.6
by Martin Meredith
Import upstream version 3.9.6 |
41 |
}
|
42 |
}
|
|
43 |
||
44 |
||
1.2.4
by Martin Meredith
Import upstream version 3.9.3 |
45 |
size_t Archive::ReadHeader() |
1
by Chris Anderson
Import upstream version 3.3.6 |
46 |
{
|
1.2.12
by Martin Meredith
Import upstream version 4.1.4 |
47 |
// Once we failed to decrypt an encrypted block, there is no reason to
|
48 |
// attempt to do it further. We'll never be successful and only generate
|
|
49 |
// endless errors.
|
|
50 |
if (FailedHeaderDecryption) |
|
51 |
return 0; |
|
52 |
||
1
by Chris Anderson
Import upstream version 3.3.6 |
53 |
CurBlockPos=Tell(); |
54 |
||
55 |
#ifndef SFX_MODULE
|
|
56 |
if (OldFormat) |
|
57 |
return(ReadOldHeader()); |
|
58 |
#endif
|
|
59 |
||
60 |
RawRead Raw(this); |
|
61 |
||
1.2.4
by Martin Meredith
Import upstream version 3.9.3 |
62 |
bool Decrypt=Encrypted && CurBlockPos>=(int64)SFXSize+SIZEOF_MARKHEAD+SIZEOF_NEWMHD; |
1
by Chris Anderson
Import upstream version 3.3.6 |
63 |
|
64 |
if (Decrypt) |
|
65 |
{
|
|
1.2.12
by Martin Meredith
Import upstream version 4.1.4 |
66 |
#if defined(SHELL_EXT) || defined(RAR_NOCRYPT)
|
1
by Chris Anderson
Import upstream version 3.3.6 |
67 |
return(0); |
68 |
#else
|
|
69 |
if (Read(HeadersSalt,SALT_SIZE)!=SALT_SIZE) |
|
1.2.6
by Martin Meredith
Import upstream version 3.9.6 |
70 |
{
|
71 |
UnexpEndArcMsg(); |
|
1
by Chris Anderson
Import upstream version 3.3.6 |
72 |
return(0); |
1.2.6
by Martin Meredith
Import upstream version 3.9.6 |
73 |
}
|
1.2.13
by Nick Andrik
Import upstream version 4.2.4 |
74 |
if (!Cmd->Password.IsSet()) |
1.2.10
by Martin Meredith
Import upstream version 4.0.2 |
75 |
{
|
1
by Chris Anderson
Import upstream version 3.3.6 |
76 |
#ifdef RARDLL
|
1.2.13
by Nick Andrik
Import upstream version 4.2.4 |
77 |
if (Cmd->Callback!=NULL) |
78 |
{
|
|
79 |
wchar PasswordW[MAXPASSWORD]; |
|
80 |
*PasswordW=0; |
|
81 |
if (Cmd->Callback(UCM_NEEDPASSWORDW,Cmd->UserData,(LPARAM)PasswordW,ASIZE(PasswordW))==-1) |
|
82 |
*PasswordW=0; |
|
83 |
if (*PasswordW==0) |
|
84 |
{
|
|
85 |
char PasswordA[MAXPASSWORD]; |
|
86 |
*PasswordA=0; |
|
87 |
if (Cmd->Callback(UCM_NEEDPASSWORD,Cmd->UserData,(LPARAM)PasswordA,ASIZE(PasswordA))==-1) |
|
88 |
*PasswordA=0; |
|
89 |
GetWideName(PasswordA,NULL,PasswordW,ASIZE(PasswordW)); |
|
90 |
cleandata(PasswordA,sizeof(PasswordA)); |
|
91 |
}
|
|
92 |
Cmd->Password.Set(PasswordW); |
|
93 |
cleandata(PasswordW,sizeof(PasswordW)); |
|
94 |
}
|
|
95 |
if (!Cmd->Password.IsSet()) |
|
1
by Chris Anderson
Import upstream version 3.3.6 |
96 |
{
|
97 |
Close(); |
|
1.2.13
by Nick Andrik
Import upstream version 4.2.4 |
98 |
Cmd->DllError=ERAR_MISSING_PASSWORD; |
99 |
ErrHandler.Exit(RARX_USERBREAK); |
|
1
by Chris Anderson
Import upstream version 3.3.6 |
100 |
}
|
101 |
#else
|
|
1.2.13
by Nick Andrik
Import upstream version 4.2.4 |
102 |
if (!GetPassword(PASSWORD_ARCHIVE,FileName,FileNameW,&Cmd->Password)) |
1
by Chris Anderson
Import upstream version 3.3.6 |
103 |
{
|
104 |
Close(); |
|
1.2.13
by Nick Andrik
Import upstream version 4.2.4 |
105 |
ErrHandler.Exit(RARX_USERBREAK); |
1
by Chris Anderson
Import upstream version 3.3.6 |
106 |
}
|
107 |
#endif
|
|
1.2.10
by Martin Meredith
Import upstream version 4.0.2 |
108 |
}
|
1.2.13
by Nick Andrik
Import upstream version 4.2.4 |
109 |
HeadersCrypt.SetCryptKeys(&Cmd->Password,HeadersSalt,false,false,NewMhd.EncryptVer>=36); |
1
by Chris Anderson
Import upstream version 3.3.6 |
110 |
Raw.SetCrypt(&HeadersCrypt); |
111 |
#endif
|
|
112 |
}
|
|
113 |
||
114 |
Raw.Read(SIZEOF_SHORTBLOCKHEAD); |
|
115 |
if (Raw.Size()==0) |
|
116 |
{
|
|
1.2.6
by Martin Meredith
Import upstream version 3.9.6 |
117 |
UnexpEndArcMsg(); |
1
by Chris Anderson
Import upstream version 3.3.6 |
118 |
return(0); |
119 |
}
|
|
120 |
||
121 |
Raw.Get(ShortBlock.HeadCRC); |
|
122 |
byte HeadType; |
|
123 |
Raw.Get(HeadType); |
|
124 |
ShortBlock.HeadType=(HEADER_TYPE)HeadType; |
|
125 |
Raw.Get(ShortBlock.Flags); |
|
126 |
Raw.Get(ShortBlock.HeadSize); |
|
127 |
if (ShortBlock.HeadSize<SIZEOF_SHORTBLOCKHEAD) |
|
128 |
{
|
|
129 |
#ifndef SHELL_EXT
|
|
130 |
Log(FileName,St(MLogFileHead),"???"); |
|
131 |
#endif
|
|
132 |
BrokenFileHeader=true; |
|
1.2.13
by Nick Andrik
Import upstream version 4.2.4 |
133 |
ErrHandler.SetErrorCode(RARX_CRC); |
1
by Chris Anderson
Import upstream version 3.3.6 |
134 |
return(0); |
135 |
}
|
|
136 |
||
137 |
if (ShortBlock.HeadType==COMM_HEAD) |
|
1.2.10
by Martin Meredith
Import upstream version 4.0.2 |
138 |
{
|
139 |
// Old style (up to RAR 2.9) comment header embedded into main
|
|
140 |
// or file header. We must not read the entire ShortBlock.HeadSize here
|
|
141 |
// to not break the comment processing logic later.
|
|
1
by Chris Anderson
Import upstream version 3.3.6 |
142 |
Raw.Read(SIZEOF_COMMHEAD-SIZEOF_SHORTBLOCKHEAD); |
1.2.10
by Martin Meredith
Import upstream version 4.0.2 |
143 |
}
|
1
by Chris Anderson
Import upstream version 3.3.6 |
144 |
else
|
145 |
if (ShortBlock.HeadType==MAIN_HEAD && (ShortBlock.Flags & MHD_COMMENT)!=0) |
|
1.2.10
by Martin Meredith
Import upstream version 4.0.2 |
146 |
{
|
147 |
// Old style (up to RAR 2.9) main archive comment embedded into
|
|
148 |
// the main archive header found. While we can read the entire
|
|
149 |
// ShortBlock.HeadSize here and remove this part of "if", it would be
|
|
150 |
// waste of memory, because we'll read and process this comment data
|
|
151 |
// in other function anyway and we do not need them here now.
|
|
1
by Chris Anderson
Import upstream version 3.3.6 |
152 |
Raw.Read(SIZEOF_NEWMHD-SIZEOF_SHORTBLOCKHEAD); |
1.2.10
by Martin Meredith
Import upstream version 4.0.2 |
153 |
}
|
1
by Chris Anderson
Import upstream version 3.3.6 |
154 |
else
|
155 |
Raw.Read(ShortBlock.HeadSize-SIZEOF_SHORTBLOCKHEAD); |
|
156 |
||
157 |
NextBlockPos=CurBlockPos+ShortBlock.HeadSize; |
|
158 |
||
159 |
switch(ShortBlock.HeadType) |
|
160 |
{
|
|
161 |
case MAIN_HEAD: |
|
162 |
*(BaseBlock *)&NewMhd=ShortBlock; |
|
163 |
Raw.Get(NewMhd.HighPosAV); |
|
164 |
Raw.Get(NewMhd.PosAV); |
|
1.1.4
by Martin Meredith
Import upstream version 3.6.8 |
165 |
if (NewMhd.Flags & MHD_ENCRYPTVER) |
166 |
Raw.Get(NewMhd.EncryptVer); |
|
1
by Chris Anderson
Import upstream version 3.3.6 |
167 |
break; |
168 |
case ENDARC_HEAD: |
|
169 |
*(BaseBlock *)&EndArcHead=ShortBlock; |
|
170 |
if (EndArcHead.Flags & EARC_DATACRC) |
|
171 |
Raw.Get(EndArcHead.ArcDataCRC); |
|
1.1.1
by Chris Anderson
Import upstream version 3.4.3 |
172 |
if (EndArcHead.Flags & EARC_VOLNUMBER) |
173 |
Raw.Get(EndArcHead.VolNumber); |
|
1
by Chris Anderson
Import upstream version 3.3.6 |
174 |
break; |
175 |
case FILE_HEAD: |
|
176 |
case NEWSUB_HEAD: |
|
177 |
{
|
|
178 |
FileHeader *hd=ShortBlock.HeadType==FILE_HEAD ? &NewLhd:&SubHead; |
|
179 |
*(BaseBlock *)hd=ShortBlock; |
|
180 |
Raw.Get(hd->PackSize); |
|
181 |
Raw.Get(hd->UnpSize); |
|
182 |
Raw.Get(hd->HostOS); |
|
183 |
Raw.Get(hd->FileCRC); |
|
184 |
Raw.Get(hd->FileTime); |
|
185 |
Raw.Get(hd->UnpVer); |
|
186 |
Raw.Get(hd->Method); |
|
187 |
Raw.Get(hd->NameSize); |
|
188 |
Raw.Get(hd->FileAttr); |
|
189 |
if (hd->Flags & LHD_LARGE) |
|
190 |
{
|
|
191 |
Raw.Get(hd->HighPackSize); |
|
192 |
Raw.Get(hd->HighUnpSize); |
|
193 |
}
|
|
194 |
else
|
|
1.1.1
by Chris Anderson
Import upstream version 3.4.3 |
195 |
{
|
1
by Chris Anderson
Import upstream version 3.3.6 |
196 |
hd->HighPackSize=hd->HighUnpSize=0; |
1.1.1
by Chris Anderson
Import upstream version 3.4.3 |
197 |
if (hd->UnpSize==0xffffffff) |
198 |
{
|
|
1.2.4
by Martin Meredith
Import upstream version 3.9.3 |
199 |
// UnpSize equal to 0xffffffff without LHD_LARGE flag indicates
|
200 |
// that we do not know the unpacked file size and must unpack it
|
|
201 |
// until we find the end of file marker in compressed data.
|
|
202 |
hd->UnpSize=(uint)(INT64NDF); |
|
203 |
hd->HighUnpSize=(uint)(INT64NDF>>32); |
|
1.1.1
by Chris Anderson
Import upstream version 3.4.3 |
204 |
}
|
205 |
}
|
|
1.2.4
by Martin Meredith
Import upstream version 3.9.3 |
206 |
hd->FullPackSize=INT32TO64(hd->HighPackSize,hd->PackSize); |
207 |
hd->FullUnpSize=INT32TO64(hd->HighUnpSize,hd->UnpSize); |
|
1
by Chris Anderson
Import upstream version 3.3.6 |
208 |
|
209 |
char FileName[NM*4]; |
|
1.2.12
by Martin Meredith
Import upstream version 4.1.4 |
210 |
size_t NameSize=Min(hd->NameSize,sizeof(FileName)-1); |
1
by Chris Anderson
Import upstream version 3.3.6 |
211 |
Raw.Get((byte *)FileName,NameSize); |
212 |
FileName[NameSize]=0; |
|
213 |
||
1.1.5
by Martin Meredith
Import upstream version 3.7.2 |
214 |
strncpyz(hd->FileName,FileName,ASIZE(hd->FileName)); |
1
by Chris Anderson
Import upstream version 3.3.6 |
215 |
|
216 |
if (hd->HeadType==NEWSUB_HEAD) |
|
217 |
{
|
|
1.2.7
by Martin Meredith
Import upstream version 3.9.7 |
218 |
// Let's calculate the size of optional data.
|
1
by Chris Anderson
Import upstream version 3.3.6 |
219 |
int DataSize=hd->HeadSize-hd->NameSize-SIZEOF_NEWLHD; |
220 |
if (hd->Flags & LHD_SALT) |
|
221 |
DataSize-=SALT_SIZE; |
|
1.2.7
by Martin Meredith
Import upstream version 3.9.7 |
222 |
|
1
by Chris Anderson
Import upstream version 3.3.6 |
223 |
if (DataSize>0) |
224 |
{
|
|
1.2.7
by Martin Meredith
Import upstream version 3.9.7 |
225 |
// Here we read optional additional fields for subheaders.
|
226 |
// They are stored after the file name and before salt.
|
|
1
by Chris Anderson
Import upstream version 3.3.6 |
227 |
hd->SubData.Alloc(DataSize); |
228 |
Raw.Get(&hd->SubData[0],DataSize); |
|
229 |
if (hd->CmpName(SUBHEAD_TYPE_RR)) |
|
230 |
{
|
|
231 |
byte *D=&hd->SubData[8]; |
|
232 |
RecoverySectors=D[0]+((uint)D[1]<<8)+((uint)D[2]<<16)+((uint)D[3]<<24); |
|
233 |
}
|
|
234 |
}
|
|
235 |
}
|
|
236 |
else
|
|
237 |
if (hd->HeadType==FILE_HEAD) |
|
238 |
{
|
|
239 |
if (hd->Flags & LHD_UNICODE) |
|
240 |
{
|
|
241 |
EncodeFileName NameCoder; |
|
1.2.4
by Martin Meredith
Import upstream version 3.9.3 |
242 |
size_t Length=strlen(FileName); |
1.1.4
by Martin Meredith
Import upstream version 3.6.8 |
243 |
if (Length==hd->NameSize) |
244 |
{
|
|
245 |
UtfToWide(FileName,hd->FileNameW,sizeof(hd->FileNameW)/sizeof(hd->FileNameW[0])-1); |
|
246 |
WideToChar(hd->FileNameW,hd->FileName,sizeof(hd->FileName)/sizeof(hd->FileName[0])-1); |
|
247 |
ExtToInt(hd->FileName,hd->FileName); |
|
248 |
}
|
|
249 |
else
|
|
250 |
{
|
|
251 |
Length++; |
|
252 |
NameCoder.Decode(FileName,(byte *)FileName+Length, |
|
253 |
hd->NameSize-Length,hd->FileNameW, |
|
254 |
sizeof(hd->FileNameW)/sizeof(hd->FileNameW[0])); |
|
255 |
}
|
|
1
by Chris Anderson
Import upstream version 3.3.6 |
256 |
if (*hd->FileNameW==0) |
257 |
hd->Flags &= ~LHD_UNICODE; |
|
258 |
}
|
|
259 |
else
|
|
260 |
*hd->FileNameW=0; |
|
261 |
#ifndef SFX_MODULE
|
|
262 |
ConvertNameCase(hd->FileName); |
|
263 |
ConvertNameCase(hd->FileNameW); |
|
264 |
#endif
|
|
265 |
ConvertUnknownHeader(); |
|
266 |
}
|
|
267 |
if (hd->Flags & LHD_SALT) |
|
268 |
Raw.Get(hd->Salt,SALT_SIZE); |
|
269 |
hd->mtime.SetDos(hd->FileTime); |
|
270 |
hd->ctime.Reset(); |
|
271 |
hd->atime.Reset(); |
|
272 |
hd->arctime.Reset(); |
|
273 |
if (hd->Flags & LHD_EXTTIME) |
|
274 |
{
|
|
275 |
ushort Flags; |
|
276 |
Raw.Get(Flags); |
|
277 |
RarTime *tbl[4]; |
|
278 |
tbl[0]=&NewLhd.mtime; |
|
279 |
tbl[1]=&NewLhd.ctime; |
|
280 |
tbl[2]=&NewLhd.atime; |
|
281 |
tbl[3]=&NewLhd.arctime; |
|
282 |
for (int I=0;I<4;I++) |
|
283 |
{
|
|
284 |
RarTime *CurTime=tbl[I]; |
|
285 |
uint rmode=Flags>>(3-I)*4; |
|
286 |
if ((rmode & 8)==0) |
|
287 |
continue; |
|
288 |
if (I!=0) |
|
289 |
{
|
|
290 |
uint DosTime; |
|
291 |
Raw.Get(DosTime); |
|
292 |
CurTime->SetDos(DosTime); |
|
293 |
}
|
|
294 |
RarLocalTime rlt; |
|
295 |
CurTime->GetLocal(&rlt); |
|
296 |
if (rmode & 4) |
|
297 |
rlt.Second++; |
|
298 |
rlt.Reminder=0; |
|
299 |
int count=rmode&3; |
|
300 |
for (int J=0;J<count;J++) |
|
301 |
{
|
|
302 |
byte CurByte; |
|
303 |
Raw.Get(CurByte); |
|
304 |
rlt.Reminder|=(((uint)CurByte)<<((J+3-count)*8)); |
|
305 |
}
|
|
306 |
CurTime->SetLocal(&rlt); |
|
307 |
}
|
|
308 |
}
|
|
309 |
NextBlockPos+=hd->FullPackSize; |
|
310 |
bool CRCProcessedOnly=(hd->Flags & LHD_COMMENT)!=0; |
|
311 |
HeaderCRC=~Raw.GetCRC(CRCProcessedOnly)&0xffff; |
|
312 |
if (hd->HeadCRC!=HeaderCRC) |
|
313 |
{
|
|
1.2.10
by Martin Meredith
Import upstream version 4.0.2 |
314 |
if (hd->HeadType==NEWSUB_HEAD && strlen(hd->FileName)<ASIZE(hd->FileName)-5) |
1
by Chris Anderson
Import upstream version 3.3.6 |
315 |
strcat(hd->FileName,"- ???"); |
316 |
BrokenFileHeader=true; |
|
1.2.13
by Nick Andrik
Import upstream version 4.2.4 |
317 |
ErrHandler.SetErrorCode(RARX_WARNING); |
1.2.10
by Martin Meredith
Import upstream version 4.0.2 |
318 |
|
319 |
// If we have a broken encrypted header, we do not need to display
|
|
320 |
// the error message here, because it will be displayed for such
|
|
321 |
// headers later in this function. Also such headers are unlikely
|
|
322 |
// to have anything sensible in file name field, so it is useless
|
|
323 |
// to display the file name.
|
|
324 |
bool EncBroken=Decrypt && ShortBlock.HeadCRC!=(~Raw.GetCRC(false)&0xffff); |
|
325 |
if (!EncBroken) |
|
326 |
{
|
|
1
by Chris Anderson
Import upstream version 3.3.6 |
327 |
#ifndef SHELL_EXT
|
1.2.10
by Martin Meredith
Import upstream version 4.0.2 |
328 |
Log(Archive::FileName,St(MLogFileHead),IntNameToExt(hd->FileName)); |
329 |
Alarm(); |
|
1
by Chris Anderson
Import upstream version 3.3.6 |
330 |
#endif
|
1.2.10
by Martin Meredith
Import upstream version 4.0.2 |
331 |
}
|
1
by Chris Anderson
Import upstream version 3.3.6 |
332 |
}
|
333 |
}
|
|
334 |
break; |
|
335 |
#ifndef SFX_MODULE
|
|
336 |
case COMM_HEAD: |
|
337 |
*(BaseBlock *)&CommHead=ShortBlock; |
|
338 |
Raw.Get(CommHead.UnpSize); |
|
339 |
Raw.Get(CommHead.UnpVer); |
|
340 |
Raw.Get(CommHead.Method); |
|
341 |
Raw.Get(CommHead.CommCRC); |
|
342 |
break; |
|
343 |
case SIGN_HEAD: |
|
344 |
*(BaseBlock *)&SignHead=ShortBlock; |
|
345 |
Raw.Get(SignHead.CreationTime); |
|
346 |
Raw.Get(SignHead.ArcNameSize); |
|
347 |
Raw.Get(SignHead.UserNameSize); |
|
348 |
break; |
|
349 |
case AV_HEAD: |
|
350 |
*(BaseBlock *)&AVHead=ShortBlock; |
|
351 |
Raw.Get(AVHead.UnpVer); |
|
352 |
Raw.Get(AVHead.Method); |
|
353 |
Raw.Get(AVHead.AVVer); |
|
354 |
Raw.Get(AVHead.AVInfoCRC); |
|
355 |
break; |
|
356 |
case PROTECT_HEAD: |
|
357 |
*(BaseBlock *)&ProtectHead=ShortBlock; |
|
358 |
Raw.Get(ProtectHead.DataSize); |
|
359 |
Raw.Get(ProtectHead.Version); |
|
360 |
Raw.Get(ProtectHead.RecSectors); |
|
361 |
Raw.Get(ProtectHead.TotalBlocks); |
|
362 |
Raw.Get(ProtectHead.Mark,8); |
|
363 |
NextBlockPos+=ProtectHead.DataSize; |
|
364 |
RecoverySectors=ProtectHead.RecSectors; |
|
365 |
break; |
|
366 |
case SUB_HEAD: |
|
367 |
*(BaseBlock *)&SubBlockHead=ShortBlock; |
|
368 |
Raw.Get(SubBlockHead.DataSize); |
|
369 |
NextBlockPos+=SubBlockHead.DataSize; |
|
370 |
Raw.Get(SubBlockHead.SubType); |
|
371 |
Raw.Get(SubBlockHead.Level); |
|
372 |
switch(SubBlockHead.SubType) |
|
373 |
{
|
|
374 |
case UO_HEAD: |
|
375 |
*(SubBlockHeader *)&UOHead=SubBlockHead; |
|
376 |
Raw.Get(UOHead.OwnerNameSize); |
|
377 |
Raw.Get(UOHead.GroupNameSize); |
|
378 |
if (UOHead.OwnerNameSize>NM-1) |
|
379 |
UOHead.OwnerNameSize=NM-1; |
|
380 |
if (UOHead.GroupNameSize>NM-1) |
|
381 |
UOHead.GroupNameSize=NM-1; |
|
382 |
Raw.Get((byte *)UOHead.OwnerName,UOHead.OwnerNameSize); |
|
383 |
Raw.Get((byte *)UOHead.GroupName,UOHead.GroupNameSize); |
|
384 |
UOHead.OwnerName[UOHead.OwnerNameSize]=0; |
|
385 |
UOHead.GroupName[UOHead.GroupNameSize]=0; |
|
386 |
break; |
|
387 |
case MAC_HEAD: |
|
388 |
*(SubBlockHeader *)&MACHead=SubBlockHead; |
|
389 |
Raw.Get(MACHead.fileType); |
|
390 |
Raw.Get(MACHead.fileCreator); |
|
391 |
break; |
|
392 |
case EA_HEAD: |
|
393 |
case BEEA_HEAD: |
|
394 |
case NTACL_HEAD: |
|
395 |
*(SubBlockHeader *)&EAHead=SubBlockHead; |
|
396 |
Raw.Get(EAHead.UnpSize); |
|
397 |
Raw.Get(EAHead.UnpVer); |
|
398 |
Raw.Get(EAHead.Method); |
|
399 |
Raw.Get(EAHead.EACRC); |
|
400 |
break; |
|
401 |
case STREAM_HEAD: |
|
402 |
*(SubBlockHeader *)&StreamHead=SubBlockHead; |
|
403 |
Raw.Get(StreamHead.UnpSize); |
|
404 |
Raw.Get(StreamHead.UnpVer); |
|
405 |
Raw.Get(StreamHead.Method); |
|
406 |
Raw.Get(StreamHead.StreamCRC); |
|
407 |
Raw.Get(StreamHead.StreamNameSize); |
|
408 |
if (StreamHead.StreamNameSize>NM-1) |
|
409 |
StreamHead.StreamNameSize=NM-1; |
|
410 |
Raw.Get((byte *)StreamHead.StreamName,StreamHead.StreamNameSize); |
|
411 |
StreamHead.StreamName[StreamHead.StreamNameSize]=0; |
|
412 |
break; |
|
413 |
}
|
|
414 |
break; |
|
415 |
#endif
|
|
416 |
default: |
|
417 |
if (ShortBlock.Flags & LONG_BLOCK) |
|
418 |
{
|
|
419 |
uint DataSize; |
|
420 |
Raw.Get(DataSize); |
|
421 |
NextBlockPos+=DataSize; |
|
422 |
}
|
|
423 |
break; |
|
424 |
}
|
|
425 |
HeaderCRC=~Raw.GetCRC(false)&0xffff; |
|
426 |
CurHeaderType=ShortBlock.HeadType; |
|
427 |
if (Decrypt) |
|
428 |
{
|
|
429 |
NextBlockPos+=Raw.PaddedSize()+SALT_SIZE; |
|
430 |
||
431 |
if (ShortBlock.HeadCRC!=HeaderCRC) |
|
432 |
{
|
|
433 |
bool Recovered=false; |
|
434 |
if (ShortBlock.HeadType==ENDARC_HEAD && (EndArcHead.Flags & EARC_REVSPACE)!=0) |
|
435 |
{
|
|
1.2.1
by Martin Meredith
Import upstream version 3.8.2 |
436 |
// Last 7 bytes of recovered volume can contain zeroes, because
|
437 |
// REV files store its own information (volume number, etc.) here.
|
|
1
by Chris Anderson
Import upstream version 3.3.6 |
438 |
SaveFilePos SavePos(*this); |
1.2.4
by Martin Meredith
Import upstream version 3.9.3 |
439 |
int64 Length=Tell(); |
1
by Chris Anderson
Import upstream version 3.3.6 |
440 |
Seek(Length-7,SEEK_SET); |
441 |
Recovered=true; |
|
442 |
for (int J=0;J<7;J++) |
|
443 |
if (GetByte()!=0) |
|
444 |
Recovered=false; |
|
445 |
}
|
|
446 |
if (!Recovered) |
|
447 |
{
|
|
448 |
#ifndef SILENT
|
|
449 |
Log(FileName,St(MEncrBadCRC),FileName); |
|
450 |
#endif
|
|
1.2.12
by Martin Meredith
Import upstream version 4.1.4 |
451 |
// Close();
|
452 |
FailedHeaderDecryption=true; |
|
1
by Chris Anderson
Import upstream version 3.3.6 |
453 |
BrokenFileHeader=true; |
1.2.12
by Martin Meredith
Import upstream version 4.1.4 |
454 |
|
1.2.13
by Nick Andrik
Import upstream version 4.2.4 |
455 |
ErrHandler.SetErrorCode(RARX_CRC); |
1
by Chris Anderson
Import upstream version 3.3.6 |
456 |
return(0); |
457 |
}
|
|
458 |
}
|
|
459 |
}
|
|
460 |
||
461 |
if (NextBlockPos<=CurBlockPos) |
|
462 |
{
|
|
463 |
#ifndef SHELL_EXT
|
|
464 |
Log(FileName,St(MLogFileHead),"???"); |
|
465 |
#endif
|
|
466 |
BrokenFileHeader=true; |
|
1.2.13
by Nick Andrik
Import upstream version 4.2.4 |
467 |
ErrHandler.SetErrorCode(RARX_CRC); |
1
by Chris Anderson
Import upstream version 3.3.6 |
468 |
return(0); |
469 |
}
|
|
470 |
return(Raw.Size()); |
|
471 |
}
|
|
472 |
||
473 |
||
474 |
#ifndef SFX_MODULE
|
|
1.2.4
by Martin Meredith
Import upstream version 3.9.3 |
475 |
size_t Archive::ReadOldHeader() |
1
by Chris Anderson
Import upstream version 3.3.6 |
476 |
{
|
477 |
RawRead Raw(this); |
|
1.2.4
by Martin Meredith
Import upstream version 3.9.3 |
478 |
if (CurBlockPos<=(int64)SFXSize) |
1
by Chris Anderson
Import upstream version 3.3.6 |
479 |
{
|
480 |
Raw.Read(SIZEOF_OLDMHD); |
|
481 |
Raw.Get(OldMhd.Mark,4); |
|
482 |
Raw.Get(OldMhd.HeadSize); |
|
483 |
Raw.Get(OldMhd.Flags); |
|
484 |
NextBlockPos=CurBlockPos+OldMhd.HeadSize; |
|
485 |
CurHeaderType=MAIN_HEAD; |
|
486 |
}
|
|
487 |
else
|
|
488 |
{
|
|
489 |
OldFileHeader OldLhd; |
|
490 |
Raw.Read(SIZEOF_OLDLHD); |
|
491 |
NewLhd.HeadType=FILE_HEAD; |
|
492 |
Raw.Get(NewLhd.PackSize); |
|
493 |
Raw.Get(NewLhd.UnpSize); |
|
494 |
Raw.Get(OldLhd.FileCRC); |
|
495 |
Raw.Get(NewLhd.HeadSize); |
|
496 |
Raw.Get(NewLhd.FileTime); |
|
497 |
Raw.Get(OldLhd.FileAttr); |
|
498 |
Raw.Get(OldLhd.Flags); |
|
499 |
Raw.Get(OldLhd.UnpVer); |
|
500 |
Raw.Get(OldLhd.NameSize); |
|
501 |
Raw.Get(OldLhd.Method); |
|
502 |
||
503 |
NewLhd.Flags=OldLhd.Flags|LONG_BLOCK; |
|
504 |
NewLhd.UnpVer=(OldLhd.UnpVer==2) ? 13 : 10; |
|
505 |
NewLhd.Method=OldLhd.Method+0x30; |
|
506 |
NewLhd.NameSize=OldLhd.NameSize; |
|
507 |
NewLhd.FileAttr=OldLhd.FileAttr; |
|
508 |
NewLhd.FileCRC=OldLhd.FileCRC; |
|
509 |
NewLhd.FullPackSize=NewLhd.PackSize; |
|
510 |
NewLhd.FullUnpSize=NewLhd.UnpSize; |
|
511 |
||
1.1.2
by Jeroen van Wolffelaar
Import upstream version 3.5.2 |
512 |
NewLhd.mtime.SetDos(NewLhd.FileTime); |
513 |
NewLhd.ctime.Reset(); |
|
514 |
NewLhd.atime.Reset(); |
|
515 |
NewLhd.arctime.Reset(); |
|
516 |
||
1
by Chris Anderson
Import upstream version 3.3.6 |
517 |
Raw.Read(OldLhd.NameSize); |
518 |
Raw.Get((byte *)NewLhd.FileName,OldLhd.NameSize); |
|
519 |
NewLhd.FileName[OldLhd.NameSize]=0; |
|
520 |
ConvertNameCase(NewLhd.FileName); |
|
521 |
*NewLhd.FileNameW=0; |
|
522 |
||
523 |
if (Raw.Size()!=0) |
|
524 |
NextBlockPos=CurBlockPos+NewLhd.HeadSize+NewLhd.PackSize; |
|
525 |
CurHeaderType=FILE_HEAD; |
|
526 |
}
|
|
1.1.1
by Chris Anderson
Import upstream version 3.4.3 |
527 |
return(NextBlockPos>CurBlockPos ? Raw.Size():0); |
1
by Chris Anderson
Import upstream version 3.3.6 |
528 |
}
|
529 |
#endif
|
|
530 |
||
531 |
||
532 |
void Archive::ConvertNameCase(char *Name) |
|
533 |
{
|
|
534 |
if (Cmd->ConvertNames==NAMES_UPPERCASE) |
|
535 |
{
|
|
536 |
IntToExt(Name,Name); |
|
537 |
strupper(Name); |
|
538 |
ExtToInt(Name,Name); |
|
539 |
}
|
|
540 |
if (Cmd->ConvertNames==NAMES_LOWERCASE) |
|
541 |
{
|
|
542 |
IntToExt(Name,Name); |
|
543 |
strlower(Name); |
|
544 |
ExtToInt(Name,Name); |
|
545 |
}
|
|
546 |
}
|
|
547 |
||
548 |
||
549 |
#ifndef SFX_MODULE
|
|
550 |
void Archive::ConvertNameCase(wchar *Name) |
|
551 |
{
|
|
552 |
if (Cmd->ConvertNames==NAMES_UPPERCASE) |
|
1.2.10
by Martin Meredith
Import upstream version 4.0.2 |
553 |
wcsupper(Name); |
1
by Chris Anderson
Import upstream version 3.3.6 |
554 |
if (Cmd->ConvertNames==NAMES_LOWERCASE) |
1.2.10
by Martin Meredith
Import upstream version 4.0.2 |
555 |
wcslower(Name); |
1
by Chris Anderson
Import upstream version 3.3.6 |
556 |
}
|
557 |
#endif
|
|
558 |
||
559 |
||
560 |
bool Archive::IsArcDir() |
|
561 |
{
|
|
562 |
return((NewLhd.Flags & LHD_WINDOWMASK)==LHD_DIRECTORY); |
|
563 |
}
|
|
564 |
||
565 |
||
566 |
bool Archive::IsArcLabel() |
|
567 |
{
|
|
568 |
return(NewLhd.HostOS<=HOST_WIN32 && (NewLhd.FileAttr & 8)); |
|
569 |
}
|
|
570 |
||
571 |
||
572 |
void Archive::ConvertAttributes() |
|
573 |
{
|
|
1.2.10
by Martin Meredith
Import upstream version 4.0.2 |
574 |
#if defined(_WIN_ALL) || defined(_EMX)
|
1
by Chris Anderson
Import upstream version 3.3.6 |
575 |
switch(NewLhd.HostOS) |
576 |
{
|
|
577 |
case HOST_MSDOS: |
|
578 |
case HOST_OS2: |
|
579 |
case HOST_WIN32: |
|
580 |
break; |
|
581 |
case HOST_UNIX: |
|
582 |
case HOST_BEOS: |
|
583 |
if ((NewLhd.Flags & LHD_WINDOWMASK)==LHD_DIRECTORY) |
|
584 |
NewLhd.FileAttr=0x10; |
|
585 |
else
|
|
586 |
NewLhd.FileAttr=0x20; |
|
587 |
break; |
|
588 |
default: |
|
589 |
if ((NewLhd.Flags & LHD_WINDOWMASK)==LHD_DIRECTORY) |
|
590 |
NewLhd.FileAttr=0x10; |
|
591 |
else
|
|
592 |
NewLhd.FileAttr=0x20; |
|
593 |
break; |
|
594 |
}
|
|
595 |
#endif
|
|
596 |
#ifdef _UNIX
|
|
1.2.4
by Martin Meredith
Import upstream version 3.9.3 |
597 |
// umask defines which permission bits must not be set by default
|
1.2.12
by Martin Meredith
Import upstream version 4.1.4 |
598 |
// when creating a file or directory. The typical default value
|
599 |
// for the process umask is S_IWGRP | S_IWOTH (octal 022),
|
|
600 |
// resulting in 0644 mode for new files.
|
|
1
by Chris Anderson
Import upstream version 3.3.6 |
601 |
static mode_t mask = (mode_t) -1; |
602 |
||
603 |
if (mask == (mode_t) -1) |
|
604 |
{
|
|
1.2.4
by Martin Meredith
Import upstream version 3.9.3 |
605 |
// umask call returns the current umask value. Argument (022) is not
|
1.2.12
by Martin Meredith
Import upstream version 4.1.4 |
606 |
// really important here.
|
1
by Chris Anderson
Import upstream version 3.3.6 |
607 |
mask = umask(022); |
1.2.4
by Martin Meredith
Import upstream version 3.9.3 |
608 |
|
609 |
// Restore the original umask value, which was changed to 022 above.
|
|
1
by Chris Anderson
Import upstream version 3.3.6 |
610 |
umask(mask); |
611 |
}
|
|
1.2.4
by Martin Meredith
Import upstream version 3.9.3 |
612 |
|
1
by Chris Anderson
Import upstream version 3.3.6 |
613 |
switch(NewLhd.HostOS) |
614 |
{
|
|
615 |
case HOST_MSDOS: |
|
616 |
case HOST_OS2: |
|
617 |
case HOST_WIN32: |
|
1.2.4
by Martin Meredith
Import upstream version 3.9.3 |
618 |
{
|
619 |
// Mapping MSDOS, OS/2 and Windows file attributes to Unix.
|
|
620 |
||
621 |
if (NewLhd.FileAttr & 0x10) // FILE_ATTRIBUTE_DIRECTORY |
|
622 |
{
|
|
623 |
// For directories we use 0777 mask.
|
|
624 |
NewLhd.FileAttr=0777 & ~mask; |
|
625 |
}
|
|
1
by Chris Anderson
Import upstream version 3.3.6 |
626 |
else
|
1.2.4
by Martin Meredith
Import upstream version 3.9.3 |
627 |
if (NewLhd.FileAttr & 1) // FILE_ATTRIBUTE_READONLY |
628 |
{
|
|
629 |
// For read only files we use 0444 mask with 'w' bits turned off.
|
|
630 |
NewLhd.FileAttr=0444 & ~mask; |
|
631 |
}
|
|
632 |
else
|
|
633 |
{
|
|
1.2.5
by Martin Meredith
Import upstream version 3.9.5 |
634 |
// umask does not set +x for regular files, so we use 0666
|
1.2.4
by Martin Meredith
Import upstream version 3.9.3 |
635 |
// instead of 0777 as for directories.
|
636 |
NewLhd.FileAttr=0666 & ~mask; |
|
637 |
}
|
|
638 |
}
|
|
1
by Chris Anderson
Import upstream version 3.3.6 |
639 |
break; |
640 |
case HOST_UNIX: |
|
641 |
case HOST_BEOS: |
|
642 |
break; |
|
643 |
default: |
|
644 |
if ((NewLhd.Flags & LHD_WINDOWMASK)==LHD_DIRECTORY) |
|
645 |
NewLhd.FileAttr=0x41ff & ~mask; |
|
646 |
else
|
|
647 |
NewLhd.FileAttr=0x81b6 & ~mask; |
|
648 |
break; |
|
649 |
}
|
|
650 |
#endif
|
|
651 |
}
|
|
652 |
||
653 |
||
654 |
void Archive::ConvertUnknownHeader() |
|
655 |
{
|
|
656 |
if (NewLhd.UnpVer<20 && (NewLhd.FileAttr & 0x10)) |
|
657 |
NewLhd.Flags|=LHD_DIRECTORY; |
|
658 |
if (NewLhd.HostOS>=HOST_MAX) |
|
659 |
{
|
|
660 |
if ((NewLhd.Flags & LHD_WINDOWMASK)==LHD_DIRECTORY) |
|
661 |
NewLhd.FileAttr=0x10; |
|
662 |
else
|
|
663 |
NewLhd.FileAttr=0x20; |
|
664 |
}
|
|
665 |
for (char *s=NewLhd.FileName;*s!=0;s=charnext(s)) |
|
666 |
{
|
|
667 |
if (*s=='/' || *s=='\\') |
|
668 |
*s=CPATHDIVIDER; |
|
669 |
#if defined(_APPLE) && !defined(UNICODE_SUPPORTED)
|
|
670 |
if ((byte)*s<32 || (byte)*s>127) |
|
671 |
*s='_'; |
|
672 |
#endif
|
|
1.2.1
by Martin Meredith
Import upstream version 3.8.2 |
673 |
|
1.2.10
by Martin Meredith
Import upstream version 4.0.2 |
674 |
#if defined(_WIN_ALL) || defined(_EMX)
|
1.2.1
by Martin Meredith
Import upstream version 3.8.2 |
675 |
// ':' in file names is allowed in Unix, but not in Windows.
|
676 |
// Even worse, file data will be written to NTFS stream on NTFS,
|
|
677 |
// so automatic name correction on file create error in extraction
|
|
1.2.2
by Martin Meredith
Import upstream version 3.8.4 |
678 |
// routine does not work. In Windows and DOS versions we better
|
679 |
// replace ':' now.
|
|
680 |
if (*s==':') |
|
1.2.1
by Martin Meredith
Import upstream version 3.8.2 |
681 |
*s='_'; |
682 |
#endif
|
|
683 |
||
1
by Chris Anderson
Import upstream version 3.3.6 |
684 |
}
|
1.2.1
by Martin Meredith
Import upstream version 3.8.2 |
685 |
|
1
by Chris Anderson
Import upstream version 3.3.6 |
686 |
for (wchar *s=NewLhd.FileNameW;*s!=0;s++) |
1.2.1
by Martin Meredith
Import upstream version 3.8.2 |
687 |
{
|
1
by Chris Anderson
Import upstream version 3.3.6 |
688 |
if (*s=='/' || *s=='\\') |
689 |
*s=CPATHDIVIDER; |
|
1.2.1
by Martin Meredith
Import upstream version 3.8.2 |
690 |
|
1.2.10
by Martin Meredith
Import upstream version 4.0.2 |
691 |
#if defined(_WIN_ALL) || defined(_EMX)
|
1.2.1
by Martin Meredith
Import upstream version 3.8.2 |
692 |
// ':' in file names is allowed in Unix, but not in Windows.
|
693 |
// Even worse, file data will be written to NTFS stream on NTFS,
|
|
694 |
// so automatic name correction on file create error in extraction
|
|
1.2.2
by Martin Meredith
Import upstream version 3.8.4 |
695 |
// routine does not work. In Windows and DOS versions we better
|
696 |
// replace ':' now.
|
|
697 |
if (*s==':') |
|
1.2.1
by Martin Meredith
Import upstream version 3.8.2 |
698 |
*s='_'; |
699 |
#endif
|
|
700 |
}
|
|
1
by Chris Anderson
Import upstream version 3.3.6 |
701 |
}
|
702 |
||
703 |
||
704 |
#ifndef SHELL_EXT
|
|
705 |
bool Archive::ReadSubData(Array<byte> *UnpData,File *DestFile) |
|
706 |
{
|
|
707 |
if (HeaderCRC!=SubHead.HeadCRC) |
|
708 |
{
|
|
709 |
#ifndef SHELL_EXT
|
|
710 |
Log(FileName,St(MSubHeadCorrupt)); |
|
711 |
#endif
|
|
1.2.13
by Nick Andrik
Import upstream version 4.2.4 |
712 |
ErrHandler.SetErrorCode(RARX_CRC); |
1
by Chris Anderson
Import upstream version 3.3.6 |
713 |
return(false); |
714 |
}
|
|
1.1.4
by Martin Meredith
Import upstream version 3.6.8 |
715 |
if (SubHead.Method<0x30 || SubHead.Method>0x35 || SubHead.UnpVer>/*PACK_VER*/36) |
1
by Chris Anderson
Import upstream version 3.3.6 |
716 |
{
|
717 |
#ifndef SHELL_EXT
|
|
718 |
Log(FileName,St(MSubHeadUnknown)); |
|
719 |
#endif
|
|
720 |
return(false); |
|
721 |
}
|
|
722 |
||
723 |
if (SubHead.PackSize==0 && (SubHead.Flags & LHD_SPLIT_AFTER)==0) |
|
724 |
return(true); |
|
725 |
||
726 |
SubDataIO.Init(); |
|
727 |
Unpack Unpack(&SubDataIO); |
|
728 |
Unpack.Init(); |
|
729 |
||
730 |
if (DestFile==NULL) |
|
731 |
{
|
|
732 |
UnpData->Alloc(SubHead.UnpSize); |
|
733 |
SubDataIO.SetUnpackToMemory(&(*UnpData)[0],SubHead.UnpSize); |
|
734 |
}
|
|
735 |
if (SubHead.Flags & LHD_PASSWORD) |
|
1.2.13
by Nick Andrik
Import upstream version 4.2.4 |
736 |
if (Cmd->Password.IsSet()) |
737 |
SubDataIO.SetEncryption(SubHead.UnpVer,&Cmd->Password, |
|
1.1.4
by Martin Meredith
Import upstream version 3.6.8 |
738 |
(SubHead.Flags & LHD_SALT) ? SubHead.Salt:NULL,false, |
739 |
SubHead.UnpVer>=36); |
|
1
by Chris Anderson
Import upstream version 3.3.6 |
740 |
else
|
741 |
return(false); |
|
742 |
SubDataIO.SetPackedSizeToRead(SubHead.PackSize); |
|
743 |
SubDataIO.EnableShowProgress(false); |
|
744 |
SubDataIO.SetFiles(this,DestFile); |
|
1.2.4
by Martin Meredith
Import upstream version 3.9.3 |
745 |
SubDataIO.UnpVolume=(SubHead.Flags & LHD_SPLIT_AFTER)!=0; |
1
by Chris Anderson
Import upstream version 3.3.6 |
746 |
SubDataIO.SetSubHeader(&SubHead,NULL); |
747 |
Unpack.SetDestSize(SubHead.UnpSize); |
|
748 |
if (SubHead.Method==0x30) |
|
749 |
CmdExtract::UnstoreFile(SubDataIO,SubHead.UnpSize); |
|
750 |
else
|
|
751 |
Unpack.DoUnpack(SubHead.UnpVer,false); |
|
752 |
||
753 |
if (SubHead.FileCRC!=~SubDataIO.UnpFileCRC) |
|
754 |
{
|
|
755 |
#ifndef SHELL_EXT
|
|
756 |
Log(FileName,St(MSubHeadDataCRC),SubHead.FileName); |
|
757 |
#endif
|
|
1.2.13
by Nick Andrik
Import upstream version 4.2.4 |
758 |
ErrHandler.SetErrorCode(RARX_CRC); |
1
by Chris Anderson
Import upstream version 3.3.6 |
759 |
if (UnpData!=NULL) |
760 |
UnpData->Reset(); |
|
761 |
return(false); |
|
762 |
}
|
|
763 |
return(true); |
|
764 |
}
|
|
765 |
#endif
|