Esempio n. 1
0
// Convert archived names and comments to Unicode.
// Allows user to select a code page in GUI.
void ArcCharToWide(const char *Src,wchar *Dest,size_t DestSize,ACTW_ENCODING Encoding)
{
#if defined(_WIN_ALL) // Console Windows RAR.
  if (Encoding==ACTW_UTF8)
    UtfToWide(Src,Dest,DestSize);
  else
  {
    Array<char> NameA;
    if (Encoding==ACTW_OEM)
    {
      NameA.Alloc(DestSize+1);
      IntToExt(Src,&NameA[0],NameA.Size());
      Src=&NameA[0];
    }
    CharToWide(Src,Dest,DestSize);
  }
#else // RAR for Unix.
  if (Encoding==ACTW_UTF8)
    UtfToWide(Src,Dest,DestSize);
  else
    CharToWide(Src,Dest,DestSize);
#endif
  // Ensure that we return a zero terminate string for security reason.
  // While [Jni]CharToWide might already do it, be protected in case of future
  // changes in these functions.
  if (DestSize>0)
    Dest[DestSize-1]=0;
}
Esempio n. 2
0
bool FindFile::FastFind(const char *FindMask,const wchar *FindMaskW,struct FindData *fd,bool GetSymLink)
{
  fd->Error=false;
#ifndef _UNIX
  if (IsWildcard(FindMask,FindMaskW))
    return(false);
#endif    
#ifdef _WIN_32
  HANDLE hFind=Win32Find(INVALID_HANDLE_VALUE,FindMask,FindMaskW,fd);
  if (hFind==INVALID_HANDLE_VALUE)
    return(false);
  FindClose(hFind);
#else
  struct stat st;
  if (GetSymLink)
  {
#ifdef SAVE_LINKS
    if (lstat(FindMask,&st)!=0)
#else
    if (stat(FindMask,&st)!=0)
#endif
    {
      fd->Error=(errno!=ENOENT);
      return(false);
    }
  }
  else
    if (stat(FindMask,&st)!=0)
    {
      fd->Error=(errno!=ENOENT);
      return(false);
    }
#ifdef _DJGPP
  fd->FileAttr=_chmod(FindMask,0);
#elif defined(_EMX)
  fd->FileAttr=st.st_attr;
#else
  fd->FileAttr=st.st_mode;
#endif
  fd->IsDir=IsDir(st.st_mode);
  fd->Size=st.st_size;
  fd->mtime=st.st_mtime;
  fd->atime=st.st_atime;
  fd->ctime=st.st_ctime;
  fd->FileTime=fd->mtime.GetDos();
  strcpy(fd->Name,FindMask);

  *fd->NameW=0;
#ifdef _APPLE
  if (!LowAscii(fd->Name))
    UtfToWide(fd->Name,fd->NameW,sizeof(fd->NameW));
#elif defined(UNICODE_SUPPORTED)
  if (!LowAscii(fd->Name) && UnicodeEnabled())
    CharToWide(fd->Name,fd->NameW);
#endif
#endif
  fd->Flags=0;
  fd->IsDir=IsDir(fd->FileAttr);
  return(true);
}
Esempio n. 3
0
bool CharToWide(const char *Src,wchar *Dest,size_t DestSize)
{
  bool RetCode=true;
  *Dest=0; // Set 'Dest' to zero just in case the conversion will fail.

#ifdef _WIN_ALL
  if (MultiByteToWideChar(CP_ACP,0,Src,-1,Dest,(int)DestSize)==0)
    RetCode=false;

#elif defined(_APPLE)
  UtfToWide(Src,Dest,DestSize);

#elif defined(MBFUNCTIONS)
  size_t ResultingSize=mbstowcs(Dest,Src,DestSize);
  if (ResultingSize==(size_t)-1)
    RetCode=false;
  if (ResultingSize==0 && *Src!=0)
    RetCode=false;

  if ((!RetCode || *Dest==0 && *Src!=0) && DestSize>NM && strlen(Src)<NM)
  {
    /* Workaround for strange Linux Unicode functions bug.
       Some of wcstombs and mbstowcs implementations in some situations
       (we are yet to find out what it depends on) can return an empty
       string and success code if buffer size value is too large.
    */
    return(CharToWide(Src,Dest,NM));
  }
#else
  if (UnicodeEnabled())
  {
#if defined(_EMX) && !defined(_DJGPP)
    int len=Min(strlen(Src)+1,DestSize-1);
    if (uni_toucs((char*)Src,len,(UniChar*)Dest,(size_t*)&DestSize)==-1 ||
        DestSize>len)
      DestSize=0;
    RetCode=false;
#endif
  }
  else
    for (int I=0;I<DestSize;I++)
    {
      Dest[I]=(wchar_t)Src[I];
      if (Src[I]==0)
        break;
    }
#endif

  // We tried to return the zero terminated string if conversion is failed,
  // but it does not work well. MultiByteToWideChar returns 'failed' code
  // even if we wanted to convert only a part of string and passed DestSize
  // smaller than required for fully converted string. Such call is the valid
  // behavior in RAR code and we do not expect the empty string in this case.

  return(RetCode);
}
Esempio n. 4
0
bool CharToWide(const char *Src,wchar *Dest,size_t DestSize)
{
  bool RetCode=true;
#ifdef _WIN_32
  if (MultiByteToWideChar(CP_ACP,0,Src,-1,Dest,(int)DestSize)==0)
    RetCode=false;
#else
#ifdef _APPLE
  UtfToWide(Src,Dest,DestSize);
#else
#ifdef MBFUNCTIONS

  size_t ResultingSize=mbstowcs(Dest,Src,DestSize);
  if (ResultingSize==(size_t)-1)
    RetCode=false;
  if (ResultingSize==0 && *Src!=0)
    RetCode=false;

  if ((!RetCode || *Dest==0 && *Src!=0) && DestSize>NM && strlen(Src)<NM)
  {
    /* Workaround for strange Linux Unicode functions bug.
       Some of wcstombs and mbstowcs implementations in some situations
       (we are yet to find out what it depends on) can return an empty
       string and success code if buffer size value is too large.
    */
    return(CharToWide(Src,Dest,NM));
  }
#else
  if (UnicodeEnabled())
  {
#if defined(_EMX) && !defined(_DJGPP)
    int len=Min(strlen(Src)+1,DestSize-1);
    if (uni_toucs((char*)Src,len,(UniChar*)Dest,(size_t*)&DestSize)==-1 ||
        DestSize>len)
      DestSize=0;
    RetCode=false;
#endif
  }
  else
    for (int I=0;I<DestSize;I++)
    {
      Dest[I]=(wchar_t)Src[I];
      if (Src[I]==0)
        break;
    }
#endif
#endif
#endif
  return(RetCode);
}
Esempio n. 5
0
bool CharToWide(const char *Src,wchar *Dest,size_t DestSize)
{
  bool RetCode=true;
  *Dest=0; // Set 'Dest' to zero just in case the conversion will fail.

#ifdef _WIN_ALL
  if (MultiByteToWideChar(CP_ACP,0,Src,-1,Dest,(int)DestSize)==0)
    RetCode=false;

// mbstowcs is broken in Android NDK r9.
#elif defined(_APPLE) || defined(_ANDROID)
  UtfToWide(Src,Dest,DestSize);

#elif defined(MBFUNCTIONS)
  mbstate_t ps;
  memset (&ps, 0, sizeof(ps));
  const char *SrcParam=Src; // mbsrtowcs can change the pointer.
  size_t ResultingSize=mbsrtowcs(Dest,&SrcParam,DestSize,&ps);
  if (ResultingSize==(size_t)-1)
    RetCode=false;
  if (ResultingSize==0 && *Src!=0)
    RetCode=false;

  if (RetCode==false && DestSize>1)
    CharToWideMap(Src,Dest,DestSize,RetCode);
#else
  for (int I=0;I<DestSize;I++)
  {
    Dest[I]=(wchar_t)Src[I];
    if (Src[I]==0)
      break;
  }
#endif
  if (DestSize>0)
    Dest[DestSize-1]=0;

  // We tried to return the empty string if conversion is failed,
  // but it does not work well. MultiByteToWideChar returns 'failed' code
  // even if we wanted to convert only a part of string and passed DestSize
  // smaller than required for fully converted string. Such call is the valid
  // behavior in RAR code and we do not expect the empty string in this case.

  return RetCode;
}
Esempio n. 6
0
void GetStreamNameNTFS(Archive &Arc,wchar *StreamName,size_t MaxSize)
{
  byte *Data=&Arc.SubHead.SubData[0];
  size_t DataSize=Arc.SubHead.SubData.Size();
  if (Arc.Format==RARFMT15)
  {
    size_t DestSize=Min(DataSize/2,MaxSize-1);
    RawToWide(Data,StreamName,DestSize);
    StreamName[DestSize]=0;
  }
  else
  {
    char UtfString[NM*4];
    size_t DestSize=Min(DataSize,ASIZE(UtfString)-1);
    memcpy(UtfString,Data,DestSize);
    UtfString[DestSize]=0;
    UtfToWide(UtfString,StreamName,MaxSize);
  }
}
Esempio n. 7
0
bool CharToWide(const char *Src,wchar *Dest,int DestSize)
{
  bool RetCode=true;
#ifdef _WIN_32
  if (MultiByteToWideChar(CP_ACP,0,Src,-1,Dest,DestSize)==0)
    RetCode=false;
#else
#ifdef _APPLE
  UtfToWide(Src,Dest,DestSize);
#else
#ifdef MBFUNCTIONS
  if (mbstowcs(Dest,Src,DestSize)==-1)
    RetCode=false;
#else
  if (UnicodeEnabled())
  {
#if defined(_EMX) && !defined(_DJGPP)
    int len=Min(strlen(Src)+1,DestSize-1);
    if (uni_toucs((char*)Src,len,(UniChar*)Dest,(size_t*)&DestSize)==-1 ||
        DestSize>len)
      DestSize=0;
    RetCode=false;
#endif
  }
  else
    for (int I=0;I<DestSize;I++)
    {
      Dest[I]=(wchar_t)Src[I];
      if (Src[I]==0)
        break;
    }
#endif
#endif
#endif
  return(RetCode);
}
Esempio n. 8
0
bool Archive::ReadCommentData(Array<wchar> *CmtData)
{
  Array<byte> CmtRaw;
  if (!ReadSubData(&CmtRaw,NULL))
    return false;
  size_t CmtSize=CmtRaw.Size();
  CmtRaw.Push(0);
  CmtData->Alloc(CmtSize+1);
  if (Format==RARFMT50)
    UtfToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtData->Size());
  else
    if ((SubHead.SubFlags & SUBHEAD_FLAGS_CMT_UNICODE)!=0)
    {
      RawToWide(&CmtRaw[0],CmtData->Addr(0),CmtSize/2);
      (*CmtData)[CmtSize/2]=0;

    }
    else
    {
      CharToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtData->Size());
    }
  CmtData->Alloc(wcslen(CmtData->Addr(0))); // Set buffer size to actual comment length.
  return true;
}
Esempio n. 9
0
bool FindFile::Next(struct FindData *fd,bool GetSymLink)
{
  fd->Error=false;
  if (*FindMask==0)
    return(false);
#ifdef _WIN_32
  if (FirstCall)
  {
    if ((hFind=Win32Find(INVALID_HANDLE_VALUE,FindMask,FindMaskW,fd))==INVALID_HANDLE_VALUE)
      return(false);
  }
  else
    if (Win32Find(hFind,FindMask,FindMaskW,fd)==INVALID_HANDLE_VALUE)
      return(false);
#else
  if (FirstCall)
  {
    char DirName[NM];
    strcpy(DirName,FindMask);
    RemoveNameFromPath(DirName);
    if (*DirName==0)
      strcpy(DirName,".");
/*
    else
    {
      int Length=strlen(DirName);
      if (Length>1 && DirName[Length-1]==CPATHDIVIDER && (Length!=3 || !IsDriveDiv(DirName[1])))
        DirName[Length-1]=0;
    }
*/
    if ((dirp=opendir(DirName))==NULL)
    {
      fd->Error=(errno!=ENOENT);
      return(false);
    }
  }
  while (1)
  {
    struct dirent *ent=readdir(dirp);
    if (ent==NULL)
      return(false);
    if (strcmp(ent->d_name,".")==0 || strcmp(ent->d_name,"..")==0)
      continue;
    if (CmpName(FindMask,ent->d_name,MATCH_NAMES))
    {
      char FullName[NM];
      strcpy(FullName,FindMask);
      *PointToName(FullName)=0;
      if (strlen(FullName)+strlen(ent->d_name)>=ASIZE(FullName)-1)
      {
#ifndef SILENT
        Log(NULL,"\n%s%s",FullName,ent->d_name);
        Log(NULL,St(MPathTooLong));
#endif
        return(false);
      }
      strcat(FullName,ent->d_name);
      if (!FastFind(FullName,NULL,fd,GetSymLink))
      {
        ErrHandler.OpenErrorMsg(FullName);
        continue;
      }
      strcpy(fd->Name,FullName);
      break;
    }
  }
  *fd->NameW=0;
#ifdef _APPLE
  if (!LowAscii(fd->Name))
    UtfToWide(fd->Name,fd->NameW,sizeof(fd->NameW));
#elif defined(UNICODE_SUPPORTED)
  if (!LowAscii(fd->Name) && UnicodeEnabled())
    CharToWide(fd->Name,fd->NameW);
#endif
#endif
  fd->Flags=0;
  fd->IsDir=IsDir(fd->FileAttr);
  FirstCall=false;
  char *Name=PointToName(fd->Name);
  if (strcmp(Name,".")==0 || strcmp(Name,"..")==0)
    return(Next(fd));
  return(true);
}
Esempio n. 10
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
        }
      }
Esempio n. 11
0
bool WideToChar(const wchar *Src,char *Dest,int DestSize)
{
  bool RetCode=true;
#ifdef _WIN_32
  if (WideCharToMultiByte(CP_ACP,0,Src,-1,Dest,DestSize,NULL,NULL)==0)
    RetCode=false;
#else
#ifdef _APPLE
  WideToUtf(Src,Dest,DestSize);
#else
#ifdef MBFUNCTIONS
  if (wcstombs(Dest,Src,DestSize)==(uint)-1)
    RetCode=false;
#else
  if (UnicodeEnabled())
  {
    for (int I=0;I<DestSize;I++)
    {
      Dest[I]=(char)Src[I];
      if (Src[I]==0)
        break;
  }
#endif
#endif
#endif
  return(RetCode);
}


bool CharToWide(const char *Src,wchar *Dest,int DestSize)
{
  bool RetCode=true;
#ifdef _WIN_32
  if (MultiByteToWideChar(CP_ACP,0,Src,-1,Dest,DestSize)==0)
    RetCode=false;
#else
#ifdef _APPLE
  UtfToWide(Src,Dest,DestSize);
#else
#ifdef MBFUNCTIONS
  mbstowcs(Dest,Src,DestSize);
#else
  if (UnicodeEnabled())
  {
    for (int I=0;I<DestSize;I++)
    {
      Dest[I]=(wchar_t)Src[I];
      if (Src[I]==0)
        break;
  }
#endif
#endif
#endif
  return(RetCode);
}


byte* WideToRaw(const wchar *Src,byte *Dest,int DestSize)
{
  for (int I=0;I<DestSize;I++,Src++)
  {
    Dest[I*2]=(byte)*Src;
    Dest[I*2+1]=(byte)(*Src>>8);
    if (*Src==0)
      break;
  }
  return(Dest);
}


wchar* RawToWide(const byte *Src,wchar *Dest,int DestSize)
{
  for (int I=0;I<DestSize;I++)
    if ((Dest[I]=Src[I*2]+(Src[I*2+1]<<8))==0)
      break;
  return(Dest);
}


#ifdef _APPLE
void WideToUtf(const wchar *Src,char *Dest,int DestSize)
{
  DestSize--;
  while (*Src!=0 && --DestSize>=0)
  {
    uint c=*(Src++);
    if (c<0x80)
      *(Dest++)=c;
    else
      if (c<0x800 && --DestSize>=0)
      {
        *(Dest++)=(0xc0|(c>>6));
        *(Dest++)=(0x80|(c&0x3f));
      }
      else
        if (c<0x10000 && (DestSize-=2)>=0)
Esempio n. 12
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
          }
        }
      }
Esempio n. 13
0
size_t Archive::ReadHeader15()
{
  RawRead Raw(this);

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

  if (Decrypt)
  {
#ifdef RAR_NOCRYPT // For rarext.dll and unrar_nocrypt.dll.
    return 0;
#else
    RequestArcPassword();

    byte Salt[SIZE_SALT30];
    if (Read(Salt,SIZE_SALT30)!=SIZE_SALT30)
    {
      UnexpEndArcMsg();
      return(0);
    }
    HeadersCrypt.SetCryptKeys(false,CRYPT_RAR30,&Cmd->Password,Salt,NULL,0,NULL,NULL);
    Raw.SetCrypt(&HeadersCrypt);
#endif
  }

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

  ShortBlock.HeadCRC=Raw.Get2();

  ShortBlock.Reset();

  uint HeaderType=Raw.Get1();
  ShortBlock.Flags=Raw.Get2();
  ShortBlock.SkipIfUnknown=(ShortBlock.Flags & SKIP_IF_UNKNOWN)!=0;
  ShortBlock.HeadSize=Raw.Get2();

  ShortBlock.HeaderType=(HEADER_TYPE)HeaderType;
  if (ShortBlock.HeadSize<SIZEOF_SHORTBLOCKHEAD)
  {
    BrokenHeaderMsg();
    return(0);
  }

  // For simpler further processing we map header types common
  // for RAR 1.5 and 5.0 formats to RAR 5.0 values. It does not include
  // header types specific for RAR 1.5 - 4.x only.
  switch(ShortBlock.HeaderType)
  {
    case HEAD3_MAIN:    ShortBlock.HeaderType=HEAD_MAIN;     break;
    case HEAD3_FILE:    ShortBlock.HeaderType=HEAD_FILE;     break;
    case HEAD3_SERVICE: ShortBlock.HeaderType=HEAD_SERVICE;  break;
    case HEAD3_ENDARC:  ShortBlock.HeaderType=HEAD_ENDARC;   break;
    default: break;
  }
  CurHeaderType=ShortBlock.HeaderType;

  if (ShortBlock.HeaderType==HEAD3_CMT)
  {
    // 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.HeaderType==HEAD_MAIN && (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_MAINHEAD3-SIZEOF_SHORTBLOCKHEAD);
    }
    else
      Raw.Read(ShortBlock.HeadSize-SIZEOF_SHORTBLOCKHEAD);

  NextBlockPos=CurBlockPos+FullHeaderSize(ShortBlock.HeadSize);

  switch(ShortBlock.HeaderType)
  {
    case HEAD_MAIN:
      MainHead.Reset();
      *(BaseBlock *)&MainHead=ShortBlock;
      MainHead.HighPosAV=Raw.Get2();
      MainHead.PosAV=Raw.Get4();

      Volume=(MainHead.Flags & MHD_VOLUME)!=0;
      Solid=(MainHead.Flags & MHD_SOLID)!=0;
      Locked=(MainHead.Flags & MHD_LOCK)!=0;
      Protected=(MainHead.Flags & MHD_PROTECT)!=0;
      Encrypted=(MainHead.Flags & MHD_PASSWORD)!=0;
      Signed=MainHead.PosAV!=0 || MainHead.HighPosAV!=0;
      MainHead.CommentInHeader=(MainHead.Flags & MHD_COMMENT)!=0;
    
      // Only for encrypted 3.0+ archives. 2.x archives did not have this
      // flag, so for non-encrypted archives, we'll set it later based on
      // file attributes.
      FirstVolume=(MainHead.Flags & MHD_FIRSTVOLUME)!=0;

      NewNumbering=(MainHead.Flags & MHD_NEWNUMBERING)!=0;
      break;
    case HEAD_FILE:
    case HEAD_SERVICE:
      {
        bool FileBlock=ShortBlock.HeaderType==HEAD_FILE;
        FileHeader *hd=FileBlock ? &FileHead:&SubHead;
        hd->Reset();

        *(BaseBlock *)hd=ShortBlock;

        hd->SplitBefore=(hd->Flags & LHD_SPLIT_BEFORE)!=0;
        hd->SplitAfter=(hd->Flags & LHD_SPLIT_AFTER)!=0;
        hd->Encrypted=(hd->Flags & LHD_PASSWORD)!=0;
        hd->SaltSet=(hd->Flags & LHD_SALT)!=0;
        hd->Solid=FileBlock && (hd->Flags & LHD_SOLID)!=0;
        hd->SubBlock=!FileBlock && (hd->Flags & LHD_SOLID)!=0;
        hd->Dir=(hd->Flags & LHD_WINDOWMASK)==LHD_DIRECTORY;
        hd->WinSize=hd->Dir ? 0:0x10000<<((hd->Flags & LHD_WINDOWMASK)>>5);
        hd->CommentInHeader=(hd->Flags & LHD_COMMENT)!=0;
        hd->Version=(hd->Flags & LHD_VERSION)!=0;
        
        hd->DataSize=Raw.Get4();
        uint LowUnpSize=Raw.Get4();
        hd->HostOS=Raw.Get1();

        hd->FileHash.Type=HASH_CRC32;
        hd->FileHash.CRC32=Raw.Get4();

        uint FileTime=Raw.Get4();
        hd->UnpVer=Raw.Get1();
        hd->Method=Raw.Get1()-0x30;
        size_t NameSize=Raw.Get2();
        hd->FileAttr=Raw.Get4();

        hd->CryptMethod=CRYPT_NONE;
        if (hd->Encrypted)
          switch(hd->UnpVer)
          {
            case 13: hd->CryptMethod=CRYPT_RAR13; break;
            case 15: hd->CryptMethod=CRYPT_RAR15; break;
            case 20: 
            case 26: hd->CryptMethod=CRYPT_RAR20; break;
            default: hd->CryptMethod=CRYPT_RAR30; break;
          }

        hd->HSType=HSYS_UNKNOWN;
        if (hd->HostOS==HOST_UNIX || hd->HostOS==HOST_BEOS)
          hd->HSType=HSYS_UNIX;
        else
          if (hd->HostOS<HOST_MAX)
            hd->HSType=HSYS_WINDOWS;

        hd->RedirType=FSREDIR_NONE;

        // RAR 4.x Unix symlink.
        if (hd->HostOS==HOST_UNIX && (hd->FileAttr & 0xF000)==0xA000)
        {
          hd->RedirType=FSREDIR_UNIXSYMLINK;
          *hd->RedirName=0;
        }

        hd->Inherited=!FileBlock && (hd->SubFlags & SUBHEAD_FLAGS_INHERITED)!=0;
        
        hd->LargeFile=(hd->Flags & LHD_LARGE)!=0;

        uint HighPackSize,HighUnpSize;
        if (hd->LargeFile)
        {
          HighPackSize=Raw.Get4();
          HighUnpSize=Raw.Get4();
          hd->UnknownUnpSize=(LowUnpSize==0xffffffff && HighUnpSize==0xffffffff);
        }
        else 
        {
          HighPackSize=HighUnpSize=0;
          // 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->UnknownUnpSize=(LowUnpSize==0xffffffff);
        }
        hd->PackSize=INT32TO64(HighPackSize,hd->DataSize);
        hd->UnpSize=INT32TO64(HighUnpSize,LowUnpSize);
        if (hd->UnknownUnpSize)
          hd->UnpSize=INT64NDF;

        char FileName[NM*4];
        size_t ReadNameSize=Min(NameSize,ASIZE(FileName)-1);
        Raw.GetB((byte *)FileName,ReadNameSize);
        FileName[ReadNameSize]=0;

        if (FileBlock)
        {
          if ((hd->Flags & LHD_UNICODE)!=0)
          {
            EncodeFileName NameCoder;
            size_t Length=strlen(FileName);
            if (Length==NameSize)
              UtfToWide(FileName,hd->FileName,ASIZE(hd->FileName)-1);
            else
            {
              Length++;
              NameCoder.Decode(FileName,(byte *)FileName+Length,
                               NameSize-Length,hd->FileName,
                               ASIZE(hd->FileName));
            }
          }
          else
            *hd->FileName=0;

          char AnsiName[NM];
          IntToExt(FileName,AnsiName,ASIZE(AnsiName));
          GetWideName(AnsiName,hd->FileName,hd->FileName,ASIZE(hd->FileName));

#ifndef SFX_MODULE
          ConvertNameCase(hd->FileName);
#endif
          ConvertFileHeader(hd);
        }
        else
        {
          CharToWide(FileName,hd->FileName,ASIZE(hd->FileName));

          // Calculate the size of optional data.
          int DataSize=int(hd->HeadSize-NameSize-SIZEOF_FILEHEAD3);
          if ((hd->Flags & LHD_SALT)!=0)
            DataSize-=SIZE_SALT30;

          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.GetB(&hd->SubData[0],DataSize);
            if (hd->CmpName(SUBHEAD_TYPE_RR))
            {
              byte *D=&hd->SubData[8];
              RecoverySize=D[0]+((uint)D[1]<<8)+((uint)D[2]<<16)+((uint)D[3]<<24);
              RecoverySize*=512; // Sectors to size.
              int64 CurPos=Tell();
              RecoveryPercent=ToPercent(RecoverySize,CurPos);
              // Round fractional percent exceeding .5 to upper value.
              if (ToPercent(RecoverySize+CurPos/200,CurPos)>RecoveryPercent)
                RecoveryPercent++;
            }
          }

          if (hd->CmpName(SUBHEAD_TYPE_CMT))
            MainComment=true;
        }
        if ((hd->Flags & LHD_SALT)!=0)
          Raw.GetB(hd->Salt,SIZE_SALT30);
        hd->mtime.SetDos(FileTime);
        if ((hd->Flags & LHD_EXTTIME)!=0)
        {
          ushort Flags=Raw.Get2();
          RarTime *tbl[4];
          tbl[0]=&FileHead.mtime;
          tbl[1]=&FileHead.ctime;
          tbl[2]=&FileHead.atime;
          tbl[3]=NULL; // Archive time is not used now.
          for (int I=0;I<4;I++)
          {
            RarTime *CurTime=tbl[I];
            uint rmode=Flags>>(3-I)*4;
            if ((rmode & 8)==0 || CurTime==NULL)
              continue;
            if (I!=0)
            {
              uint DosTime=Raw.Get4();
              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.Get1();
              rlt.Reminder|=(((uint)CurByte)<<((J+3-count)*8));
            }
            CurTime->SetLocal(&rlt);
          }
        }
        NextBlockPos+=hd->PackSize;
        bool CRCProcessedOnly=hd->CommentInHeader;
        ushort HeaderCRC=Raw.GetCRC15(CRCProcessedOnly);
        if (hd->HeadCRC!=HeaderCRC)
        {
          BrokenHeader=true;
          ErrHandler.SetErrorCode(RARX_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.
          if (!Decrypt)
          {
#ifndef SHELL_EXT
            Log(Archive::FileName,St(MLogFileHead),hd->FileName);
#endif
          }
        }
      }
      break;
    case HEAD_ENDARC:
      *(BaseBlock *)&EndArcHead=ShortBlock;
      EndArcHead.NextVolume=(EndArcHead.Flags & EARC_NEXT_VOLUME)!=0;
      EndArcHead.DataCRC=(EndArcHead.Flags & EARC_DATACRC)!=0;
      EndArcHead.RevSpace=(EndArcHead.Flags & EARC_REVSPACE)!=0;
      EndArcHead.StoreVolNumber=(EndArcHead.Flags & EARC_VOLNUMBER)!=0;
      if (EndArcHead.DataCRC)
        EndArcHead.ArcDataCRC=Raw.Get4();
      if (EndArcHead.StoreVolNumber)
        VolNumber=EndArcHead.VolNumber=Raw.Get2();
      break;
#ifndef SFX_MODULE
    case HEAD3_CMT:
      *(BaseBlock *)&CommHead=ShortBlock;
      CommHead.UnpSize=Raw.Get2();
      CommHead.UnpVer=Raw.Get1();
      CommHead.Method=Raw.Get1();
      CommHead.CommCRC=Raw.Get2();
      break;
    case HEAD3_SIGN:
      *(BaseBlock *)&SignHead=ShortBlock;
      SignHead.CreationTime=Raw.Get4();
      SignHead.ArcNameSize=Raw.Get2();
      SignHead.UserNameSize=Raw.Get2();
      break;
    case HEAD3_AV:
      *(BaseBlock *)&AVHead=ShortBlock;
      AVHead.UnpVer=Raw.Get1();
      AVHead.Method=Raw.Get1();
      AVHead.AVVer=Raw.Get1();
      AVHead.AVInfoCRC=Raw.Get4();
      break;
    case HEAD3_PROTECT:
      *(BaseBlock *)&ProtectHead=ShortBlock;
      ProtectHead.DataSize=Raw.Get4();
      ProtectHead.Version=Raw.Get1();
      ProtectHead.RecSectors=Raw.Get2();
      ProtectHead.TotalBlocks=Raw.Get4();
      Raw.GetB(ProtectHead.Mark,8);
      NextBlockPos+=ProtectHead.DataSize;
      RecoverySize=ProtectHead.RecSectors*512;
      break;
    case HEAD3_OLDSERVICE:
      *(BaseBlock *)&SubBlockHead=ShortBlock;
      SubBlockHead.DataSize=Raw.Get4();
      NextBlockPos+=SubBlockHead.DataSize;
      SubBlockHead.SubType=Raw.Get2();
      SubBlockHead.Level=Raw.Get1();
      switch(SubBlockHead.SubType)
      {
        case UO_HEAD:
          *(SubBlockHeader *)&UOHead=SubBlockHead;
          UOHead.OwnerNameSize=Raw.Get2();
          UOHead.GroupNameSize=Raw.Get2();
          if (UOHead.OwnerNameSize>=ASIZE(UOHead.OwnerName))
            UOHead.OwnerNameSize=ASIZE(UOHead.OwnerName)-1;
          if (UOHead.GroupNameSize>=ASIZE(UOHead.GroupName))
            UOHead.GroupNameSize=ASIZE(UOHead.GroupName)-1;
          Raw.GetB(UOHead.OwnerName,UOHead.OwnerNameSize);
          Raw.GetB(UOHead.GroupName,UOHead.GroupNameSize);
          UOHead.OwnerName[UOHead.OwnerNameSize]=0;
          UOHead.GroupName[UOHead.GroupNameSize]=0;
          break;
        case MAC_HEAD:
          *(SubBlockHeader *)&MACHead=SubBlockHead;
          MACHead.fileType=Raw.Get4();
          MACHead.fileCreator=Raw.Get4();
          break;
        case EA_HEAD:
        case BEEA_HEAD:
        case NTACL_HEAD:
          *(SubBlockHeader *)&EAHead=SubBlockHead;
          EAHead.UnpSize=Raw.Get4();
          EAHead.UnpVer=Raw.Get1();
          EAHead.Method=Raw.Get1();
          EAHead.EACRC=Raw.Get4();
          break;
        case STREAM_HEAD:
          *(SubBlockHeader *)&StreamHead=SubBlockHead;
          StreamHead.UnpSize=Raw.Get4();
          StreamHead.UnpVer=Raw.Get1();
          StreamHead.Method=Raw.Get1();
          StreamHead.StreamCRC=Raw.Get4();
          StreamHead.StreamNameSize=Raw.Get2();
          if (StreamHead.StreamNameSize>=ASIZE(StreamHead.StreamName))
            StreamHead.StreamNameSize=ASIZE(StreamHead.StreamName)-1;
          Raw.GetB(StreamHead.StreamName,StreamHead.StreamNameSize);
          StreamHead.StreamName[StreamHead.StreamNameSize]=0;
          break;
      }
      break;
#endif
    default:
      if (ShortBlock.Flags & LONG_BLOCK)
        NextBlockPos+=Raw.Get4();
      break;
  }