# # patch "ChangeLog" # from [56875aead2f1816496258da64c45a0250642a0f1] # to [4932f0057b7cb0ca29fe2bcd598ea8e6c07cf59d] # # patch "botan/gzip.cpp" # from [6120187e9450c4934ae6f196829baa8653e98210] # to [aa9b02ea481b7aa497fbe90c5fd16a9b7bade2cf] # # patch "botan/gzip.h" # from [4966cf920d955ea04b7f33680e5c4e975547bfd5] # to [18beaca49947b5a5727c6396ecb6091442e4fe62] # =============================================== --- ChangeLog 56875aead2f1816496258da64c45a0250642a0f1 +++ ChangeLog 4932f0057b7cb0ca29fe2bcd598ea8e6c07cf59d @@ -1,3 +1,7 @@ +2005-08-02 Matt Johnston + + * botan/gzip.{cpp,h}: rearranged the code to be clearer. + 2005-07-29 Nathaniel Smith * globish.cc (matcher::operator()): Log what's happening. =============================================== --- botan/gzip.cpp 6120187e9450c4934ae6f196829baa8653e98210 +++ botan/gzip.cpp aa9b02ea481b7aa497fbe90c5fd16a9b7bade2cf @@ -88,26 +88,38 @@ level((l >= 9) ? 9 : l), buffer(DEFAULT_BUFFERSIZE), pipe(new Hash_Filter("CRC32")), count( 0 ) { - zlib = 0; - } -/************************************************* -* Start Compressing with Gzip * -*************************************************/ -void Gzip_Compression::start_msg() - { - clear(); zlib = new Zlib_Stream; // window_bits == -15 relies on an undocumented feature of zlib, which // supresses the zlib header on the message. We need that since gzip doesn't // use this header. The feature been confirmed to exist in 1.1.4, which // everyone should be using due to security fixes. In later versions this // feature is documented, along with the ability to do proper gzip output - // (which would be a nicer way to do things, but will have to wait until 1.2 + // (that would be a nicer way to do things, but will have to wait until 1.2 // becomes more widespread). - // The other settings are the defaults which deflateInit() gives + // The other settings are the defaults that deflateInit() gives if(deflateInit2(&(zlib->stream), level, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY) != Z_OK) + { + delete zlib; zlib = 0; throw Exception("Gzip_Compression: Memory allocation error"); + } + } + +/************************************************* +* Gzip_Compression Destructor * +*************************************************/ +Gzip_Compression::~Gzip_Compression() + { + deflateEnd(&(zlib->stream)); + delete zlib; zlib = 0; + } + +/************************************************* +* Start Compressing with Gzip * +*************************************************/ +void Gzip_Compression::start_msg() + { + clear(); put_header(); pipe.start_msg(); count = 0; @@ -129,7 +141,9 @@ { zlib->stream.next_out = (Bytef*)buffer.begin(); zlib->stream.avail_out = buffer.size(); - deflate(&(zlib->stream), Z_NO_FLUSH); + int rc = deflate(&(zlib->stream), Z_NO_FLUSH); + if (rc != Z_OK && rc != Z_STREAM_END) + throw Exception("Internal error in Gzip_Compression deflate.") send(buffer.begin(), buffer.size() - zlib->stream.avail_out); } } @@ -148,46 +162,22 @@ zlib->stream.next_out = (Bytef*)buffer.begin(); zlib->stream.avail_out = buffer.size(); rc = deflate(&(zlib->stream), Z_FINISH); + if (rc != Z_OK && rc != Z_STREAM_END) + throw Exception("Internal error in Gzip_Compression finishing deflate.") send(buffer.begin(), buffer.size() - zlib->stream.avail_out); } pipe.end_msg(); put_footer(); - clear(); } /************************************************* -* Flush the Gzip Compressor * -*************************************************/ -void Gzip_Compression::flush() - { - zlib->stream.next_in = 0; - zlib->stream.avail_in = 0; - - while(true) - { - zlib->stream.next_out = (Bytef*)buffer.begin(); - zlib->stream.avail_out = buffer.size(); - deflate(&(zlib->stream), Z_FULL_FLUSH); - send(buffer.begin(), buffer.size() - zlib->stream.avail_out); - if(zlib->stream.avail_out == buffer.size()) break; - } - } - -/************************************************* * Clean up Compression Context * *************************************************/ void Gzip_Compression::clear() { - if(zlib) - { - deflateEnd(&(zlib->stream)); - delete zlib; - zlib = 0; - } - - buffer.clear(); + deflateReset(&(zlib->stream)); } /************************************************* @@ -195,7 +185,7 @@ *************************************************/ void Gzip_Compression::put_header() { - send(GZIP::GZIP_HEADER, sizeof(GZIP::GZIP_HEADER)); + send(GZIP::GZIP_HEADER, sizeof(GZIP::GZIP_HEADER)); } /************************************************* @@ -203,49 +193,62 @@ *************************************************/ void Gzip_Compression::put_footer() { + // 4 byte CRC32, and 4 byte length field + SecureVector buf(4); + SecureVector tmpbuf(4); - // 4 byte CRC32, and 4 byte length field - SecureVector buf(4); - SecureVector tmpbuf(4); + pipe.read(tmpbuf.begin(), tmpbuf.size()); - pipe.read(tmpbuf.begin(), tmpbuf.size()); + // CRC32 is the reverse order to what gzip expects. + for (int i = 0; i < 4; i++) + buf[3-i] = tmpbuf[i]; - // CRC32 is the reverse order to what gzip expects. - for (int i = 0; i < 4; i++) - buf[3-i] = tmpbuf[i]; + send(buf.begin(), buf.size()); - send(buf.begin(), buf.size()); + // Length - LSB first + for (int i = 0; i < 4; i++) + buf[3-i] = get_byte(i, count); - // Length - LSB first - for (int i = 0; i < 4; i++) - buf[3-i] = get_byte(i, count); - - send(buf.begin(), buf.size()); + send(buf.begin(), buf.size()); } /************************************************* * Gzip_Decompression Constructor * *************************************************/ Gzip_Decompression::Gzip_Decompression() : buffer(DEFAULT_BUFFERSIZE), - pipe(new Hash_Filter("CRC32")), footer(0) + no_writes(true), pipe(new Hash_Filter("CRC32")), footer(0) { - zlib = 0; - no_writes = true; if (DEFAULT_BUFFERSIZE < sizeof(GZIP::GZIP_HEADER)) throw Exception("DEFAULT_BUFFERSIZE is too small"); + + zlib = new Zlib_Stream; + + // window_bits == -15 is raw zlib (no header) - see comment + // above about deflateInit2 + if(inflateInit2(&(zlib->stream), -15) != Z_OK) + { + delete zlib; zlib = 0; + throw Exception("Gzip_Decompression: Memory allocation error"); + } } /************************************************* +* Gzip_Decompression Destructor * +*************************************************/ +Gzip_Decompression::~Gzip_Decompression() + { + inflateEnd(&(zlib->stream)); + delete zlib; zlib = 0; + } + +/************************************************* * Start Decompressing with Gzip * *************************************************/ void Gzip_Decompression::start_msg() { - clear(); - zlib = new Zlib_Stream; - // window_bits == -15 is raw zlib (no header) - see comment - // above for deflateInit2 - if(inflateInit2(&(zlib->stream), -15) != Z_OK) - throw Exception("Gzip_Decompression: Memory allocation error"); + if (!no_writes) + throw Exception("Gzip_Decompression: start_msg after already writing"); + pipe.start_msg(); datacount = 0; pos = 0; @@ -300,7 +303,6 @@ int rc = inflate(&(zlib->stream), Z_SYNC_FLUSH); if(rc != Z_OK && rc != Z_STREAM_END) { - clear(); if(rc == Z_DATA_ERROR) throw Decoding_Error("Gzip_Decompression: Data integrity error"); if(rc == Z_NEED_DICT) @@ -341,7 +343,7 @@ if (footer.size() == GZIP::FOOTER_LENGTH) { check_footer(); - start_msg(); + clear(); } return eat_len; @@ -352,8 +354,6 @@ *************************************************/ void Gzip_Decompression::check_footer() { - if(no_writes) return; - if (footer.size() != GZIP::FOOTER_LENGTH) throw Exception("Gzip_Decompression: Error finalizing decompression"); @@ -388,7 +388,7 @@ { // All messages should end with a footer, and when a footer is successfully - // read, start_msg() will be called. + // read, clear() will reset no_writes if(no_writes) return; throw Exception("Gzip_Decompression: didn't find footer"); @@ -401,15 +401,8 @@ void Gzip_Decompression::clear() { no_writes = true; + inflateReset(&(zlib->stream)); - if(zlib) - { - inflateEnd(&(zlib->stream)); - delete zlib; - zlib = 0; - } - - buffer.clear(); footer.clear(); pos = 0; datacount = 0; =============================================== --- botan/gzip.h 4966cf920d955ea04b7f33680e5c4e975547bfd5 +++ botan/gzip.h 18beaca49947b5a5727c6396ecb6091442e4fe62 @@ -39,10 +39,8 @@ void start_msg(); void end_msg(); - void flush(); - Gzip_Compression(u32bit = 6); - ~Gzip_Compression() { clear(); } + ~Gzip_Compression(); private: void clear(); void put_header(); @@ -65,7 +63,7 @@ void end_msg(); Gzip_Decompression(); - ~Gzip_Decompression() { clear(); } + ~Gzip_Decompression(); private: u32bit eat_footer(const byte input[], u32bit length); void check_footer();