diff options
Diffstat (limited to 'CPP/7zip/Archive/Zip/ZipIn.cpp')
-rwxr-xr-x | CPP/7zip/Archive/Zip/ZipIn.cpp | 175 |
1 files changed, 79 insertions, 96 deletions
diff --git a/CPP/7zip/Archive/Zip/ZipIn.cpp b/CPP/7zip/Archive/Zip/ZipIn.cpp index 5fb53ef2..e396fe5b 100755 --- a/CPP/7zip/Archive/Zip/ZipIn.cpp +++ b/CPP/7zip/Archive/Zip/ZipIn.cpp @@ -2,17 +2,14 @@ #include "StdAfx.h" -#include "ZipIn.h" -#include "Windows/Defs.h" -#include "Common/StringConvert.h" +#include "../../../../C/CpuArch.h" + #include "Common/DynamicBuffer.h" + #include "../../Common/LimitedStreams.h" #include "../../Common/StreamUtils.h" -extern "C" -{ - #include "../../../../C/CpuArch.h" -} +#include "ZipIn.h" #define Get16(p) GetUi16(p) #define Get32(p) GetUi32(p) @@ -21,10 +18,9 @@ extern "C" namespace NArchive { namespace NZip { -// static const char kEndOfString = '\0'; - HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit) { + _inBufMode = false; Close(); RINOK(stream->Seek(0, STREAM_SEEK_CUR, &m_StreamStartPosition)); m_Position = m_StreamStartPosition; @@ -36,6 +32,7 @@ HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit) void CInArchive::Close() { + _inBuffer.ReleaseStream(); m_Stream.Release(); } @@ -117,13 +114,26 @@ HRESULT CInArchive::FindAndReadMarker(IInStream *stream, const UInt64 *searchHea HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 *processedSize) { size_t realProcessedSize = size; - HRESULT result = ReadStream(m_Stream, data, &realProcessedSize); + HRESULT result = S_OK; + if (_inBufMode) + { + try { realProcessedSize = _inBuffer.ReadBytes((Byte *)data, size); } + catch (const CInBufferException &e) { return e.ErrorCode; } + } + else + result = ReadStream(m_Stream, data, &realProcessedSize); if (processedSize != NULL) *processedSize = (UInt32)realProcessedSize; m_Position += realProcessedSize; return result; } +void CInArchive::Skip(UInt64 num) +{ + for (UInt64 i = 0; i < num; i++) + ReadByte(); +} + void CInArchive::IncreaseRealPosition(UInt64 addValue) { if (m_Stream->Seek(addValue, STREAM_SEEK_CUR, &m_Position) != S_OK) @@ -160,51 +170,42 @@ Byte CInArchive::ReadByte() UInt16 CInArchive::ReadUInt16() { - UInt16 value = 0; - for (int i = 0; i < 2; i++) - value |= (((UInt16)ReadByte()) << (8 * i)); - return value; + Byte buf[2]; + SafeReadBytes(buf, 2); + return Get16(buf); } UInt32 CInArchive::ReadUInt32() { - UInt32 value = 0; - for (int i = 0; i < 4; i++) - value |= (((UInt32)ReadByte()) << (8 * i)); - return value; + Byte buf[4]; + SafeReadBytes(buf, 4); + return Get32(buf); } UInt64 CInArchive::ReadUInt64() { - UInt64 value = 0; - for (int i = 0; i < 8; i++) - value |= (((UInt64)ReadByte()) << (8 * i)); - return value; + Byte buf[8]; + SafeReadBytes(buf, 8); + return Get64(buf); } 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)); - } + Byte buf[4]; + if (!ReadBytesAndTestSize(buf, 4)) + return false; + value = Get32(buf); return true; } - -AString CInArchive::ReadFileName(UInt32 nameSize) +void CInArchive::ReadFileName(UInt32 nameSize, AString &dest) { if (nameSize == 0) - return AString(); - char *p = m_NameBuffer.GetBuffer(nameSize); + dest.Empty(); + char *p = dest.GetBuffer((int)nameSize); SafeReadBytes(p, nameSize); p[nameSize] = 0; - m_NameBuffer.ReleaseBuffer(); - return m_NameBuffer; + dest.ReleaseBuffer(); } void CInArchive::GetArchiveInfo(CInArchiveInfo &archiveInfo) const @@ -212,38 +213,6 @@ 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); -} - -/* -static UInt16 GetUInt16(const Byte *data) -{ - return - ((UInt16)(Byte)data[0]) | - (((UInt16)(Byte)data[1]) << 8); -} -*/ - -static UInt64 GetUInt64(const Byte *data) -{ - return GetUInt32(data) | ((UInt64)GetUInt32(data + 4) << 32); -} - - - void CInArchive::ReadExtra(UInt32 extraSize, CExtraBlock &extraBlock, UInt64 &unpackSize, UInt64 &packSize, UInt64 &localHeaderOffset, UInt32 &diskStartNumber) { @@ -301,22 +270,26 @@ void CInArchive::ReadExtra(UInt32 extraSize, CExtraBlock &extraBlock, } remain -= dataSize; } - IncreaseRealPosition(remain); + Skip(remain); } HRESULT CInArchive::ReadLocalItem(CItemEx &item) { - item.ExtractVersion.Version = ReadByte(); - item.ExtractVersion.HostOS = ReadByte(); - item.Flags = ReadUInt16(); - 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); + const int kBufSize = 26; + Byte p[kBufSize]; + SafeReadBytes(p, kBufSize); + + item.ExtractVersion.Version = p[0]; + item.ExtractVersion.HostOS = p[1]; + item.Flags = Get16(p + 2); + item.CompressionMethod = Get16(p + 4); + item.Time = Get32(p + 6); + item.FileCRC = Get32(p + 10); + item.PackSize = Get32(p + 14); + item.UnPackSize = Get32(p + 18); + UInt32 fileNameSize = Get16(p + 22); + item.LocalExtraSize = Get16(p + 24); + ReadFileName(fileNameSize, item.Name); item.FileHeaderWithNameSize = 4 + NFileHeader::kLocalBlockSize + fileNameSize; if (item.LocalExtraSize > 0) { @@ -400,16 +373,16 @@ HRESULT CInArchive::ReadLocalItemDescriptor(CItemEx &item) { // descriptorSignature field is Info-ZIP's extension // to Zip specification. - UInt32 descriptorSignature = GetUInt32(buffer + i); + UInt32 descriptorSignature = Get32(buffer + i); // !!!! It must be fixed for Zip64 archives - UInt32 descriptorPackSize = GetUInt32(buffer + i + 8); + UInt32 descriptorPackSize = Get32(buffer + i + 8); if (descriptorSignature== NSignature::kDataDescriptor && descriptorPackSize == packedSize + i) { descriptorWasFound = true; - item.FileCRC = GetUInt32(buffer + i + 4); + item.FileCRC = Get32(buffer + i + 4); item.PackSize = descriptorPackSize; - item.UnPackSize = GetUInt32(buffer + i + 12); + item.UnPackSize = Get32(buffer + i + 12); IncreaseRealPosition(Int64(Int32(0 - (numBytesInBuffer - i - NFileHeader::kDataDescriptorSize)))); break; } @@ -487,7 +460,7 @@ HRESULT CInArchive::ReadCdItem(CItemEx &item) item.InternalAttributes = Get16(p + 32); item.ExternalAttributes = Get32(p + 34); item.LocalHeaderPosition = Get32(p + 38); - item.Name = ReadFileName(headerNameSize); + ReadFileName(headerNameSize, item.Name); if (headerExtraSize > 0) { @@ -515,11 +488,11 @@ HRESULT CInArchive::TryEcd64(UInt64 offset, CCdInfo &cdInfo) Byte buf[kEcd64Size]; if (!ReadBytesAndTestSize(buf, kEcd64Size)) return S_FALSE; - if (GetUInt32(buf) != NSignature::kZip64EndOfCentralDir) + if (Get32(buf) != NSignature::kZip64EndOfCentralDir) return S_FALSE; - // cdInfo.NumEntries = GetUInt64(buf + 24); - cdInfo.Size = GetUInt64(buf + 40); - cdInfo.Offset = GetUInt64(buf + 48); + // cdInfo.NumEntries = Get64(buf + 24); + cdInfo.Size = Get64(buf + 40); + cdInfo.Offset = Get64(buf + 48); return S_OK; } @@ -540,14 +513,14 @@ HRESULT CInArchive::FindCd(CCdInfo &cdInfo) return S_FALSE; for (int i = (int)(bufSize - kEcdSize); i >= 0; i--) { - if (GetUInt32(buf + i) == NSignature::kEndOfCentralDir) + if (Get32(buf + i) == NSignature::kEndOfCentralDir) { if (i >= kZip64EcdLocatorSize) { const Byte *locator = buf + i - kZip64EcdLocatorSize; - if (GetUInt32(locator) == NSignature::kZip64EndOfCentralDirLocator) + if (Get32(locator) == NSignature::kZip64EndOfCentralDirLocator) { - UInt64 ecd64Offset = GetUInt64(locator + 8); + UInt64 ecd64Offset = Get64(locator + 8); if (TryEcd64(ecd64Offset, cdInfo) == S_OK) return S_OK; if (TryEcd64(m_ArchiveInfo.StartPosition + ecd64Offset, cdInfo) == S_OK) @@ -557,11 +530,11 @@ HRESULT CInArchive::FindCd(CCdInfo &cdInfo) } } } - if (GetUInt32(buf + i + 4) == 0) + if (Get32(buf + i + 4) == 0) { // cdInfo.NumEntries = GetUInt16(buf + i + 10); - cdInfo.Size = GetUInt32(buf + i + 12); - cdInfo.Offset = GetUInt32(buf + i + 16); + cdInfo.Size = Get32(buf + i + 12); + cdInfo.Offset = Get32(buf + i + 16); UInt64 curPos = endPosition - bufSize + i; UInt64 cdEnd = cdInfo.Size + cdInfo.Offset; if (curPos > cdEnd) @@ -579,6 +552,13 @@ HRESULT CInArchive::TryReadCd(CObjectVector<CItemEx> &items, UInt64 cdOffset, UI RINOK(m_Stream->Seek(cdOffset, STREAM_SEEK_SET, &m_Position)); if (m_Position != cdOffset) return S_FALSE; + + if (!_inBuffer.Create(1 << 15)) + return E_OUTOFMEMORY; + _inBuffer.SetStream(m_Stream); + _inBuffer.Init(); + _inBufMode = true; + while(m_Position - cdOffset < cdSize) { if (ReadUInt32() != NSignature::kCentralFileHeader) @@ -765,6 +745,7 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *pr if (res == S_FALSE) { + _inBufMode = false; m_ArchiveInfo.Base = 0; RINOK(m_Stream->Seek(m_ArchiveInfo.StartPosition, STREAM_SEEK_SET, &m_Position)); if (m_Position != m_ArchiveInfo.StartPosition) @@ -789,7 +770,7 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *pr SafeReadBytes(buf, kBufSize); ecd64.Parse(buf); - IncreaseRealPosition(recordSize - kZip64EcdSize); + Skip(recordSize - kZip64EcdSize); if (!ReadUInt32(m_Signature)) return S_FALSE; if (ecd64.thisDiskNumber != 0 || ecd64.startCDDiskNumber != 0) @@ -838,6 +819,8 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *pr (!items.IsEmpty()))) return S_FALSE; + _inBufMode = false; + _inBuffer.Free(); return S_OK; } |