Example #1
0
size_t Archive::ReadHeader()
{
  // Once we failed to decrypt an encrypted block, there is no reason to
  // attempt to do it further. We'll never be successful and only generate
  // endless errors.
  if (FailedHeaderDecryption)
    return 0;

  CurBlockPos=Tell();

#ifndef SFX_MODULE
  if (OldFormat)
    return(ReadOldHeader());
#endif

  RawRead Raw(this);

  bool Decrypt=Encrypted && CurBlockPos>=(int64)SFXSize+SIZEOF_MARKHEAD+SIZEOF_NEWMHD;

  if (Decrypt)
  {
#if defined(SHELL_EXT) || defined(RAR_NOCRYPT)
    return(0);
#else
    if (Read(HeadersSalt,SALT_SIZE)!=SALT_SIZE)
    {
      UnexpEndArcMsg();
      return(0);
    }
    if (*Cmd->Password==0)
    {
#ifdef RARDLL
      char PasswordA[MAXPASSWORD];
      if (Cmd->Callback==NULL ||
          Cmd->Callback(UCM_NEEDPASSWORD,Cmd->UserData,(LPARAM)PasswordA,ASIZE(PasswordA))==-1)
      {
        Close();
        //ErrHandler.Exit(USER_BREAK); original
        ErrHandler.Exit(NO_PASSWORD_ERROR);
      }
      GetWideName(PasswordA,NULL,Cmd->Password,ASIZE(Cmd->Password));
#else
      if (!GetPassword(PASSWORD_ARCHIVE,FileName,FileNameW,Cmd->Password,ASIZE(Cmd->Password)))
      {
        Close();
        ErrHandler.Exit(USER_BREAK);
      }
#endif
    }
    HeadersCrypt.SetCryptKeys(Cmd->Password,HeadersSalt,false,false,NewMhd.EncryptVer>=36);
    Raw.SetCrypt(&HeadersCrypt);
#endif
  }

  Raw.Read(SIZEOF_SHORTBLOCKHEAD);
  if (Raw.Size()==0)
  {
    UnexpEndArcMsg();
    return(0);
  }

  Raw.Get(ShortBlock.HeadCRC);
  byte HeadType;
  Raw.Get(HeadType);
  ShortBlock.HeadType=(HEADER_TYPE)HeadType;
  Raw.Get(ShortBlock.Flags);
  Raw.Get(ShortBlock.HeadSize);
  if (ShortBlock.HeadSize<SIZEOF_SHORTBLOCKHEAD)
  {
#ifndef SHELL_EXT
    Log(FileName,St(MLogFileHead),"???");
#endif
    BrokenFileHeader=true;
    ErrHandler.SetErrorCode(CRC_ERROR);
    return(0);
  }

  if (ShortBlock.HeadType==COMM_HEAD)
  {
    // Old style (up to RAR 2.9) comment header embedded into main
    // or file header. We must not read the entire ShortBlock.HeadSize here
    // to not break the comment processing logic later.
    Raw.Read(SIZEOF_COMMHEAD-SIZEOF_SHORTBLOCKHEAD);
  }
  else
    if (ShortBlock.HeadType==MAIN_HEAD && (ShortBlock.Flags & MHD_COMMENT)!=0)
    {
      // Old style (up to RAR 2.9) main archive comment embedded into
      // the main archive header found. While we can read the entire 
      // ShortBlock.HeadSize here and remove this part of "if", it would be
      // waste of memory, because we'll read and process this comment data
      // in other function anyway and we do not need them here now.
      Raw.Read(SIZEOF_NEWMHD-SIZEOF_SHORTBLOCKHEAD);
    }
    else
      Raw.Read(ShortBlock.HeadSize-SIZEOF_SHORTBLOCKHEAD);

  NextBlockPos=CurBlockPos+ShortBlock.HeadSize;

  switch(ShortBlock.HeadType)
  {
    case MAIN_HEAD:
      *(BaseBlock *)&NewMhd=ShortBlock;
      Raw.Get(NewMhd.HighPosAV);
      Raw.Get(NewMhd.PosAV);
      if (NewMhd.Flags & MHD_ENCRYPTVER)
        Raw.Get(NewMhd.EncryptVer);
      break;
    case ENDARC_HEAD:
      *(BaseBlock *)&EndArcHead=ShortBlock;
      if (EndArcHead.Flags & EARC_DATACRC)
        Raw.Get(EndArcHead.ArcDataCRC);
      if (EndArcHead.Flags & EARC_VOLNUMBER)
        Raw.Get(EndArcHead.VolNumber);
      break;
    case FILE_HEAD:
    case NEWSUB_HEAD:
      {
        FileHeader *hd=ShortBlock.HeadType==FILE_HEAD ? &NewLhd:&SubHead;
        *(BaseBlock *)hd=ShortBlock;
        Raw.Get(hd->PackSize);
        Raw.Get(hd->UnpSize);
        Raw.Get(hd->HostOS);
        Raw.Get(hd->FileCRC);
        Raw.Get(hd->FileTime);
        Raw.Get(hd->UnpVer);
        Raw.Get(hd->Method);
        Raw.Get(hd->NameSize);
        Raw.Get(hd->FileAttr);
        if (hd->Flags & LHD_LARGE)
        {
          Raw.Get(hd->HighPackSize);
          Raw.Get(hd->HighUnpSize);
        }
        else 
        {
          hd->HighPackSize=hd->HighUnpSize=0;
          if (hd->UnpSize==0xffffffff)
          {
            // UnpSize equal to 0xffffffff without LHD_LARGE flag indicates
            // that we do not know the unpacked file size and must unpack it
            // until we find the end of file marker in compressed data.
            hd->UnpSize=(uint)(INT64NDF);
            hd->HighUnpSize=(uint)(INT64NDF>>32);
          }
        }
        hd->FullPackSize=INT32TO64(hd->HighPackSize,hd->PackSize);
        hd->FullUnpSize=INT32TO64(hd->HighUnpSize,hd->UnpSize);

        char FileName[NM*4];
        size_t NameSize=Min(hd->NameSize,sizeof(FileName)-1);
        Raw.Get((byte *)FileName,NameSize);
        FileName[NameSize]=0;

        strncpyz(hd->FileName,FileName,ASIZE(hd->FileName));

        if (hd->HeadType==NEWSUB_HEAD)
        {
          // Let's calculate the size of optional data.
          int DataSize=hd->HeadSize-hd->NameSize-SIZEOF_NEWLHD;
          if (hd->Flags & LHD_SALT)
            DataSize-=SALT_SIZE;
          if (DataSize>0)
          {
            // Here we read optional additional fields for subheaders.
            // They are stored after the file name and before salt.
            hd->SubData.Alloc(DataSize);
            Raw.Get(&hd->SubData[0],DataSize);
            if (hd->CmpName(SUBHEAD_TYPE_RR))
            {
              byte *D=&hd->SubData[8];
              RecoverySectors=D[0]+((uint)D[1]<<8)+((uint)D[2]<<16)+((uint)D[3]<<24);
            }
          }
        }
        else
          if (hd->HeadType==FILE_HEAD)
          {
            if (hd->Flags & LHD_UNICODE)
            {
              EncodeFileName NameCoder;
              size_t Length=strlen(FileName);
              if (Length==hd->NameSize)
              {
                UtfToWide(FileName,hd->FileNameW,sizeof(hd->FileNameW)/sizeof(hd->FileNameW[0])-1);
                WideToChar(hd->FileNameW,hd->FileName,sizeof(hd->FileName)/sizeof(hd->FileName[0])-1);
                ExtToInt(hd->FileName,hd->FileName);
              }
              else
              {
                Length++;
                NameCoder.Decode(FileName,(byte *)FileName+Length,
                                 hd->NameSize-Length,hd->FileNameW,
                                 sizeof(hd->FileNameW)/sizeof(hd->FileNameW[0]));
              }
              if (*hd->FileNameW==0)
                hd->Flags &= ~LHD_UNICODE;
            }
            else
              *hd->FileNameW=0;
#ifndef SFX_MODULE
            ConvertNameCase(hd->FileName);
            ConvertNameCase(hd->FileNameW);
#endif
            ConvertUnknownHeader();
          }
        if (hd->Flags & LHD_SALT)
          Raw.Get(hd->Salt,SALT_SIZE);
        hd->mtime.SetDos(hd->FileTime);
        hd->ctime.Reset();
        hd->atime.Reset();
        hd->arctime.Reset();
        if (hd->Flags & LHD_EXTTIME)
        {
          ushort Flags;
          Raw.Get(Flags);
          RarTime *tbl[4];
          tbl[0]=&NewLhd.mtime;
          tbl[1]=&NewLhd.ctime;
          tbl[2]=&NewLhd.atime;
          tbl[3]=&NewLhd.arctime;
          for (int I=0;I<4;I++)
          {
            RarTime *CurTime=tbl[I];
            uint rmode=Flags>>(3-I)*4;
            if ((rmode & 8)==0)
              continue;
            if (I!=0)
            {
              uint DosTime;
              Raw.Get(DosTime);
              CurTime->SetDos(DosTime);
            }
            RarLocalTime rlt;
            CurTime->GetLocal(&rlt);
            if (rmode & 4)
              rlt.Second++;
            rlt.Reminder=0;
            int count=rmode&3;
            for (int J=0;J<count;J++)
            {
              byte CurByte;
              Raw.Get(CurByte);
              rlt.Reminder|=(((uint)CurByte)<<((J+3-count)*8));
            }
            CurTime->SetLocal(&rlt);
          }
        }
        NextBlockPos+=hd->FullPackSize;
        bool CRCProcessedOnly=(hd->Flags & LHD_COMMENT)!=0;
        HeaderCRC=~Raw.GetCRC(CRCProcessedOnly)&0xffff;
        if (hd->HeadCRC!=HeaderCRC)
        {
          if (hd->HeadType==NEWSUB_HEAD && strlen(hd->FileName)<ASIZE(hd->FileName)-5)
            strcat(hd->FileName,"- ???");
          BrokenFileHeader=true;
          ErrHandler.SetErrorCode(WARNING);

          // If we have a broken encrypted header, we do not need to display
          // the error message here, because it will be displayed for such
          // headers later in this function. Also such headers are unlikely
          // to have anything sensible in file name field, so it is useless
          // to display the file name.
          bool EncBroken=Decrypt && ShortBlock.HeadCRC!=(~Raw.GetCRC(false)&0xffff);
          if (!EncBroken)
          {
#ifndef SHELL_EXT
            Log(Archive::FileName,St(MLogFileHead),IntNameToExt(hd->FileName));
            Alarm();
#endif
          }
        }
      }
Example #2
0
int Archive::ReadHeader()
{
  CurBlockPos=Tell();

#ifndef SFX_MODULE
  if (OldFormat)
    return(ReadOldHeader());
#endif

  RawRead Raw(this);

  bool Decrypt=Encrypted && CurBlockPos>=SFXSize+SIZEOF_MARKHEAD+SIZEOF_NEWMHD;

  if (Decrypt)
  {
#if defined(SHELL_EXT) || defined(NOCRYPT)
    return(0);
#else
    if (Read(HeadersSalt,SALT_SIZE)!=SALT_SIZE)
      return(0);
    if (*Cmd->Password==0)
#ifdef RARDLL
      if (Cmd->Callback==NULL ||
          Cmd->Callback(UCM_NEEDPASSWORD,Cmd->UserData,(LPARAM)Cmd->Password,sizeof(Cmd->Password))==-1)
      {
        Close();
        ErrHandler.Exit(USER_BREAK);
      }

#else
      if (!GetPassword(PASSWORD_ARCHIVE,FileName,Cmd->Password,sizeof(Cmd->Password)))
      {
        Close();
        ErrHandler.Exit(USER_BREAK);
      }
#endif
    HeadersCrypt.SetCryptKeys(Cmd->Password,HeadersSalt,false,false,NewMhd.EncryptVer>=36);
    Raw.SetCrypt(&HeadersCrypt);
#endif
  }

  Raw.Read(SIZEOF_SHORTBLOCKHEAD);
  if (Raw.Size()==0)
  {
    Int64 ArcSize=FileLength();
    if (CurBlockPos>ArcSize || NextBlockPos>ArcSize)
    {
  #ifndef SHELL_EXT
      Log(FileName,St(MLogUnexpEOF));
  #endif
      ErrHandler.SetErrorCode(WARNING);
    }
    return(0);
  }

  Raw.Get(ShortBlock.HeadCRC);
  byte HeadType;
  Raw.Get(HeadType);
  ShortBlock.HeadType=(HEADER_TYPE)HeadType;
  Raw.Get(ShortBlock.Flags);
  Raw.Get(ShortBlock.HeadSize);
  if (ShortBlock.HeadSize<SIZEOF_SHORTBLOCKHEAD)
  {
#ifndef SHELL_EXT
    Log(FileName,St(MLogFileHead),"???");
#endif
    BrokenFileHeader=true;
    ErrHandler.SetErrorCode(CRC_ERROR);
    return(0);
  }

  if (ShortBlock.HeadType==COMM_HEAD)
    Raw.Read(SIZEOF_COMMHEAD-SIZEOF_SHORTBLOCKHEAD);
  else
    if (ShortBlock.HeadType==MAIN_HEAD && (ShortBlock.Flags & MHD_COMMENT)!=0)
      Raw.Read(SIZEOF_NEWMHD-SIZEOF_SHORTBLOCKHEAD);
    else
      Raw.Read(ShortBlock.HeadSize-SIZEOF_SHORTBLOCKHEAD);

  NextBlockPos=CurBlockPos+ShortBlock.HeadSize;

  switch(ShortBlock.HeadType)
  {
    case MAIN_HEAD:
      *(BaseBlock *)&NewMhd=ShortBlock;
      Raw.Get(NewMhd.HighPosAV);
      Raw.Get(NewMhd.PosAV);
      if (NewMhd.Flags & MHD_ENCRYPTVER)
        Raw.Get(NewMhd.EncryptVer);
      break;
    case ENDARC_HEAD:
      *(BaseBlock *)&EndArcHead=ShortBlock;
      if (EndArcHead.Flags & EARC_DATACRC)
        Raw.Get(EndArcHead.ArcDataCRC);
      if (EndArcHead.Flags & EARC_VOLNUMBER)
        Raw.Get(EndArcHead.VolNumber);
      break;
    case FILE_HEAD:
    case NEWSUB_HEAD:
      {
        FileHeader *hd=ShortBlock.HeadType==FILE_HEAD ? &NewLhd:&SubHead;
        *(BaseBlock *)hd=ShortBlock;
        Raw.Get(hd->PackSize);
        Raw.Get(hd->UnpSize);
        Raw.Get(hd->HostOS);
        Raw.Get(hd->FileCRC);
        Raw.Get(hd->FileTime);
        Raw.Get(hd->UnpVer);
        Raw.Get(hd->Method);
        Raw.Get(hd->NameSize);
        Raw.Get(hd->FileAttr);
        if (hd->Flags & LHD_LARGE)
        {
          Raw.Get(hd->HighPackSize);
          Raw.Get(hd->HighUnpSize);
        }
        else 
        {
          hd->HighPackSize=hd->HighUnpSize=0;
          if (hd->UnpSize==0xffffffff)
          {
            hd->UnpSize=int64to32(INT64MAX);
            hd->HighUnpSize=int64to32(INT64MAX>>32);
          }
        }
        hd->FullPackSize=int32to64(hd->HighPackSize,hd->PackSize);
        hd->FullUnpSize=int32to64(hd->HighUnpSize,hd->UnpSize);

        char FileName[NM*4];
        int NameSize=Min(hd->NameSize,sizeof(FileName)-1);
        Raw.Get((byte *)FileName,NameSize);
        FileName[NameSize]=0;

        strncpyz(hd->FileName,FileName,ASIZE(hd->FileName));

        if (hd->HeadType==NEWSUB_HEAD)
        {
          int DataSize=hd->HeadSize-hd->NameSize-SIZEOF_NEWLHD;
          if (hd->Flags & LHD_SALT)
            DataSize-=SALT_SIZE;
          if (DataSize>0)
          {
            hd->SubData.Alloc(DataSize);
            Raw.Get(&hd->SubData[0],DataSize);
            if (hd->CmpName(SUBHEAD_TYPE_RR))
            {
              byte *D=&hd->SubData[8];
              RecoverySectors=D[0]+((uint)D[1]<<8)+((uint)D[2]<<16)+((uint)D[3]<<24);
            }
          }
        }
        else
          if (hd->HeadType==FILE_HEAD)
          {
            if (hd->Flags & LHD_UNICODE)
            {
              EncodeFileName NameCoder;
              int Length=strlen(FileName);
              if (Length==hd->NameSize)
              {
                UtfToWide(FileName,hd->FileNameW,sizeof(hd->FileNameW)/sizeof(hd->FileNameW[0])-1);
                WideToChar(hd->FileNameW,hd->FileName,sizeof(hd->FileName)/sizeof(hd->FileName[0])-1);
                ExtToInt(hd->FileName,hd->FileName);
              }
              else
              {
                Length++;
                NameCoder.Decode(FileName,(byte *)FileName+Length,
                                 hd->NameSize-Length,hd->FileNameW,
                                 sizeof(hd->FileNameW)/sizeof(hd->FileNameW[0]));
              }
              if (*hd->FileNameW==0)
                hd->Flags &= ~LHD_UNICODE;
            }
            else
              *hd->FileNameW=0;
#ifndef SFX_MODULE
            ConvertNameCase(hd->FileName);
            ConvertNameCase(hd->FileNameW);
#endif
            ConvertUnknownHeader();
          }
        if (hd->Flags & LHD_SALT)
          Raw.Get(hd->Salt,SALT_SIZE);
        hd->mtime.SetDos(hd->FileTime);
        hd->ctime.Reset();
        hd->atime.Reset();
        hd->arctime.Reset();
        if (hd->Flags & LHD_EXTTIME)
        {
          ushort Flags;
          Raw.Get(Flags);
          RarTime *tbl[4];
          tbl[0]=&NewLhd.mtime;
          tbl[1]=&NewLhd.ctime;
          tbl[2]=&NewLhd.atime;
          tbl[3]=&NewLhd.arctime;
          for (int I=0;I<4;I++)
          {
            RarTime *CurTime=tbl[I];
            uint rmode=Flags>>(3-I)*4;
            if ((rmode & 8)==0)
              continue;
            if (I!=0)
            {
              uint DosTime;
              Raw.Get(DosTime);
              CurTime->SetDos(DosTime);
            }
            RarLocalTime rlt;
            CurTime->GetLocal(&rlt);
            if (rmode & 4)
              rlt.Second++;
            rlt.Reminder=0;
            int count=rmode&3;
            for (int J=0;J<count;J++)
            {
              byte CurByte;
              Raw.Get(CurByte);
              rlt.Reminder|=(((uint)CurByte)<<((J+3-count)*8));
            }
            CurTime->SetLocal(&rlt);
          }
        }
        NextBlockPos+=hd->FullPackSize;
        bool CRCProcessedOnly=(hd->Flags & LHD_COMMENT)!=0;
        HeaderCRC=~Raw.GetCRC(CRCProcessedOnly)&0xffff;
        if (hd->HeadCRC!=HeaderCRC)
        {
          if (hd->HeadType==NEWSUB_HEAD)
            strcat(hd->FileName,"- ???");
          BrokenFileHeader=true;
          ErrHandler.SetErrorCode(WARNING);
#ifndef SHELL_EXT
          Log(Archive::FileName,St(MLogFileHead),IntNameToExt(hd->FileName));
          Alarm();
#endif
        }
      }
Example #3
0
int Archive::ReadHeader()
{
  CurBlockPos=Tell();

#ifndef SFX_MODULE
  if (OldFormat)
    return(ReadOldHeader());
#endif

  RawRead Raw(this);

  bool Decrypt=Encrypted && CurBlockPos>=SFXSize+SIZEOF_MARKHEAD+SIZEOF_NEWMHD;

  if (Decrypt)
  {
#if defined(SHELL_EXT) || defined(NOCRYPT)
    return(0);
#else
    if (Read(HeadersSalt,SALT_SIZE)!=SALT_SIZE)
      return(0);
    if (*Cmd->Password==0)
#ifdef RARDLL
      if (Cmd->Callback==NULL ||
          Cmd->Callback(UCM_NEEDPASSWORD,Cmd->UserData,(LONG)Cmd->Password,sizeof(Cmd->Password))==-1)
      {
        Close();
        ErrHandler.Exit(USER_BREAK);
      }

#else
      if (!GetPassword(PASSWORD_ARCHIVE,FileName,Cmd->Password,sizeof(Cmd->Password)))
      {
        Close();
        ErrHandler.Exit(USER_BREAK);
      }
#endif
    HeadersCrypt.SetCryptKeys(Cmd->Password,HeadersSalt,false);
    Raw.SetCrypt(&HeadersCrypt);
#endif
  }

  Raw.Read(SIZEOF_SHORTBLOCKHEAD);
  if (Raw.Size()==0)
  {
    Int64 ArcSize=FileLength();
    if (CurBlockPos>ArcSize || NextBlockPos>ArcSize)
    {
  #ifndef SHELL_EXT
      Log(FileName,St(MLogUnexpEOF));
  #endif
      ErrHandler.SetErrorCode(WARNING);
    }
    return(0);
  }

  Raw.Get(ShortBlock.HeadCRC);
  unsigned char HeadType;
  Raw.Get(HeadType);
  ShortBlock.HeadType=(HEADER_TYPE)HeadType;
  Raw.Get(ShortBlock.Flags);
  Raw.Get(ShortBlock.HeadSize);
  if (ShortBlock.HeadSize<SIZEOF_SHORTBLOCKHEAD)
  {
#ifndef SHELL_EXT
    Log(FileName,St(MLogFileHead),"???");
#endif
    BrokenFileHeader=true;
    ErrHandler.SetErrorCode(CRC_ERROR);
    return(0);
  }

  if (ShortBlock.HeadType==COMM_HEAD)
    Raw.Read(SIZEOF_COMMHEAD-SIZEOF_SHORTBLOCKHEAD);
  else
    if (ShortBlock.HeadType==MAIN_HEAD && (ShortBlock.Flags & MHD_COMMENT)!=0)
      Raw.Read(SIZEOF_NEWMHD-SIZEOF_SHORTBLOCKHEAD);
    else
      Raw.Read(ShortBlock.HeadSize-SIZEOF_SHORTBLOCKHEAD);

  NextBlockPos=CurBlockPos+ShortBlock.HeadSize;

  switch(ShortBlock.HeadType)
  {
    case MAIN_HEAD:
      *(BaseBlock *)&NewMhd=ShortBlock;
      Raw.Get(NewMhd.HighPosAV);
      Raw.Get(NewMhd.PosAV);
      break;
    case ENDARC_HEAD:
      *(BaseBlock *)&EndArcHead=ShortBlock;
      if (EndArcHead.Flags & EARC_DATACRC)
        Raw.Get(EndArcHead.ArcDataCRC);
      break;
    case FILE_HEAD:
    case NEWSUB_HEAD:
      {
        FileHeader *hd=ShortBlock.HeadType==FILE_HEAD ? &NewLhd:&SubHead;
        *(BaseBlock *)hd=ShortBlock;
        Raw.Get(hd->PackSize);
        Raw.Get(hd->UnpSize);
        Raw.Get(hd->HostOS);
        Raw.Get(hd->FileCRC);
        Raw.Get(hd->FileTime);
        Raw.Get(hd->UnpVer);
        Raw.Get(hd->Method);
        Raw.Get(hd->NameSize);
        Raw.Get(hd->FileAttr);
        if (hd->Flags & LHD_LARGE)
        {
          Raw.Get(hd->HighPackSize);
          Raw.Get(hd->HighUnpSize);
        }
        else 
          hd->HighPackSize=hd->HighUnpSize=0;
        hd->FullPackSize=int32to64(hd->HighPackSize,hd->PackSize);
        hd->FullUnpSize=int32to64(hd->HighUnpSize,hd->UnpSize);

        char FileName[NM*4];
        int NameSize=Min(hd->NameSize,sizeof(FileName)-1);
        Raw.Get((unsigned char *)FileName,NameSize);
        FileName[NameSize]=0;

        strncpy(hd->FileName,FileName,sizeof(hd->FileName));
        hd->FileName[sizeof(hd->FileName)-1]=0;

        if (hd->HeadType==NEWSUB_HEAD)
        {
          int DataSize=hd->HeadSize-hd->NameSize-SIZEOF_NEWLHD;
          if (hd->Flags & LHD_SALT)
            DataSize-=SALT_SIZE;
          if (DataSize>0)
          {
            hd->SubData.Alloc(DataSize);
            Raw.Get(&hd->SubData[0],DataSize);
            if (hd->CmpName(SUBHEAD_TYPE_RR))
            {
              unsigned char *D=&hd->SubData[8];
              RecoverySectors=D[0]+((unsigned int)D[1]<<8)+((unsigned int)D[2]<<16)+((unsigned int)D[3]<<24);
            }
          }
        }
        else
          if (hd->HeadType==FILE_HEAD)
          {
            if (hd->Flags & LHD_UNICODE)
            {
              EncodeFileName NameCoder;
              int Length=strlen(FileName)+1;
              NameCoder.Decode(FileName,(unsigned char *)FileName+Length,
                               hd->NameSize-Length,hd->FileNameW,
                               sizeof(hd->FileNameW)/sizeof(hd->FileNameW[0]));
              if (*hd->FileNameW==0)
                hd->Flags &= ~LHD_UNICODE;
            }
            else
              *hd->FileNameW=0;
#ifndef SFX_MODULE
            ConvertNameCase(hd->FileName);
            ConvertNameCase(hd->FileNameW);
#endif
            ConvertUnknownHeader();
          }
        if (hd->Flags & LHD_SALT)
          Raw.Get(hd->Salt,SALT_SIZE);
        hd->mtime.SetDos(hd->FileTime);
        hd->ctime.Reset();
        hd->atime.Reset();
        hd->arctime.Reset();
        if (hd->Flags & LHD_EXTTIME)
        {
          unsigned short Flags;
          Raw.Get(Flags);
          RarTime *tbl[4];
          tbl[0]=&NewLhd.mtime;
          tbl[1]=&NewLhd.ctime;
          tbl[2]=&NewLhd.atime;
          tbl[3]=&NewLhd.arctime;
          for (int I=0;I<4;I++)
          {
            RarTime *CurTime=tbl[I];
            unsigned int rmode=Flags>>(3-I)*4;
            if ((rmode & 8)==0)
              continue;
            if (I!=0)
            {
              unsigned int DosTime;
              Raw.Get(DosTime);
              CurTime->SetDos(DosTime);
            }
            RarLocalTime rlt;
            CurTime->GetLocal(&rlt);
            if (rmode & 4)
              rlt.Second++;
            rlt.Reminder=0;
            int count=rmode&3;
            for (int J=0;J<count;J++)
            {
              unsigned char CurByte;
              Raw.Get(CurByte);
              rlt.Reminder|=(((unsigned int)CurByte)<<((J+3-count)*8));
            }
            CurTime->SetLocal(&rlt);
          }
        }
        NextBlockPos+=hd->FullPackSize;
        bool CRCProcessedOnly=(hd->Flags & LHD_COMMENT)!=0;
        HeaderCRC=~Raw.GetCRC(CRCProcessedOnly)&0xffff;
        if (hd->HeadCRC!=HeaderCRC)
        {
          if (hd->HeadType==NEWSUB_HEAD)
            strcat(hd->FileName,"- ???");
          BrokenFileHeader=true;
          ErrHandler.SetErrorCode(WARNING);
#ifndef SHELL_EXT
          Log(Archive::FileName,St(MLogFileHead),IntNameToExt(hd->FileName));
          Alarm();
#endif
        }
      }
      break;
#ifndef SFX_MODULE
    case COMM_HEAD:
      *(BaseBlock *)&CommHead=ShortBlock;
      Raw.Get(CommHead.UnpSize);
      Raw.Get(CommHead.UnpVer);
      Raw.Get(CommHead.Method);
      Raw.Get(CommHead.CommCRC);
      break;
    case SIGN_HEAD:
      *(BaseBlock *)&SignHead=ShortBlock;
      Raw.Get(SignHead.CreationTime);
      Raw.Get(SignHead.ArcNameSize);
      Raw.Get(SignHead.UserNameSize);
      break;
    case AV_HEAD:
      *(BaseBlock *)&AVHead=ShortBlock;
      Raw.Get(AVHead.UnpVer);
      Raw.Get(AVHead.Method);
      Raw.Get(AVHead.AVVer);
      Raw.Get(AVHead.AVInfoCRC);
      break;
    case PROTECT_HEAD:
      *(BaseBlock *)&ProtectHead=ShortBlock;
      Raw.Get(ProtectHead.DataSize);
      Raw.Get(ProtectHead.Version);
      Raw.Get(ProtectHead.RecSectors);
      Raw.Get(ProtectHead.TotalBlocks);
      Raw.Get(ProtectHead.Mark,8);
      NextBlockPos+=ProtectHead.DataSize;
      RecoverySectors=ProtectHead.RecSectors;
      break;
    case SUB_HEAD:
      *(BaseBlock *)&SubBlockHead=ShortBlock;
      Raw.Get(SubBlockHead.DataSize);
      NextBlockPos+=SubBlockHead.DataSize;
      Raw.Get(SubBlockHead.SubType);
      Raw.Get(SubBlockHead.Level);
      switch(SubBlockHead.SubType)
      {
        case UO_HEAD:
          *(SubBlockHeader *)&UOHead=SubBlockHead;
          Raw.Get(UOHead.OwnerNameSize);
          Raw.Get(UOHead.GroupNameSize);
          Raw.Get((unsigned char *)UOHead.OwnerName,UOHead.OwnerNameSize);
          Raw.Get((unsigned char *)UOHead.GroupName,UOHead.GroupNameSize);
          if (UOHead.OwnerNameSize>NM-1)
            UOHead.OwnerNameSize=NM-1;
          if (UOHead.GroupNameSize>NM-1)
            UOHead.GroupNameSize=NM-1;
          UOHead.OwnerName[UOHead.OwnerNameSize]=0;
          UOHead.GroupName[UOHead.GroupNameSize]=0;
          break;
        case MAC_HEAD:
          *(SubBlockHeader *)&MACHead=SubBlockHead;
          Raw.Get(MACHead.fileType);
          Raw.Get(MACHead.fileCreator);
          break;
        case EA_HEAD:
        case BEEA_HEAD:
        case NTACL_HEAD:
          *(SubBlockHeader *)&EAHead=SubBlockHead;
          Raw.Get(EAHead.UnpSize);
          Raw.Get(EAHead.UnpVer);
          Raw.Get(EAHead.Method);
          Raw.Get(EAHead.EACRC);
          break;
        case STREAM_HEAD:
          *(SubBlockHeader *)&StreamHead=SubBlockHead;
          Raw.Get(StreamHead.UnpSize);
          Raw.Get(StreamHead.UnpVer);
          Raw.Get(StreamHead.Method);
          Raw.Get(StreamHead.StreamCRC);
          Raw.Get(StreamHead.StreamNameSize);
          if (StreamHead.StreamNameSize>NM-1)
            StreamHead.StreamNameSize=NM-1;
          Raw.Get((unsigned char *)StreamHead.StreamName,StreamHead.StreamNameSize);
          StreamHead.StreamName[StreamHead.StreamNameSize]=0;
          break;
      }
      break;
#endif
    default:
      if (ShortBlock.Flags & LONG_BLOCK)
      {
        unsigned int DataSize;
        Raw.Get(DataSize);
        NextBlockPos+=DataSize;
      }
      break;
  }