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