Botan 3.4.0
Crypto and TLS for C&
zlib.cpp
Go to the documentation of this file.
1/*
2* Zlib Compressor
3* (C) 2001 Peter J Jones
4* 2001-2007,2014 Jack Lloyd
5* 2006 Matt Johnston
6*
7* Botan is released under the Simplified BSD License (see license.txt)
8*/
9
10#include <botan/zlib.h>
11
12#include <botan/exceptn.h>
13#include <botan/internal/compress_utils.h>
14#include <zlib.h>
15
16namespace Botan {
17
18namespace {
19
20class Zlib_Stream : public Zlib_Style_Stream<z_stream, Bytef, unsigned int> {
21 public:
22 Zlib_Stream() {
23 streamp()->opaque = alloc();
24 streamp()->zalloc = Compression_Alloc_Info::malloc<unsigned int>;
25 streamp()->zfree = Compression_Alloc_Info::free;
26 }
27
28 uint32_t run_flag() const override { return Z_NO_FLUSH; }
29
30 uint32_t flush_flag() const override { return Z_SYNC_FLUSH; }
31
32 uint32_t finish_flag() const override { return Z_FINISH; }
33
34 int compute_window_bits(int wbits, int wbits_offset) const {
35 if(wbits_offset == -1) {
36 return -wbits;
37 } else {
38 return wbits + wbits_offset;
39 }
40 }
41};
42
43class Zlib_Compression_Stream : public Zlib_Stream {
44 public:
45 Zlib_Compression_Stream(size_t level, int wbits, int wbits_offset = 0) {
46 wbits = compute_window_bits(wbits, wbits_offset);
47
48 if(level >= 9) {
49 level = 9;
50 } else if(level == 0) {
51 level = 6;
52 }
53
54 int rc = ::deflateInit2(streamp(), static_cast<int>(level), Z_DEFLATED, wbits, 8, Z_DEFAULT_STRATEGY);
55
56 if(rc != Z_OK) {
57 throw Compression_Error("deflateInit2", ErrorType::ZlibError, rc);
58 }
59 }
60
61 ~Zlib_Compression_Stream() override { ::deflateEnd(streamp()); }
62
63 Zlib_Compression_Stream(const Zlib_Compression_Stream& other) = delete;
64 Zlib_Compression_Stream(Zlib_Compression_Stream&& other) = delete;
65 Zlib_Compression_Stream& operator=(const Zlib_Compression_Stream& other) = delete;
66 Zlib_Compression_Stream& operator=(Zlib_Compression_Stream&& other) = delete;
67
68 bool run(uint32_t flags) override {
69 int rc = ::deflate(streamp(), flags);
70
71 if(rc != Z_OK && rc != Z_STREAM_END && rc != Z_BUF_ERROR) {
72 throw Compression_Error("zlib deflate", ErrorType::ZlibError, rc);
73 }
74
75 return (rc == Z_STREAM_END);
76 }
77};
78
79class Zlib_Decompression_Stream : public Zlib_Stream {
80 public:
81 Zlib_Decompression_Stream(int wbits, int wbits_offset = 0) {
82 int rc = ::inflateInit2(streamp(), compute_window_bits(wbits, wbits_offset));
83
84 if(rc != Z_OK) {
85 throw Compression_Error("inflateInit2", ErrorType::ZlibError, rc);
86 }
87 }
88
89 ~Zlib_Decompression_Stream() override { ::inflateEnd(streamp()); }
90
91 Zlib_Decompression_Stream(const Zlib_Decompression_Stream& other) = delete;
92 Zlib_Decompression_Stream(Zlib_Decompression_Stream&& other) = delete;
93 Zlib_Decompression_Stream& operator=(const Zlib_Decompression_Stream& other) = delete;
94 Zlib_Decompression_Stream& operator=(Zlib_Decompression_Stream&& other) = delete;
95
96 bool run(uint32_t flags) override {
97 int rc = ::inflate(streamp(), flags);
98
99 if(rc != Z_OK && rc != Z_STREAM_END && rc != Z_BUF_ERROR) {
100 throw Compression_Error("zlib inflate", ErrorType::ZlibError, rc);
101 }
102
103 return (rc == Z_STREAM_END);
104 }
105};
106
107class Deflate_Compression_Stream final : public Zlib_Compression_Stream {
108 public:
109 Deflate_Compression_Stream(size_t level, int wbits) : Zlib_Compression_Stream(level, wbits, -1) {}
110};
111
112class Deflate_Decompression_Stream final : public Zlib_Decompression_Stream {
113 public:
114 explicit Deflate_Decompression_Stream(int wbits) : Zlib_Decompression_Stream(wbits, -1) {}
115};
116
117class Gzip_Compression_Stream final : public Zlib_Compression_Stream {
118 public:
119 Gzip_Compression_Stream(size_t level, int wbits, uint8_t os_code, uint64_t hdr_time) :
120 Zlib_Compression_Stream(level, wbits, 16) {
121 clear_mem(&m_header, 1);
122 m_header.os = os_code;
123 m_header.time = static_cast<uLong>(hdr_time);
124
125 int rc = deflateSetHeader(streamp(), &m_header);
126 if(rc != Z_OK) {
127 throw Compression_Error("deflateSetHeader", ErrorType::ZlibError, rc);
128 }
129 }
130
131 private:
132 ::gz_header m_header;
133};
134
135class Gzip_Decompression_Stream final : public Zlib_Decompression_Stream {
136 public:
137 explicit Gzip_Decompression_Stream(int wbits) : Zlib_Decompression_Stream(wbits, 16) {}
138};
139
140} // namespace
141
142std::unique_ptr<Compression_Stream> Zlib_Compression::make_stream(size_t level) const {
143 return std::make_unique<Zlib_Compression_Stream>(level, 15);
144}
145
146std::unique_ptr<Compression_Stream> Zlib_Decompression::make_stream() const {
147 return std::make_unique<Zlib_Decompression_Stream>(15);
148}
149
150std::unique_ptr<Compression_Stream> Deflate_Compression::make_stream(size_t level) const {
151 return std::make_unique<Deflate_Compression_Stream>(level, 15);
152}
153
154std::unique_ptr<Compression_Stream> Deflate_Decompression::make_stream() const {
155 return std::make_unique<Deflate_Decompression_Stream>(15);
156}
157
158std::unique_ptr<Compression_Stream> Gzip_Compression::make_stream(size_t level) const {
159 return std::make_unique<Gzip_Compression_Stream>(level, 15, m_os_code, m_hdr_time);
160}
161
162std::unique_ptr<Compression_Stream> Gzip_Decompression::make_stream() const {
163 return std::make_unique<Gzip_Decompression_Stream>(15);
164}
165
166} // namespace Botan
static void free(void *self, void *ptr)
int(* final)(unsigned char *, CTX *)
constexpr void clear_mem(T *ptr, size_t n)
Definition mem_ops.h:120
Public Header.