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