1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
// CabBlockInStream.cpp
#include "StdAfx.h"
#include "../../../../C/Alloc.h"
#include "../../../../C/CpuArch.h"
#include "../../Common/StreamUtils.h"
#include "CabBlockInStream.h"
namespace NArchive {
namespace NCab {
static const UInt32 kBlockSize = (1 << 16);
bool CCabBlockInStream::Create()
{
if (!_buf)
_buf = (Byte *)::MyAlloc(kBlockSize);
return _buf != 0;
}
CCabBlockInStream::~CCabBlockInStream()
{
::MyFree(_buf);
}
static UInt32 CheckSum(const Byte *p, UInt32 size)
{
UInt32 sum = 0;
for (UInt32 i = size >> 2; i != 0; i--)
{
sum ^= GetUi32(p);
p += 4;
}
size &= 3;
if (size > 2) sum ^= (UInt32)(*p++) << 16;
if (size > 1) sum ^= (UInt32)(*p++) << 8;
if (size > 0) sum ^= (UInt32)(*p++);
return sum;
}
HRESULT CCabBlockInStream::PreRead(ISequentialInStream *stream, UInt32 &packSize, UInt32 &unpackSize)
{
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;
RINOK(ReadStream_FALSE(stream, _buf + _size, packSize));
if (MsZip)
{
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;
}
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)
{
UInt32 rem = _size - _pos;
if (size > rem)
size = rem;
memcpy(data, _buf + _pos, size);
_pos += size;
if (processedSize)
*processedSize = size;
return S_OK;
}
}}
|