mirror of
https://github.com/tumic0/QtPBFImagePlugin.git
synced 2024-11-24 03:35:54 +01:00
Only accept PBF gziped files in canRead()
This commit is contained in:
parent
402e1e3adc
commit
a298cfc47d
64
src/gzip.cpp
64
src/gzip.cpp
@ -3,33 +3,57 @@
|
|||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
#include "gzip.h"
|
#include "gzip.h"
|
||||||
|
|
||||||
|
#define CHUNK 16384
|
||||||
|
|
||||||
QByteArray Gzip::uncompress(const QByteArray &data)
|
QByteArray Gzip::uncompress(QIODevice *device, qint64 limit)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
|
z_stream strm;
|
||||||
|
unsigned char in[CHUNK];
|
||||||
|
unsigned char out[CHUNK];
|
||||||
|
qint64 rs;
|
||||||
QByteArray uba;
|
QByteArray uba;
|
||||||
z_stream stream;
|
|
||||||
|
|
||||||
quint32 *size = (quint32*)(data.constData() + data.size() - sizeof(quint32));
|
|
||||||
uba.resize(qFromLittleEndian(*size));
|
|
||||||
|
|
||||||
stream.zalloc = Z_NULL;
|
strm.zalloc = Z_NULL;
|
||||||
stream.zfree = Z_NULL;
|
strm.zfree = Z_NULL;
|
||||||
stream.opaque = Z_NULL;
|
strm.opaque = Z_NULL;
|
||||||
|
strm.avail_in = 0;
|
||||||
|
strm.next_in = Z_NULL;
|
||||||
|
if (inflateInit2(&strm, MAX_WBITS + 16) != Z_OK)
|
||||||
|
return QByteArray();
|
||||||
|
|
||||||
stream.next_in = (Bytef*)data.constData();
|
do {
|
||||||
stream.avail_in = data.size();
|
rs = device->read((char*)in, CHUNK);
|
||||||
stream.next_out = (Bytef*)uba.data();
|
if (rs < 0) {
|
||||||
stream.avail_out = uba.size();
|
(void)inflateEnd(&strm);
|
||||||
|
return QByteArray();
|
||||||
|
} else if (rs == 0)
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
strm.avail_in = (uInt)rs;
|
||||||
|
strm.next_in = in;
|
||||||
|
|
||||||
if (inflateInit2(&stream, MAX_WBITS + 16) != Z_OK)
|
do {
|
||||||
return uba;
|
strm.avail_out = CHUNK;
|
||||||
|
strm.next_out = out;
|
||||||
if (inflate(&stream, Z_NO_FLUSH) != Z_STREAM_END) {
|
ret = inflate(&strm, Z_NO_FLUSH);
|
||||||
qCritical() << "Invalid gzip data";
|
Q_ASSERT(ret != Z_STREAM_ERROR);
|
||||||
uba = QByteArray();
|
switch (ret) {
|
||||||
|
case Z_NEED_DICT:
|
||||||
|
case Z_DATA_ERROR:
|
||||||
|
case Z_MEM_ERROR:
|
||||||
|
(void)inflateEnd(&strm);
|
||||||
|
return QByteArray();
|
||||||
}
|
}
|
||||||
|
uba.append((char*)out, CHUNK - strm.avail_out);
|
||||||
inflateEnd(&stream);
|
if (limit && uba.size() >= limit) {
|
||||||
|
(void)inflateEnd(&strm);
|
||||||
return uba;
|
return uba;
|
||||||
}
|
}
|
||||||
|
} while (!strm.avail_out);
|
||||||
|
} while (ret != Z_STREAM_END);
|
||||||
|
|
||||||
|
(void)inflateEnd(&strm);
|
||||||
|
return (ret == Z_STREAM_END) ? uba : QByteArray();
|
||||||
|
}
|
||||||
|
@ -3,9 +3,11 @@
|
|||||||
|
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
|
|
||||||
|
class QIODevice;
|
||||||
|
|
||||||
namespace Gzip
|
namespace Gzip
|
||||||
{
|
{
|
||||||
QByteArray uncompress(const QByteArray &data);
|
QByteArray uncompress(QIODevice *device, qint64 limit = 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // GZIP_H
|
#endif // GZIP_H
|
||||||
|
@ -10,22 +10,22 @@
|
|||||||
|
|
||||||
#define TILE_SIZE 512
|
#define TILE_SIZE 512
|
||||||
|
|
||||||
#define GZIP_MAGIC 0x1F8B0800
|
#define GZIP_MAGIC 0x1F8B
|
||||||
#define GZIP_MAGIC_MASK 0xFFFFFF00
|
#define GZIP_MAGIC_MASK 0xFFFF
|
||||||
#define PBF_MAGIC 0x1A000000
|
#define PBF_MAGIC 0x1A00
|
||||||
#define PBF_MAGIC_MASK 0xFF000000
|
#define PBF_MAGIC_MASK 0xFF00
|
||||||
|
|
||||||
static bool isMagic(quint32 magic, quint32 mask, quint32 value)
|
static bool isMagic(quint16 magic, quint16 mask, quint16 value)
|
||||||
{
|
{
|
||||||
return ((qFromBigEndian(value) & mask) == magic);
|
return ((qFromBigEndian(value) & mask) == magic);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isGZIPPBF(quint32 magic)
|
static bool isGZIPPBF(quint16 magic)
|
||||||
{
|
{
|
||||||
return isMagic(GZIP_MAGIC, GZIP_MAGIC_MASK, magic);
|
return isMagic(GZIP_MAGIC, GZIP_MAGIC_MASK, magic);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isPlainPBF(quint32 magic)
|
static bool isPlainPBF(quint16 magic)
|
||||||
{
|
{
|
||||||
return isMagic(PBF_MAGIC, PBF_MAGIC_MASK, magic);
|
return isMagic(PBF_MAGIC, PBF_MAGIC_MASK, magic);
|
||||||
}
|
}
|
||||||
@ -42,23 +42,31 @@ bool PBFHandler::canRead() const
|
|||||||
|
|
||||||
bool PBFHandler::canRead(QIODevice *device)
|
bool PBFHandler::canRead(QIODevice *device)
|
||||||
{
|
{
|
||||||
quint32 magic;
|
quint16 magic;
|
||||||
qint64 size = device->peek((char*)&magic, sizeof(magic));
|
qint64 size = device->peek((char*)&magic, sizeof(magic));
|
||||||
if (size != sizeof(magic))
|
if (size != sizeof(magic))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return (isGZIPPBF(magic) || isPlainPBF(magic));
|
if (isPlainPBF(magic))
|
||||||
|
return true;
|
||||||
|
else if (isGZIPPBF(magic)) {
|
||||||
|
QByteArray ba(Gzip::uncompress(device, sizeof(magic)));
|
||||||
|
if (ba.size() < (int)sizeof(magic))
|
||||||
|
return false;
|
||||||
|
return isPlainPBF(*((quint16*)ba.constData()));
|
||||||
|
} else
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PBFHandler::read(QImage *image)
|
bool PBFHandler::read(QImage *image)
|
||||||
{
|
{
|
||||||
quint32 magic;
|
quint16 magic;
|
||||||
if (device()->peek((char*)&magic, sizeof(magic)) != sizeof(magic))
|
if (device()->peek((char*)&magic, sizeof(magic)) != sizeof(magic))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
QByteArray ba;
|
QByteArray ba;
|
||||||
if (isGZIPPBF(magic))
|
if (isGZIPPBF(magic))
|
||||||
ba = Gzip::uncompress(device()->readAll());
|
ba = Gzip::uncompress(device());
|
||||||
else if (isPlainPBF(magic))
|
else if (isPlainPBF(magic))
|
||||||
ba = device()->readAll();
|
ba = device()->readAll();
|
||||||
if (ba.isNull())
|
if (ba.isNull())
|
||||||
|
Loading…
Reference in New Issue
Block a user