mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-14 20:11:38 -06:00
4.20
This commit is contained in:
committed by
Kornel Lesiński
parent
8c1b5c7b7e
commit
3c510ba80b
@@ -1,153 +1,175 @@
|
||||
// Archive/CabInBuffer.cpp
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "Common/Types.h"
|
||||
#include "Common/MyCom.h"
|
||||
#include "Windows/Defs.h"
|
||||
#include "../../../Common/Alloc.h"
|
||||
#include "../../../Common/MyCom.h"
|
||||
#include "../../../Windows/Defs.h"
|
||||
#include "CabInBuffer.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
|
||||
#pragma pack(push, PragmaCabDataHeader)
|
||||
#pragma pack(push, 1)
|
||||
|
||||
static const UInt32 kDataBlockHeaderSize = 8;
|
||||
/*
|
||||
struct CDataBlockHeader
|
||||
{
|
||||
UINT32 CheckSum; /* checksum of this CFDATA entry */
|
||||
UINT16 PackSize; /* number of compressed bytes in this block */
|
||||
UINT16 UnPackSize; /* number of uncompressed bytes in this block */
|
||||
// BYTE abReserve[]; /* (optional) per-datablock reserved area */
|
||||
// BYTE ab[cbData]; /* compressed data bytes */
|
||||
UInt32 CheckSum; // checksum of this CFDATA entry
|
||||
UInt16 PackSize; // number of compressed bytes in this block
|
||||
UInt16 UnPackSize; // number of uncompressed bytes in this block
|
||||
// Byte abReserve[]; // (optional) per-datablock reserved area
|
||||
// Byte ab[cbData]; // compressed data bytes
|
||||
};
|
||||
*/
|
||||
|
||||
class CTempCabInBuffer
|
||||
{
|
||||
public:
|
||||
Byte *Buffer;
|
||||
UInt32 Size;
|
||||
UInt32 Pos;
|
||||
Byte ReadByte()
|
||||
{
|
||||
if (Pos >= Size)
|
||||
throw "overflow";
|
||||
return Buffer[Pos++];
|
||||
}
|
||||
UInt32 ReadUInt32()
|
||||
{
|
||||
UInt32 value = 0;
|
||||
for (int i = 0; i < 4; i++)
|
||||
value |= (((UInt32)ReadByte()) << (8 * i));
|
||||
return value;
|
||||
}
|
||||
UInt16 ReadUInt16()
|
||||
{
|
||||
UInt16 value = 0;
|
||||
for (int i = 0; i < 2; i++)
|
||||
value |= (((UInt16)ReadByte()) << (8 * i));
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
#pragma pack(pop, PragmaCabDataHeader)
|
||||
|
||||
CInBuffer::CInBuffer(UINT32 bufferSize):
|
||||
m_BufferSize(bufferSize),
|
||||
m_Stream(0)
|
||||
bool CInBuffer::Create(UInt32 bufferSize)
|
||||
{
|
||||
m_Buffer = new BYTE[m_BufferSize];
|
||||
const UInt32 kMinBlockSize = 1;
|
||||
if (bufferSize < kMinBlockSize)
|
||||
bufferSize = kMinBlockSize;
|
||||
if (m_Buffer != 0 && m_BufferSize == bufferSize)
|
||||
return true;
|
||||
Free();
|
||||
m_BufferSize = bufferSize;
|
||||
m_Buffer = (Byte *)::BigAlloc(bufferSize);
|
||||
return (m_Buffer != 0);
|
||||
}
|
||||
|
||||
CInBuffer::~CInBuffer()
|
||||
void CInBuffer::Free()
|
||||
{
|
||||
delete []m_Buffer;
|
||||
// ReleaseStream();
|
||||
BigFree(m_Buffer);
|
||||
m_Buffer = 0;
|
||||
}
|
||||
|
||||
void CInBuffer::Init(ISequentialInStream *inStream, BYTE reservedSize, UINT32 numBlocks)
|
||||
void CInBuffer::Init(Byte reservedSize, UInt32 numBlocks)
|
||||
{
|
||||
m_ReservedSize = reservedSize;
|
||||
m_NumBlocks = numBlocks;
|
||||
m_CurrentBlockIndex = 0;
|
||||
// ReleaseStream();
|
||||
m_Stream = inStream;
|
||||
// m_Stream->AddRef();
|
||||
m_ProcessedSize = 0;
|
||||
m_Pos = 0;
|
||||
m_NumReadBytesInBuffer = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
void CInBuffer::ReleaseStream()
|
||||
{
|
||||
if(m_Stream != 0)
|
||||
{
|
||||
m_Stream->Release();
|
||||
m_Stream = 0;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
class CCheckSum
|
||||
{
|
||||
UINT32 m_Value;
|
||||
UInt32 m_Value;
|
||||
public:
|
||||
CCheckSum(): m_Value(0){};
|
||||
void Init() { m_Value = 0; }
|
||||
void Update(const void *data, UINT32 size);
|
||||
UINT32 GetResult() const { return m_Value; }
|
||||
void Update(const void *data, UInt32 size);
|
||||
void UpdateUInt32(UInt32 v) { m_Value ^= v; }
|
||||
UInt32 GetResult() const { return m_Value; }
|
||||
};
|
||||
|
||||
void CCheckSum::Update(const void *data, UINT32 size)
|
||||
void CCheckSum::Update(const void *data, UInt32 size)
|
||||
{
|
||||
UINT32 checkSum = m_Value;
|
||||
const BYTE *aDataPointer = (const BYTE *)data;
|
||||
int numUINT32Words = size / 4; // Number of ULONGs
|
||||
UInt32 checkSum = m_Value;
|
||||
const Byte *dataPointer = (const Byte *)data;
|
||||
int numUINT32Words = size / 4; // Number of ULONGs
|
||||
|
||||
// dataPointer += numUINT32Words * 4;
|
||||
|
||||
UINT32 temp;
|
||||
const UINT32 *aDataPointer32 = (const UINT32 *)data;
|
||||
UInt32 temp;
|
||||
while (numUINT32Words-- > 0)
|
||||
{
|
||||
// temp ^= *aDataPointer32++;
|
||||
temp = *aDataPointer++; // Get low-order byte
|
||||
temp |= (((ULONG)(*aDataPointer++)) << 8); // Add 2nd byte
|
||||
temp |= (((ULONG)(*aDataPointer++)) << 16); // Add 3nd byte
|
||||
temp |= (((ULONG)(*aDataPointer++)) << 24); // Add 4th byte
|
||||
checkSum ^= temp; // Update checksum
|
||||
temp = *dataPointer++;
|
||||
temp |= (((UInt32)(*dataPointer++)) << 8);
|
||||
temp |= (((UInt32)(*dataPointer++)) << 16);
|
||||
temp |= (((UInt32)(*dataPointer++)) << 24);
|
||||
checkSum ^= temp;
|
||||
}
|
||||
|
||||
temp = 0;
|
||||
switch (size % 4)
|
||||
{
|
||||
case 3:
|
||||
temp |= (((ULONG)(*aDataPointer++)) << 16); // Add 3nd byte
|
||||
case 2:
|
||||
temp |= (((ULONG)(*aDataPointer++)) << 8); // Add 2nd byte
|
||||
case 1:
|
||||
temp |= *aDataPointer++; // Get low-order byte
|
||||
default:
|
||||
break;
|
||||
}
|
||||
int rem = (size & 3);
|
||||
if (rem >= 3)
|
||||
temp |= (((UInt32)(*dataPointer++)) << 16);
|
||||
if (rem >= 2)
|
||||
temp |= (((UInt32)(*dataPointer++)) << 8);
|
||||
if (rem >= 1)
|
||||
temp |= *dataPointer++;
|
||||
checkSum ^= temp;
|
||||
m_Value = checkSum;
|
||||
}
|
||||
HRESULT CInBuffer::ReadBlock(UINT32 &uncompressedSize, bool &dataAreCorrect)
|
||||
|
||||
HRESULT CInBuffer::ReadBlock(UInt32 &uncompressedSize, bool &dataAreCorrect)
|
||||
{
|
||||
if (m_CurrentBlockIndex >= m_NumBlocks)
|
||||
throw "there is no more data blocks";
|
||||
|
||||
m_ProcessedSize += m_NumReadBytesInBuffer;
|
||||
|
||||
CDataBlockHeader dataBlockHeader;
|
||||
UINT32 numProcessedBytes;
|
||||
RINOK(m_Stream->Read(&dataBlockHeader, sizeof(dataBlockHeader), &numProcessedBytes));
|
||||
if (numProcessedBytes != sizeof(dataBlockHeader))
|
||||
Byte buffer[kDataBlockHeaderSize];
|
||||
UInt32 numProcessedBytes;
|
||||
RINOK(m_Stream->Read(buffer, kDataBlockHeaderSize, &numProcessedBytes));
|
||||
if (numProcessedBytes != kDataBlockHeaderSize)
|
||||
throw "bad block";
|
||||
|
||||
CTempCabInBuffer inBuffer;
|
||||
inBuffer.Size = kDataBlockHeaderSize;
|
||||
inBuffer.Buffer = (Byte *)buffer;
|
||||
inBuffer.Pos = 0;
|
||||
|
||||
UInt32 checkSum = inBuffer.ReadUInt32(); // checksum of this CFDATA entry
|
||||
UInt16 packSize = inBuffer.ReadUInt16(); // number of compressed bytes in this block
|
||||
UInt16 unPackSize = inBuffer.ReadUInt16(); // number of uncompressed bytes in this block
|
||||
|
||||
if (m_ReservedSize != 0)
|
||||
{
|
||||
BYTE reservedArea[256];
|
||||
Byte reservedArea[256];
|
||||
RINOK(m_Stream->Read(reservedArea, m_ReservedSize, &numProcessedBytes));
|
||||
if (numProcessedBytes != m_ReservedSize)
|
||||
throw "bad block";
|
||||
}
|
||||
|
||||
RINOK(m_Stream->Read(m_Buffer, dataBlockHeader.PackSize, &m_NumReadBytesInBuffer));
|
||||
if (m_NumReadBytesInBuffer != dataBlockHeader.PackSize)
|
||||
RINOK(m_Stream->Read(m_Buffer, packSize, &m_NumReadBytesInBuffer));
|
||||
if (m_NumReadBytesInBuffer != packSize)
|
||||
throw "bad block";
|
||||
|
||||
if (dataBlockHeader.CheckSum == 0)
|
||||
// Now I don't remember why (checkSum == 0) check is disbaled
|
||||
// Cab specification:
|
||||
// checkSum: May be set to zero if the checksum is not supplied.
|
||||
// but seems it's stupid rule.
|
||||
if (checkSum == 0)
|
||||
dataAreCorrect = true;
|
||||
{
|
||||
CCheckSum checkSum;
|
||||
checkSum.Update(m_Buffer, dataBlockHeader.PackSize);
|
||||
checkSum.Update(&dataBlockHeader.PackSize,
|
||||
sizeof(dataBlockHeader) - sizeof(dataBlockHeader.CheckSum));
|
||||
dataAreCorrect = (checkSum.GetResult() == dataBlockHeader.CheckSum);
|
||||
CCheckSum checkSumCalc;
|
||||
checkSumCalc.Update(m_Buffer, packSize);
|
||||
checkSumCalc.UpdateUInt32(packSize | (((UInt32)unPackSize) << 16));
|
||||
dataAreCorrect = (checkSumCalc.GetResult() == checkSum);
|
||||
}
|
||||
|
||||
m_Pos = 0;
|
||||
uncompressedSize = dataBlockHeader.UnPackSize;
|
||||
uncompressedSize = unPackSize;
|
||||
|
||||
m_CurrentBlockIndex++;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user