* Start Compressing with Gzip *␊ |
*************************************************/␊ |
void Gzip_Compression::start_msg()␊ |
{␊ |
clear();␊ |
put_header();␊ |
pipe.start_msg();␊ |
count = 0;␊ |
}␊ |
␊ |
/*************************************************␊ |
* Compress Input with Gzip *␊ |
*************************************************/␊ |
|
void Gzip_Compression::write(const byte input[], filter_length_t length)␊ |
{␊ |
␊ |
count += length;␊ |
pipe.write(input, length);␊ |
␊ |
zlib->stream.next_in = (Bytef*)input;␊ |
zlib->stream.avail_in = length;␊ |
␊ |
while(zlib->stream.avail_in != 0)␊ |
{␊ |
zlib->stream.next_out = (Bytef*)buffer.begin();␊ |
zlib->stream.avail_out = buffer.size();␊ |
int rc = deflate(&(zlib->stream), Z_NO_FLUSH);␊ |
|
{␊ |
if (!no_writes)␊ |
throw Exception("Gzip_Decompression: start_msg after already writing");␊ |
␊ |
pipe.start_msg();␊ |
datacount = 0;␊ |
pos = 0;␊ |
in_footer = false;␊ |
}␊ |
␊ |
/*************************************************␊ |
* Decompress Input with Gzip *␊ |
*************************************************/␊ |
|
void Gzip_Decompression::write(const byte input[], filter_length_t length)␊ |
{␊ |
if(length) no_writes = false;␊ |
␊ |
// If we're in the footer, take what we need, then go to the next block␊ |
if (in_footer)␊ |
{␊ |
u32bit eat_len = eat_footer(input, length);␊ |
input += eat_len;␊ |
length -= eat_len;␊ |
if (length == 0)␊ |
return;␊ |
}␊ |
␊ |
// Check the gzip header␊ |
if (pos < sizeof(GZIP::GZIP_HEADER))␊ |
{␊ |
|
|
filter_length_t len = std::min((filter_length_t)sizeof(GZIP::GZIP_HEADER)-pos, length);␊ |
filter_length_t cmplen = len;␊ |
// The last byte is the OS flag - we don't care about that␊ |
if (pos + len - 1 >= GZIP::HEADER_POS_OS)␊ |
cmplen--;␊ |
␊ |
if (std::memcmp(input, &GZIP::GZIP_HEADER[pos], cmplen) != 0)␊ |
{␊ |
throw Decoding_Error("Gzip_Decompression: Data integrity error in header");␊ |
}␊ |
input += len;␊ |
length -= len;␊ |
pos += len;␊ |
}␊ |
␊ |
|
zlib->stream.avail_in = length;␊ |
}␊ |
}␊ |
}␊ |
␊ |
/*************************************************␊ |
* Store the footer bytes *␊ |
*************************************************/␊ |
u32bit Gzip_Decompression::eat_footer(const byte input[], u32bit length)␊ |
{␊ |
if (footer.size() >= GZIP::FOOTER_LENGTH)␊ |
throw Decoding_Error("Gzip_Decompression: Data integrity error in footer");␊ |
␊ |
#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,9,11)␊ |
size_t eat_len = std::min(GZIP::FOOTER_LENGTH-footer.size(),␊ |
static_cast<size_t>(length));␊ |
footer += std::make_pair(input, eat_len);␊ |
#else␊ |
u32bit eat_len = std::min(GZIP::FOOTER_LENGTH-footer.size(), length);␊ |
footer.append(input, eat_len);␊ |
#endif␊ |
␊ |
if (footer.size() == GZIP::FOOTER_LENGTH)␊ |
{␊ |
check_footer();␊ |
clear();␊ |
}␊ |
␊ |
return eat_len;␊ |
}␊ |
␊ |
/*************************************************␊ |
* Check the gzip footer *␊ |
*************************************************/␊ |
|
throw Exception("Gzip_Decompression: Error finalizing decompression");␊ |
␊ |
pipe.end_msg();␊ |
␊ |
// 4 byte CRC32, and 4 byte length field␊ |
SecureVector<byte> buf(4);␊ |
SecureVector<byte> tmpbuf(4);␊ |
pipe.read(tmpbuf.begin(), tmpbuf.size(), Pipe::LAST_MESSAGE);␊ |
␊ |
// CRC32 is the reverse order to what gzip expects.␊ |
for (int i = 0; i < 4; i++)␊ |
buf[3-i] = tmpbuf[i];␊ |
␊ |
#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,9,11)␊ |
tmpbuf.resize(4);␊ |
tmpbuf.copy(footer.begin(), 4);␊ |
#else␊ |
tmpbuf.set(footer.begin(), 4);␊ |
#endif␊ |
if (buf != tmpbuf)␊ |
throw Decoding_Error("Gzip_Decompression: Data integrity error - CRC32 error");␊ |
␊ |
// Check the length matches - it is encoded LSB-first␊ |
for (int i = 0; i < 4; i++)␊ |
{␊ |
if (footer.begin()[GZIP::FOOTER_LENGTH-1-i] != get_byte(i, datacount))␊ |
throw Decoding_Error("Gzip_Decompression: Data integrity error - incorrect length");␊ |
}␊ |
␊ |
}␊ |
␊ |
/*************************************************␊ |
|
␊ |
throw Exception("Gzip_Decompression: didn't find footer");␊ |
␊ |
}␊ |
␊ |
/*************************************************␊ |
* Clean up Decompression Context *␊ |
*************************************************/␊ |
void Gzip_Decompression::clear()␊ |
{␊ |
no_writes = true;␊ |
inflateReset(&(zlib->stream));␊ |
␊ |
#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,9,11)␊ |
footer.clear();␊ |
#else␊ |
footer.destroy();␊ |
#endif␊ |
pos = 0;␊ |
datacount = 0;␊ |
}␊ |
␊ |
}␊ |
␊ |
// Local Variables:␊ |
// mode: C++␊ |
// fill-column: 76␊ |
// c-file-style: "gnu"␊ |
// indent-tabs-mode: nil␊ |
// End:␊ |
// vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s:␊ |