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 + -
显示快捷键?