3 int Archive::SearchBlock(int BlockType)
6 while ((Size=ReadHeader())!=0 &&
7 (BlockType==ENDARC_HEAD || GetHeaderType()!=ENDARC_HEAD))
9 if ((++Count & 127)==0)
11 if (GetHeaderType()==BlockType)
19 int Archive::SearchSubBlock(const char *Type)
22 while ((Size=ReadHeader())!=0 && GetHeaderType()!=ENDARC_HEAD)
24 if (GetHeaderType()==NEWSUB_HEAD && SubHead.CmpName(Type))
32 int Archive::ReadHeader()
38 return(ReadOldHeader());
43 bool Decrypt=Encrypted && CurBlockPos>=SFXSize+SIZEOF_MARKHEAD+SIZEOF_NEWMHD;
47 #if defined(SHELL_EXT) || defined(NOCRYPT)
50 if (Read(HeadersSalt,SALT_SIZE)!=SALT_SIZE)
52 if (*Cmd->Password==0)
54 if (Cmd->Callback==NULL ||
55 Cmd->Callback(UCM_NEEDPASSWORD,Cmd->UserData,(LONG)Cmd->Password,sizeof(Cmd->Password))==-1)
58 ErrHandler.Exit(USER_BREAK);
62 if (!GetPassword(PASSWORD_ARCHIVE,FileName,Cmd->Password,sizeof(Cmd->Password)))
65 ErrHandler.Exit(USER_BREAK);
68 HeadersCrypt.SetCryptKeys(Cmd->Password,HeadersSalt,false);
69 Raw.SetCrypt(&HeadersCrypt);
73 Raw.Read(SIZEOF_SHORTBLOCKHEAD);
76 Int64 ArcSize=FileLength();
77 if (CurBlockPos>ArcSize || NextBlockPos>ArcSize)
80 Log(FileName,St(MLogUnexpEOF));
82 ErrHandler.SetErrorCode(WARNING);
87 Raw.Get(ShortBlock.HeadCRC);
90 ShortBlock.HeadType=(HEADER_TYPE)HeadType;
91 Raw.Get(ShortBlock.Flags);
92 Raw.Get(ShortBlock.HeadSize);
93 if (ShortBlock.HeadSize<SIZEOF_SHORTBLOCKHEAD)
96 Log(FileName,St(MLogFileHead),"???");
98 BrokenFileHeader=true;
99 ErrHandler.SetErrorCode(CRC_ERROR);
103 if (ShortBlock.HeadType==COMM_HEAD)
104 Raw.Read(SIZEOF_COMMHEAD-SIZEOF_SHORTBLOCKHEAD);
106 if (ShortBlock.HeadType==MAIN_HEAD && (ShortBlock.Flags & MHD_COMMENT)!=0)
107 Raw.Read(SIZEOF_NEWMHD-SIZEOF_SHORTBLOCKHEAD);
109 Raw.Read(ShortBlock.HeadSize-SIZEOF_SHORTBLOCKHEAD);
111 NextBlockPos=CurBlockPos+ShortBlock.HeadSize;
113 switch(ShortBlock.HeadType)
116 *(BaseBlock *)&NewMhd=ShortBlock;
117 Raw.Get(NewMhd.HighPosAV);
118 Raw.Get(NewMhd.PosAV);
121 *(BaseBlock *)&EndArcHead=ShortBlock;
122 if (EndArcHead.Flags & EARC_DATACRC)
123 Raw.Get(EndArcHead.ArcDataCRC);
124 if (EndArcHead.Flags & EARC_VOLNUMBER)
125 Raw.Get(EndArcHead.VolNumber);
130 FileHeader *hd=ShortBlock.HeadType==FILE_HEAD ? &NewLhd:&SubHead;
131 *(BaseBlock *)hd=ShortBlock;
132 Raw.Get(hd->PackSize);
133 Raw.Get(hd->UnpSize);
135 Raw.Get(hd->FileCRC);
136 Raw.Get(hd->FileTime);
139 Raw.Get(hd->NameSize);
140 Raw.Get(hd->FileAttr);
141 if (hd->Flags & LHD_LARGE)
143 Raw.Get(hd->HighPackSize);
144 Raw.Get(hd->HighUnpSize);
148 hd->HighPackSize=hd->HighUnpSize=0;
149 if (hd->UnpSize==0xffffffff)
151 hd->UnpSize=int64to32(INT64MAX);
152 hd->HighUnpSize=int64to32(INT64MAX>>32);
155 hd->FullPackSize=int32to64(hd->HighPackSize,hd->PackSize);
156 hd->FullUnpSize=int32to64(hd->HighUnpSize,hd->UnpSize);
159 int NameSize=Min(hd->NameSize,sizeof(FileName)-1);
160 Raw.Get((byte *)FileName,NameSize);
161 FileName[NameSize]=0;
163 strncpy(hd->FileName,FileName,sizeof(hd->FileName));
164 hd->FileName[sizeof(hd->FileName)-1]=0;
166 if (hd->HeadType==NEWSUB_HEAD)
168 int DataSize=hd->HeadSize-hd->NameSize-SIZEOF_NEWLHD;
169 if (hd->Flags & LHD_SALT)
173 hd->SubData.Alloc(DataSize);
174 Raw.Get(&hd->SubData[0],DataSize);
175 if (hd->CmpName(SUBHEAD_TYPE_RR))
177 byte *D=&hd->SubData[8];
178 RecoverySectors=D[0]+((uint)D[1]<<8)+((uint)D[2]<<16)+((uint)D[3]<<24);
183 if (hd->HeadType==FILE_HEAD)
185 if (hd->Flags & LHD_UNICODE)
187 EncodeFileName NameCoder;
188 int Length=strlen(FileName)+1;
189 NameCoder.Decode(FileName,(byte *)FileName+Length,
190 hd->NameSize-Length,hd->FileNameW,
191 sizeof(hd->FileNameW)/sizeof(hd->FileNameW[0]));
192 if (*hd->FileNameW==0)
193 hd->Flags &= ~LHD_UNICODE;
198 ConvertNameCase(hd->FileName);
199 ConvertNameCase(hd->FileNameW);
201 ConvertUnknownHeader();
203 if (hd->Flags & LHD_SALT)
204 Raw.Get(hd->Salt,SALT_SIZE);
205 hd->mtime.SetDos(hd->FileTime);
209 if (hd->Flags & LHD_EXTTIME)
214 tbl[0]=&NewLhd.mtime;
215 tbl[1]=&NewLhd.ctime;
216 tbl[2]=&NewLhd.atime;
217 tbl[3]=&NewLhd.arctime;
218 for (int I=0;I<4;I++)
220 RarTime *CurTime=tbl[I];
221 uint rmode=Flags>>(3-I)*4;
228 CurTime->SetDos(DosTime);
231 CurTime->GetLocal(&rlt);
236 for (int J=0;J<count;J++)
240 rlt.Reminder|=(((uint)CurByte)<<((J+3-count)*8));
242 CurTime->SetLocal(&rlt);
245 NextBlockPos+=hd->FullPackSize;
246 bool CRCProcessedOnly=(hd->Flags & LHD_COMMENT)!=0;
247 HeaderCRC = ~Raw.GetCRC(CRCProcessedOnly) & 0xffff;
248 if (hd->HeadCRC!=HeaderCRC)
250 if (hd->HeadType==NEWSUB_HEAD)
251 strcat(hd->FileName,"- ???");
252 BrokenFileHeader=true;
253 ErrHandler.SetErrorCode(WARNING);
255 Log(Archive::FileName,St(MLogFileHead),IntNameToExt(hd->FileName));
263 *(BaseBlock *)&CommHead=ShortBlock;
264 Raw.Get(CommHead.UnpSize);
265 Raw.Get(CommHead.UnpVer);
266 Raw.Get(CommHead.Method);
267 Raw.Get(CommHead.CommCRC);
270 *(BaseBlock *)&SignHead=ShortBlock;
271 Raw.Get(SignHead.CreationTime);
272 Raw.Get(SignHead.ArcNameSize);
273 Raw.Get(SignHead.UserNameSize);
276 *(BaseBlock *)&AVHead=ShortBlock;
277 Raw.Get(AVHead.UnpVer);
278 Raw.Get(AVHead.Method);
279 Raw.Get(AVHead.AVVer);
280 Raw.Get(AVHead.AVInfoCRC);
283 *(BaseBlock *)&ProtectHead=ShortBlock;
284 Raw.Get(ProtectHead.DataSize);
285 Raw.Get(ProtectHead.Version);
286 Raw.Get(ProtectHead.RecSectors);
287 Raw.Get(ProtectHead.TotalBlocks);
288 Raw.Get(ProtectHead.Mark,8);
289 NextBlockPos+=ProtectHead.DataSize;
290 RecoverySectors=ProtectHead.RecSectors;
293 *(BaseBlock *)&SubBlockHead=ShortBlock;
294 Raw.Get(SubBlockHead.DataSize);
295 NextBlockPos+=SubBlockHead.DataSize;
296 Raw.Get(SubBlockHead.SubType);
297 Raw.Get(SubBlockHead.Level);
298 switch(SubBlockHead.SubType)
301 *(SubBlockHeader *)&UOHead=SubBlockHead;
302 Raw.Get(UOHead.OwnerNameSize);
303 Raw.Get(UOHead.GroupNameSize);
304 if (UOHead.OwnerNameSize>NM-1)
305 UOHead.OwnerNameSize=NM-1;
306 if (UOHead.GroupNameSize>NM-1)
307 UOHead.GroupNameSize=NM-1;
308 Raw.Get((byte *)UOHead.OwnerName,UOHead.OwnerNameSize);
309 Raw.Get((byte *)UOHead.GroupName,UOHead.GroupNameSize);
310 UOHead.OwnerName[UOHead.OwnerNameSize]=0;
311 UOHead.GroupName[UOHead.GroupNameSize]=0;
314 *(SubBlockHeader *)&MACHead=SubBlockHead;
315 Raw.Get(MACHead.fileType);
316 Raw.Get(MACHead.fileCreator);
321 *(SubBlockHeader *)&EAHead=SubBlockHead;
322 Raw.Get(EAHead.UnpSize);
323 Raw.Get(EAHead.UnpVer);
324 Raw.Get(EAHead.Method);
325 Raw.Get(EAHead.EACRC);
328 *(SubBlockHeader *)&StreamHead=SubBlockHead;
329 Raw.Get(StreamHead.UnpSize);
330 Raw.Get(StreamHead.UnpVer);
331 Raw.Get(StreamHead.Method);
332 Raw.Get(StreamHead.StreamCRC);
333 Raw.Get(StreamHead.StreamNameSize);
334 if (StreamHead.StreamNameSize>NM-1)
335 StreamHead.StreamNameSize=NM-1;
336 Raw.Get((byte *)StreamHead.StreamName,StreamHead.StreamNameSize);
337 StreamHead.StreamName[StreamHead.StreamNameSize]=0;
343 if (ShortBlock.Flags & LONG_BLOCK)
347 NextBlockPos+=DataSize;
351 HeaderCRC=~Raw.GetCRC(false)&0xffff;
352 CurHeaderType=ShortBlock.HeadType;
355 NextBlockPos+=Raw.PaddedSize()+SALT_SIZE;
357 if (ShortBlock.HeadCRC!=HeaderCRC)
359 bool Recovered=false;
360 if (ShortBlock.HeadType==ENDARC_HEAD && (EndArcHead.Flags & EARC_REVSPACE)!=0)
362 SaveFilePos SavePos(*this);
364 Seek(Length-7,SEEK_SET);
366 for (int J=0;J<7;J++)
373 Log(FileName,St(MEncrBadCRC),FileName);
377 BrokenFileHeader=true;
378 ErrHandler.SetErrorCode(CRC_ERROR);
380 // ErrHandler.Exit(CRC_ERROR);
385 if (NextBlockPos<=CurBlockPos)
388 Log(FileName,St(MLogFileHead),"???");
390 BrokenFileHeader=true;
391 ErrHandler.SetErrorCode(CRC_ERROR);
399 int Archive::ReadOldHeader()
402 if (CurBlockPos<=SFXSize)
404 Raw.Read(SIZEOF_OLDMHD);
405 Raw.Get(OldMhd.Mark,4);
406 Raw.Get(OldMhd.HeadSize);
407 Raw.Get(OldMhd.Flags);
408 NextBlockPos=CurBlockPos+OldMhd.HeadSize;
409 CurHeaderType=MAIN_HEAD;
413 OldFileHeader OldLhd;
414 Raw.Read(SIZEOF_OLDLHD);
415 NewLhd.HeadType=FILE_HEAD;
416 Raw.Get(NewLhd.PackSize);
417 Raw.Get(NewLhd.UnpSize);
418 Raw.Get(OldLhd.FileCRC);
419 Raw.Get(NewLhd.HeadSize);
420 Raw.Get(NewLhd.FileTime);
421 Raw.Get(OldLhd.FileAttr);
422 Raw.Get(OldLhd.Flags);
423 Raw.Get(OldLhd.UnpVer);
424 Raw.Get(OldLhd.NameSize);
425 Raw.Get(OldLhd.Method);
427 NewLhd.Flags=OldLhd.Flags|LONG_BLOCK;
428 NewLhd.UnpVer=(OldLhd.UnpVer==2) ? 13 : 10;
429 NewLhd.Method=OldLhd.Method+0x30;
430 NewLhd.NameSize=OldLhd.NameSize;
431 NewLhd.FileAttr=OldLhd.FileAttr;
432 NewLhd.FileCRC=OldLhd.FileCRC;
433 NewLhd.FullPackSize=NewLhd.PackSize;
434 NewLhd.FullUnpSize=NewLhd.UnpSize;
436 NewLhd.mtime.SetDos(NewLhd.FileTime);
437 NewLhd.ctime.Reset();
438 NewLhd.atime.Reset();
439 NewLhd.arctime.Reset();
441 Raw.Read(OldLhd.NameSize);
442 Raw.Get((byte *)NewLhd.FileName,OldLhd.NameSize);
443 NewLhd.FileName[OldLhd.NameSize]=0;
444 ConvertNameCase(NewLhd.FileName);
448 NextBlockPos=CurBlockPos+NewLhd.HeadSize+NewLhd.PackSize;
449 CurHeaderType=FILE_HEAD;
451 return(NextBlockPos>CurBlockPos ? Raw.Size():0);
456 void Archive::ConvertNameCase(char *Name)
458 if (Cmd->ConvertNames==NAMES_UPPERCASE)
464 if (Cmd->ConvertNames==NAMES_LOWERCASE)
474 void Archive::ConvertNameCase(wchar *Name)
476 if (Cmd->ConvertNames==NAMES_UPPERCASE)
478 if (Cmd->ConvertNames==NAMES_LOWERCASE)
484 bool Archive::IsArcDir()
486 return((NewLhd.Flags & LHD_WINDOWMASK)==LHD_DIRECTORY);
490 bool Archive::IsArcLabel()
492 return(NewLhd.HostOS<=HOST_WIN32 && (NewLhd.FileAttr & 8));
496 void Archive::ConvertAttributes()
498 #if defined(_WIN_32) || defined(_EMX)
499 switch(NewLhd.HostOS)
507 if ((NewLhd.Flags & LHD_WINDOWMASK)==LHD_DIRECTORY)
508 NewLhd.FileAttr=0x10;
510 NewLhd.FileAttr=0x20;
513 if ((NewLhd.Flags & LHD_WINDOWMASK)==LHD_DIRECTORY)
514 NewLhd.FileAttr=0x10;
516 NewLhd.FileAttr=0x20;
521 static mode_t mask = (mode_t) -1;
523 if (mask == (mode_t) -1)
528 switch(NewLhd.HostOS)
533 if (NewLhd.FileAttr & 0x10)
534 NewLhd.FileAttr=0x41ff & ~mask;
536 if (NewLhd.FileAttr & 1)
537 NewLhd.FileAttr=0x8124 & ~mask;
539 NewLhd.FileAttr=0x81b6 & ~mask;
545 if ((NewLhd.Flags & LHD_WINDOWMASK)==LHD_DIRECTORY)
546 NewLhd.FileAttr=0x41ff & ~mask;
548 NewLhd.FileAttr=0x81b6 & ~mask;
555 void Archive::ConvertUnknownHeader()
557 if (NewLhd.UnpVer<20 && (NewLhd.FileAttr & 0x10))
558 NewLhd.Flags|=LHD_DIRECTORY;
559 if (NewLhd.HostOS>=HOST_MAX)
561 if ((NewLhd.Flags & LHD_WINDOWMASK)==LHD_DIRECTORY)
562 NewLhd.FileAttr=0x10;
564 NewLhd.FileAttr=0x20;
566 for (char *s=NewLhd.FileName;*s!=0;s=charnext(s))
568 if (*s=='/' || *s=='\\')
570 #if defined(_APPLE) && !defined(UNICODE_SUPPORTED)
571 if ((byte)*s<32 || (byte)*s>127)
575 for (wchar *s=NewLhd.FileNameW;*s!=0;s++)
576 if (*s=='/' || *s=='\\')
581 bool Archive::ReadSubData(Array<byte> *UnpData,File *DestFile)
583 if (HeaderCRC!=SubHead.HeadCRC)
586 Log(FileName,St(MSubHeadCorrupt));
588 ErrHandler.SetErrorCode(CRC_ERROR);
591 if (SubHead.Method<0x30 || SubHead.Method>0x35 || SubHead.UnpVer>PACK_VER)
594 Log(FileName,St(MSubHeadUnknown));
599 if (SubHead.PackSize==0 && (SubHead.Flags & LHD_SPLIT_AFTER)==0)
603 Unpack Unpack(&SubDataIO);
608 UnpData->Alloc(SubHead.UnpSize);
609 SubDataIO.SetUnpackToMemory(&(*UnpData)[0],SubHead.UnpSize);
611 if (SubHead.Flags & LHD_PASSWORD)
614 SubDataIO.SetEncryption(SubHead.UnpVer,Cmd->Password,
615 (SubHead.Flags & LHD_SALT) ? SubHead.Salt:NULL,false);
619 SubDataIO.SetPackedSizeToRead(SubHead.PackSize);
620 SubDataIO.EnableShowProgress(false);
621 SubDataIO.SetFiles(this,DestFile);
622 SubDataIO.UnpVolume=(SubHead.Flags & LHD_SPLIT_AFTER);
623 SubDataIO.SetSubHeader(&SubHead,NULL);
624 Unpack.SetDestSize(SubHead.UnpSize);
625 if (SubHead.Method==0x30)
626 CmdExtract::UnstoreFile(SubDataIO,SubHead.UnpSize);
628 Unpack.DoUnpack(SubHead.UnpVer,false);
630 if (SubHead.FileCRC!=~SubDataIO.UnpFileCRC)
633 Log(FileName,St(MSubHeadDataCRC),SubHead.FileName);
635 ErrHandler.SetErrorCode(CRC_ERROR);