Crypto++ 8.7
Free C++ class library of cryptographic schemes
gzip.cpp
1// gzip.cpp - originally written and placed in the public domain by Wei Dai
2
3#include "pch.h"
4#include "gzip.h"
5#include "argnames.h"
6
7NAMESPACE_BEGIN(CryptoPP)
8
9// Checks whether the character is valid for ISO/IEC 8859-1 as required by RFC 1952
10static inline bool Is8859Character(char c) {
11 const unsigned char cc = static_cast<unsigned char>(c);
12 return (cc >= 32 && cc <= 126) || (cc >= 160);
13}
14
16{
18
20 if (parameters.GetValue(Name::FileName(), v))
21 m_filename.assign(reinterpret_cast<const char*>(v.begin()), v.size());
22 if (parameters.GetValue(Name::Comment(), v))
23 m_comment.assign(reinterpret_cast<const char*>(v.begin()), v.size());
24 m_filetime = parameters.GetIntValueWithDefault(Name::FileTime(), 0);
25}
26
27void Gzip::WritePrestreamHeader()
28{
29 m_totalLen = 0;
30 m_crc.Restart();
31
32 int flags = 0;
33 if(!m_filename.empty())
34 flags |= FILENAME;
35 if(!m_comment.empty())
36 flags |= COMMENTS;
37
38 AttachedTransformation()->Put(MAGIC1);
39 AttachedTransformation()->Put(MAGIC2);
40 AttachedTransformation()->Put(DEFLATED);
41 AttachedTransformation()->Put((byte)flags); // general flag
42 AttachedTransformation()->PutWord32(m_filetime, LITTLE_ENDIAN_ORDER); // time stamp
43 byte extra = static_cast<byte>((GetDeflateLevel() == 1) ?
44 FAST : ((GetDeflateLevel() == 9) ? SLOW : 0));
46 AttachedTransformation()->Put(GZIP_OS_CODE);
47
48 // Filename is NULL terminated, hence the +1
49 if(!m_filename.empty())
50 AttachedTransformation()->Put((const unsigned char*)m_filename.data(), m_filename.size() +1);
51
52 // Comment is NULL terminated, hence the +1
53 if(!m_comment.empty())
54 AttachedTransformation()->Put((const unsigned char*)m_comment.data(), m_comment.size() +1);
55}
56
57void Gzip::ProcessUncompressedData(const byte *inString, size_t length)
58{
59 m_crc.Update(inString, length);
60 m_totalLen += (word32)length;
61}
62
63void Gzip::WritePoststreamTail()
64{
65 SecByteBlock crc(4);
66 m_crc.Final(crc);
67 AttachedTransformation()->Put(crc, 4);
69
70 m_filetime = 0;
71 m_filename.clear();
72 m_comment.clear();
73}
74
75void Gzip::SetComment(const std::string& comment, bool throwOnEncodingError)
76{
77 if(throwOnEncodingError)
78 {
79 for(size_t i = 0; i < comment.length(); i++) {
80 const char c = comment[i];
81 if(!Is8859Character(c))
82 throw InvalidDataFormat("The comment is not ISO/IEC 8859-1 encoded");
83 }
84 }
85
86 m_comment = comment;
87}
88
89void Gzip::SetFilename(const std::string& filename, bool throwOnEncodingError)
90{
91 if(throwOnEncodingError)
92 {
93 for(size_t i = 0; i < filename.length(); i++) {
94 const char c = filename[i];
95 if(!Is8859Character(c))
96 throw InvalidDataFormat("The filename is not ISO/IEC 8859-1 encoded");
97 }
98 }
99
100 m_filename = filename;
101}
102
103// *************************************************************
104
105Gunzip::Gunzip(BufferedTransformation *attachment, bool repeat, int propagation)
106 : Inflator(attachment, repeat, propagation), m_length(0), m_filetime(0)
107{
108}
109
110void Gunzip::ProcessPrestreamHeader()
111{
112 m_length = 0;
113 m_crc.Restart();
114
115 m_filetime = 0;
116 m_filename.clear();
117 m_comment.clear();
118
119 byte buf[6];
120 byte b, flags;
121
122 if (m_inQueue.Get(buf, 2)!=2) throw HeaderErr();
123 if (buf[0] != MAGIC1 || buf[1] != MAGIC2) throw HeaderErr();
124 if (!m_inQueue.Get(b) || (b != DEFLATED)) throw HeaderErr(); // skip CM flag
125 if (!m_inQueue.Get(flags)) throw HeaderErr();
126 if (flags & (ENCRYPTED | CONTINUED)) throw HeaderErr();
127 if (m_inQueue.GetWord32(m_filetime, LITTLE_ENDIAN_ORDER) != 4) throw HeaderErr();
128 if (m_inQueue.Skip(2)!=2) throw HeaderErr(); // Skip extra flags and OS type
129
130 if (flags & EXTRA_FIELDS) // skip extra fields
131 {
132 word16 length;
133 if (m_inQueue.GetWord16(length, LITTLE_ENDIAN_ORDER) != 2) throw HeaderErr();
134 if (m_inQueue.Skip(length)!=length) throw HeaderErr();
135 }
136
137 if (flags & FILENAME) // extract filename
138 {
139 do
140 {
141 if(!m_inQueue.Get(b)) throw HeaderErr();
142 if(b) m_filename.append( 1, (char)b );
143 }
144 while (b);
145 }
146
147 if (flags & COMMENTS) // extract comments
148 {
149 do
150 {
151 if(!m_inQueue.Get(b)) throw HeaderErr();
152 if(b) m_comment.append( 1, (char)b );
153 }
154 while (b);
155 }
156}
157
158void Gunzip::ProcessDecompressedData(const byte *inString, size_t length)
159{
160 AttachedTransformation()->Put(inString, length);
161 m_crc.Update(inString, length);
162 m_length += (word32)length;
163}
164
165void Gunzip::ProcessPoststreamTail()
166{
167 SecByteBlock crc(4);
168 if (m_inQueue.Get(crc, 4) != 4)
169 throw TailErr();
170 if (!m_crc.Verify(crc))
171 throw CrcErr();
172
173 word32 lengthCheck;
174 if (m_inQueue.GetWord32(lengthCheck, LITTLE_ENDIAN_ORDER) != 4)
175 throw TailErr();
176 if (lengthCheck != m_length)
177 throw LengthErr();
178}
179
180const std::string& Gunzip::GetComment(bool throwOnEncodingError) const
181{
182 if(throwOnEncodingError)
183 {
184 for(size_t i = 0; i < m_comment.length(); i++) {
185 const char c = m_comment[i];
186 if(!Is8859Character(c))
187 throw InvalidDataFormat("The comment is not ISO/IEC 8859-1 encoded");
188 }
189 }
190
191 return m_comment;
192}
193
194const std::string& Gunzip::GetFilename(bool throwOnEncodingError) const
195{
196 if(throwOnEncodingError)
197 {
198 for(size_t i = 0; i < m_filename.length(); i++) {
199 const char c = m_filename[i];
200 if(!Is8859Character(c))
201 throw InvalidDataFormat("The filename is not ISO/IEC 8859-1 encoded");
202 }
203 }
204
205 return m_filename;
206}
207
208NAMESPACE_END
Standard names for retrieving values by name when working with NameValuePairs.
Interface for buffered transformations.
Definition: cryptlib.h:1652
size_t Put(byte inByte, bool blocking=true)
Input a byte for processing.
Definition: cryptlib.h:1673
size_t PutWord32(word32 value, ByteOrder order=BIG_ENDIAN_ORDER, bool blocking=true)
Input a 32-bit word for processing.
void Update(const byte *input, size_t length)
Updates a hash with additional input.
Definition: crc.cpp:147
Used to pass byte array input as part of a NameValuePairs object.
Definition: algparam.h:25
const byte * begin() const
Pointer to the first byte in the memory block.
Definition: algparam.h:84
size_t size() const
Length of the memory block.
Definition: algparam.h:88
void IsolatedInitialize(const NameValuePairs &parameters)
Initialize or reinitialize this object, without signal propagation.
Definition: zdeflate.cpp:265
int GetDeflateLevel() const
Retrieves the deflation level.
Definition: zdeflate.h:118
BufferedTransformation * AttachedTransformation()
Retrieve attached transformation.
Gunzip(BufferedTransformation *attachment=NULL, bool repeat=false, int autoSignalPropagation=-1)
Construct a Gunzip decompressor.
Definition: gzip.cpp:105
const std::string & GetComment(bool throwOnEncodingError=false) const
Definition: gzip.cpp:180
const std::string & GetFilename(bool throwOnEncodingError=false) const
Definition: gzip.cpp:194
void SetComment(const std::string &comment, bool throwOnEncodingError=false)
Definition: gzip.cpp:75
void IsolatedInitialize(const NameValuePairs &parameters)
Initialize or reinitialize this object, without signal propagation.
Definition: gzip.cpp:15
void SetFilename(const std::string &filename, bool throwOnEncodingError=false)
Definition: gzip.cpp:89
virtual bool Verify(const byte *digest)
Verifies the hash of the current message.
Definition: cryptlib.h:1200
virtual void Restart()
Restart the hash.
Definition: cryptlib.h:1147
virtual void Final(byte *digest)
Computes the hash of the current message.
Definition: cryptlib.h:1142
DEFLATE decompressor (RFC 1951)
Definition: zinflate.h:95
Input data was received that did not conform to expected format.
Definition: cryptlib.h:213
Interface for retrieving values given their names.
Definition: cryptlib.h:322
bool GetValue(const char *name, T &value) const
Get a named value.
Definition: cryptlib.h:379
CRYPTOPP_DLL int GetIntValueWithDefault(const char *name, int defaultValue) const
Get a named value with type int, with default.
Definition: cryptlib.h:424
SecBlock<byte> typedef.
Definition: secblock.h:1226
unsigned int word32
32-bit unsigned datatype
Definition: config_int.h:62
unsigned short word16
16-bit unsigned datatype
Definition: config_int.h:59
@ LITTLE_ENDIAN_ORDER
byte order is little-endian
Definition: cryptlib.h:145
GZIP compression and decompression (RFC 1952)
Crypto++ library namespace.
const char * FileName()
const char *
Definition: argnames.h:91
const char * Comment()
const char *
Definition: argnames.h:93
const char * FileTime()
int
Definition: argnames.h:92
Precompiled header file.