rarin.cpp

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

CPP
533
字号
// Archive/RarIn.cpp#include "StdAfx.h"#include "Common/StringConvert.h"#include "Common/CRC.h"#include "Common/UTFConvert.h"#include "RarIn.h"#include "../../Common/LimitedStreams.h"#include "../../Common/StreamUtils.h"namespace NArchive {namespace NRar { static const char kEndOfString = '\0';  void CInArchive::ThrowExceptionWithCode(    CInArchiveException::CCauseType cause){  throw CInArchiveException(cause);}bool CInArchive::Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit){  m_CryptoMode = false;  if(inStream->Seek(0, STREAM_SEEK_CUR, &m_StreamStartPosition) != S_OK)    return false;  m_Position = m_StreamStartPosition;  m_Stream = inStream;  if (ReadMarkerAndArchiveHeader(searchHeaderSizeLimit))    return true;  m_Stream.Release();  return false;}void CInArchive::Close(){  m_Stream.Release();}static inline bool TestMarkerCandidate(const void *aTestBytes){  for (UInt32 i = 0; i < NHeader::kMarkerSize; i++)    if (((const Byte *)aTestBytes)[i] != NHeader::kMarker[i])      return false;  return true;}bool CInArchive::FindAndReadMarker(const UInt64 *searchHeaderSizeLimit){  // if (m_Length < NHeader::kMarkerSize)  //   return false;  m_ArchiveStartPosition = 0;  m_Position = m_StreamStartPosition;  if(m_Stream->Seek(m_StreamStartPosition, STREAM_SEEK_SET, NULL) != S_OK)    return false;  Byte marker[NHeader::kMarkerSize];  UInt32 processedSize;   ReadBytes(marker, NHeader::kMarkerSize, &processedSize);  if(processedSize != NHeader::kMarkerSize)    return false;  if (TestMarkerCandidate(marker))    return true;  CByteDynamicBuffer dynamicBuffer;  static const UInt32 kSearchMarkerBufferSize = 0x10000;  dynamicBuffer.EnsureCapacity(kSearchMarkerBufferSize);  Byte *buffer = dynamicBuffer;  UInt32 numBytesPrev = NHeader::kMarkerSize - 1;  memmove(buffer, marker + 1, numBytesPrev);  UInt64 curTestPos = m_StreamStartPosition + 1;  while(true)  {    if (searchHeaderSizeLimit != NULL)      if (curTestPos - m_StreamStartPosition > *searchHeaderSizeLimit)        return false;    UInt32 numReadBytes = kSearchMarkerBufferSize - numBytesPrev;    ReadBytes(buffer + numBytesPrev, numReadBytes, &processedSize);    UInt32 numBytesInBuffer = numBytesPrev + processedSize;    if (numBytesInBuffer < NHeader::kMarkerSize)      return false;    UInt32 numTests = numBytesInBuffer - NHeader::kMarkerSize + 1;    for(UInt32 pos = 0; pos < numTests; pos++, curTestPos++)    {       if (TestMarkerCandidate(buffer + pos))      {        m_ArchiveStartPosition = curTestPos;        m_Position = curTestPos + NHeader::kMarkerSize;        if(m_Stream->Seek(m_Position, STREAM_SEEK_SET, NULL) != S_OK)          return false;        return true;      }    }    numBytesPrev = numBytesInBuffer - numTests;    memmove(buffer, buffer + numTests, numBytesPrev);  }  return false;}void CInArchive::ThrowUnexpectedEndOfArchiveException(){  ThrowExceptionWithCode(CInArchiveException::kUnexpectedEndOfArchive);}bool CInArchive::ReadBytesAndTestSize(void *data, UInt32 size){  if (m_CryptoMode)  {    const Byte *bufData = (const Byte *)m_DecryptedData;    UInt32 bufSize = m_DecryptedDataSize;    UInt32 i;    for (i = 0; i < size && m_CryptoPos < bufSize; i++)      ((Byte *)data)[i] = bufData[m_CryptoPos++];    return (i == size);  }  UInt32 processedSize;  ReadStream(m_Stream, data, size, &processedSize);  return (processedSize == size);}void CInArchive::ReadBytesAndTestResult(void *data, UInt32 size){  if(!ReadBytesAndTestSize(data,size))    ThrowUnexpectedEndOfArchiveException();}HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 *processedSize){  UInt32 realProcessedSize;  HRESULT result = ReadStream(m_Stream, data, size, &realProcessedSize);  if(processedSize != NULL)    *processedSize = realProcessedSize;  AddToSeekValue(realProcessedSize);  return result;}bool CInArchive::ReadMarkerAndArchiveHeader(const UInt64 *searchHeaderSizeLimit){  if (!FindAndReadMarker(searchHeaderSizeLimit))    return false;  Byte buf[NHeader::NArchive::kArchiveHeaderSize];  UInt32 processedSize;  ReadBytes(buf, sizeof(buf), &processedSize);  if (processedSize != sizeof(buf))    return false;  m_CurData = buf;  m_CurPos  = 0;  m_PosLimit = sizeof(buf);  m_ArchiveHeader.CRC = ReadUInt16();  m_ArchiveHeader.Type = ReadByte();  m_ArchiveHeader.Flags = ReadUInt16();  m_ArchiveHeader.Size = ReadUInt16();  m_ArchiveHeader.Reserved1 = ReadUInt16();  m_ArchiveHeader.Reserved2 = ReadUInt32();  m_ArchiveHeader.EncryptVersion = 0;  CCRC crc;  crc.UpdateByte(m_ArchiveHeader.Type);  crc.UpdateUInt16(m_ArchiveHeader.Flags);  crc.UpdateUInt16(m_ArchiveHeader.Size);  crc.UpdateUInt16(m_ArchiveHeader.Reserved1);  crc.UpdateUInt32(m_ArchiveHeader.Reserved2);  if (m_ArchiveHeader.IsThereEncryptVer() && m_ArchiveHeader.Size > NHeader::NArchive::kArchiveHeaderSize)  {    ReadBytes(&m_ArchiveHeader.EncryptVersion, 1, &processedSize);    if (processedSize != 1)      return false;    crc.UpdateByte(m_ArchiveHeader.EncryptVersion);  }  UInt32 u = crc.GetDigest();  if(m_ArchiveHeader.CRC != (crc.GetDigest() & 0xFFFF))    ThrowExceptionWithCode(CInArchiveException::kArchiveHeaderCRCError);  if (m_ArchiveHeader.Type != NHeader::NBlockType::kArchiveHeader)    return false;  m_ArchiveCommentPosition = m_Position;  m_SeekOnArchiveComment = true;  return true;}void CInArchive::SkipArchiveComment(){  if (!m_SeekOnArchiveComment)    return;  AddToSeekValue(m_ArchiveHeader.Size - m_ArchiveHeader.GetBaseSize());  m_SeekOnArchiveComment = false;}void CInArchive::GetArchiveInfo(CInArchiveInfo &archiveInfo) const{  archiveInfo.StartPosition = m_ArchiveStartPosition;  archiveInfo.Flags = m_ArchiveHeader.Flags;  archiveInfo.CommentPosition = m_ArchiveCommentPosition;  archiveInfo.CommentSize = m_ArchiveHeader.Size - NHeader::NArchive::kArchiveHeaderSize;}static void DecodeUnicodeFileName(const char *name, const Byte *encName,     int encSize, wchar_t *unicodeName, int maxDecSize){  int encPos = 0;  int decPos = 0;  int flagBits = 0;  Byte flags = 0;  Byte highByte = encName[encPos++];  while (encPos < encSize && decPos < maxDecSize)  {    if (flagBits == 0)    {      flags = encName[encPos++];      flagBits = 8;    }    switch(flags >> 6)    {      case 0:        unicodeName[decPos++] = encName[encPos++];        break;      case 1:        unicodeName[decPos++] = encName[encPos++] + (highByte << 8);        break;      case 2:        unicodeName[decPos++] = encName[encPos] + (encName[encPos + 1] << 8);        encPos += 2;        break;      case 3:        {          int length = encName[encPos++];          if (length & 0x80)          {            Byte correction = encName[encPos++];            for (length = (length & 0x7f) + 2;                 length > 0 && decPos < maxDecSize; length--, decPos++)              unicodeName[decPos] = ((name[decPos] + correction) & 0xff) + (highByte << 8);          }          else            for (length += 2; length > 0 && decPos < maxDecSize; length--, decPos++)              unicodeName[decPos] = name[decPos];        }        break;    }    flags <<= 2;    flagBits -= 2;  }  unicodeName[decPos < maxDecSize ? decPos : maxDecSize - 1] = 0;}void CInArchive::ReadName(CItemEx &item, int nameSize){  item.UnicodeName.Empty();  if (nameSize > 0)  {    m_NameBuffer.EnsureCapacity(nameSize + 1);    char *buffer = (char *)m_NameBuffer;    for (int i = 0; i < nameSize; i++)      buffer[i] = ReadByte();    int mainLen;    for (mainLen = 0; mainLen < nameSize; mainLen++)      if (buffer[mainLen] == '\0')        break;    buffer[mainLen] = '\0';

⌨️ 快捷键说明

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