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