1
by weidai
Initial revision |
1 |
// gzip.cpp - written and placed in the public domain by Wei Dai
|
2 |
||
3 |
#include "pch.h" |
|
4 |
#include "gzip.h" |
|
5 |
||
6 |
NAMESPACE_BEGIN(CryptoPP) |
|
7 |
||
8 |
void Gzip::WritePrestreamHeader() |
|
9 |
{
|
|
10 |
m_totalLen = 0; |
|
11 |
m_crc.Restart(); |
|
12 |
||
13 |
AttachedTransformation()->Put(MAGIC1); |
|
14 |
AttachedTransformation()->Put(MAGIC2); |
|
15 |
AttachedTransformation()->Put(DEFLATED); |
|
16 |
AttachedTransformation()->Put(0); // general flag |
|
17 |
AttachedTransformation()->PutWord32(0); // time stamp |
|
18 |
byte extra = (GetDeflateLevel() == 1) ? FAST : ((GetDeflateLevel() == 9) ? SLOW : 0); |
|
19 |
AttachedTransformation()->Put(extra); |
|
20 |
AttachedTransformation()->Put(GZIP_OS_CODE); |
|
21 |
}
|
|
22 |
||
23 |
void Gzip::ProcessUncompressedData(const byte *inString, unsigned int length) |
|
24 |
{
|
|
25 |
m_crc.Update(inString, length); |
|
26 |
m_totalLen += length; |
|
27 |
}
|
|
28 |
||
29 |
void Gzip::WritePoststreamTail() |
|
30 |
{
|
|
31 |
SecByteBlock crc(4); |
|
32 |
m_crc.Final(crc); |
|
33 |
AttachedTransformation()->Put(crc, 4); |
|
34 |
AttachedTransformation()->PutWord32(m_totalLen, LITTLE_ENDIAN_ORDER); |
|
35 |
}
|
|
36 |
||
37 |
// *************************************************************
|
|
38 |
||
39 |
Gunzip::Gunzip(BufferedTransformation *attachment, bool repeat, int propagation) |
|
40 |
: Inflator(attachment, repeat, propagation) |
|
41 |
{
|
|
42 |
}
|
|
43 |
||
44 |
void Gunzip::ProcessPrestreamHeader() |
|
45 |
{
|
|
46 |
m_length = 0; |
|
47 |
m_crc.Restart(); |
|
48 |
||
49 |
byte buf[6]; |
|
50 |
byte b, flags; |
|
51 |
||
52 |
if (m_inQueue.Get(buf, 2)!=2) throw HeaderErr(); |
|
53 |
if (buf[0] != MAGIC1 || buf[1] != MAGIC2) throw HeaderErr(); |
|
54 |
if (!m_inQueue.Skip(1)) throw HeaderErr(); // skip extra flags |
|
55 |
if (!m_inQueue.Get(flags)) throw HeaderErr(); |
|
56 |
if (flags & (ENCRYPTED | CONTINUED)) throw HeaderErr(); |
|
57 |
if (m_inQueue.Skip(6)!=6) throw HeaderErr(); // Skip file time, extra flags and OS type |
|
58 |
||
59 |
if (flags & EXTRA_FIELDS) // skip extra fields |
|
60 |
{
|
|
61 |
word16 length; |
|
62 |
if (m_inQueue.GetWord16(length, LITTLE_ENDIAN_ORDER) != 2) throw HeaderErr(); |
|
63 |
if (m_inQueue.Skip(length)!=length) throw HeaderErr(); |
|
64 |
}
|
|
65 |
||
66 |
if (flags & FILENAME) // skip filename |
|
67 |
do
|
|
68 |
if(!m_inQueue.Get(b)) throw HeaderErr(); |
|
69 |
while (b); |
|
70 |
||
71 |
if (flags & COMMENTS) // skip comments |
|
72 |
do
|
|
73 |
if(!m_inQueue.Get(b)) throw HeaderErr(); |
|
74 |
while (b); |
|
75 |
}
|
|
76 |
||
77 |
void Gunzip::ProcessDecompressedData(const byte *inString, unsigned int length) |
|
78 |
{
|
|
79 |
AttachedTransformation()->Put(inString, length); |
|
80 |
m_crc.Update(inString, length); |
|
81 |
m_length += length; |
|
82 |
}
|
|
83 |
||
84 |
void Gunzip::ProcessPoststreamTail() |
|
85 |
{
|
|
86 |
SecByteBlock crc(4); |
|
87 |
if (m_inQueue.Get(crc, 4) != 4) |
|
88 |
throw TailErr(); |
|
89 |
if (!m_crc.Verify(crc)) |
|
90 |
throw CrcErr(); |
|
91 |
||
92 |
word32 lengthCheck; |
|
93 |
if (m_inQueue.GetWord32(lengthCheck, LITTLE_ENDIAN_ORDER) != 4) |
|
94 |
throw TailErr(); |
|
95 |
if (lengthCheck != m_length) |
|
96 |
throw LengthErr(); |
|
97 |
}
|
|
98 |
||
99 |
NAMESPACE_END
|