MythTV  master
unziputil.cpp
Go to the documentation of this file.
1 #include "unziputil.h"
2 
3 #include <array>
4 
5 #include "zlib.h"
6 #undef Z_NULL
7 #define Z_NULL nullptr
8 
9 // Qt headers
10 #include <QByteArray>
11 #include <QFile>
12 
13 // libmythbase headers
14 #include "mythlogging.h"
15 #include "unzip2.h"
16 
17 bool extractZIP(QString zipFile, const QString& outDir)
18 {
19  UnZip unzip(std::move(zipFile));
20  return unzip.extractFile(outDir);
21 }
22 
23 bool gzipFile(const QString &inFilename, const QString &gzipFilename)
24 {
25  QFile infile(inFilename);
26  QFile outfile(gzipFilename);
27 
28  if (!infile.open(QIODevice::ReadOnly))
29  {
30  LOG(VB_GENERAL, LOG_ERR, QString("gzipFile(): Error opening file for reading '%1'").arg(inFilename));
31  return false;
32  }
33 
34  if (!outfile.open(QIODevice::WriteOnly))
35  {
36  LOG(VB_GENERAL, LOG_ERR, QString("gzipFile(): Error opening file for writing '%1'").arg(gzipFilename));
37  infile.close();
38  return false;
39  }
40 
41  QByteArray uncompressedData = infile.readAll();
42  QByteArray compressedData = gzipCompress(uncompressedData);
43 
44  if (!outfile.write(compressedData))
45  {
46  LOG(VB_GENERAL, LOG_ERR, QString("gzipFile(): Error while writing to '%1'").arg(gzipFilename));
47  infile.close();
48  outfile.close();
49  return false;
50  }
51 
52  infile.close();
53  outfile.close();
54 
55  return true;
56 }
57 
58 bool gunzipFile(const QString &gzipFilename, const QString &outFilename)
59 {
60  QFile infile(gzipFilename);
61  QFile outfile(outFilename);
62 
63  if (!infile.open(QIODevice::ReadOnly))
64  {
65  LOG(VB_GENERAL, LOG_ERR, QString("gunzipFile(): Error opening file for reading '%1'").arg(gzipFilename));
66  return false;
67  }
68 
69  if (!outfile.open(QIODevice::WriteOnly))
70  {
71  LOG(VB_GENERAL, LOG_ERR, QString("gunzipFile(): Error opening file for writing '%1'").arg(outFilename));
72  infile.close();
73  return false;
74  }
75 
76  QByteArray compressedData = infile.readAll();
77  QByteArray uncompressedData = gzipUncompress(compressedData);
78 
79  if (outfile.write(uncompressedData) < uncompressedData.size())
80  {
81  LOG(VB_GENERAL, LOG_ERR, QString("gunzipFile(): Error while writing to '%1'").arg(outFilename));
82  infile.close();
83  outfile.close();
84  return false;
85  }
86 
87  infile.close();
88  outfile.close();
89 
90  return true;
91 }
92 
93 QByteArray gzipCompress(const QByteArray& data)
94 {
95  if (data.length() == 0)
96  return {};
97 
98  std::array <char,1024> out {};
99 
100  // allocate inflate state
101  z_stream strm {};
102 
103  strm.zalloc = Z_NULL;
104  strm.zfree = Z_NULL;
105  strm.opaque = Z_NULL;
106  strm.avail_in = data.length();
107  strm.next_in = (Bytef*)(data.data());
108 
109  int ret = deflateInit2(&strm,
110  Z_DEFAULT_COMPRESSION,
111  Z_DEFLATED,
112  15 + 16,
113  8,
114  Z_DEFAULT_STRATEGY ); // gzip encoding
115  if (ret != Z_OK)
116  return {};
117 
118  QByteArray result;
119 
120  // run deflate()
121  do
122  {
123  strm.avail_out = out.size();
124  strm.next_out = (Bytef*)(out.data());
125 
126  ret = deflate(&strm, Z_FINISH);
127 
128  Q_ASSERT(ret != Z_STREAM_ERROR); // state not clobbered
129 
130  switch (ret)
131  {
132  case Z_NEED_DICT:
133  case Z_DATA_ERROR:
134  case Z_MEM_ERROR:
135  (void)deflateEnd(&strm);
136  return {};
137  }
138 
139  result.append(out.data(), out.size() - strm.avail_out);
140  }
141  while (strm.avail_out == 0);
142 
143  // clean up and return
144 
145  deflateEnd(&strm);
146 
147  return result;
148 }
149 
150 QByteArray gzipUncompress(const QByteArray &data)
151 {
152  if (data.length() == 0)
153  return {};
154 
155  std::array<char,1024> out {};
156 
157  // allocate inflate state
158  z_stream strm;
159  strm.total_in = 0;
160  strm.total_out = 0;
161  strm.zalloc = Z_NULL;
162  strm.zfree = Z_NULL;
163  strm.opaque = Z_NULL;
164  strm.avail_in = data.length();
165  strm.next_in = (Bytef*)(data.data());
166 
167  int ret = inflateInit2(&strm, 15 + 16);
168 
169  if (ret != Z_OK)
170  return {};
171 
172  QByteArray result;
173 
174  do
175  {
176  strm.avail_out = out.size();
177  strm.next_out = (Bytef*)out.data();
178  ret = inflate(&strm, Z_NO_FLUSH);
179 
180  Q_ASSERT(ret != Z_STREAM_ERROR); // state not clobbered
181 
182  switch (ret)
183  {
184  case Z_NEED_DICT:
185  case Z_DATA_ERROR:
186  case Z_MEM_ERROR:
187  (void) deflateEnd(&strm);
188  return {};
189  }
190 
191  result.append(out.data(), out.size() - strm.avail_out);
192  }
193  while (strm.avail_out == 0);
194 
195  (void) inflateEnd(& strm);
196 
197  return result;
198 }
199 
extractZIP
bool extractZIP(QString zipFile, const QString &outDir)
Definition: unziputil.cpp:17
unziputil.h
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
unzip2.h
Z_NULL
#define Z_NULL
Definition: unziputil.cpp:7
mythlogging.h
gzipCompress
QByteArray gzipCompress(const QByteArray &data)
Definition: unziputil.cpp:93
gunzipFile
bool gunzipFile(const QString &gzipFilename, const QString &outFilename)
Definition: unziputil.cpp:58
gzipUncompress
QByteArray gzipUncompress(const QByteArray &data)
Definition: unziputil.cpp:150
UnZip::extractFile
bool extractFile(const QString &outDir)
Definition: unzip2.cpp:264
UnZip
Definition: unzip2.h:29
gzipFile
bool gzipFile(const QString &inFilename, const QString &gzipFilename)
Definition: unziputil.cpp:23