📄 zipin.cpp
字号:
// Archive/ZipIn.cpp#include "StdAfx.h"#include "ZipIn.h"#include "Windows/Defs.h"#include "Common/StringConvert.h"#include "Common/DynamicBuffer.h"#include "../../Common/LimitedStreams.h"#include "../../Common/StreamUtils.h"namespace NArchive {namespace NZip { // static const char kEndOfString = '\0'; bool CInArchive::Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit){ m_Stream = inStream; if(m_Stream->Seek(0, STREAM_SEEK_CUR, &m_StreamStartPosition) != S_OK) return false; m_Position = m_StreamStartPosition; return FindAndReadMarker(searchHeaderSizeLimit);}void CInArchive::Close(){ m_Stream.Release();}//////////////////////////////////////// Markersstatic inline bool TestMarkerCandidate(const Byte *p, UInt32 &value){ value = p[0] | (((UInt32)p[1]) << 8) | (((UInt32)p[2]) << 16) | (((UInt32)p[3]) << 24); return (value == NSignature::kLocalFileHeader) || (value == NSignature::kEndOfCentralDir);}bool CInArchive::FindAndReadMarker(const UInt64 *searchHeaderSizeLimit){ m_ArchiveInfo.Clear(); m_ArchiveInfo.StartPosition = 0; m_Position = m_StreamStartPosition; if(m_Stream->Seek(m_StreamStartPosition, STREAM_SEEK_SET, NULL) != S_OK) return false; Byte marker[NSignature::kMarkerSize]; UInt32 processedSize; ReadBytes(marker, NSignature::kMarkerSize, &processedSize); if(processedSize != NSignature::kMarkerSize) return false; if (TestMarkerCandidate(marker, m_Signature)) return true; CByteDynamicBuffer dynamicBuffer; static const UInt32 kSearchMarkerBufferSize = 0x10000; dynamicBuffer.EnsureCapacity(kSearchMarkerBufferSize); Byte *buffer = dynamicBuffer; UInt32 numBytesPrev = NSignature::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 < NSignature::kMarkerSize) return false; UInt32 numTests = numBytesInBuffer - NSignature::kMarkerSize + 1; for(UInt32 pos = 0; pos < numTests; pos++, curTestPos++) { if (TestMarkerCandidate(buffer + pos, m_Signature)) { m_ArchiveInfo.StartPosition = curTestPos; m_Position = curTestPos + NSignature::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); }}HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 *processedSize){ UInt32 realProcessedSize; HRESULT result = ReadStream(m_Stream, data, size, &realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; m_Position += realProcessedSize; return result;}void CInArchive::IncreaseRealPosition(UInt64 addValue){ if(m_Stream->Seek(addValue, STREAM_SEEK_CUR, &m_Position) != S_OK) throw CInArchiveException(CInArchiveException::kSeekStreamError);}bool CInArchive::ReadBytesAndTestSize(void *data, UInt32 size){ UInt32 realProcessedSize; if(ReadBytes(data, size, &realProcessedSize) != S_OK) throw CInArchiveException(CInArchiveException::kReadStreamError); return (realProcessedSize == size);}void CInArchive::SafeReadBytes(void *data, UInt32 size){ if(!ReadBytesAndTestSize(data, size)) throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive);}void CInArchive::ReadBuffer(CByteBuffer &buffer, UInt32 size){ buffer.SetCapacity(size); if (size > 0) SafeReadBytes(buffer, size);}Byte CInArchive::ReadByte(){ Byte b; SafeReadBytes(&b, 1); return b;}UInt16 CInArchive::ReadUInt16(){ UInt16 value = 0; for (int i = 0; i < 2; i++) value |= (((UInt16)ReadByte()) << (8 * i)); return value;}UInt32 CInArchive::ReadUInt32(){ UInt32 value = 0; for (int i = 0; i < 4; i++) value |= (((UInt32)ReadByte()) << (8 * i)); return value;}UInt64 CInArchive::ReadUInt64(){ UInt64 value = 0; for (int i = 0; i < 8; i++) value |= (((UInt64)ReadByte()) << (8 * i)); return value;}bool CInArchive::ReadUInt32(UInt32 &value){ value = 0; for (int i = 0; i < 4; i++) { Byte b; if (!ReadBytesAndTestSize(&b, 1)) return false; value |= (UInt32(b) << (8 * i)); } return true;}AString CInArchive::ReadFileName(UInt32 nameSize){ if (nameSize == 0) return AString(); SafeReadBytes(m_NameBuffer.GetBuffer(nameSize), nameSize); m_NameBuffer.ReleaseBuffer(nameSize); return m_NameBuffer;}void CInArchive::GetArchiveInfo(CInArchiveInfo &archiveInfo) const{ archiveInfo = m_ArchiveInfo;}void CInArchive::ThrowIncorrectArchiveException(){ throw CInArchiveException(CInArchiveException::kIncorrectArchive);}static UInt32 GetUInt32(const Byte *data){ return ((UInt32)(Byte)data[0]) | (((UInt32)(Byte)data[1]) << 8) | (((UInt32)(Byte)data[2]) << 16) | (((UInt32)(Byte)data[3]) << 24);}void CInArchive::ReadExtra(UInt32 extraSize, CExtraBlock &extraBlock, UInt64 &unpackSize, UInt64 &packSize, UInt64 &localHeaderOffset, UInt32 &diskStartNumber){ extraBlock.Clear(); UInt32 remain = extraSize; while(remain >= 4) { CExtraSubBlock subBlock; subBlock.ID = ReadUInt16(); UInt32 dataSize = ReadUInt16(); remain -= 4; if (dataSize > remain) // it's bug dataSize = remain; if (subBlock.ID == 0x1) { if (unpackSize == 0xFFFFFFFF) { if (dataSize < 8) break; unpackSize = ReadUInt64(); remain -= 8; dataSize -= 8; } if (packSize == 0xFFFFFFFF) { if (dataSize < 8) break; packSize = ReadUInt64(); remain -= 8; dataSize -= 8; } if (localHeaderOffset == 0xFFFFFFFF) { if (dataSize < 8) break; localHeaderOffset = ReadUInt64(); remain -= 8; dataSize -= 8; } if (diskStartNumber == 0xFFFF) { if (dataSize < 4) break; diskStartNumber = ReadUInt32(); remain -= 4; dataSize -= 4; } for (UInt32 i = 0; i < dataSize; i++) ReadByte(); } else { ReadBuffer(subBlock.Data, dataSize); extraBlock.SubBlocks.Add(subBlock); } remain -= dataSize; } IncreaseRealPosition(remain);}HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *progress){ // m_Signature must be kLocalFileHeaderSignature or // kEndOfCentralDirSignature // m_Position points to next byte after signature items.Clear(); if (progress != 0) { UInt64 numItems = items.Size(); RINOK(progress->SetCompleted(&numItems)); } while(m_Signature == NSignature::kLocalFileHeader) { // FSeek points to next byte after signature // NFileHeader::CLocalBlock localHeader; CItemEx item; item.LocalHeaderPosition = m_Position - m_StreamStartPosition - 4; // points to signature; // SafeReadBytes(&localHeader, sizeof(localHeader)); item.ExtractVersion.Version = ReadByte(); item.ExtractVersion.HostOS = ReadByte(); item.Flags = ReadUInt16() & NFileHeader::NFlags::kUsedBitsMask; item.CompressionMethod = ReadUInt16(); item.Time = ReadUInt32(); item.FileCRC = ReadUInt32(); item.PackSize = ReadUInt32(); item.UnPackSize = ReadUInt32(); UInt32 fileNameSize = ReadUInt16(); item.LocalExtraSize = ReadUInt16(); item.Name = ReadFileName(fileNameSize); /* if (!NItemName::IsNameLegal(item.Name))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -