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