mirror of
https://github.com/qbittorrent/qBittorrent
synced 2025-07-13 00:33:09 -07:00
Revise Utils::Gzip::decompress
Rename from uncompress to decompress Change signature Use proper casting Use larger buffer for the output of inflate() Reserve 1 MBytes for output buffer Change function signature
This commit is contained in:
parent
302c8ba850
commit
617f19e599
4 changed files with 44 additions and 40 deletions
|
@ -92,8 +92,8 @@ void DownloadHandler::processFinishedDownload()
|
||||||
// Success
|
// Success
|
||||||
QByteArray replyData = m_reply->readAll();
|
QByteArray replyData = m_reply->readAll();
|
||||||
if (m_reply->rawHeader("Content-Encoding") == "gzip") {
|
if (m_reply->rawHeader("Content-Encoding") == "gzip") {
|
||||||
// uncompress gzip reply
|
// decompress gzip reply
|
||||||
Utils::Gzip::uncompress(replyData, replyData);
|
replyData = Utils::Gzip::decompress(replyData);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_saveToFile) {
|
if (m_saveToFile) {
|
||||||
|
|
|
@ -416,8 +416,10 @@ void GeoIPManager::downloadFinished(const QString &url, QByteArray data)
|
||||||
{
|
{
|
||||||
Q_UNUSED(url);
|
Q_UNUSED(url);
|
||||||
|
|
||||||
if (!Utils::Gzip::uncompress(data, data)) {
|
bool ok = false;
|
||||||
Logger::instance()->addMessage(tr("Could not uncompress GeoIP database file."), Log::WARNING);
|
data = Utils::Gzip::decompress(data, &ok);
|
||||||
|
if (!ok) {
|
||||||
|
Logger::instance()->addMessage(tr("Could not decompress GeoIP database file."), Log::WARNING);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -94,54 +94,56 @@ QByteArray Utils::Gzip::compress(const QByteArray &data, const int level, bool *
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Utils::Gzip::uncompress(QByteArray src, QByteArray &dest)
|
QByteArray Utils::Gzip::decompress(const QByteArray &data, bool *ok)
|
||||||
{
|
{
|
||||||
dest.clear();
|
if (ok) *ok = false;
|
||||||
|
|
||||||
if (src.size() <= 4) {
|
if (data.isEmpty())
|
||||||
qWarning("uncompress: Input data is truncated");
|
return {};
|
||||||
return false;
|
|
||||||
}
|
const int BUFSIZE = 1024 * 1024;
|
||||||
|
char tmpBuf[BUFSIZE] = {0};
|
||||||
|
|
||||||
z_stream strm;
|
z_stream strm;
|
||||||
static const int CHUNK_SIZE = 1024;
|
|
||||||
char out[CHUNK_SIZE];
|
|
||||||
|
|
||||||
/* allocate inflate state */
|
|
||||||
strm.zalloc = Z_NULL;
|
strm.zalloc = Z_NULL;
|
||||||
strm.zfree = Z_NULL;
|
strm.zfree = Z_NULL;
|
||||||
strm.opaque = Z_NULL;
|
strm.opaque = Z_NULL;
|
||||||
strm.avail_in = static_cast<uint>(src.size());
|
strm.next_in = reinterpret_cast<const Bytef *>(data.constData());
|
||||||
strm.next_in = reinterpret_cast<uchar *>(src.data());
|
strm.avail_in = uInt(data.size());
|
||||||
|
strm.next_out = reinterpret_cast<Bytef *>(tmpBuf);
|
||||||
|
strm.avail_out = BUFSIZE;
|
||||||
|
|
||||||
const int windowBits = 15;
|
// windowBits must be greater than or equal to the windowBits value provided to deflateInit2() while compressing
|
||||||
const int ENABLE_ZLIB_GZIP = 32;
|
// Add 32 to windowBits to enable zlib and gzip decoding with automatic header detection
|
||||||
|
int result = inflateInit2(&strm, (15 + 32));
|
||||||
|
if (result != Z_OK)
|
||||||
|
return {};
|
||||||
|
|
||||||
int ret = inflateInit2(&strm, windowBits | ENABLE_ZLIB_GZIP); // gzip decoding
|
QByteArray output;
|
||||||
if (ret != Z_OK)
|
// from lzbench, level 9 average compression ratio is: 31.92%, which decompression ratio is: 1 / 0.3192 = 3.13
|
||||||
return false;
|
output.reserve(data.size() * 3);
|
||||||
|
|
||||||
// run inflate()
|
// run inflate
|
||||||
do {
|
while (true) {
|
||||||
strm.avail_out = CHUNK_SIZE;
|
result = inflate(&strm, Z_NO_FLUSH);
|
||||||
strm.next_out = reinterpret_cast<uchar *>(out);
|
|
||||||
|
|
||||||
ret = inflate(&strm, Z_NO_FLUSH);
|
if (result == Z_STREAM_END) {
|
||||||
Q_ASSERT(ret != Z_STREAM_ERROR); // state not clobbered
|
output.append(tmpBuf, (BUFSIZE - strm.avail_out));
|
||||||
|
break;
|
||||||
switch (ret) {
|
|
||||||
case Z_NEED_DICT:
|
|
||||||
case Z_DATA_ERROR:
|
|
||||||
case Z_MEM_ERROR:
|
|
||||||
inflateEnd(&strm);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dest.append(out, CHUNK_SIZE - strm.avail_out);
|
if (result != Z_OK) {
|
||||||
}
|
inflateEnd(&strm);
|
||||||
while (!strm.avail_out);
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
output.append(tmpBuf, (BUFSIZE - strm.avail_out));
|
||||||
|
strm.next_out = reinterpret_cast<Bytef *>(tmpBuf);
|
||||||
|
strm.avail_out = BUFSIZE;
|
||||||
|
}
|
||||||
|
|
||||||
// clean up and return
|
|
||||||
inflateEnd(&strm);
|
inflateEnd(&strm);
|
||||||
return true;
|
|
||||||
|
if (ok) *ok = true;
|
||||||
|
return output;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ namespace Utils
|
||||||
namespace Gzip
|
namespace Gzip
|
||||||
{
|
{
|
||||||
QByteArray compress(const QByteArray &data, int level = 6, bool *ok = nullptr);
|
QByteArray compress(const QByteArray &data, int level = 6, bool *ok = nullptr);
|
||||||
bool uncompress(QByteArray src, QByteArray &dest);
|
QByteArray decompress(const QByteArray &data, bool *ok = nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue