Botan  1.11.15
src/lib/compression/zlib/zlib.cpp
Go to the documentation of this file.
00001 /*
00002 * Zlib Compressor
00003 * (C) 2001 Peter J Jones
00004 *     2001-2007,2014 Jack Lloyd
00005 *     2006 Matt Johnston
00006 *
00007 * Botan is released under the Simplified BSD License (see license.txt)
00008 */
00009 
00010 #include <botan/zlib.h>
00011 #include <botan/internal/compress_utils.h>
00012 #include <ctime>
00013 #include <zlib.h>
00014 
00015 namespace Botan {
00016 
00017 BOTAN_REGISTER_COMPRESSION(Zlib_Compression, Zlib_Decompression);
00018 BOTAN_REGISTER_COMPRESSION(Gzip_Compression, Gzip_Decompression);
00019 BOTAN_REGISTER_COMPRESSION(Deflate_Compression, Deflate_Decompression);
00020 
00021 namespace {
00022 
00023 class Zlib_Stream : public Zlib_Style_Stream<z_stream, Bytef>
00024    {
00025    public:
00026       Zlib_Stream()
00027          {
00028          streamp()->opaque = alloc();
00029          streamp()->zalloc = Compression_Alloc_Info::malloc<unsigned int>;
00030          streamp()->zfree = Compression_Alloc_Info::free;
00031          }
00032 
00033       u32bit run_flag() const override { return Z_NO_FLUSH; }
00034       u32bit flush_flag() const override { return Z_FULL_FLUSH; }
00035       u32bit finish_flag() const override { return Z_FINISH; }
00036 
00037       int compute_window_bits(int wbits, int wbits_offset) const
00038          {
00039          if(wbits_offset == -1)
00040             return -wbits;
00041          else
00042             return wbits + wbits_offset;
00043          }
00044    };
00045 
00046 class Zlib_Compression_Stream : public Zlib_Stream
00047    {
00048    public:
00049       Zlib_Compression_Stream(size_t level, int wbits, int wbits_offset = 0)
00050          {
00051          wbits = compute_window_bits(wbits, wbits_offset);
00052 
00053          int rc = deflateInit2(streamp(), level, Z_DEFLATED, wbits,
00054                                8, Z_DEFAULT_STRATEGY);
00055          if(rc != Z_OK)
00056             throw std::runtime_error("zlib deflate initialization failed");
00057          }
00058 
00059       ~Zlib_Compression_Stream()
00060          {
00061          deflateEnd(streamp());
00062          }
00063 
00064       bool run(u32bit flags) override
00065          {
00066          int rc = deflate(streamp(), flags);
00067 
00068          if(rc == Z_MEM_ERROR)
00069             throw std::bad_alloc();
00070          else if(rc != Z_OK && rc != Z_STREAM_END)
00071             throw std::runtime_error("zlib deflate error");
00072 
00073          return (rc == Z_STREAM_END);
00074          }
00075    };
00076 
00077 class Zlib_Decompression_Stream : public Zlib_Stream
00078    {
00079    public:
00080       Zlib_Decompression_Stream(int wbits, int wbits_offset = 0)
00081          {
00082          int rc = inflateInit2(streamp(), compute_window_bits(wbits, wbits_offset));
00083 
00084          if(rc == Z_MEM_ERROR)
00085             throw std::bad_alloc();
00086          else if(rc != Z_OK)
00087             throw std::runtime_error("zlib inflate initialization failed");
00088          }
00089 
00090       ~Zlib_Decompression_Stream()
00091          {
00092          inflateEnd(streamp());
00093          }
00094 
00095       bool run(u32bit flags) override
00096          {
00097          int rc = inflate(streamp(), flags);
00098 
00099          if(rc == Z_MEM_ERROR)
00100             throw std::bad_alloc();
00101          else if(rc != Z_OK && rc != Z_STREAM_END)
00102             throw std::runtime_error("zlib deflate error");
00103 
00104          return (rc == Z_STREAM_END);
00105          }
00106    };
00107 
00108 class Deflate_Compression_Stream : public Zlib_Compression_Stream
00109    {
00110    public:
00111       Deflate_Compression_Stream(size_t level, int wbits) :
00112          Zlib_Compression_Stream(level, wbits, -1) {}
00113    };
00114 
00115 class Deflate_Decompression_Stream : public Zlib_Decompression_Stream
00116    {
00117    public:
00118       Deflate_Decompression_Stream(int wbits) : Zlib_Decompression_Stream(wbits, -1) {}
00119    };
00120 
00121 class Gzip_Compression_Stream : public Zlib_Compression_Stream
00122    {
00123    public:
00124       Gzip_Compression_Stream(size_t level, int wbits, byte os_code) :
00125          Zlib_Compression_Stream(level, wbits, 16)
00126          {
00127          clear_mem(&m_header, 1);
00128          m_header.os = os_code;
00129          m_header.time = std::time(nullptr);
00130 
00131          int rc = deflateSetHeader(streamp(), &m_header);
00132          if(rc != Z_OK)
00133             throw std::runtime_error("setting gzip header failed");
00134          }
00135 
00136    private:
00137       ::gz_header m_header;
00138    };
00139 
00140 class Gzip_Decompression_Stream : public Zlib_Decompression_Stream
00141    {
00142    public:
00143       Gzip_Decompression_Stream(int wbits) : Zlib_Decompression_Stream(wbits, 16) {}
00144    };
00145 
00146 }
00147 
00148 Compression_Stream* Zlib_Compression::make_stream() const
00149    {
00150    return new Zlib_Compression_Stream(m_level, 15);
00151    }
00152 
00153 Compression_Stream* Zlib_Decompression::make_stream() const
00154    {
00155    return new Zlib_Decompression_Stream(15);
00156    }
00157 
00158 Compression_Stream* Deflate_Compression::make_stream() const
00159    {
00160    return new Deflate_Compression_Stream(m_level, 15);
00161    }
00162 
00163 Compression_Stream* Deflate_Decompression::make_stream() const
00164    {
00165    return new Deflate_Decompression_Stream(15);
00166    }
00167 
00168 Compression_Stream* Gzip_Compression::make_stream() const
00169    {
00170    return new Gzip_Compression_Stream(m_level, 15, m_os_code);
00171    }
00172 
00173 Compression_Stream* Gzip_Decompression::make_stream() const
00174    {
00175    return new Gzip_Decompression_Stream(15);
00176    }
00177 
00178 }