mirror of
https://github.com/Xevion/easy7zip.git
synced 2026-02-01 12:24:16 -06:00
4.20
This commit is contained in:
committed by
Kornel Lesiński
parent
8c1b5c7b7e
commit
3c510ba80b
+120
-54
@@ -11,38 +11,38 @@
|
||||
namespace NArchive{
|
||||
namespace NCab{
|
||||
|
||||
static HRESULT ReadBytes(IInStream *inStream, void *data, UINT32 size)
|
||||
static HRESULT ReadBytes(IInStream *inStream, void *data, UInt32 size)
|
||||
{
|
||||
UINT32 realProcessedSize;
|
||||
UInt32 realProcessedSize;
|
||||
RINOK(inStream->Read(data, size, &realProcessedSize));
|
||||
if(realProcessedSize != size)
|
||||
return S_FALSE;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT SafeRead(IInStream *inStream, void *data, UINT32 size)
|
||||
static HRESULT SafeRead(IInStream *inStream, void *data, UInt32 size)
|
||||
{
|
||||
UINT32 realProcessedSize;
|
||||
UInt32 realProcessedSize;
|
||||
RINOK(inStream->Read(data, size, &realProcessedSize));
|
||||
if(realProcessedSize != size)
|
||||
throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static void SafeInByteRead(CInBuffer &inBuffer, void *data, UINT32 size)
|
||||
static void SafeInByteRead(::CInBuffer &inBuffer, void *data, UInt32 size)
|
||||
{
|
||||
UINT32 realProcessedSize;
|
||||
UInt32 realProcessedSize;
|
||||
inBuffer.ReadBytes(data, size, realProcessedSize);
|
||||
if(realProcessedSize != size)
|
||||
throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive);
|
||||
}
|
||||
|
||||
static void SafeReadName(CInBuffer &inBuffer, AString &name)
|
||||
static void SafeReadName(::CInBuffer &inBuffer, AString &name)
|
||||
{
|
||||
name.Empty();
|
||||
while(true)
|
||||
{
|
||||
BYTE b;
|
||||
Byte b;
|
||||
if (!inBuffer.ReadByte(b))
|
||||
throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive);
|
||||
if (b == 0)
|
||||
@@ -51,31 +51,63 @@ static void SafeReadName(CInBuffer &inBuffer, AString &name)
|
||||
}
|
||||
}
|
||||
|
||||
Byte CInArchive::ReadByte()
|
||||
{
|
||||
if (_blockPos >= _blockSize)
|
||||
throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive);
|
||||
return _block[_blockPos++];
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
HRESULT CInArchive::Open(IInStream *inStream,
|
||||
const UINT64 *searchHeaderSizeLimit,
|
||||
const UInt64 *searchHeaderSizeLimit,
|
||||
CInArchiveInfo &inArchiveInfo,
|
||||
CObjectVector<NHeader::CFolder> &folders,
|
||||
CObjectVector<CItem> &files,
|
||||
CProgressVirt *progressVirt)
|
||||
{
|
||||
UINT64 startPosition;
|
||||
UInt64 startPosition;
|
||||
RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &startPosition));
|
||||
|
||||
NHeader::NArchive::CBlock archiveHeader;
|
||||
// NHeader::NArchive::CBlock archiveHeader;
|
||||
|
||||
{
|
||||
CInBuffer inBuffer;
|
||||
inBuffer.Init(inStream);
|
||||
UINT64 value = 0;
|
||||
const int kSignatureSize = sizeof(value);
|
||||
UINT64 kSignature64 = NHeader::NArchive::kSignature;
|
||||
::CInBuffer inBuffer;
|
||||
if (!inBuffer.Create(1 << 17))
|
||||
return E_OUTOFMEMORY;
|
||||
inBuffer.SetStream(inStream);
|
||||
inBuffer.Init();
|
||||
UInt64 value = 0;
|
||||
const int kSignatureSize = 8;
|
||||
UInt64 kSignature64 = NHeader::NArchive::kSignature;
|
||||
while(true)
|
||||
{
|
||||
BYTE b;
|
||||
Byte b;
|
||||
if (!inBuffer.ReadByte(b))
|
||||
return S_FALSE;
|
||||
value >>= 8;
|
||||
value |= ((UINT64)b) << ((kSignatureSize - 1) * 8);
|
||||
value |= ((UInt64)b) << ((kSignatureSize - 1) * 8);
|
||||
if (inBuffer.GetProcessedSize() >= kSignatureSize)
|
||||
{
|
||||
if (value == kSignature64)
|
||||
@@ -88,40 +120,59 @@ HRESULT CInArchive::Open(IInStream *inStream,
|
||||
startPosition += inBuffer.GetProcessedSize() - kSignatureSize;
|
||||
}
|
||||
RINOK(inStream->Seek(startPosition, STREAM_SEEK_SET, NULL));
|
||||
RINOK(ReadBytes(inStream, &archiveHeader, sizeof(archiveHeader)));
|
||||
|
||||
RINOK(ReadBytes(inStream, _block, NHeader::NArchive::kArchiveHeaderSize));
|
||||
_blockSize = NHeader::NArchive::kArchiveHeaderSize;
|
||||
_blockPos = 0;
|
||||
|
||||
ReadUInt32(); // Signature; // cabinet file signature
|
||||
// if (archiveHeader.Signature != NHeader::NArchive::kSignature)
|
||||
// return S_FALSE;
|
||||
|
||||
if (archiveHeader.Reserved1 != 0 ||
|
||||
archiveHeader.Reserved2 != 0 ||
|
||||
archiveHeader.Reserved3 != 0)
|
||||
throw CInArchiveException(CInArchiveException::kUnsupported);
|
||||
|
||||
inArchiveInfo.VersionMinor = archiveHeader.VersionMinor;
|
||||
inArchiveInfo.VersionMajor = archiveHeader.VersionMajor;
|
||||
inArchiveInfo.NumFolders = archiveHeader.NumFolders;
|
||||
inArchiveInfo.NumFiles = archiveHeader.NumFiles;
|
||||
inArchiveInfo.Flags = archiveHeader.Flags;
|
||||
UInt32 reserved1 = ReadUInt32();
|
||||
UInt32 size = ReadUInt32(); // size of this cabinet file in bytes
|
||||
UInt32 reserved2 = ReadUInt32();
|
||||
UInt32 fileOffset = ReadUInt32(); // offset of the first CFFILE entry
|
||||
UInt32 reserved3 = ReadUInt32();
|
||||
|
||||
inArchiveInfo.VersionMinor = ReadByte(); // cabinet file format version, minor
|
||||
inArchiveInfo.VersionMajor = ReadByte(); // cabinet file format version, major
|
||||
inArchiveInfo.NumFolders = ReadUInt16(); // number of CFFOLDER entries in this cabinet
|
||||
inArchiveInfo.NumFiles = ReadUInt16(); // number of CFFILE entries in this cabinet
|
||||
inArchiveInfo.Flags = ReadUInt16(); // number of CFFILE entries in this cabinet
|
||||
UInt16 setID = ReadUInt16(); // must be the same for all cabinets in a set
|
||||
UInt16 cabinetNumber = ReadUInt16(); // number of this cabinet file in a set
|
||||
|
||||
if (reserved1 != 0 || reserved2 != 0 || reserved3 != 0)
|
||||
throw CInArchiveException(CInArchiveException::kUnsupported);
|
||||
|
||||
if (inArchiveInfo.ReserveBlockPresent())
|
||||
{
|
||||
RINOK(SafeRead(inStream, &inArchiveInfo.PerDataSizes,
|
||||
sizeof(inArchiveInfo.PerDataSizes)));
|
||||
RINOK(SafeRead(inStream, _block, NHeader::NArchive::kPerDataSizesHeaderSize));
|
||||
_blockSize = NHeader::NArchive::kPerDataSizesHeaderSize;
|
||||
_blockPos = 0;
|
||||
|
||||
inArchiveInfo.PerDataSizes.PerCabinetAreaSize = ReadUInt16(); // (optional) size of per-cabinet reserved area
|
||||
inArchiveInfo.PerDataSizes.PerFolderAreaSize = ReadByte(); // (optional) size of per-folder reserved area
|
||||
inArchiveInfo.PerDataSizes.PerDatablockAreaSize = ReadByte(); // (optional) size of per-datablock reserved area
|
||||
RINOK(inStream->Seek(inArchiveInfo.PerDataSizes.PerCabinetAreaSize,
|
||||
STREAM_SEEK_CUR, NULL));
|
||||
}
|
||||
|
||||
{
|
||||
UINT64 foldersStartPosition;
|
||||
UInt64 foldersStartPosition;
|
||||
RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &foldersStartPosition));
|
||||
CInBuffer inBuffer;
|
||||
inBuffer.Init(inStream);
|
||||
if ((archiveHeader.Flags & NHeader::NArchive::NFlags::kPrevCabinet) != 0)
|
||||
::CInBuffer inBuffer;
|
||||
if (!inBuffer.Create(1 << 17))
|
||||
return E_OUTOFMEMORY;
|
||||
inBuffer.SetStream(inStream);
|
||||
inBuffer.Init();
|
||||
if ((inArchiveInfo.Flags & NHeader::NArchive::NFlags::kPrevCabinet) != 0)
|
||||
{
|
||||
SafeReadName(inBuffer, inArchiveInfo.PreviousCabinetName);
|
||||
SafeReadName(inBuffer, inArchiveInfo.PreviousDiskName);
|
||||
}
|
||||
if ((archiveHeader.Flags & NHeader::NArchive::NFlags::kNextCabinet) != 0)
|
||||
if ((inArchiveInfo.Flags & NHeader::NArchive::NFlags::kNextCabinet) != 0)
|
||||
{
|
||||
SafeReadName(inBuffer, inArchiveInfo.NextCabinetName);
|
||||
SafeReadName(inBuffer, inArchiveInfo.NextDiskName);
|
||||
@@ -132,54 +183,69 @@ HRESULT CInArchive::Open(IInStream *inStream,
|
||||
|
||||
if (progressVirt != NULL)
|
||||
{
|
||||
UINT64 numFiles = archiveHeader.NumFiles;
|
||||
UInt64 numFiles = inArchiveInfo.NumFiles;
|
||||
RINOK(progressVirt->SetTotal(&numFiles));
|
||||
}
|
||||
folders.Clear();
|
||||
for(int i = 0; i < archiveHeader.NumFolders; i++)
|
||||
int i;
|
||||
for(i = 0; i < inArchiveInfo.NumFolders; i++)
|
||||
{
|
||||
if (progressVirt != NULL)
|
||||
{
|
||||
UINT64 numFiles = 0;
|
||||
UInt64 numFiles = 0;
|
||||
RINOK(progressVirt->SetCompleted(&numFiles));
|
||||
}
|
||||
NHeader::CFolder folder;
|
||||
RINOK(SafeRead(inStream, &folder, sizeof(folder)));
|
||||
RINOK(SafeRead(inStream, _block, NHeader::kFolderHeaderSize));
|
||||
_blockSize = NHeader::kFolderHeaderSize;
|
||||
_blockPos = 0;
|
||||
|
||||
folder.DataStart = ReadUInt32();
|
||||
folder.NumDataBlocks = ReadUInt16();
|
||||
folder.CompressionTypeMajor = ReadByte();
|
||||
folder.CompressionTypeMinor = ReadByte();
|
||||
|
||||
if (inArchiveInfo.ReserveBlockPresent())
|
||||
{
|
||||
RINOK(inStream->Seek(
|
||||
inArchiveInfo.PerDataSizes.PerFolderAreaSize, STREAM_SEEK_CUR, NULL));
|
||||
}
|
||||
folder.DataStart += (UINT32)startPosition;
|
||||
folder.DataStart += (UInt32)startPosition;
|
||||
folders.Add(folder);
|
||||
}
|
||||
|
||||
RINOK(inStream->Seek(startPosition + archiveHeader.FileOffset,
|
||||
RINOK(inStream->Seek(startPosition + fileOffset,
|
||||
STREAM_SEEK_SET, NULL));
|
||||
|
||||
CInBuffer inBuffer;
|
||||
inBuffer.Init(inStream);
|
||||
::CInBuffer inBuffer;
|
||||
if (!inBuffer.Create(1 << 17))
|
||||
return E_OUTOFMEMORY;
|
||||
inBuffer.SetStream(inStream);
|
||||
inBuffer.Init();
|
||||
files.Clear();
|
||||
if (progressVirt != NULL)
|
||||
{
|
||||
UINT64 numFiles = files.Size();
|
||||
UInt64 numFiles = files.Size();
|
||||
RINOK(progressVirt->SetCompleted(&numFiles));
|
||||
}
|
||||
for(i = 0; i < archiveHeader.NumFiles; i++)
|
||||
for(i = 0; i < inArchiveInfo.NumFiles; i++)
|
||||
{
|
||||
NHeader::CFile fileHeader;
|
||||
SafeInByteRead(inBuffer, &fileHeader, sizeof(fileHeader));
|
||||
SafeInByteRead(inBuffer, _block, NHeader::kFileHeaderSize);
|
||||
_blockSize = NHeader::kFileHeaderSize;
|
||||
_blockPos = 0;
|
||||
CItem item;
|
||||
item.UnPackSize = fileHeader.UnPackSize;
|
||||
item.UnPackOffset = fileHeader.UnPackOffset;
|
||||
item.FolderIndex = fileHeader.FolderIndex;
|
||||
item.Time = ((UINT32(fileHeader.PureDate) << 16)) | fileHeader.PureTime;
|
||||
item.Attributes = fileHeader.Attributes;
|
||||
item.UnPackSize = ReadUInt32();
|
||||
item.UnPackOffset = ReadUInt32();
|
||||
item.FolderIndex = ReadUInt16();
|
||||
UInt16 pureDate = ReadUInt16();
|
||||
UInt16 pureTime = ReadUInt16();
|
||||
item.Time = ((UInt32(pureDate) << 16)) | pureTime;
|
||||
item.Attributes = ReadUInt16();
|
||||
SafeReadName(inBuffer, item.Name);
|
||||
files.Add(item);
|
||||
if (progressVirt != NULL)
|
||||
{
|
||||
UINT64 numFiles = files.Size();
|
||||
UInt64 numFiles = files.Size();
|
||||
RINOK(progressVirt->SetCompleted(&numFiles));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user