mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-11 14:07:13 -06:00
9.34
This commit is contained in:
committed by
Kornel Lesiński
parent
83f8ddcc5b
commit
f08f4dcc3c
193
CPP/7zip/Archive/Cab/CabBlockInStream.cpp
Executable file → Normal file
193
CPP/7zip/Archive/Cab/CabBlockInStream.cpp
Executable file → Normal file
@@ -3,8 +3,7 @@
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../../C/Alloc.h"
|
||||
|
||||
#include "Common/Defs.h"
|
||||
#include "../../../../C/CpuArch.h"
|
||||
|
||||
#include "../../Common/StreamUtils.h"
|
||||
|
||||
@@ -17,173 +16,73 @@ static const UInt32 kBlockSize = (1 << 16);
|
||||
|
||||
bool CCabBlockInStream::Create()
|
||||
{
|
||||
if (!_buffer)
|
||||
_buffer = (Byte *)::MyAlloc(kBlockSize);
|
||||
return (_buffer != 0);
|
||||
if (!_buf)
|
||||
_buf = (Byte *)::MyAlloc(kBlockSize);
|
||||
return _buf != 0;
|
||||
}
|
||||
|
||||
CCabBlockInStream::~CCabBlockInStream()
|
||||
{
|
||||
MyFree(_buffer);
|
||||
::MyFree(_buf);
|
||||
}
|
||||
|
||||
class CCheckSum2
|
||||
static UInt32 CheckSum(const Byte *p, UInt32 size)
|
||||
{
|
||||
UInt32 m_Value;
|
||||
int m_Pos;
|
||||
Byte m_Hist[4];
|
||||
public:
|
||||
CCheckSum2(): m_Value(0){};
|
||||
void Init() { m_Value = 0; m_Pos = 0; }
|
||||
void Update(const void *data, UInt32 size);
|
||||
void FinishDataUpdate()
|
||||
UInt32 sum = 0;
|
||||
for (UInt32 i = size >> 2; i != 0; i--)
|
||||
{
|
||||
for (int i = 0; i < m_Pos; i++)
|
||||
m_Value ^= ((UInt32)(m_Hist[i])) << (8 * (m_Pos - i - 1));
|
||||
sum ^= GetUi32(p);
|
||||
p += 4;
|
||||
}
|
||||
void UpdateUInt32(UInt32 v) { m_Value ^= v; }
|
||||
UInt32 GetResult() const { return m_Value; }
|
||||
};
|
||||
|
||||
void CCheckSum2::Update(const void *data, UInt32 size)
|
||||
{
|
||||
UInt32 checkSum = m_Value;
|
||||
const Byte *dataPointer = (const Byte *)data;
|
||||
|
||||
while (size != 0 && m_Pos != 0)
|
||||
{
|
||||
m_Hist[m_Pos] = *dataPointer++;
|
||||
m_Pos = (m_Pos + 1) & 3;
|
||||
size--;
|
||||
if (m_Pos == 0)
|
||||
for (int i = 0; i < 4; i++)
|
||||
checkSum ^= ((UInt32)m_Hist[i]) << (8 * i);
|
||||
}
|
||||
|
||||
int numWords = size / 4;
|
||||
|
||||
while (numWords-- != 0)
|
||||
{
|
||||
UInt32 temp = *dataPointer++;
|
||||
temp |= ((UInt32)(*dataPointer++)) << 8;
|
||||
temp |= ((UInt32)(*dataPointer++)) << 16;
|
||||
temp |= ((UInt32)(*dataPointer++)) << 24;
|
||||
checkSum ^= temp;
|
||||
}
|
||||
m_Value = checkSum;
|
||||
|
||||
size &= 3;
|
||||
|
||||
while (size != 0)
|
||||
{
|
||||
m_Hist[m_Pos] = *dataPointer++;
|
||||
m_Pos = (m_Pos + 1) & 3;
|
||||
size--;
|
||||
}
|
||||
if (size > 2) sum ^= (UInt32)(*p++) << 16;
|
||||
if (size > 1) sum ^= (UInt32)(*p++) << 8;
|
||||
if (size > 0) sum ^= (UInt32)(*p++);
|
||||
return sum;
|
||||
}
|
||||
|
||||
static const UInt32 kDataBlockHeaderSize = 8;
|
||||
|
||||
class CTempCabInBuffer2
|
||||
HRESULT CCabBlockInStream::PreRead(ISequentialInStream *stream, UInt32 &packSize, UInt32 &unpackSize)
|
||||
{
|
||||
public:
|
||||
Byte Buffer[kDataBlockHeaderSize];
|
||||
UInt32 Pos;
|
||||
Byte ReadByte()
|
||||
{
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
HRESULT CCabBlockInStream::PreRead(UInt32 &packSize, UInt32 &unpackSize)
|
||||
{
|
||||
CTempCabInBuffer2 inBuffer;
|
||||
inBuffer.Pos = 0;
|
||||
RINOK(ReadStream_FALSE(_stream, inBuffer.Buffer, kDataBlockHeaderSize))
|
||||
|
||||
UInt32 checkSum = inBuffer.ReadUInt32();
|
||||
packSize = inBuffer.ReadUInt16();
|
||||
unpackSize = inBuffer.ReadUInt16();
|
||||
if (ReservedSize != 0)
|
||||
{
|
||||
RINOK(ReadStream_FALSE(_stream, _buffer, ReservedSize));
|
||||
}
|
||||
_pos = 0;
|
||||
CCheckSum2 checkSumCalc;
|
||||
checkSumCalc.Init();
|
||||
UInt32 packSize2 = packSize;
|
||||
if (MsZip && _size == 0)
|
||||
{
|
||||
if (packSize < 2)
|
||||
return S_FALSE; // bad block;
|
||||
Byte sig[2];
|
||||
RINOK(ReadStream_FALSE(_stream, sig, 2));
|
||||
if (sig[0] != 0x43 || sig[1] != 0x4B)
|
||||
return S_FALSE;
|
||||
packSize2 -= 2;
|
||||
checkSumCalc.Update(sig, 2);
|
||||
}
|
||||
|
||||
if (kBlockSize - _size < packSize2)
|
||||
const UInt32 kHeaderSize = 8;
|
||||
const UInt32 kReservedMax = 256;
|
||||
Byte header[kHeaderSize + kReservedMax];
|
||||
RINOK(ReadStream_FALSE(stream, header, kHeaderSize + ReservedSize))
|
||||
packSize = GetUi16(header + 4);
|
||||
unpackSize = GetUi16(header + 6);
|
||||
if (packSize > kBlockSize - _size)
|
||||
return S_FALSE;
|
||||
|
||||
UInt32 curSize = packSize2;
|
||||
if (curSize != 0)
|
||||
RINOK(ReadStream_FALSE(stream, _buf + _size, packSize));
|
||||
|
||||
if (MsZip)
|
||||
{
|
||||
size_t processedSizeLoc = curSize;
|
||||
RINOK(ReadStream(_stream, _buffer + _size, &processedSizeLoc));
|
||||
checkSumCalc.Update(_buffer + _size, (UInt32)processedSizeLoc);
|
||||
_size += (UInt32)processedSizeLoc;
|
||||
if (processedSizeLoc != curSize)
|
||||
if (_size == 0)
|
||||
{
|
||||
if (packSize < 2 || _buf[0] != 0x43 || _buf[1] != 0x4B)
|
||||
return S_FALSE;
|
||||
_pos = 2;
|
||||
}
|
||||
if (_size + packSize > ((UInt32)1 << 15) + 12) /* v9.31 fix. MSZIP specification */
|
||||
return S_FALSE;
|
||||
}
|
||||
TotalPackSize = _size;
|
||||
|
||||
checkSumCalc.FinishDataUpdate();
|
||||
|
||||
bool dataError;
|
||||
if (checkSum == 0)
|
||||
dataError = false;
|
||||
else
|
||||
{
|
||||
checkSumCalc.UpdateUInt32(packSize | (((UInt32)unpackSize) << 16));
|
||||
dataError = (checkSumCalc.GetResult() != checkSum);
|
||||
}
|
||||
DataError |= dataError;
|
||||
return dataError ? S_FALSE : S_OK;
|
||||
if (GetUi32(header) != 0) // checkSum
|
||||
if (CheckSum(header, kHeaderSize + ReservedSize) != CheckSum(_buf + _size, packSize))
|
||||
return S_FALSE;
|
||||
|
||||
_size += packSize;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CCabBlockInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (processedSize != 0)
|
||||
*processedSize = 0;
|
||||
if (size == 0)
|
||||
return S_OK;
|
||||
if (_size != 0)
|
||||
{
|
||||
size = MyMin(_size, size);
|
||||
memmove(data, _buffer + _pos, size);
|
||||
_pos += size;
|
||||
_size -= size;
|
||||
if (processedSize != 0)
|
||||
*processedSize = size;
|
||||
return S_OK;
|
||||
}
|
||||
return S_OK; // no blocks data
|
||||
UInt32 rem = _size - _pos;
|
||||
if (size > rem)
|
||||
size = rem;
|
||||
memcpy(data, _buf + _pos, size);
|
||||
_pos += size;
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user