Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'CPP/7zip/Archive/Zip/ZipIn.cpp')
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipIn.cpp175
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;
}