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
17bool extractZIP(QString zipFile, const QString& outDir)
18{
19 UnZip unzip(std::move(zipFile));
20 return unzip.extractFile(outDir);
21}
22
23bool 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
58bool 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
93QByteArray 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 strm.avail_out = 0;
122 while (strm.avail_out == 0)
123 {
124 strm.avail_out = out.size();
125 strm.next_out = (Bytef*)(out.data());
126
127 ret = deflate(&strm, Z_FINISH);
128
129 Q_ASSERT(ret != Z_STREAM_ERROR); // state not clobbered
130
131 switch (ret)
132 {
133 case Z_NEED_DICT:
134 case Z_DATA_ERROR:
135 case Z_MEM_ERROR:
136 (void)deflateEnd(&strm);
137 return {};
138 }
139
140 result.append(out.data(), out.size() - strm.avail_out);
141 }
142
143 // clean up and return
144
145 deflateEnd(&strm);
146
147 return result;
148}
149
150QByteArray 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 strm.avail_out = 0;
175 while (strm.avail_out == 0)
176 {
177 strm.avail_out = out.size();
178 strm.next_out = (Bytef*)out.data();
179 ret = inflate(&strm, Z_NO_FLUSH);
180
181 Q_ASSERT(ret != Z_STREAM_ERROR); // state not clobbered
182
183 switch (ret)
184 {
185 case Z_NEED_DICT:
186 case Z_DATA_ERROR:
187 case Z_MEM_ERROR:
188 (void) deflateEnd(&strm);
189 return {};
190 }
191
192 result.append(out.data(), out.size() - strm.avail_out);
193 }
194
195 (void) inflateEnd(& strm);
196
197 return result;
198}
199
Definition: unzip2.h:30
bool extractFile(const QString &outDir)
Definition: unzip2.cpp:264
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
bool extractZIP(QString zipFile, const QString &outDir)
Definition: unziputil.cpp:17
bool gunzipFile(const QString &gzipFilename, const QString &outFilename)
Definition: unziputil.cpp:58
QByteArray gzipUncompress(const QByteArray &data)
Definition: unziputil.cpp:150
QByteArray gzipCompress(const QByteArray &data)
Definition: unziputil.cpp:93
bool gzipFile(const QString &inFilename, const QString &gzipFilename)
Definition: unziputil.cpp:23
#define Z_NULL
Definition: unziputil.cpp:7