| * 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:␊ |