rarin.cpp

来自「由7-zip提供的压缩、解压缩程序」· C++ 代码 · 共 533 行 · 第 1/2 页

CPP
533
字号
    item.Name = buffer;    if(item.HasUnicodeName())    {      if(mainLen < nameSize)      {        int unicodeNameSizeMax = MyMin(nameSize, (0x400));        _unicodeNameBuffer.EnsureCapacity(unicodeNameSizeMax + 1);        DecodeUnicodeFileName(buffer, (const Byte *)buffer + mainLen + 1,             nameSize - (mainLen + 1), _unicodeNameBuffer, unicodeNameSizeMax);        item.UnicodeName = _unicodeNameBuffer;      }      else if (!ConvertUTF8ToUnicode(item.Name, item.UnicodeName))        item.UnicodeName.Empty();    }  }  else    item.Name.Empty();}Byte CInArchive::ReadByte(){  if (m_CurPos >= m_PosLimit)    throw CInArchiveException(CInArchiveException::kIncorrectArchive);  return m_CurData[m_CurPos++];}UInt16 CInArchive::ReadUInt16(){  UInt16 value = 0;  for (int i = 0; i < 2; i++)  {    Byte b = ReadByte();    value |= (UInt16(b) << (8 * i));  }  return value;}UInt32 CInArchive::ReadUInt32(){  UInt32 value = 0;  for (int i = 0; i < 4; i++)  {    Byte b = ReadByte();    value |= (UInt32(b) << (8 * i));  }  return value;}void CInArchive::ReadTime(Byte mask, CRarTime &rarTime){  rarTime.LowSecond = ((mask & 4) != 0) ? 1 : 0;  int numDigits = (mask & 3);  rarTime.SubTime[0] = rarTime.SubTime[1] = rarTime.SubTime[2] = 0;  for (int i = 0; i < numDigits; i++)    rarTime.SubTime[3 - numDigits + i] = ReadByte();}void CInArchive::ReadHeaderReal(CItemEx &item){  item.Flags = m_BlockHeader.Flags;   item.PackSize = ReadUInt32();  item.UnPackSize = ReadUInt32();  item.HostOS = ReadByte();  item.FileCRC = ReadUInt32();  item.LastWriteTime.DosTime = ReadUInt32();  item.UnPackVersion = ReadByte();  item.Method = ReadByte();  int nameSize = ReadUInt16();  item.Attributes = ReadUInt32();  item.LastWriteTime.LowSecond = 0;  item.LastWriteTime.SubTime[0] =       item.LastWriteTime.SubTime[1] =       item.LastWriteTime.SubTime[2] = 0;  if((item.Flags & NHeader::NFile::kSize64Bits) != 0)  {    item.PackSize |= ((UInt64)ReadUInt32() << 32);    item.UnPackSize |= ((UInt64)ReadUInt32() << 32);  }  ReadName(item, nameSize);  if (item.HasSalt())    for (int i = 0; i < sizeof(item.Salt); i++)      item.Salt[i] = ReadByte();  if (item.HasExtTime())  {    Byte accessMask = ReadByte() >> 4;    Byte b = ReadByte();    Byte modifMask = b >> 4;    Byte createMask = b & 0xF;    if ((modifMask & 8) != 0)      ReadTime(modifMask, item.LastWriteTime);    if (item.IsCreationTimeDefined = ((createMask & 8) != 0))    {      item.CreationTime.DosTime = ReadUInt32();      ReadTime(createMask, item.CreationTime);    }    if (item.IsLastAccessTimeDefined = ((accessMask & 8) != 0))    {      item.LastAccessTime.DosTime = ReadUInt32();      ReadTime(accessMask, item.LastAccessTime);    }  }  UInt16 fileHeaderWithNameSize = (UInt16)m_CurPos;    item.Position = m_Position;  item.MainPartSize = fileHeaderWithNameSize;  item.CommentSize = m_BlockHeader.HeadSize - fileHeaderWithNameSize;  if (m_CryptoMode)    item.AlignSize = (16 - ((m_BlockHeader.HeadSize) & 0xF)) & 0xF;  else    item.AlignSize = 0;  AddToSeekValue(m_BlockHeader.HeadSize);}void CInArchive::AddToSeekValue(UInt64 addValue){  m_Position += addValue;}HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPassword){  if (m_SeekOnArchiveComment)    SkipArchiveComment();  while (true)  {    if(!SeekInArchive(m_Position))      return S_FALSE;    if (!m_CryptoMode && (m_ArchiveHeader.Flags &         NHeader::NArchive::kBlockHeadersAreEncrypted) != 0)    {      m_CryptoMode = false;      if (getTextPassword == 0)        return S_FALSE;      if(!SeekInArchive(m_Position))        return S_FALSE;      if (!m_RarAES)      {        m_RarAESSpec = new NCrypto::NRar29::CDecoder;        m_RarAES = m_RarAESSpec;      }      m_RarAESSpec->SetRar350Mode(m_ArchiveHeader.IsEncryptOld());      // Salt      const UInt32 kSaltSize = 8;      Byte salt[kSaltSize];      if(!ReadBytesAndTestSize(salt, kSaltSize))        return false;      m_Position += kSaltSize;      RINOK(m_RarAESSpec->SetDecoderProperties2(salt, kSaltSize))      // Password      CMyComBSTR password;      RINOK(getTextPassword->CryptoGetTextPassword(&password))      UString unicodePassword(password);      CByteBuffer buffer;      const UInt32 sizeInBytes = unicodePassword.Length() * 2;      buffer.SetCapacity(sizeInBytes);      for (int i = 0; i < unicodePassword.Length(); i++)      {        wchar_t c = unicodePassword[i];        ((Byte *)buffer)[i * 2] = (Byte)c;        ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);      }      RINOK(m_RarAESSpec->CryptoSetPassword((const Byte *)buffer, sizeInBytes));      const UInt32 kDecryptedBufferSize = (1 << 12);      if (m_DecryptedData.GetCapacity() == 0)      {        m_DecryptedData.SetCapacity(kDecryptedBufferSize);      }      RINOK(m_RarAES->Init());      RINOK(ReadStream(m_Stream, (Byte *)m_DecryptedData, kDecryptedBufferSize, &m_DecryptedDataSize));      m_DecryptedDataSize = m_RarAES->Filter((Byte *)m_DecryptedData, m_DecryptedDataSize);      m_CryptoMode = true;      m_CryptoPos = 0;    }    m_FileHeaderData.EnsureCapacity(7);    if(!ReadBytesAndTestSize((Byte *)m_FileHeaderData, 7))      return S_FALSE;    m_CurData = (Byte *)m_FileHeaderData;    m_CurPos = 0;    m_PosLimit = 7;    m_BlockHeader.CRC = ReadUInt16();    m_BlockHeader.Type = ReadByte();    m_BlockHeader.Flags = ReadUInt16();    m_BlockHeader.HeadSize = ReadUInt16();    if (m_BlockHeader.HeadSize < 7)      ThrowExceptionWithCode(CInArchiveException::kIncorrectArchive);    if (m_BlockHeader.Type == NHeader::NBlockType::kEndOfArchive)       return S_FALSE;    if (m_BlockHeader.Type == NHeader::NBlockType::kFileHeader)     {      m_FileHeaderData.EnsureCapacity(m_BlockHeader.HeadSize);      m_CurData = (Byte *)m_FileHeaderData;      m_PosLimit = m_BlockHeader.HeadSize;      ReadBytesAndTestResult(m_CurData + m_CurPos, m_BlockHeader.HeadSize - 7);      ReadHeaderReal(item);       if ((CCRC::CalculateDigest(m_CurData + 2,           m_BlockHeader.HeadSize - item.CommentSize - 2) & 0xFFFF) != m_BlockHeader.CRC)        ThrowExceptionWithCode(CInArchiveException::kFileHeaderCRCError);      FinishCryptoBlock();      m_CryptoMode = false;      SeekInArchive(m_Position); // Move Position to compressed Data;          AddToSeekValue(item.PackSize);  // m_Position points to next header;      return S_OK;    }    if (m_CryptoMode && m_BlockHeader.HeadSize > (1 << 12))      return E_FAIL; // it's for bad passwords    if ((m_BlockHeader.Flags & NHeader::NBlock::kLongBlock) != 0)    {      m_FileHeaderData.EnsureCapacity(7 + 4);      m_CurData = (Byte *)m_FileHeaderData;      ReadBytesAndTestResult(m_CurData + m_CurPos, 4); // test it      m_PosLimit = 7 + 4;      UInt32 dataSize = ReadUInt32();      AddToSeekValue(dataSize);      if (m_CryptoMode && dataSize > (1 << 27))        return E_FAIL; // it's for bad passwords      m_CryptoPos = m_BlockHeader.HeadSize;    }    else      m_CryptoPos = 0;    AddToSeekValue(m_BlockHeader.HeadSize);    FinishCryptoBlock();    m_CryptoMode = false;  }}void CInArchive::DirectGetBytes(void *data, UInt32 size){    ReadStream(m_Stream, data, size, NULL);}bool CInArchive::SeekInArchive(UInt64 position){  UInt64 newPosition;  m_Stream->Seek(position, STREAM_SEEK_SET, &newPosition);  return newPosition == position;}ISequentialInStream* CInArchive::CreateLimitedStream(UInt64 position, UInt64 size){  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;  CMyComPtr<ISequentialInStream> inStream(streamSpec);  SeekInArchive(position);  streamSpec->Init(m_Stream, size);  return inStream.Detach();}}}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?