mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-07-18 08:22:15 -07:00
Adjust to rebase.
Took 7 minutes
This commit is contained in:
parent
e08f28b110
commit
be00edd581
14 changed files with 1315 additions and 1283 deletions
|
|
@ -32,6 +32,7 @@ set(cockatrice_SOURCES
|
|||
src/interface/widgets/dialogs/dlg_forgot_password_challenge.cpp
|
||||
src/interface/widgets/dialogs/dlg_forgot_password_request.cpp
|
||||
src/interface/widgets/dialogs/dlg_forgot_password_reset.cpp
|
||||
src/interface/widgets/dialogs/dlg_import_precons.cpp
|
||||
src/interface/widgets/dialogs/dlg_load_deck.cpp
|
||||
src/interface/widgets/dialogs/dlg_load_deck_from_clipboard.cpp
|
||||
src/interface/widgets/dialogs/dlg_load_deck_from_website.cpp
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
#include "dlg_import_precons.h"
|
||||
|
||||
#include "../deck/deck_loader.h"
|
||||
#include "../../deck_loader/deck_loader.h"
|
||||
#include "../settings/cache_settings.h"
|
||||
#include "libcockatrice/deck_list/deck_list_card_node.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QFileDialog>
|
||||
|
|
@ -11,7 +12,7 @@
|
|||
#include <QNetworkReply>
|
||||
#include <QPushButton>
|
||||
#include <QTemporaryDir>
|
||||
#include <decklist.h>
|
||||
#include <libcockatrice/deck_list/deck_list.h>
|
||||
|
||||
#ifdef HAS_LZMA
|
||||
#include "../../src/utility/external/lzma/decompress.h"
|
||||
|
|
@ -309,7 +310,7 @@ bool LoadPreconsPage::parsePreconsFromByteArray(const QByteArray &data, QString
|
|||
|
||||
qInfo() << "Importing '" << deckName << "' from" << shortName;
|
||||
|
||||
auto *precon = new DeckLoader();
|
||||
auto *precon = new DeckLoader(this);
|
||||
|
||||
for (const auto &cardVal : mainBoard) {
|
||||
QJsonObject cardObj = cardVal.toObject();
|
||||
|
|
@ -319,20 +320,20 @@ bool LoadPreconsPage::parsePreconsFromByteArray(const QByteArray &data, QString
|
|||
int count = cardObj.value("count").toInt();
|
||||
QString scryfallId = cardObj.value("identifiers").toObject().value("scryfallId").toString();
|
||||
|
||||
DecklistCardNode *addedCard = precon->addCard(name, "main", -1, setCode, number, scryfallId);
|
||||
DecklistCardNode *addedCard = precon->getDeckList()->addCard(name, "main", -1, setCode, number, scryfallId);
|
||||
if (count != 1) {
|
||||
addedCard->setNumber(count);
|
||||
}
|
||||
}
|
||||
|
||||
precon->setName(deckName);
|
||||
precon->getDeckList()->setName(deckName);
|
||||
|
||||
QJsonArray commanderArray = preconData.value("commander").toArray();
|
||||
if (!commanderArray.isEmpty()) {
|
||||
QJsonObject commanderObj = commanderArray.first().toObject();
|
||||
QString commanderName = commanderObj.value("name").toString();
|
||||
QString commanderId = commanderObj.value("identifiers").toObject().value("scryfallId").toString();
|
||||
precon->setBannerCard(QPair<QString, QString>(commanderName, commanderId));
|
||||
precon->getDeckList()->setBannerCard({commanderName, commanderId});
|
||||
} else {
|
||||
qInfo() << "No commander data found.";
|
||||
}
|
||||
|
|
@ -340,7 +341,7 @@ bool LoadPreconsPage::parsePreconsFromByteArray(const QByteArray &data, QString
|
|||
QString dirPath = QDir::cleanPath(folderPath + QDir::separator() + deckType + QDir::separator() +
|
||||
QString::number(releaseYear) + QDir::separator() + shortName);
|
||||
|
||||
QString fullPath = QDir(dirPath).filePath(precon->getName());
|
||||
QString fullPath = QDir(dirPath).filePath(precon->getDeckList()->getName());
|
||||
|
||||
QDir dir;
|
||||
if (!dir.exists(dirPath)) {
|
||||
|
|
@ -350,7 +351,7 @@ bool LoadPreconsPage::parsePreconsFromByteArray(const QByteArray &data, QString
|
|||
}
|
||||
}
|
||||
|
||||
if (precon->getCardList().length() > 1) {
|
||||
if (precon->getDeckList()->getCardList().length() > 1) {
|
||||
precon->saveToFile(fullPath + ".cod", DeckLoader::CockatriceFormat);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
#include "../main.h"
|
||||
#include "logger.h"
|
||||
#include "version_string.h"
|
||||
#include "widgets/dialogs/dlg_import_precons.h"
|
||||
#include "widgets/utility/get_text_with_max.h"
|
||||
|
||||
#include <QAction>
|
||||
|
|
|
|||
|
|
@ -9,16 +9,13 @@
|
|||
* You can do whatever you want with this file.
|
||||
*/
|
||||
|
||||
|
||||
#include <lzma.h>
|
||||
#include <QDebug>
|
||||
|
||||
#include "decompress.h"
|
||||
|
||||
XzDecompressor::XzDecompressor(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
#include <QDebug>
|
||||
#include <lzma.h>
|
||||
|
||||
XzDecompressor::XzDecompressor(QObject *parent) : QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
bool XzDecompressor::decompress(QBuffer *in, QBuffer *out)
|
||||
|
|
@ -74,8 +71,7 @@ bool XzDecompressor::init_decoder(lzma_stream *strm)
|
|||
// (src/liblzma/api/lzma/container.h in the source package or e.g.
|
||||
// /usr/include/lzma/container.h depending on the install prefix)
|
||||
// for details.
|
||||
lzma_ret ret = lzma_stream_decoder(
|
||||
strm, UINT64_MAX, LZMA_CONCATENATED);
|
||||
lzma_ret ret = lzma_stream_decoder(strm, UINT64_MAX, LZMA_CONCATENATED);
|
||||
|
||||
// Return successfully if the initialization went fine.
|
||||
if (ret == LZMA_OK)
|
||||
|
|
@ -114,7 +110,6 @@ bool XzDecompressor::init_decoder(lzma_stream *strm)
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool XzDecompressor::internal_decompress(lzma_stream *strm, QBuffer *in, QBuffer *out)
|
||||
{
|
||||
// When LZMA_CONCATENATED flag was used when initializing the decoder,
|
||||
|
|
@ -141,18 +136,18 @@ bool XzDecompressor::internal_decompress(lzma_stream *strm, QBuffer *in, QBuffer
|
|||
if (strm->avail_in == 0) {
|
||||
strm->next_in = inbuf;
|
||||
bytesAvailable = in->bytesAvailable();
|
||||
if(bytesAvailable == 0) {
|
||||
if (bytesAvailable == 0) {
|
||||
// Once the end of the input file has been reached,
|
||||
// we need to tell lzma_code() that no more input
|
||||
// will be coming. As said before, this isn't required
|
||||
// if the LZMA_CONCATENATED flag isn't used when
|
||||
// initializing the decoder.
|
||||
action = LZMA_FINISH;
|
||||
} else if(bytesAvailable >= BUFSIZ) {
|
||||
in->read((char*) inbuf, BUFSIZ);
|
||||
} else if (bytesAvailable >= BUFSIZ) {
|
||||
in->read((char *)inbuf, BUFSIZ);
|
||||
strm->avail_in = BUFSIZ;
|
||||
} else {
|
||||
in->read((char*) inbuf, bytesAvailable);
|
||||
in->read((char *)inbuf, bytesAvailable);
|
||||
strm->avail_in = bytesAvailable;
|
||||
}
|
||||
}
|
||||
|
|
@ -162,7 +157,7 @@ bool XzDecompressor::internal_decompress(lzma_stream *strm, QBuffer *in, QBuffer
|
|||
if (strm->avail_out == 0 || ret == LZMA_STREAM_END) {
|
||||
qint64 write_size = sizeof(outbuf) - strm->avail_out;
|
||||
|
||||
if (out->write((char *) outbuf, write_size) != write_size) {
|
||||
if (out->write((char *)outbuf, write_size) != write_size) {
|
||||
qDebug() << "Write error";
|
||||
return false;
|
||||
}
|
||||
|
|
@ -247,4 +242,3 @@ bool XzDecompressor::internal_decompress(lzma_stream *strm, QBuffer *in, QBuffer
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,17 @@
|
|||
#ifndef XZ_DECOMPRESS_H
|
||||
#define XZ_DECOMPRESS_H
|
||||
|
||||
#include <lzma.h>
|
||||
#include <QBuffer>
|
||||
#include <lzma.h>
|
||||
|
||||
class XzDecompressor : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
XzDecompressor(QObject *parent = 0);
|
||||
~XzDecompressor() { };
|
||||
~XzDecompressor() {};
|
||||
bool decompress(QBuffer *in, QBuffer *out);
|
||||
|
||||
private:
|
||||
bool init_decoder(lzma_stream *strm);
|
||||
bool internal_decompress(lzma_stream *strm, QBuffer *in, QBuffer *out);
|
||||
|
|
|
|||
23
cockatrice/src/utility/external/qt-json/json.h
vendored
23
cockatrice/src/utility/external/qt-json/json.h
vendored
|
|
@ -33,8 +33,8 @@
|
|||
#ifndef JSON_H
|
||||
#define JSON_H
|
||||
|
||||
#include <QVariant>
|
||||
#include <QString>
|
||||
#include <QVariant>
|
||||
|
||||
namespace QtJson
|
||||
{
|
||||
|
|
@ -66,7 +66,7 @@ enum JsonToken
|
|||
*/
|
||||
class Json
|
||||
{
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Parse a JSON string
|
||||
*
|
||||
|
|
@ -100,7 +100,7 @@ class Json
|
|||
*/
|
||||
static QByteArray serialize(const QVariant &data, bool &success);
|
||||
|
||||
private:
|
||||
private:
|
||||
/**
|
||||
* Parses a value starting from index
|
||||
*
|
||||
|
|
@ -110,8 +110,7 @@ class Json
|
|||
*
|
||||
* \return QVariant The parsed value
|
||||
*/
|
||||
static QVariant parseValue(const QString &json, int &index,
|
||||
bool &success);
|
||||
static QVariant parseValue(const QString &json, int &index, bool &success);
|
||||
|
||||
/**
|
||||
* Parses an object starting from index
|
||||
|
|
@ -122,8 +121,7 @@ class Json
|
|||
*
|
||||
* \return QVariant The parsed object map
|
||||
*/
|
||||
static QVariant parseObject(const QString &json, int &index,
|
||||
bool &success);
|
||||
static QVariant parseObject(const QString &json, int &index, bool &success);
|
||||
|
||||
/**
|
||||
* Parses an array starting from index
|
||||
|
|
@ -134,8 +132,7 @@ class Json
|
|||
*
|
||||
* \return QVariant The parsed variant array
|
||||
*/
|
||||
static QVariant parseArray(const QString &json, int &index,
|
||||
bool &success);
|
||||
static QVariant parseArray(const QString &json, int &index, bool &success);
|
||||
|
||||
/**
|
||||
* Parses a string starting from index
|
||||
|
|
@ -146,8 +143,7 @@ class Json
|
|||
*
|
||||
* \return QVariant The parsed string
|
||||
*/
|
||||
static QVariant parseString(const QString &json, int &index,
|
||||
bool &success);
|
||||
static QVariant parseString(const QString &json, int &index, bool &success);
|
||||
|
||||
/**
|
||||
* Parses a number starting from index
|
||||
|
|
@ -198,7 +194,6 @@ class Json
|
|||
static int nextToken(const QString &json, int &index);
|
||||
};
|
||||
|
||||
} // namespace QtJson
|
||||
|
||||
} //end namespace
|
||||
|
||||
#endif //JSON_H
|
||||
#endif // JSON_H
|
||||
|
|
|
|||
288
cockatrice/src/utility/external/zip/unzip.cpp
vendored
Executable file → Normal file
288
cockatrice/src/utility/external/zip/unzip.cpp
vendored
Executable file → Normal file
|
|
@ -26,6 +26,7 @@
|
|||
**********************************************************************/
|
||||
|
||||
#include "unzip.h"
|
||||
|
||||
#include "unzip_p.h"
|
||||
#include "zipentry_p.h"
|
||||
|
||||
|
|
@ -64,7 +65,8 @@
|
|||
\value UnZip::CreateDirFailed Could not create a directory.
|
||||
\value UnZip::InvalidDevice A null device has been passed as parameter.
|
||||
\value UnZip::InvalidArchive This is not a valid (or supported) ZIP archive.
|
||||
\value UnZip::HeaderConsistencyError Local header record info does not match with the central directory record info. The archive may be corrupted.
|
||||
\value UnZip::HeaderConsistencyError Local header record info does not match with the central directory record info.
|
||||
The archive may be corrupted.
|
||||
|
||||
\value UnZip::Skip Internal use only.
|
||||
\value UnZip::SkipAll Internal use only.
|
||||
|
|
@ -133,11 +135,10 @@
|
|||
#define UNZIP_VERSION 0x14
|
||||
|
||||
//! CRC32 routine
|
||||
#define CRC32(c, b) crcTable[((int)c^b) & 0xff] ^ (c >> 8)
|
||||
#define CRC32(c, b) crcTable[((int)c ^ b) & 0xff] ^ (c >> 8)
|
||||
|
||||
OSDAB_BEGIN_NAMESPACE(Zip)
|
||||
|
||||
|
||||
/************************************************************************
|
||||
ZipEntry
|
||||
*************************************************************************/
|
||||
|
|
@ -153,39 +154,28 @@ UnZip::ZipEntry::ZipEntry()
|
|||
encrypted = false;
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************
|
||||
Private interface
|
||||
*************************************************************************/
|
||||
|
||||
//! \internal
|
||||
UnzipPrivate::UnzipPrivate() :
|
||||
password(),
|
||||
skipAllEncrypted(false),
|
||||
headers(0),
|
||||
device(0),
|
||||
file(0),
|
||||
uBuffer(0),
|
||||
crcTable(0),
|
||||
cdOffset(0),
|
||||
eocdOffset(0),
|
||||
cdEntryCount(0),
|
||||
unsupportedEntryCount(0),
|
||||
comment()
|
||||
UnzipPrivate::UnzipPrivate()
|
||||
: password(), skipAllEncrypted(false), headers(0), device(0), file(0), uBuffer(0), crcTable(0), cdOffset(0),
|
||||
eocdOffset(0), cdEntryCount(0), unsupportedEntryCount(0), comment()
|
||||
{
|
||||
uBuffer = (unsigned char*) buffer1;
|
||||
crcTable = (quint32*) get_crc_table();
|
||||
uBuffer = (unsigned char *)buffer1;
|
||||
crcTable = (quint32 *)get_crc_table();
|
||||
}
|
||||
|
||||
//! \internal
|
||||
void UnzipPrivate::deviceDestroyed(QObject*)
|
||||
void UnzipPrivate::deviceDestroyed(QObject *)
|
||||
{
|
||||
qDebug("Unexpected device destruction detected.");
|
||||
do_closeArchive();
|
||||
}
|
||||
|
||||
//! \internal Parses a Zip archive.
|
||||
UnZip::ErrorCode UnzipPrivate::openArchive(QIODevice* dev)
|
||||
UnZip::ErrorCode UnzipPrivate::openArchive(QIODevice *dev)
|
||||
{
|
||||
Q_ASSERT(!device);
|
||||
Q_ASSERT(dev);
|
||||
|
|
@ -197,7 +187,7 @@ UnZip::ErrorCode UnzipPrivate::openArchive(QIODevice* dev)
|
|||
|
||||
device = dev;
|
||||
if (device != file)
|
||||
connect(device, SIGNAL(destroyed(QObject*)), this, SLOT(deviceDestroyed(QObject*)));
|
||||
connect(device, SIGNAL(destroyed(QObject *)), this, SLOT(deviceDestroyed(QObject *)));
|
||||
|
||||
UnZip::ErrorCode ec;
|
||||
|
||||
|
|
@ -228,7 +218,7 @@ UnZip::ErrorCode UnzipPrivate::openArchive(QIODevice* dev)
|
|||
}
|
||||
}
|
||||
|
||||
if (! (buffer1[0] == 'P' && buffer1[1] == 'K' && buffer1[2] == 0x01 && buffer1[3] == 0x02) )
|
||||
if (!(buffer1[0] == 'P' && buffer1[1] == 'K' && buffer1[2] == 0x01 && buffer1[3] == 0x02))
|
||||
break;
|
||||
|
||||
if ((ec = parseCentralDirectoryRecord()) != UnZip::Ok)
|
||||
|
|
@ -262,7 +252,7 @@ UnZip::ErrorCode UnzipPrivate::openArchive(QIODevice* dev)
|
|||
file name (variable size)
|
||||
extra field (variable size)
|
||||
*/
|
||||
UnZip::ErrorCode UnzipPrivate::parseLocalHeaderRecord(const QString& path, const ZipEntryP& entry)
|
||||
UnZip::ErrorCode UnzipPrivate::parseLocalHeaderRecord(const QString &path, const ZipEntryP &entry)
|
||||
{
|
||||
Q_ASSERT(device);
|
||||
|
||||
|
|
@ -302,8 +292,7 @@ UnZip::ErrorCode UnzipPrivate::parseLocalHeaderRecord(const QString& path, const
|
|||
checkFailed = entry.modDate[0] != uBuffer[UNZIP_LH_OFF_MODD];
|
||||
if (!checkFailed)
|
||||
checkFailed = entry.modDate[1] != uBuffer[UNZIP_LH_OFF_MODD + 1];
|
||||
if (!hasDataDescriptor)
|
||||
{
|
||||
if (!hasDataDescriptor) {
|
||||
if (!checkFailed)
|
||||
checkFailed = entry.crc != getULong(uBuffer, UNZIP_LH_OFF_CRC32);
|
||||
if (!checkFailed)
|
||||
|
|
@ -361,11 +350,9 @@ UnZip::ErrorCode UnzipPrivate::parseLocalHeaderRecord(const QString& path, const
|
|||
}
|
||||
|
||||
// DD: crc, compressed size, uncompressed size
|
||||
if (
|
||||
entry.crc != getULong((unsigned char*)buffer2, UNZIP_DD_OFF_CRC32) ||
|
||||
entry.szComp != getULong((unsigned char*)buffer2, UNZIP_DD_OFF_CSIZE) ||
|
||||
entry.szUncomp != getULong((unsigned char*)buffer2, UNZIP_DD_OFF_USIZE)
|
||||
)
|
||||
if (entry.crc != getULong((unsigned char *)buffer2, UNZIP_DD_OFF_CRC32) ||
|
||||
entry.szComp != getULong((unsigned char *)buffer2, UNZIP_DD_OFF_CSIZE) ||
|
||||
entry.szUncomp != getULong((unsigned char *)buffer2, UNZIP_DD_OFF_USIZE))
|
||||
return UnZip::HeaderConsistencyError;
|
||||
}
|
||||
|
||||
|
|
@ -403,7 +390,7 @@ UnZip::ErrorCode UnzipPrivate::seekToCentralDirectory()
|
|||
if (length < UNZIP_EOCD_SIZE)
|
||||
return UnZip::InvalidArchive;
|
||||
|
||||
if (!device->seek( offset ))
|
||||
if (!device->seek(offset))
|
||||
return UnZip::SeekFailed;
|
||||
|
||||
if (device->read(buffer1, UNZIP_EOCD_SIZE) != UNZIP_EOCD_SIZE)
|
||||
|
|
@ -416,22 +403,22 @@ UnZip::ErrorCode UnzipPrivate::seekToCentralDirectory()
|
|||
eocdOffset = offset;
|
||||
} else {
|
||||
qint64 read;
|
||||
char* p = 0;
|
||||
char *p = 0;
|
||||
|
||||
offset -= UNZIP_EOCD_SIZE;
|
||||
|
||||
if (offset <= 0)
|
||||
return UnZip::InvalidArchive;
|
||||
|
||||
if (!device->seek( offset ))
|
||||
if (!device->seek(offset))
|
||||
return UnZip::SeekFailed;
|
||||
|
||||
while ((read = device->read(buffer1, UNZIP_EOCD_SIZE)) >= 0) {
|
||||
if ( (p = strstr(buffer1, "PK\5\6")) != 0) {
|
||||
if ((p = strstr(buffer1, "PK\5\6")) != 0) {
|
||||
// Seek to the start of the EOCD record so we can read it fully
|
||||
// Yes... we could simply read the missing bytes and append them to the buffer
|
||||
// but this is far easier so heck it!
|
||||
device->seek( offset + (p - buffer1) );
|
||||
device->seek(offset + (p - buffer1));
|
||||
eocdFound = true;
|
||||
eocdOffset = offset + (p - buffer1);
|
||||
|
||||
|
|
@ -447,7 +434,7 @@ UnZip::ErrorCode UnzipPrivate::seekToCentralDirectory()
|
|||
if (offset <= 0)
|
||||
return UnZip::InvalidArchive;
|
||||
|
||||
if (!device->seek( offset ))
|
||||
if (!device->seek(offset))
|
||||
return UnZip::SeekFailed;
|
||||
}
|
||||
}
|
||||
|
|
@ -456,13 +443,13 @@ UnZip::ErrorCode UnzipPrivate::seekToCentralDirectory()
|
|||
return UnZip::InvalidArchive;
|
||||
|
||||
// Parse EOCD to locate CD offset
|
||||
offset = getULong((const unsigned char*)buffer1, UNZIP_EOCD_OFF_CDOFF + 4);
|
||||
offset = getULong((const unsigned char *)buffer1, UNZIP_EOCD_OFF_CDOFF + 4);
|
||||
|
||||
cdOffset = offset;
|
||||
|
||||
cdEntryCount = getUShort((const unsigned char*)buffer1, UNZIP_EOCD_OFF_ENTRIES + 4);
|
||||
cdEntryCount = getUShort((const unsigned char *)buffer1, UNZIP_EOCD_OFF_ENTRIES + 4);
|
||||
|
||||
quint16 commentLength = getUShort((const unsigned char*)buffer1, UNZIP_EOCD_OFF_COMMLEN + 4);
|
||||
quint16 commentLength = getUShort((const unsigned char *)buffer1, UNZIP_EOCD_OFF_COMMLEN + 4);
|
||||
if (commentLength != 0) {
|
||||
QByteArray c = device->read(commentLength);
|
||||
if (c.size() != commentLength)
|
||||
|
|
@ -472,7 +459,7 @@ UnZip::ErrorCode UnzipPrivate::seekToCentralDirectory()
|
|||
}
|
||||
|
||||
// Seek to the start of the CD record
|
||||
if (!device->seek( cdOffset ))
|
||||
if (!device->seek(cdOffset))
|
||||
return UnZip::SeekFailed;
|
||||
|
||||
return UnZip::Ok;
|
||||
|
|
@ -568,7 +555,7 @@ UnZip::ErrorCode UnzipPrivate::parseCentralDirectoryRecord()
|
|||
|
||||
if (skipEntry) {
|
||||
if (ec == UnZip::Ok) {
|
||||
if (!device->seek( device->pos() + skipLength ))
|
||||
if (!device->seek(device->pos() + skipLength))
|
||||
ec = UnZip::SeekFailed;
|
||||
unsupportedEntryCount++;
|
||||
}
|
||||
|
|
@ -576,7 +563,7 @@ UnZip::ErrorCode UnzipPrivate::parseCentralDirectoryRecord()
|
|||
return ec;
|
||||
}
|
||||
|
||||
ZipEntryP* h = new ZipEntryP;
|
||||
ZipEntryP *h = new ZipEntryP;
|
||||
h->compMethod = compMethod;
|
||||
|
||||
h->gpFlag[0] = buffer1[UNZIP_CD_OFF_GPFLAG];
|
||||
|
|
@ -594,7 +581,7 @@ UnZip::ErrorCode UnzipPrivate::parseCentralDirectoryRecord()
|
|||
|
||||
// Skip extra field (if any)
|
||||
if (szExtra != 0) {
|
||||
if (!device->seek( device->pos() + szExtra )) {
|
||||
if (!device->seek(device->pos() + szExtra)) {
|
||||
delete h;
|
||||
return UnZip::SeekFailed;
|
||||
}
|
||||
|
|
@ -613,7 +600,7 @@ UnZip::ErrorCode UnzipPrivate::parseCentralDirectoryRecord()
|
|||
h->lhOffset = getULong(uBuffer, UNZIP_CD_OFF_LHOFFSET);
|
||||
|
||||
if (!headers)
|
||||
headers = new QMap<QString, ZipEntryP*>();
|
||||
headers = new QMap<QString, ZipEntryP *>();
|
||||
headers->insert(filename, h);
|
||||
|
||||
return UnZip::Ok;
|
||||
|
|
@ -659,8 +646,10 @@ void UnzipPrivate::do_closeArchive()
|
|||
}
|
||||
|
||||
//! \internal
|
||||
UnZip::ErrorCode UnzipPrivate::extractFile(const QString& path, const ZipEntryP& entry,
|
||||
const QDir& dir, UnZip::ExtractionOptions options)
|
||||
UnZip::ErrorCode UnzipPrivate::extractFile(const QString &path,
|
||||
const ZipEntryP &entry,
|
||||
const QDir &dir,
|
||||
UnZip::ExtractionOptions options)
|
||||
{
|
||||
QString name(path);
|
||||
QString dirname;
|
||||
|
|
@ -742,8 +731,10 @@ UnZip::ErrorCode UnzipPrivate::extractFile(const QString& path, const ZipEntryP&
|
|||
}
|
||||
|
||||
//! \internal
|
||||
UnZip::ErrorCode UnzipPrivate::extractStoredFile(
|
||||
const quint32 szComp, quint32** keys, quint32& myCRC, QIODevice* outDev,
|
||||
UnZip::ErrorCode UnzipPrivate::extractStoredFile(const quint32 szComp,
|
||||
quint32 **keys,
|
||||
quint32 &myCRC,
|
||||
QIODevice *outDev,
|
||||
UnZip::ExtractionOptions options)
|
||||
{
|
||||
const bool verify = (options & UnZip::VerifyOnly);
|
||||
|
|
@ -757,7 +748,7 @@ UnZip::ErrorCode UnzipPrivate::extractStoredFile(
|
|||
qint64 read;
|
||||
quint64 tot = 0;
|
||||
|
||||
while ( (read = device->read(buffer1, cur < rep ? UNZIP_READ_BUFFER : rem)) > 0 ) {
|
||||
while ((read = device->read(buffer1, cur < rep ? UNZIP_READ_BUFFER : rem)) > 0) {
|
||||
if (isEncrypted)
|
||||
decryptBytes(*keys, buffer1, read);
|
||||
|
||||
|
|
@ -773,14 +764,14 @@ UnZip::ErrorCode UnzipPrivate::extractStoredFile(
|
|||
break;
|
||||
}
|
||||
|
||||
return (read < 0)
|
||||
? UnZip::ReadFailed
|
||||
: UnZip::Ok;
|
||||
return (read < 0) ? UnZip::ReadFailed : UnZip::Ok;
|
||||
}
|
||||
|
||||
//! \internal
|
||||
UnZip::ErrorCode UnzipPrivate::inflateFile(
|
||||
const quint32 szComp, quint32** keys, quint32& myCRC, QIODevice* outDev,
|
||||
UnZip::ErrorCode UnzipPrivate::inflateFile(const quint32 szComp,
|
||||
quint32 **keys,
|
||||
quint32 &myCRC,
|
||||
QIODevice *outDev,
|
||||
UnZip::ExtractionOptions options)
|
||||
{
|
||||
const bool verify = (options & UnZip::VerifyOnly);
|
||||
|
|
@ -805,7 +796,7 @@ UnZip::ErrorCode UnzipPrivate::inflateFile(
|
|||
int zret;
|
||||
|
||||
// Use inflateInit2 with negative windowBits to get raw decompression
|
||||
if ( (zret = inflateInit2_(&zstr, -MAX_WBITS, ZLIB_VERSION, sizeof(z_stream))) != Z_OK )
|
||||
if ((zret = inflateInit2_(&zstr, -MAX_WBITS, ZLIB_VERSION, sizeof(z_stream))) != Z_OK)
|
||||
return UnZip::ZlibError;
|
||||
|
||||
int szDecomp;
|
||||
|
|
@ -826,13 +817,14 @@ UnZip::ErrorCode UnzipPrivate::inflateFile(
|
|||
|
||||
cur++;
|
||||
|
||||
zstr.avail_in = (uInt) read;
|
||||
zstr.next_in = (Bytef*) buffer1;
|
||||
zstr.avail_in = (uInt)read;
|
||||
zstr.next_in = (Bytef *)buffer1;
|
||||
|
||||
// Run inflate() on input until output buffer not full
|
||||
do {
|
||||
zstr.avail_out = UNZIP_READ_BUFFER;
|
||||
zstr.next_out = (Bytef*) buffer2;;
|
||||
zstr.next_out = (Bytef *)buffer2;
|
||||
;
|
||||
|
||||
zret = inflate(&zstr, Z_NO_FLUSH);
|
||||
|
||||
|
|
@ -842,8 +834,7 @@ UnZip::ErrorCode UnzipPrivate::inflateFile(
|
|||
case Z_MEM_ERROR:
|
||||
inflateEnd(&zstr);
|
||||
return UnZip::WriteFailed;
|
||||
default:
|
||||
;
|
||||
default:;
|
||||
}
|
||||
|
||||
szDecomp = UNZIP_READ_BUFFER - zstr.avail_out;
|
||||
|
|
@ -854,7 +845,7 @@ UnZip::ErrorCode UnzipPrivate::inflateFile(
|
|||
}
|
||||
}
|
||||
|
||||
myCRC = crc32(myCRC, (const Bytef*) buffer2, szDecomp);
|
||||
myCRC = crc32(myCRC, (const Bytef *)buffer2, szDecomp);
|
||||
|
||||
} while (zstr.avail_out == 0);
|
||||
|
||||
|
|
@ -865,8 +856,10 @@ UnZip::ErrorCode UnzipPrivate::inflateFile(
|
|||
}
|
||||
|
||||
//! \internal \p outDev is null if the VerifyOnly option is set
|
||||
UnZip::ErrorCode UnzipPrivate::extractFile(const QString& path, const ZipEntryP& entry,
|
||||
QIODevice* outDev, UnZip::ExtractionOptions options)
|
||||
UnZip::ErrorCode UnzipPrivate::extractFile(const QString &path,
|
||||
const ZipEntryP &entry,
|
||||
QIODevice *outDev,
|
||||
UnZip::ExtractionOptions options)
|
||||
{
|
||||
const bool verify = (options & UnZip::VerifyOnly);
|
||||
|
||||
|
|
@ -889,11 +882,10 @@ UnZip::ErrorCode UnzipPrivate::extractFile(const QString& path, const ZipEntryP&
|
|||
quint32 szComp = entry.szComp;
|
||||
if (entry.isEncrypted()) {
|
||||
UnZip::ErrorCode e = testPassword(keys, path, entry);
|
||||
if (e != UnZip::Ok)
|
||||
{
|
||||
if (e != UnZip::Ok) {
|
||||
qDebug() << QString("Unable to decrypt %1").arg(path);
|
||||
return e;
|
||||
}//! Encryption header size
|
||||
} //! Encryption header size
|
||||
szComp -= UNZIP_LOCAL_ENC_HEADER_SIZE; // remove encryption header size
|
||||
}
|
||||
|
||||
|
|
@ -904,7 +896,7 @@ UnZip::ErrorCode UnzipPrivate::extractFile(const QString& path, const ZipEntryP&
|
|||
}
|
||||
|
||||
quint32 myCRC = crc32(0L, Z_NULL, 0);
|
||||
quint32* k = keys;
|
||||
quint32 *k = keys;
|
||||
|
||||
UnZip::ErrorCode ec = UnZip::Ok;
|
||||
if (entry.compMethod == 0) {
|
||||
|
|
@ -920,7 +912,7 @@ UnZip::ErrorCode UnzipPrivate::extractFile(const QString& path, const ZipEntryP&
|
|||
}
|
||||
|
||||
//! \internal Creates a new directory and all the needed parent directories.
|
||||
bool UnzipPrivate::createDirectory(const QString& path)
|
||||
bool UnzipPrivate::createDirectory(const QString &path)
|
||||
{
|
||||
QDir d(path);
|
||||
if (!d.exists() && !d.mkpath(path)) {
|
||||
|
|
@ -934,12 +926,12 @@ bool UnzipPrivate::createDirectory(const QString& path)
|
|||
/*!
|
||||
\internal Reads an quint32 (4 bytes) from a byte array starting at given offset.
|
||||
*/
|
||||
quint32 UnzipPrivate::getULong(const unsigned char* data, quint32 offset) const
|
||||
quint32 UnzipPrivate::getULong(const unsigned char *data, quint32 offset) const
|
||||
{
|
||||
quint32 res = (quint32) data[offset];
|
||||
res |= (((quint32)data[offset+1]) << 8);
|
||||
res |= (((quint32)data[offset+2]) << 16);
|
||||
res |= (((quint32)data[offset+3]) << 24);
|
||||
quint32 res = (quint32)data[offset];
|
||||
res |= (((quint32)data[offset + 1]) << 8);
|
||||
res |= (((quint32)data[offset + 2]) << 16);
|
||||
res |= (((quint32)data[offset + 3]) << 24);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
@ -947,16 +939,16 @@ quint32 UnzipPrivate::getULong(const unsigned char* data, quint32 offset) const
|
|||
/*!
|
||||
\internal Reads an quint64 (8 bytes) from a byte array starting at given offset.
|
||||
*/
|
||||
quint64 UnzipPrivate::getULLong(const unsigned char* data, quint32 offset) const
|
||||
quint64 UnzipPrivate::getULLong(const unsigned char *data, quint32 offset) const
|
||||
{
|
||||
quint64 res = (quint64) data[offset];
|
||||
res |= (((quint64)data[offset+1]) << 8);
|
||||
res |= (((quint64)data[offset+2]) << 16);
|
||||
res |= (((quint64)data[offset+3]) << 24);
|
||||
res |= (((quint64)data[offset+1]) << 32);
|
||||
res |= (((quint64)data[offset+2]) << 40);
|
||||
res |= (((quint64)data[offset+3]) << 48);
|
||||
res |= (((quint64)data[offset+3]) << 56);
|
||||
quint64 res = (quint64)data[offset];
|
||||
res |= (((quint64)data[offset + 1]) << 8);
|
||||
res |= (((quint64)data[offset + 2]) << 16);
|
||||
res |= (((quint64)data[offset + 3]) << 24);
|
||||
res |= (((quint64)data[offset + 1]) << 32);
|
||||
res |= (((quint64)data[offset + 2]) << 40);
|
||||
res |= (((quint64)data[offset + 3]) << 48);
|
||||
res |= (((quint64)data[offset + 3]) << 56);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
@ -964,9 +956,9 @@ quint64 UnzipPrivate::getULLong(const unsigned char* data, quint32 offset) const
|
|||
/*!
|
||||
\internal Reads an quint16 (2 bytes) from a byte array starting at given offset.
|
||||
*/
|
||||
quint16 UnzipPrivate::getUShort(const unsigned char* data, quint32 offset) const
|
||||
quint16 UnzipPrivate::getUShort(const unsigned char *data, quint32 offset) const
|
||||
{
|
||||
return (quint16) data[offset] | (((quint16)data[offset+1]) << 8);
|
||||
return (quint16)data[offset] | (((quint16)data[offset + 1]) << 8);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -981,7 +973,7 @@ int UnzipPrivate::decryptByte(quint32 key2) const
|
|||
/*!
|
||||
\internal Update the encryption keys with the next byte of plain text
|
||||
*/
|
||||
void UnzipPrivate::updateKeys(quint32* keys, int c) const
|
||||
void UnzipPrivate::updateKeys(quint32 *keys, int c) const
|
||||
{
|
||||
keys[0] = CRC32(keys[0], c);
|
||||
keys[1] += keys[0] & 0xff;
|
||||
|
|
@ -993,7 +985,7 @@ void UnzipPrivate::updateKeys(quint32* keys, int c) const
|
|||
\internal Initialize the encryption keys and the random header according to
|
||||
the given password.
|
||||
*/
|
||||
void UnzipPrivate::initKeys(const QString& pwd, quint32* keys) const
|
||||
void UnzipPrivate::initKeys(const QString &pwd, quint32 *keys) const
|
||||
{
|
||||
keys[0] = 305419896L;
|
||||
keys[1] = 591751049L;
|
||||
|
|
@ -1001,7 +993,7 @@ void UnzipPrivate::initKeys(const QString& pwd, quint32* keys) const
|
|||
|
||||
QByteArray pwdBytes = pwd.toLatin1();
|
||||
int sz = pwdBytes.size();
|
||||
const char* ascii = pwdBytes.data();
|
||||
const char *ascii = pwdBytes.data();
|
||||
|
||||
for (int i = 0; i < sz; ++i)
|
||||
updateKeys(keys, (int)ascii[i]);
|
||||
|
|
@ -1012,7 +1004,7 @@ void UnzipPrivate::initKeys(const QString& pwd, quint32* keys) const
|
|||
The \p file parameter can be used in the user interface or for debugging purposes
|
||||
as it is the name of the encrypted file for wich the password is being tested.
|
||||
*/
|
||||
UnZip::ErrorCode UnzipPrivate::testPassword(quint32* keys, const QString&_file, const ZipEntryP& header)
|
||||
UnZip::ErrorCode UnzipPrivate::testPassword(quint32 *keys, const QString &_file, const ZipEntryP &header)
|
||||
{
|
||||
Q_UNUSED(_file);
|
||||
Q_ASSERT(device);
|
||||
|
|
@ -1032,7 +1024,7 @@ UnZip::ErrorCode UnzipPrivate::testPassword(quint32* keys, const QString&_file,
|
|||
/*!
|
||||
\internal Tests a set of keys on the encryption header.
|
||||
*/
|
||||
bool UnzipPrivate::testKeys(const ZipEntryP& header, quint32* keys)
|
||||
bool UnzipPrivate::testKeys(const ZipEntryP &header, quint32 *keys)
|
||||
{
|
||||
char lastByte;
|
||||
|
||||
|
|
@ -1051,7 +1043,7 @@ bool UnzipPrivate::testKeys(const ZipEntryP& header, quint32* keys)
|
|||
/*!
|
||||
\internal Decrypts an array of bytes long \p read.
|
||||
*/
|
||||
void UnzipPrivate::decryptBytes(quint32* keys, char* buffer, qint64 read)
|
||||
void UnzipPrivate::decryptBytes(quint32 *keys, char *buffer, qint64 read)
|
||||
{
|
||||
for (int i = 0; i < (int)read; ++i)
|
||||
updateKeys(keys, buffer[i] ^= decryptByte(keys[2]));
|
||||
|
|
@ -1081,7 +1073,6 @@ QDateTime UnzipPrivate::convertDateTime(const unsigned char date[2], const unsig
|
|||
return dt;
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************
|
||||
Public interface
|
||||
*************************************************************************/
|
||||
|
|
@ -1113,7 +1104,7 @@ bool UnZip::isOpen() const
|
|||
/*!
|
||||
Opens a zip archive and reads the files list. Closes any previously opened archive.
|
||||
*/
|
||||
UnZip::ErrorCode UnZip::openArchive(const QString& filename)
|
||||
UnZip::ErrorCode UnZip::openArchive(const QString &filename)
|
||||
{
|
||||
closeArchive();
|
||||
|
||||
|
|
@ -1140,7 +1131,7 @@ UnZip::ErrorCode UnZip::openArchive(const QString& filename)
|
|||
Closes any previously opened archive.
|
||||
\warning The class takes DOES NOT take ownership of the device.
|
||||
*/
|
||||
UnZip::ErrorCode UnZip::openArchive(QIODevice* device)
|
||||
UnZip::ErrorCode UnZip::openArchive(QIODevice *device)
|
||||
{
|
||||
closeArchive();
|
||||
|
||||
|
|
@ -1170,25 +1161,56 @@ QString UnZip::archiveComment() const
|
|||
*/
|
||||
QString UnZip::formatError(UnZip::ErrorCode c) const
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case Ok: return QCoreApplication::translate("UnZip", "ZIP operation completed successfully."); break;
|
||||
case ZlibInit: return QCoreApplication::translate("UnZip", "Failed to initialize or load zlib library."); break;
|
||||
case ZlibError: return QCoreApplication::translate("UnZip", "zlib library error."); break;
|
||||
case OpenFailed: return QCoreApplication::translate("UnZip", "Unable to create or open file."); break;
|
||||
case PartiallyCorrupted: return QCoreApplication::translate("UnZip", "Partially corrupted archive. Some files might be extracted."); break;
|
||||
case Corrupted: return QCoreApplication::translate("UnZip", "Corrupted archive."); break;
|
||||
case WrongPassword: return QCoreApplication::translate("UnZip", "Wrong password."); break;
|
||||
case NoOpenArchive: return QCoreApplication::translate("UnZip", "No archive has been created yet."); break;
|
||||
case FileNotFound: return QCoreApplication::translate("UnZip", "File or directory does not exist."); break;
|
||||
case ReadFailed: return QCoreApplication::translate("UnZip", "File read error."); break;
|
||||
case WriteFailed: return QCoreApplication::translate("UnZip", "File write error."); break;
|
||||
case SeekFailed: return QCoreApplication::translate("UnZip", "File seek error."); break;
|
||||
case CreateDirFailed: return QCoreApplication::translate("UnZip", "Unable to create a directory."); break;
|
||||
case InvalidDevice: return QCoreApplication::translate("UnZip", "Invalid device."); break;
|
||||
case InvalidArchive: return QCoreApplication::translate("UnZip", "Invalid or incompatible zip archive."); break;
|
||||
case HeaderConsistencyError: return QCoreApplication::translate("UnZip", "Inconsistent headers. Archive might be corrupted."); break;
|
||||
default: ;
|
||||
switch (c) {
|
||||
case Ok:
|
||||
return QCoreApplication::translate("UnZip", "ZIP operation completed successfully.");
|
||||
break;
|
||||
case ZlibInit:
|
||||
return QCoreApplication::translate("UnZip", "Failed to initialize or load zlib library.");
|
||||
break;
|
||||
case ZlibError:
|
||||
return QCoreApplication::translate("UnZip", "zlib library error.");
|
||||
break;
|
||||
case OpenFailed:
|
||||
return QCoreApplication::translate("UnZip", "Unable to create or open file.");
|
||||
break;
|
||||
case PartiallyCorrupted:
|
||||
return QCoreApplication::translate("UnZip", "Partially corrupted archive. Some files might be extracted.");
|
||||
break;
|
||||
case Corrupted:
|
||||
return QCoreApplication::translate("UnZip", "Corrupted archive.");
|
||||
break;
|
||||
case WrongPassword:
|
||||
return QCoreApplication::translate("UnZip", "Wrong password.");
|
||||
break;
|
||||
case NoOpenArchive:
|
||||
return QCoreApplication::translate("UnZip", "No archive has been created yet.");
|
||||
break;
|
||||
case FileNotFound:
|
||||
return QCoreApplication::translate("UnZip", "File or directory does not exist.");
|
||||
break;
|
||||
case ReadFailed:
|
||||
return QCoreApplication::translate("UnZip", "File read error.");
|
||||
break;
|
||||
case WriteFailed:
|
||||
return QCoreApplication::translate("UnZip", "File write error.");
|
||||
break;
|
||||
case SeekFailed:
|
||||
return QCoreApplication::translate("UnZip", "File seek error.");
|
||||
break;
|
||||
case CreateDirFailed:
|
||||
return QCoreApplication::translate("UnZip", "Unable to create a directory.");
|
||||
break;
|
||||
case InvalidDevice:
|
||||
return QCoreApplication::translate("UnZip", "Invalid device.");
|
||||
break;
|
||||
case InvalidArchive:
|
||||
return QCoreApplication::translate("UnZip", "Invalid or incompatible zip archive.");
|
||||
break;
|
||||
case HeaderConsistencyError:
|
||||
return QCoreApplication::translate("UnZip", "Inconsistent headers. Archive might be corrupted.");
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
|
||||
return QCoreApplication::translate("UnZip", "Unknown error.");
|
||||
|
|
@ -1197,7 +1219,7 @@ QString UnZip::formatError(UnZip::ErrorCode c) const
|
|||
/*!
|
||||
Returns true if the archive contains a file with the given path and name.
|
||||
*/
|
||||
bool UnZip::contains(const QString& file) const
|
||||
bool UnZip::contains(const QString &file) const
|
||||
{
|
||||
return d->headers ? d->headers->contains(file) : false;
|
||||
}
|
||||
|
|
@ -1219,9 +1241,8 @@ QList<UnZip::ZipEntry> UnZip::entryList() const
|
|||
if (!d->headers)
|
||||
return list;
|
||||
|
||||
for (QMap<QString,ZipEntryP*>::ConstIterator it = d->headers->constBegin();
|
||||
it != d->headers->constEnd(); ++it) {
|
||||
const ZipEntryP* entry = it.value();
|
||||
for (QMap<QString, ZipEntryP *>::ConstIterator it = d->headers->constBegin(); it != d->headers->constEnd(); ++it) {
|
||||
const ZipEntryP *entry = it.value();
|
||||
Q_ASSERT(entry != 0);
|
||||
|
||||
ZipEntry z;
|
||||
|
|
@ -1256,7 +1277,7 @@ UnZip::ErrorCode UnZip::verifyArchive()
|
|||
/*!
|
||||
Extracts the whole archive to a directory.
|
||||
*/
|
||||
UnZip::ErrorCode UnZip::extractAll(const QString& dirname, ExtractionOptions options)
|
||||
UnZip::ErrorCode UnZip::extractAll(const QString &dirname, ExtractionOptions options)
|
||||
{
|
||||
return extractAll(QDir(dirname), options);
|
||||
}
|
||||
|
|
@ -1265,7 +1286,7 @@ UnZip::ErrorCode UnZip::extractAll(const QString& dirname, ExtractionOptions opt
|
|||
Extracts the whole archive to a directory.
|
||||
Stops extraction at the first error.
|
||||
*/
|
||||
UnZip::ErrorCode UnZip::extractAll(const QDir& dir, ExtractionOptions options)
|
||||
UnZip::ErrorCode UnZip::extractAll(const QDir &dir, ExtractionOptions options)
|
||||
{
|
||||
// this should only happen if we didn't call openArchive() yet
|
||||
if (!d->device)
|
||||
|
|
@ -1276,10 +1297,10 @@ UnZip::ErrorCode UnZip::extractAll(const QDir& dir, ExtractionOptions options)
|
|||
|
||||
ErrorCode ec = Ok;
|
||||
|
||||
QMap<QString,ZipEntryP*>::ConstIterator it = d->headers->constBegin();
|
||||
const QMap<QString,ZipEntryP*>::ConstIterator end = d->headers->constEnd();
|
||||
QMap<QString, ZipEntryP *>::ConstIterator it = d->headers->constBegin();
|
||||
const QMap<QString, ZipEntryP *>::ConstIterator end = d->headers->constEnd();
|
||||
while (it != end) {
|
||||
ZipEntryP* entry = it.value();
|
||||
ZipEntryP *entry = it.value();
|
||||
Q_ASSERT(entry != 0);
|
||||
if ((entry->isEncrypted()) && d->skipAllEncrypted) {
|
||||
++it;
|
||||
|
|
@ -1301,8 +1322,7 @@ UnZip::ErrorCode UnZip::extractAll(const QDir& dir, ExtractionOptions options)
|
|||
skip = true;
|
||||
d->skipAllEncrypted = true;
|
||||
break;
|
||||
default:
|
||||
;
|
||||
default:;
|
||||
}
|
||||
|
||||
if (ec != Ok && !skip) {
|
||||
|
|
@ -1318,7 +1338,7 @@ UnZip::ErrorCode UnZip::extractAll(const QDir& dir, ExtractionOptions options)
|
|||
/*!
|
||||
Extracts a single file to a directory.
|
||||
*/
|
||||
UnZip::ErrorCode UnZip::extractFile(const QString& filename, const QString& dirname, ExtractionOptions options)
|
||||
UnZip::ErrorCode UnZip::extractFile(const QString &filename, const QString &dirname, ExtractionOptions options)
|
||||
{
|
||||
return extractFile(filename, QDir(dirname), options);
|
||||
}
|
||||
|
|
@ -1326,16 +1346,16 @@ UnZip::ErrorCode UnZip::extractFile(const QString& filename, const QString& dirn
|
|||
/*!
|
||||
Extracts a single file to a directory.
|
||||
*/
|
||||
UnZip::ErrorCode UnZip::extractFile(const QString& filename, const QDir& dir, ExtractionOptions options)
|
||||
UnZip::ErrorCode UnZip::extractFile(const QString &filename, const QDir &dir, ExtractionOptions options)
|
||||
{
|
||||
if (!d->device)
|
||||
return NoOpenArchive;
|
||||
if (!d->headers)
|
||||
return FileNotFound;
|
||||
|
||||
QMap<QString,ZipEntryP*>::Iterator itr = d->headers->find(filename);
|
||||
QMap<QString, ZipEntryP *>::Iterator itr = d->headers->find(filename);
|
||||
if (itr != d->headers->end()) {
|
||||
ZipEntryP* entry = itr.value();
|
||||
ZipEntryP *entry = itr.value();
|
||||
Q_ASSERT(entry != 0);
|
||||
return d->extractFile(itr.key(), *entry, dir, options);
|
||||
}
|
||||
|
|
@ -1346,7 +1366,7 @@ UnZip::ErrorCode UnZip::extractFile(const QString& filename, const QDir& dir, Ex
|
|||
/*!
|
||||
Extracts a single file to a directory.
|
||||
*/
|
||||
UnZip::ErrorCode UnZip::extractFile(const QString& filename, QIODevice* outDev, ExtractionOptions options)
|
||||
UnZip::ErrorCode UnZip::extractFile(const QString &filename, QIODevice *outDev, ExtractionOptions options)
|
||||
{
|
||||
if (!d->device)
|
||||
return NoOpenArchive;
|
||||
|
|
@ -1355,9 +1375,9 @@ UnZip::ErrorCode UnZip::extractFile(const QString& filename, QIODevice* outDev,
|
|||
if (!outDev)
|
||||
return InvalidDevice;
|
||||
|
||||
QMap<QString,ZipEntryP*>::Iterator itr = d->headers->find(filename);
|
||||
QMap<QString, ZipEntryP *>::Iterator itr = d->headers->find(filename);
|
||||
if (itr != d->headers->end()) {
|
||||
ZipEntryP* entry = itr.value();
|
||||
ZipEntryP *entry = itr.value();
|
||||
Q_ASSERT(entry != 0);
|
||||
return d->extractFile(itr.key(), *entry, outDev, options);
|
||||
}
|
||||
|
|
@ -1369,7 +1389,7 @@ UnZip::ErrorCode UnZip::extractFile(const QString& filename, QIODevice* outDev,
|
|||
Extracts a list of files.
|
||||
Stops extraction at the first error (but continues if a file does not exist in the archive).
|
||||
*/
|
||||
UnZip::ErrorCode UnZip::extractFiles(const QStringList& filenames, const QString& dirname, ExtractionOptions options)
|
||||
UnZip::ErrorCode UnZip::extractFiles(const QStringList &filenames, const QString &dirname, ExtractionOptions options)
|
||||
{
|
||||
if (!d->device)
|
||||
return NoOpenArchive;
|
||||
|
|
@ -1394,7 +1414,7 @@ UnZip::ErrorCode UnZip::extractFiles(const QStringList& filenames, const QString
|
|||
Extracts a list of files.
|
||||
Stops extraction at the first error (but continues if a file does not exist in the archive).
|
||||
*/
|
||||
UnZip::ErrorCode UnZip::extractFiles(const QStringList& filenames, const QDir& dir, ExtractionOptions options)
|
||||
UnZip::ErrorCode UnZip::extractFiles(const QStringList &filenames, const QDir &dir, ExtractionOptions options)
|
||||
{
|
||||
if (!d->device)
|
||||
return NoOpenArchive;
|
||||
|
|
@ -1417,7 +1437,7 @@ UnZip::ErrorCode UnZip::extractFiles(const QStringList& filenames, const QDir& d
|
|||
/*!
|
||||
Remove/replace this method to add your own password retrieval routine.
|
||||
*/
|
||||
void UnZip::setPassword(const QString& pwd)
|
||||
void UnZip::setPassword(const QString &pwd)
|
||||
{
|
||||
d->password = pwd;
|
||||
}
|
||||
|
|
|
|||
56
cockatrice/src/utility/external/zip/unzip_p.h
vendored
Executable file → Normal file
56
cockatrice/src/utility/external/zip/unzip_p.h
vendored
Executable file → Normal file
|
|
@ -47,7 +47,7 @@
|
|||
|
||||
// zLib authors suggest using larger buffers (128K or 256K) for (de)compression (especially for inflate())
|
||||
// we use a 256K buffer here - if you want to use this code on a pre-iceage mainframe please change it ;)
|
||||
#define UNZIP_READ_BUFFER (256*1024)
|
||||
#define UNZIP_READ_BUFFER (256 * 1024)
|
||||
|
||||
OSDAB_BEGIN_NAMESPACE(Zip)
|
||||
|
||||
|
|
@ -63,16 +63,16 @@ public:
|
|||
|
||||
bool skipAllEncrypted;
|
||||
|
||||
QMap<QString,ZipEntryP*>* headers;
|
||||
QMap<QString, ZipEntryP *> *headers;
|
||||
|
||||
QIODevice* device;
|
||||
QFile* file;
|
||||
QIODevice *device;
|
||||
QFile *file;
|
||||
|
||||
char buffer1[UNZIP_READ_BUFFER];
|
||||
char buffer2[UNZIP_READ_BUFFER];
|
||||
|
||||
unsigned char* uBuffer;
|
||||
const quint32* crcTable;
|
||||
unsigned char *uBuffer;
|
||||
const quint32 *crcTable;
|
||||
|
||||
// Central Directory (CD) offset
|
||||
quint32 cdOffset;
|
||||
|
|
@ -87,41 +87,49 @@ public:
|
|||
|
||||
QString comment;
|
||||
|
||||
UnZip::ErrorCode openArchive(QIODevice* device);
|
||||
UnZip::ErrorCode openArchive(QIODevice *device);
|
||||
|
||||
UnZip::ErrorCode seekToCentralDirectory();
|
||||
UnZip::ErrorCode parseCentralDirectoryRecord();
|
||||
UnZip::ErrorCode parseLocalHeaderRecord(const QString& path, const ZipEntryP& entry);
|
||||
UnZip::ErrorCode parseLocalHeaderRecord(const QString &path, const ZipEntryP &entry);
|
||||
|
||||
void closeArchive();
|
||||
|
||||
UnZip::ErrorCode extractFile(const QString& path, const ZipEntryP& entry, const QDir& dir, UnZip::ExtractionOptions options);
|
||||
UnZip::ErrorCode extractFile(const QString& path, const ZipEntryP& entry, QIODevice* device, UnZip::ExtractionOptions options);
|
||||
UnZip::ErrorCode
|
||||
extractFile(const QString &path, const ZipEntryP &entry, const QDir &dir, UnZip::ExtractionOptions options);
|
||||
UnZip::ErrorCode
|
||||
extractFile(const QString &path, const ZipEntryP &entry, QIODevice *device, UnZip::ExtractionOptions options);
|
||||
|
||||
UnZip::ErrorCode testPassword(quint32* keys, const QString&_file, const ZipEntryP& header);
|
||||
bool testKeys(const ZipEntryP& header, quint32* keys);
|
||||
UnZip::ErrorCode testPassword(quint32 *keys, const QString &_file, const ZipEntryP &header);
|
||||
bool testKeys(const ZipEntryP &header, quint32 *keys);
|
||||
|
||||
bool createDirectory(const QString& path);
|
||||
bool createDirectory(const QString &path);
|
||||
|
||||
inline void decryptBytes(quint32* keys, char* buffer, qint64 read);
|
||||
inline void decryptBytes(quint32 *keys, char *buffer, qint64 read);
|
||||
|
||||
inline quint32 getULong(const unsigned char* data, quint32 offset) const;
|
||||
inline quint64 getULLong(const unsigned char* data, quint32 offset) const;
|
||||
inline quint16 getUShort(const unsigned char* data, quint32 offset) const;
|
||||
inline quint32 getULong(const unsigned char *data, quint32 offset) const;
|
||||
inline quint64 getULLong(const unsigned char *data, quint32 offset) const;
|
||||
inline quint16 getUShort(const unsigned char *data, quint32 offset) const;
|
||||
inline int decryptByte(quint32 key2) const;
|
||||
inline void updateKeys(quint32* keys, int c) const;
|
||||
inline void initKeys(const QString& pwd, quint32* keys) const;
|
||||
inline void updateKeys(quint32 *keys, int c) const;
|
||||
inline void initKeys(const QString &pwd, quint32 *keys) const;
|
||||
|
||||
inline QDateTime convertDateTime(const unsigned char date[2], const unsigned char time[2]) const;
|
||||
|
||||
private slots:
|
||||
void deviceDestroyed(QObject*);
|
||||
void deviceDestroyed(QObject *);
|
||||
|
||||
private:
|
||||
UnZip::ErrorCode extractStoredFile(const quint32 szComp, quint32** keys,
|
||||
quint32& myCRC, QIODevice* outDev, UnZip::ExtractionOptions options);
|
||||
UnZip::ErrorCode inflateFile(const quint32 szComp, quint32** keys,
|
||||
quint32& myCRC, QIODevice* outDev, UnZip::ExtractionOptions options);
|
||||
UnZip::ErrorCode extractStoredFile(const quint32 szComp,
|
||||
quint32 **keys,
|
||||
quint32 &myCRC,
|
||||
QIODevice *outDev,
|
||||
UnZip::ExtractionOptions options);
|
||||
UnZip::ErrorCode inflateFile(const quint32 szComp,
|
||||
quint32 **keys,
|
||||
quint32 &myCRC,
|
||||
QIODevice *outDev,
|
||||
UnZip::ExtractionOptions options);
|
||||
void do_closeArchive();
|
||||
};
|
||||
|
||||
|
|
|
|||
364
cockatrice/src/utility/external/zip/zip.cpp
vendored
Executable file → Normal file
364
cockatrice/src/utility/external/zip/zip.cpp
vendored
Executable file → Normal file
|
|
@ -26,12 +26,11 @@
|
|||
**********************************************************************/
|
||||
|
||||
#include "zip.h"
|
||||
|
||||
#include "zip_p.h"
|
||||
#include "zipentry_p.h"
|
||||
|
||||
// we only use this to seed the random number generator
|
||||
#include <ctime>
|
||||
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QtCore/QDateTime>
|
||||
#include <QtCore/QDir>
|
||||
|
|
@ -39,11 +38,11 @@
|
|||
#include <QtCore/QMap>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QStringList>
|
||||
#include <ctime>
|
||||
|
||||
// You can remove this #include if you replace the qDebug() statements.
|
||||
#include <QtCore/QtDebug>
|
||||
|
||||
|
||||
/*! #define OSDAB_ZIP_NO_PNG_RLE to disable the use of Z_RLE compression strategy with
|
||||
PNG files (achieves slightly better compression levels according to the authors).
|
||||
*/
|
||||
|
|
@ -231,16 +230,20 @@
|
|||
\value Zip::AutoFull Use both CPU and MIME type detection.
|
||||
*/
|
||||
|
||||
namespace {
|
||||
namespace
|
||||
{
|
||||
|
||||
struct ZippedDir {
|
||||
struct ZippedDir
|
||||
{
|
||||
bool init;
|
||||
QString actualRoot;
|
||||
int files;
|
||||
ZippedDir() : init(false), actualRoot(), files(0) {}
|
||||
ZippedDir() : init(false), actualRoot(), files(0)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
void checkRootPath(QString& path)
|
||||
void checkRootPath(QString &path)
|
||||
{
|
||||
const bool isUnixRoot = path.length() == 1 && path.at(0) == QLatin1Char('/');
|
||||
if (!path.isEmpty() && !isUnixRoot) {
|
||||
|
|
@ -248,20 +251,21 @@ void checkRootPath(QString& path)
|
|||
path.truncate(path.length() - 1);
|
||||
|
||||
int sepCount = 0;
|
||||
for (int i = path.length()-1; i >= 0; --i) {
|
||||
for (int i = path.length() - 1; i >= 0; --i) {
|
||||
if (path.at(i) == QLatin1Char('/'))
|
||||
++sepCount;
|
||||
else break;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (sepCount > 1)
|
||||
path.truncate(path.length() - (sepCount-1));
|
||||
path.truncate(path.length() - (sepCount - 1));
|
||||
else if (sepCount == 0)
|
||||
path.append(QLatin1String("/"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -272,17 +276,10 @@ OSDAB_BEGIN_NAMESPACE(Zip)
|
|||
*************************************************************************/
|
||||
|
||||
//! \internal
|
||||
ZipPrivate::ZipPrivate() :
|
||||
headers(0),
|
||||
device(0),
|
||||
file(0),
|
||||
uBuffer(0),
|
||||
crcTable(0),
|
||||
comment(),
|
||||
password()
|
||||
ZipPrivate::ZipPrivate() : headers(0), device(0), file(0), uBuffer(0), crcTable(0), comment(), password()
|
||||
{
|
||||
// keep an unsigned pointer so we avoid to over bloat the code with casts
|
||||
uBuffer = (unsigned char*) buffer1;
|
||||
uBuffer = (unsigned char *)buffer1;
|
||||
crcTable = get_crc_table();
|
||||
}
|
||||
|
||||
|
|
@ -293,7 +290,7 @@ ZipPrivate::~ZipPrivate()
|
|||
}
|
||||
|
||||
//! \internal
|
||||
Zip::ErrorCode ZipPrivate::createArchive(QIODevice* dev)
|
||||
Zip::ErrorCode ZipPrivate::createArchive(QIODevice *dev)
|
||||
{
|
||||
Q_ASSERT(dev);
|
||||
|
||||
|
|
@ -302,7 +299,7 @@ Zip::ErrorCode ZipPrivate::createArchive(QIODevice* dev)
|
|||
|
||||
device = dev;
|
||||
if (device != file)
|
||||
connect(device, SIGNAL(destroyed(QObject*)), this, SLOT(deviceDestroyed(QObject*)));
|
||||
connect(device, SIGNAL(destroyed(QObject *)), this, SLOT(deviceDestroyed(QObject *)));
|
||||
|
||||
if (!device->isOpen()) {
|
||||
if (!device->open(QIODevice::ReadOnly)) {
|
||||
|
|
@ -313,12 +310,12 @@ Zip::ErrorCode ZipPrivate::createArchive(QIODevice* dev)
|
|||
}
|
||||
}
|
||||
|
||||
headers = new QMap<QString,ZipEntryP*>;
|
||||
headers = new QMap<QString, ZipEntryP *>;
|
||||
return Zip::Ok;
|
||||
}
|
||||
|
||||
//! \internal
|
||||
void ZipPrivate::deviceDestroyed(QObject*)
|
||||
void ZipPrivate::deviceDestroyed(QObject *)
|
||||
{
|
||||
qDebug("Unexpected device destruction detected.");
|
||||
do_closeArchive();
|
||||
|
|
@ -327,7 +324,7 @@ void ZipPrivate::deviceDestroyed(QObject*)
|
|||
/*! Returns true if an entry for \p info has already been added.
|
||||
Uses file size and lower case absolute path to compare entries.
|
||||
*/
|
||||
bool ZipPrivate::containsEntry(const QFileInfo& info) const
|
||||
bool ZipPrivate::containsEntry(const QFileInfo &info) const
|
||||
{
|
||||
if (!headers || headers->isEmpty())
|
||||
return false;
|
||||
|
|
@ -335,10 +332,10 @@ bool ZipPrivate::containsEntry(const QFileInfo& info) const
|
|||
const qint64 sz = info.size();
|
||||
const QString path = info.absoluteFilePath().toLower();
|
||||
|
||||
QMap<QString,ZipEntryP*>::ConstIterator b = headers->constBegin();
|
||||
const QMap<QString,ZipEntryP*>::ConstIterator e = headers->constEnd();
|
||||
QMap<QString, ZipEntryP *>::ConstIterator b = headers->constBegin();
|
||||
const QMap<QString, ZipEntryP *>::ConstIterator e = headers->constEnd();
|
||||
while (b != e) {
|
||||
const ZipEntryP* e = b.value();
|
||||
const ZipEntryP *e = b.value();
|
||||
if (e->fileSize == sz && e->absolutePath == path)
|
||||
return true;
|
||||
++b;
|
||||
|
|
@ -348,9 +345,12 @@ bool ZipPrivate::containsEntry(const QFileInfo& info) const
|
|||
}
|
||||
|
||||
//! \internal Actual implementation of the addDirectory* methods.
|
||||
Zip::ErrorCode ZipPrivate::addDirectory(const QString& path, const QString& root,
|
||||
Zip::CompressionOptions options, Zip::CompressionLevel level, int hierarchyLevel,
|
||||
int* addedFiles)
|
||||
Zip::ErrorCode ZipPrivate::addDirectory(const QString &path,
|
||||
const QString &root,
|
||||
Zip::CompressionOptions options,
|
||||
Zip::CompressionLevel level,
|
||||
int hierarchyLevel,
|
||||
int *addedFiles)
|
||||
{
|
||||
if (addedFiles)
|
||||
++(*addedFiles);
|
||||
|
|
@ -396,13 +396,8 @@ Zip::ErrorCode ZipPrivate::addDirectory(const QString& path, const QString& root
|
|||
const bool skipBad = options & Zip::SkipBadFiles;
|
||||
const bool noDups = options & Zip::CheckForDuplicates;
|
||||
|
||||
const QDir::Filters dir_filter =
|
||||
QDir::Files |
|
||||
QDir::Dirs |
|
||||
QDir::NoDotAndDotDot |
|
||||
QDir::NoSymLinks;
|
||||
const QDir::SortFlags dir_sort =
|
||||
QDir::DirsFirst;
|
||||
const QDir::Filters dir_filter = QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks;
|
||||
const QDir::SortFlags dir_sort = QDir::DirsFirst;
|
||||
QFileInfoList list = dir.entryInfoList(dir_filter, dir_sort);
|
||||
|
||||
Zip::ErrorCode ec = Zip::Ok;
|
||||
|
|
@ -411,7 +406,8 @@ Zip::ErrorCode ZipPrivate::addDirectory(const QString& path, const QString& root
|
|||
Zip::CompressionOptions recursionOptions;
|
||||
if (path_ignore)
|
||||
recursionOptions |= Zip::IgnorePaths;
|
||||
else recursionOptions |= Zip::RelativePaths;
|
||||
else
|
||||
recursionOptions |= Zip::RelativePaths;
|
||||
|
||||
for (int i = 0; i < list.size(); ++i) {
|
||||
QFileInfo info = list.at(i);
|
||||
|
|
@ -420,8 +416,7 @@ Zip::ErrorCode ZipPrivate::addDirectory(const QString& path, const QString& root
|
|||
continue;
|
||||
if (info.isDir()) {
|
||||
// Recursion
|
||||
ec = addDirectory(absPath, actualRoot, recursionOptions,
|
||||
level, hierarchyLevel + 1, addedFiles);
|
||||
ec = addDirectory(absPath, actualRoot, recursionOptions, level, hierarchyLevel + 1, addedFiles);
|
||||
} else {
|
||||
ec = createEntry(info, actualRoot, level);
|
||||
if (ec == Zip::Ok) {
|
||||
|
|
@ -445,9 +440,11 @@ Zip::ErrorCode ZipPrivate::addDirectory(const QString& path, const QString& root
|
|||
}
|
||||
|
||||
//! \internal Actual implementation of the addFile methods.
|
||||
Zip::ErrorCode ZipPrivate::addFiles(const QStringList& files, const QString& root,
|
||||
Zip::CompressionOptions options, Zip::CompressionLevel level,
|
||||
int* addedFiles)
|
||||
Zip::ErrorCode ZipPrivate::addFiles(const QStringList &files,
|
||||
const QString &root,
|
||||
Zip::CompressionOptions options,
|
||||
Zip::CompressionLevel level,
|
||||
int *addedFiles)
|
||||
{
|
||||
if (addedFiles)
|
||||
*addedFiles = 0;
|
||||
|
|
@ -493,10 +490,10 @@ Zip::ErrorCode ZipPrivate::addFiles(const QStringList& files, const QString& roo
|
|||
QHash<QString, ZippedDir> dirMap;
|
||||
|
||||
for (int i = 0; i < paths.size(); ++i) {
|
||||
const QFileInfo& info = paths.at(i);
|
||||
const QFileInfo &info = paths.at(i);
|
||||
const QString path = QFileInfo(QDir::cleanPath(info.absolutePath())).absolutePath();
|
||||
|
||||
ZippedDir& zd = dirMap[path];
|
||||
ZippedDir &zd = dirMap[path];
|
||||
if (!zd.init) {
|
||||
zd.init = true;
|
||||
zd.actualRoot = actualRoot;
|
||||
|
|
@ -518,8 +515,7 @@ Zip::ErrorCode ZipPrivate::addFiles(const QStringList& files, const QString& roo
|
|||
|
||||
if (info.isDir()) {
|
||||
// Recursion
|
||||
ec = addDirectory(info.absoluteFilePath(), actualRoot, options,
|
||||
level, 1, addedFiles);
|
||||
ec = addDirectory(info.absoluteFilePath(), actualRoot, options, level, 1, addedFiles);
|
||||
} else {
|
||||
ec = createEntry(info, actualRoot, level);
|
||||
if (ec == Zip::Ok) {
|
||||
|
|
@ -539,7 +535,7 @@ Zip::ErrorCode ZipPrivate::addFiles(const QStringList& files, const QString& roo
|
|||
QHash<QString, ZippedDir>::ConstIterator b = dirMap.constBegin();
|
||||
const QHash<QString, ZippedDir>::ConstIterator e = dirMap.constEnd();
|
||||
while (b != e) {
|
||||
const ZippedDir& zd = b.value();
|
||||
const ZippedDir &zd = b.value();
|
||||
if (zd.files <= 0) {
|
||||
ec = createEntry(b.key(), zd.actualRoot, level);
|
||||
}
|
||||
|
|
@ -551,8 +547,11 @@ Zip::ErrorCode ZipPrivate::addFiles(const QStringList& files, const QString& roo
|
|||
}
|
||||
|
||||
//! \internal \p file must be a file and not a directory.
|
||||
Zip::ErrorCode ZipPrivate::deflateFile(const QFileInfo& fileInfo,
|
||||
quint32& crc, qint64& written, const Zip::CompressionLevel& level, quint32** keys)
|
||||
Zip::ErrorCode ZipPrivate::deflateFile(const QFileInfo &fileInfo,
|
||||
quint32 &crc,
|
||||
qint64 &written,
|
||||
const Zip::CompressionLevel &level,
|
||||
quint32 **keys)
|
||||
{
|
||||
const QString path = fileInfo.absoluteFilePath();
|
||||
QFile file(path);
|
||||
|
|
@ -561,8 +560,7 @@ Zip::ErrorCode ZipPrivate::deflateFile(const QFileInfo& fileInfo,
|
|||
return Zip::OpenFailed;
|
||||
}
|
||||
|
||||
const Zip::ErrorCode ec = (level == Zip::Store)
|
||||
? storeFile(path, file, crc, written, keys)
|
||||
const Zip::ErrorCode ec = (level == Zip::Store) ? storeFile(path, file, crc, written, keys)
|
||||
: compressFile(path, file, crc, written, level, keys);
|
||||
|
||||
file.close();
|
||||
|
|
@ -570,8 +568,8 @@ Zip::ErrorCode ZipPrivate::deflateFile(const QFileInfo& fileInfo,
|
|||
}
|
||||
|
||||
//! \internal
|
||||
Zip::ErrorCode ZipPrivate::storeFile(const QString& path, QIODevice& file,
|
||||
quint32& crc, qint64& totalWritten, quint32** keys)
|
||||
Zip::ErrorCode
|
||||
ZipPrivate::storeFile(const QString &path, QIODevice &file, quint32 &crc, qint64 &totalWritten, quint32 **keys)
|
||||
{
|
||||
Q_UNUSED(path);
|
||||
|
||||
|
|
@ -583,7 +581,7 @@ Zip::ErrorCode ZipPrivate::storeFile(const QString& path, QIODevice& file,
|
|||
totalWritten = 0;
|
||||
crc = crc32(0L, Z_NULL, 0);
|
||||
|
||||
while ( (read = file.read(buffer1, ZIP_READ_BUFFER)) > 0 ) {
|
||||
while ((read = file.read(buffer1, ZIP_READ_BUFFER)) > 0) {
|
||||
crc = crc32(crc, uBuffer, read);
|
||||
if (encrypt)
|
||||
encryptBytes(*keys, buffer1, read);
|
||||
|
|
@ -598,7 +596,7 @@ Zip::ErrorCode ZipPrivate::storeFile(const QString& path, QIODevice& file,
|
|||
}
|
||||
|
||||
//! \internal
|
||||
int ZipPrivate::compressionStrategy(const QString& path, QIODevice& file) const
|
||||
int ZipPrivate::compressionStrategy(const QString &path, QIODevice &file) const
|
||||
{
|
||||
Q_UNUSED(file);
|
||||
|
||||
|
|
@ -610,8 +608,12 @@ int ZipPrivate::compressionStrategy(const QString& path, QIODevice& file) const
|
|||
}
|
||||
|
||||
//! \internal
|
||||
Zip::ErrorCode ZipPrivate::compressFile(const QString& path, QIODevice& file,
|
||||
quint32& crc, qint64& totalWritten, const Zip::CompressionLevel& level, quint32** keys)
|
||||
Zip::ErrorCode ZipPrivate::compressFile(const QString &path,
|
||||
QIODevice &file,
|
||||
quint32 &crc,
|
||||
qint64 &totalWritten,
|
||||
const Zip::CompressionLevel &level,
|
||||
quint32 **keys)
|
||||
{
|
||||
qint64 read = 0;
|
||||
qint64 written = 0;
|
||||
|
|
@ -635,16 +637,12 @@ Zip::ErrorCode ZipPrivate::compressFile(const QString& path, QIODevice& file,
|
|||
int zret;
|
||||
|
||||
// Use deflateInit2 with negative windowBits to get raw compression
|
||||
if ((zret = deflateInit2_(
|
||||
&zstr,
|
||||
if ((zret = deflateInit2_(&zstr,
|
||||
(int)level, // compression level
|
||||
Z_DEFLATED, // method
|
||||
-MAX_WBITS, // windowBits
|
||||
8, // memLevel
|
||||
strategy,
|
||||
ZLIB_VERSION,
|
||||
sizeof(z_stream)
|
||||
)) != Z_OK ) {
|
||||
strategy, ZLIB_VERSION, sizeof(z_stream))) != Z_OK) {
|
||||
qDebug() << "Could not initialize zlib for compression";
|
||||
return Zip::ZlibError;
|
||||
}
|
||||
|
|
@ -665,7 +663,7 @@ Zip::ErrorCode ZipPrivate::compressFile(const QString& path, QIODevice& file,
|
|||
|
||||
crc = crc32(crc, uBuffer, read);
|
||||
|
||||
zstr.next_in = (Bytef*) buffer1;
|
||||
zstr.next_in = (Bytef *)buffer1;
|
||||
zstr.avail_in = (uInt)read;
|
||||
|
||||
// Tell zlib if this is the last chunk we want to encode
|
||||
|
|
@ -675,7 +673,7 @@ Zip::ErrorCode ZipPrivate::compressFile(const QString& path, QIODevice& file,
|
|||
// Run deflate() on input until output buffer not full
|
||||
// finish compression if all of source has been read in
|
||||
do {
|
||||
zstr.next_out = (Bytef*) buffer2;
|
||||
zstr.next_out = (Bytef *)buffer2;
|
||||
zstr.avail_out = ZIP_READ_BUFFER;
|
||||
|
||||
zret = deflate(&zstr, flush);
|
||||
|
|
@ -712,16 +710,13 @@ Zip::ErrorCode ZipPrivate::compressFile(const QString& path, QIODevice& file,
|
|||
}
|
||||
|
||||
//! \internal Writes a new entry in the zip file.
|
||||
Zip::ErrorCode ZipPrivate::createEntry(const QFileInfo& file, const QString& root,
|
||||
Zip::CompressionLevel level)
|
||||
Zip::ErrorCode ZipPrivate::createEntry(const QFileInfo &file, const QString &root, Zip::CompressionLevel level)
|
||||
{
|
||||
const bool dirOnly = file.isDir();
|
||||
|
||||
// entryName contains the path as it should be written
|
||||
// in the zip file records
|
||||
const QString entryName = dirOnly
|
||||
? root
|
||||
: root + file.fileName();
|
||||
const QString entryName = dirOnly ? root : root + file.fileName();
|
||||
|
||||
// Directory entry
|
||||
if (dirOnly || file.size() < ZIP_COMPRESSION_THRESHOLD) {
|
||||
|
|
@ -746,12 +741,10 @@ Zip::ErrorCode ZipPrivate::createEntry(const QFileInfo& file, const QString& roo
|
|||
qDebug("Compression level for '%s': %d", entryName.toLatin1().constData(), (int)level);
|
||||
#endif
|
||||
break;
|
||||
default: ;
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// create header and store it to write a central directory later
|
||||
QScopedPointer<ZipEntryP> h(new ZipEntryP);
|
||||
h->absolutePath = file.absoluteFilePath().toLower();
|
||||
|
|
@ -784,8 +777,10 @@ Zip::ErrorCode ZipPrivate::createEntry(const QFileInfo& file, const QString& roo
|
|||
// **** Write local file header ****
|
||||
|
||||
// signature
|
||||
buffer1[0] = 'P'; buffer1[1] = 'K';
|
||||
buffer1[2] = 0x3; buffer1[3] = 0x4;
|
||||
buffer1[0] = 'P';
|
||||
buffer1[1] = 'K';
|
||||
buffer1[2] = 0x3;
|
||||
buffer1[3] = 0x4;
|
||||
|
||||
// version needed to extract
|
||||
buffer1[ZIP_LH_OFF_VERS] = ZIP_VERSION;
|
||||
|
|
@ -797,7 +792,7 @@ Zip::ErrorCode ZipPrivate::createEntry(const QFileInfo& file, const QString& roo
|
|||
|
||||
// compression method
|
||||
buffer1[ZIP_LH_OFF_CMET] = h->compMethod & 0xFF;
|
||||
buffer1[ZIP_LH_OFF_CMET + 1] = (h->compMethod>>8) & 0xFF;
|
||||
buffer1[ZIP_LH_OFF_CMET + 1] = (h->compMethod >> 8) & 0xFF;
|
||||
|
||||
// last mod file time
|
||||
buffer1[ZIP_LH_OFF_MODT] = h->modTime[0];
|
||||
|
|
@ -810,9 +805,7 @@ Zip::ErrorCode ZipPrivate::createEntry(const QFileInfo& file, const QString& roo
|
|||
// skip crc (4bytes) [14,15,16,17]
|
||||
|
||||
// skip compressed size but include evtl. encryption header (4bytes: [18,19,20,21])
|
||||
buffer1[ZIP_LH_OFF_CSIZE] =
|
||||
buffer1[ZIP_LH_OFF_CSIZE + 1] =
|
||||
buffer1[ZIP_LH_OFF_CSIZE + 2] =
|
||||
buffer1[ZIP_LH_OFF_CSIZE] = buffer1[ZIP_LH_OFF_CSIZE + 1] = buffer1[ZIP_LH_OFF_CSIZE + 2] =
|
||||
buffer1[ZIP_LH_OFF_CSIZE + 3] = 0;
|
||||
|
||||
h->szComp = encrypt ? ZIP_LOCAL_ENC_HEADER_SIZE : 0;
|
||||
|
|
@ -844,7 +837,7 @@ Zip::ErrorCode ZipPrivate::createEntry(const QFileInfo& file, const QString& roo
|
|||
}
|
||||
|
||||
// Encryption keys
|
||||
quint32 keys[3] = { 0, 0, 0 };
|
||||
quint32 keys[3] = {0, 0, 0};
|
||||
|
||||
if (encrypt) {
|
||||
// **** encryption header ****
|
||||
|
|
@ -889,7 +882,7 @@ Zip::ErrorCode ZipPrivate::createEntry(const QFileInfo& file, const QString& roo
|
|||
qint64 written = 0;
|
||||
|
||||
if (!dirOnly) {
|
||||
quint32* k = keys;
|
||||
quint32 *k = keys;
|
||||
const Zip::ErrorCode ec = deflateFile(file, crc, written, level, encrypt ? &k : 0);
|
||||
if (ec != Zip::Ok)
|
||||
return ec;
|
||||
|
|
@ -909,7 +902,7 @@ Zip::ErrorCode ZipPrivate::createEntry(const QFileInfo& file, const QString& roo
|
|||
|
||||
setULong(h->crc, buffer1, 0);
|
||||
setULong(h->szComp, buffer1, 4);
|
||||
if ( device->write(buffer1, 8) != 8) {
|
||||
if (device->write(buffer1, 8) != 8) {
|
||||
return Zip::WriteFailed;
|
||||
}
|
||||
|
||||
|
|
@ -953,16 +946,16 @@ int ZipPrivate::decryptByte(quint32 key2) const
|
|||
}
|
||||
|
||||
//! \internal Writes an quint32 (4 bytes) to a byte array at given offset.
|
||||
void ZipPrivate::setULong(quint32 v, char* buffer, unsigned int offset)
|
||||
void ZipPrivate::setULong(quint32 v, char *buffer, unsigned int offset)
|
||||
{
|
||||
buffer[offset+3] = ((v >> 24) & 0xFF);
|
||||
buffer[offset+2] = ((v >> 16) & 0xFF);
|
||||
buffer[offset+1] = ((v >> 8) & 0xFF);
|
||||
buffer[offset + 3] = ((v >> 24) & 0xFF);
|
||||
buffer[offset + 2] = ((v >> 16) & 0xFF);
|
||||
buffer[offset + 1] = ((v >> 8) & 0xFF);
|
||||
buffer[offset] = (v & 0xFF);
|
||||
}
|
||||
|
||||
//! \internal Initializes decryption keys using a password.
|
||||
void ZipPrivate::initKeys(quint32* keys) const
|
||||
void ZipPrivate::initKeys(quint32 *keys) const
|
||||
{
|
||||
// Encryption keys initialization constants are taken from the
|
||||
// PKZip file format specification docs
|
||||
|
|
@ -972,20 +965,20 @@ void ZipPrivate::initKeys(quint32* keys) const
|
|||
|
||||
QByteArray pwdBytes = password.toLatin1();
|
||||
int sz = pwdBytes.size();
|
||||
const char* ascii = pwdBytes.data();
|
||||
const char *ascii = pwdBytes.data();
|
||||
|
||||
for (int i = 0; i < sz; ++i)
|
||||
updateKeys(keys, (int)ascii[i]);
|
||||
}
|
||||
|
||||
//! Updates a one-char-only CRC; it's the Info-Zip macro re-adapted.
|
||||
quint32 ZipPrivate::updateChecksum(const quint32& crc, const quint32& val) const
|
||||
quint32 ZipPrivate::updateChecksum(const quint32 &crc, const quint32 &val) const
|
||||
{
|
||||
return quint32(crcTable[quint32(crc^val) & 0xff] ^ crc_t(crc >> 8));
|
||||
return quint32(crcTable[quint32(crc ^ val) & 0xff] ^ crc_t(crc >> 8));
|
||||
}
|
||||
|
||||
//! \internal Updates encryption keys.
|
||||
void ZipPrivate::updateKeys(quint32* keys, int c) const
|
||||
void ZipPrivate::updateKeys(quint32 *keys, int c) const
|
||||
{
|
||||
keys[0] = updateChecksum(keys[0], c);
|
||||
keys[1] += keys[0] & 0xff;
|
||||
|
|
@ -994,7 +987,7 @@ void ZipPrivate::updateKeys(quint32* keys, int c) const
|
|||
}
|
||||
|
||||
//! \internal Encrypts a byte array.
|
||||
void ZipPrivate::encryptBytes(quint32* keys, char* buffer, qint64 read)
|
||||
void ZipPrivate::encryptBytes(quint32 *keys, char *buffer, qint64 read)
|
||||
{
|
||||
char t;
|
||||
|
||||
|
|
@ -1005,79 +998,65 @@ void ZipPrivate::encryptBytes(quint32* keys, char* buffer, qint64 read)
|
|||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct KeywordHelper {
|
||||
namespace
|
||||
{
|
||||
struct KeywordHelper
|
||||
{
|
||||
const QString needle;
|
||||
inline KeywordHelper(const QString& keyword) : needle(keyword) {}
|
||||
inline KeywordHelper(const QString &keyword) : needle(keyword)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
bool operator<(const KeywordHelper& helper, const char* keyword) {
|
||||
bool operator<(const KeywordHelper &helper, const char *keyword)
|
||||
{
|
||||
return helper.needle.compare(QLatin1String(keyword)) < 0;
|
||||
}
|
||||
|
||||
bool operator<(const char* keyword, const KeywordHelper& helper) {
|
||||
bool operator<(const char *keyword, const KeywordHelper &helper)
|
||||
{
|
||||
return helper.needle.compare(QLatin1String(keyword)) > 0;
|
||||
}
|
||||
|
||||
bool hasExtension(const QString& ext, const char* const* map, int max) {
|
||||
const char* const* start = &map[0];
|
||||
const char* const* end = &map[max - 1];
|
||||
const char* const* kw = qBinaryFind(start, end, KeywordHelper(ext));
|
||||
bool hasExtension(const QString &ext, const char *const *map, int max)
|
||||
{
|
||||
const char *const *start = &map[0];
|
||||
const char *const *end = &map[max - 1];
|
||||
const char *const *kw = qBinaryFind(start, end, KeywordHelper(ext));
|
||||
return kw != end;
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
//! \internal Detects the best compression level for a given file extension.
|
||||
Zip::CompressionLevel ZipPrivate::detectCompressionByMime(const QString& ext)
|
||||
Zip::CompressionLevel ZipPrivate::detectCompressionByMime(const QString &ext)
|
||||
{
|
||||
// NOTE: Keep the MAX_* and the number of strings in the map up to date.
|
||||
// NOTE: Alphabetically sort the strings in the map -- we use a binary search!
|
||||
|
||||
// Archives or files that will hardly compress
|
||||
const int MAX_EXT1 = 14;
|
||||
const char* const ext1[MAX_EXT1] = {
|
||||
const char *const ext1[MAX_EXT1] = {
|
||||
"7z", "bin", "deb", "exe", "gz", "gz2", "jar", "rar", "rpm", "tar", "tgz", "z", "zip",
|
||||
0 // # MAX_EXT1
|
||||
};
|
||||
|
||||
// Slow or usually large files that we should not spend to much time with
|
||||
const int MAX_EXT2 = 24;
|
||||
const char* const ext2[MAX_EXT2] = {
|
||||
"asf",
|
||||
"avi",
|
||||
"divx",
|
||||
"doc",
|
||||
"docx",
|
||||
"flv",
|
||||
"gif",
|
||||
"iso",
|
||||
"jpg",
|
||||
"jpeg",
|
||||
"mka",
|
||||
"mkv",
|
||||
"mp3",
|
||||
"mp4",
|
||||
"mpeg",
|
||||
"mpg",
|
||||
"odt",
|
||||
"ogg",
|
||||
"ogm",
|
||||
"ra",
|
||||
"rm",
|
||||
"wma",
|
||||
"wmv",
|
||||
const char *const ext2[MAX_EXT2] = {
|
||||
"asf", "avi", "divx", "doc", "docx", "flv", "gif", "iso", "jpg", "jpeg", "mka", "mkv",
|
||||
"mp3", "mp4", "mpeg", "mpg", "odt", "ogg", "ogm", "ra", "rm", "wma", "wmv",
|
||||
0 // # MAX_EXT2
|
||||
};
|
||||
|
||||
// Files with high compression ratio
|
||||
const int MAX_EXT3 = 28;
|
||||
const char* const ext3[MAX_EXT3] = {
|
||||
const char *const ext3[MAX_EXT3] = {
|
||||
"asp", "bat", "c", "conf", "cpp", "cpp", "css", "csv", "cxx", "h", "hpp", "htm", "html", "hxx",
|
||||
"ini", "js", "php", "pl", "py", "rtf", "sh", "tsv", "txt", "vb", "vbs", "xml", "xst",
|
||||
0 // # MAX_EXT3
|
||||
};
|
||||
|
||||
const char* const* map = ext1;
|
||||
const char *const *map = ext1;
|
||||
if (hasExtension(ext, map, MAX_EXT1))
|
||||
return Zip::Store;
|
||||
|
||||
|
|
@ -1122,10 +1101,9 @@ Zip::ErrorCode ZipPrivate::do_closeArchive()
|
|||
Zip::ErrorCode c = Zip::Ok;
|
||||
|
||||
if (headers && device) {
|
||||
for (QMap<QString,ZipEntryP*>::ConstIterator itr = headers->constBegin();
|
||||
itr != headers->constEnd(); ++itr) {
|
||||
for (QMap<QString, ZipEntryP *>::ConstIterator itr = headers->constBegin(); itr != headers->constEnd(); ++itr) {
|
||||
const QString fileName = itr.key();
|
||||
const ZipEntryP* h = itr.value();
|
||||
const ZipEntryP *h = itr.value();
|
||||
c = writeEntry(fileName, h, szCentralDir);
|
||||
}
|
||||
}
|
||||
|
|
@ -1146,7 +1124,7 @@ Zip::ErrorCode ZipPrivate::do_closeArchive()
|
|||
}
|
||||
|
||||
//! \internal
|
||||
Zip::ErrorCode ZipPrivate::writeEntry(const QString& fileName, const ZipEntryP* h, quint32& szCentralDir)
|
||||
Zip::ErrorCode ZipPrivate::writeEntry(const QString &fileName, const ZipEntryP *h, quint32 &szCentralDir)
|
||||
{
|
||||
unsigned int sz;
|
||||
|
||||
|
|
@ -1209,9 +1187,7 @@ Zip::ErrorCode ZipPrivate::writeEntry(const QString& fileName, const ZipEntryP*
|
|||
buffer1[ZIP_CD_OFF_IATTR] = buffer1[ZIP_CD_OFF_IATTR + 1] = 0;
|
||||
|
||||
// external file attributes
|
||||
buffer1[ZIP_CD_OFF_EATTR] =
|
||||
buffer1[ZIP_CD_OFF_EATTR + 1] =
|
||||
buffer1[ZIP_CD_OFF_EATTR + 2] =
|
||||
buffer1[ZIP_CD_OFF_EATTR] = buffer1[ZIP_CD_OFF_EATTR + 1] = buffer1[ZIP_CD_OFF_EATTR + 2] =
|
||||
buffer1[ZIP_CD_OFF_EATTR + 3] = 0;
|
||||
|
||||
// relative offset of local header [42->45]
|
||||
|
|
@ -1308,7 +1284,7 @@ void ZipPrivate::reset()
|
|||
}
|
||||
|
||||
//! \internal Returns the path of the parent directory
|
||||
QString ZipPrivate::extractRoot(const QString& p, Zip::CompressionOptions o)
|
||||
QString ZipPrivate::extractRoot(const QString &p, Zip::CompressionOptions o)
|
||||
{
|
||||
Q_UNUSED(o);
|
||||
QDir d(QDir::cleanPath(p));
|
||||
|
|
@ -1321,7 +1297,6 @@ QString ZipPrivate::extractRoot(const QString& p, Zip::CompressionOptions o)
|
|||
return d.absolutePath();
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************
|
||||
Public interface
|
||||
*************************************************************************/
|
||||
|
|
@ -1356,7 +1331,7 @@ bool Zip::isOpen() const
|
|||
set password (if any).
|
||||
Closing the archive won't clear the password!
|
||||
*/
|
||||
void Zip::setPassword(const QString& pwd)
|
||||
void Zip::setPassword(const QString &pwd)
|
||||
{
|
||||
d->password = pwd;
|
||||
}
|
||||
|
|
@ -1378,7 +1353,7 @@ QString Zip::password() const
|
|||
already exist it will be overwritten.
|
||||
Any open archive will be closed.
|
||||
*/
|
||||
Zip::ErrorCode Zip::createArchive(const QString& filename, bool overwrite)
|
||||
Zip::ErrorCode Zip::createArchive(const QString &filename, bool overwrite)
|
||||
{
|
||||
closeArchive();
|
||||
Q_ASSERT(!d->device && !d->file);
|
||||
|
|
@ -1412,7 +1387,7 @@ Zip::ErrorCode Zip::createArchive(const QString& filename, bool overwrite)
|
|||
Attempts to create a new Zip archive. If there is another open archive this will be closed.
|
||||
\warning The class takes ownership of the device!
|
||||
*/
|
||||
Zip::ErrorCode Zip::createArchive(QIODevice* device)
|
||||
Zip::ErrorCode Zip::createArchive(QIODevice *device)
|
||||
{
|
||||
if (!device) {
|
||||
qDebug() << "Invalid device.";
|
||||
|
|
@ -1434,32 +1409,33 @@ QString Zip::archiveComment() const
|
|||
Sets the comment for this archive. Note: createArchive() should have been
|
||||
called before.
|
||||
*/
|
||||
void Zip::setArchiveComment(const QString& comment)
|
||||
void Zip::setArchiveComment(const QString &comment)
|
||||
{
|
||||
d->comment = comment;
|
||||
}
|
||||
|
||||
/*!
|
||||
Convenience method, same as calling Zip::addDirectory(const QString&,const QString&,CompressionOptions,CompressionLevel)
|
||||
with the Zip::IgnorePaths flag as compression option and an empty \p root parameter.
|
||||
Convenience method, same as calling Zip::addDirectory(const QString&,const
|
||||
QString&,CompressionOptions,CompressionLevel) with the Zip::IgnorePaths flag as compression option and an empty \p
|
||||
root parameter.
|
||||
|
||||
The result is that all files found in \p path (and in subdirectories) are
|
||||
added to the zip file without a directory entry.
|
||||
*/
|
||||
Zip::ErrorCode Zip::addDirectoryContents(const QString& path, CompressionLevel level)
|
||||
Zip::ErrorCode Zip::addDirectoryContents(const QString &path, CompressionLevel level)
|
||||
{
|
||||
return addDirectory(path, QString(), IgnorePaths, level);
|
||||
}
|
||||
|
||||
/*!
|
||||
Convenience method, same as calling Zip::addDirectory(const QString&,const QString&,CompressionOptions,CompressionLevel)
|
||||
with the Zip::IgnorePaths flag as compression option.
|
||||
Convenience method, same as calling Zip::addDirectory(const QString&,const
|
||||
QString&,CompressionOptions,CompressionLevel) with the Zip::IgnorePaths flag as compression option.
|
||||
|
||||
The result is that all files found in \p path (and in subdirectories) are
|
||||
added to the zip file without a directory entry (or within a directory
|
||||
structure specified by \p root).
|
||||
*/
|
||||
Zip::ErrorCode Zip::addDirectoryContents(const QString& path, const QString& root, CompressionLevel level)
|
||||
Zip::ErrorCode Zip::addDirectoryContents(const QString &path, const QString &root, CompressionLevel level)
|
||||
{
|
||||
return addDirectory(path, root, IgnorePaths, level);
|
||||
}
|
||||
|
|
@ -1469,16 +1445,16 @@ Zip::ErrorCode Zip::addDirectoryContents(const QString& path, const QString& roo
|
|||
Zip::addDirectory(const QString&,const QString&,CompressionLevel)
|
||||
with an empty \p root parameter and Zip::RelativePaths flag as compression option.
|
||||
*/
|
||||
Zip::ErrorCode Zip::addDirectory(const QString& path, CompressionLevel level)
|
||||
Zip::ErrorCode Zip::addDirectory(const QString &path, CompressionLevel level)
|
||||
{
|
||||
return addDirectory(path, QString(), Zip::RelativePaths, level);
|
||||
}
|
||||
|
||||
/*!
|
||||
Convenience method, same as calling Zip::addDirectory(const QString&,const QString&,CompressionOptions,CompressionLevel)
|
||||
with the Zip::RelativePaths flag as compression option.
|
||||
Convenience method, same as calling Zip::addDirectory(const QString&,const
|
||||
QString&,CompressionOptions,CompressionLevel) with the Zip::RelativePaths flag as compression option.
|
||||
*/
|
||||
Zip::ErrorCode Zip::addDirectory(const QString& path, const QString& root, CompressionLevel level)
|
||||
Zip::ErrorCode Zip::addDirectory(const QString &path, const QString &root, CompressionLevel level)
|
||||
{
|
||||
return addDirectory(path, root, Zip::RelativePaths, level);
|
||||
}
|
||||
|
|
@ -1497,8 +1473,11 @@ Zip::ErrorCode Zip::addDirectory(const QString& path, const QString& root, Compr
|
|||
If \p addedFiles is not null it is set to the number of successfully added
|
||||
files.
|
||||
*/
|
||||
Zip::ErrorCode Zip::addDirectory(const QString& path, const QString& root,
|
||||
CompressionOptions options, CompressionLevel level, int* addedFiles)
|
||||
Zip::ErrorCode Zip::addDirectory(const QString &path,
|
||||
const QString &root,
|
||||
CompressionOptions options,
|
||||
CompressionLevel level,
|
||||
int *addedFiles)
|
||||
{
|
||||
const int hierarchyLev = 0;
|
||||
return d->addDirectory(path, root, options, level, hierarchyLev, addedFiles);
|
||||
|
|
@ -1508,7 +1487,7 @@ Zip::ErrorCode Zip::addDirectory(const QString& path, const QString& root,
|
|||
Convenience method, same as calling Zip::addFile(const QString&,const QString&,CompressionOptions,CompressionLevel)
|
||||
with an empty \p root parameter and Zip::RelativePaths as compression option.
|
||||
*/
|
||||
Zip::ErrorCode Zip::addFile(const QString& path, CompressionLevel level)
|
||||
Zip::ErrorCode Zip::addFile(const QString &path, CompressionLevel level)
|
||||
{
|
||||
return addFile(path, QString(), Zip::RelativePaths, level);
|
||||
}
|
||||
|
|
@ -1517,8 +1496,7 @@ Zip::ErrorCode Zip::addFile(const QString& path, CompressionLevel level)
|
|||
Convenience method, same as calling Zip::addFile(const QString&,const QString&,CompressionOptions,CompressionLevel)
|
||||
with the Zip::RelativePaths flag as compression option.
|
||||
*/
|
||||
Zip::ErrorCode Zip::addFile(const QString& path, const QString& root,
|
||||
CompressionLevel level)
|
||||
Zip::ErrorCode Zip::addFile(const QString &path, const QString &root, CompressionLevel level)
|
||||
{
|
||||
return addFile(path, root, Zip::RelativePaths, level);
|
||||
}
|
||||
|
|
@ -1535,8 +1513,8 @@ Zip::ErrorCode Zip::addFile(const QString& path, const QString& root,
|
|||
The \p root parameter is ignored with the Zip::IgnorePaths parameter and used as path prefix (a trailing /
|
||||
is always added as directory separator!) otherwise (even with Zip::AbsolutePaths set!).
|
||||
*/
|
||||
Zip::ErrorCode Zip::addFile(const QString& path, const QString& root,
|
||||
CompressionOptions options, CompressionLevel level)
|
||||
Zip::ErrorCode
|
||||
Zip::addFile(const QString &path, const QString &root, CompressionOptions options, CompressionLevel level)
|
||||
{
|
||||
if (path.isEmpty())
|
||||
return Zip::Ok;
|
||||
|
|
@ -1544,20 +1522,20 @@ Zip::ErrorCode Zip::addFile(const QString& path, const QString& root,
|
|||
}
|
||||
|
||||
/*!
|
||||
Convenience method, same as calling Zip::addFiles(const QStringList&,const QString&,CompressionOptions,CompressionLevel)
|
||||
with an empty \p root parameter and Zip::RelativePaths as compression option.
|
||||
Convenience method, same as calling Zip::addFiles(const QStringList&,const
|
||||
QString&,CompressionOptions,CompressionLevel) with an empty \p root parameter and Zip::RelativePaths as compression
|
||||
option.
|
||||
*/
|
||||
Zip::ErrorCode Zip::addFiles(const QStringList& paths, CompressionLevel level)
|
||||
Zip::ErrorCode Zip::addFiles(const QStringList &paths, CompressionLevel level)
|
||||
{
|
||||
return addFiles(paths, QString(), Zip::RelativePaths, level);
|
||||
}
|
||||
|
||||
/*!
|
||||
Convenience method, same as calling Zip::addFiles(const QStringList&,const QString&,CompressionOptions,CompressionLevel)
|
||||
with the Zip::RelativePaths flag as compression option.
|
||||
Convenience method, same as calling Zip::addFiles(const QStringList&,const
|
||||
QString&,CompressionOptions,CompressionLevel) with the Zip::RelativePaths flag as compression option.
|
||||
*/
|
||||
Zip::ErrorCode Zip::addFiles(const QStringList& paths, const QString& root,
|
||||
CompressionLevel level)
|
||||
Zip::ErrorCode Zip::addFiles(const QStringList &paths, const QString &root, CompressionLevel level)
|
||||
{
|
||||
return addFiles(paths, root, Zip::RelativePaths, level);
|
||||
}
|
||||
|
|
@ -1578,8 +1556,11 @@ Zip::ErrorCode Zip::addFiles(const QStringList& paths, const QString& root,
|
|||
If \p addedFiles is not null it is set to the number of successfully added
|
||||
files.
|
||||
*/
|
||||
Zip::ErrorCode Zip::addFiles(const QStringList& paths, const QString& root,
|
||||
CompressionOptions options, CompressionLevel level, int* addedFiles)
|
||||
Zip::ErrorCode Zip::addFiles(const QStringList &paths,
|
||||
const QString &root,
|
||||
CompressionOptions options,
|
||||
CompressionLevel level,
|
||||
int *addedFiles)
|
||||
{
|
||||
return d->addFiles(paths, root, options, level, addedFiles);
|
||||
}
|
||||
|
|
@ -1599,18 +1580,35 @@ Zip::ErrorCode Zip::closeArchive()
|
|||
*/
|
||||
QString Zip::formatError(Zip::ErrorCode c) const
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case Ok: return QCoreApplication::translate("Zip", "ZIP operation completed successfully."); break;
|
||||
case ZlibInit: return QCoreApplication::translate("Zip", "Failed to initialize or load zlib library."); break;
|
||||
case ZlibError: return QCoreApplication::translate("Zip", "zlib library error."); break;
|
||||
case OpenFailed: return QCoreApplication::translate("Zip", "Unable to create or open file."); break;
|
||||
case NoOpenArchive: return QCoreApplication::translate("Zip", "No archive has been created yet."); break;
|
||||
case FileNotFound: return QCoreApplication::translate("Zip", "File or directory does not exist."); break;
|
||||
case ReadFailed: return QCoreApplication::translate("Zip", "File read error."); break;
|
||||
case WriteFailed: return QCoreApplication::translate("Zip", "File write error."); break;
|
||||
case SeekFailed: return QCoreApplication::translate("Zip", "File seek error."); break;
|
||||
default: ;
|
||||
switch (c) {
|
||||
case Ok:
|
||||
return QCoreApplication::translate("Zip", "ZIP operation completed successfully.");
|
||||
break;
|
||||
case ZlibInit:
|
||||
return QCoreApplication::translate("Zip", "Failed to initialize or load zlib library.");
|
||||
break;
|
||||
case ZlibError:
|
||||
return QCoreApplication::translate("Zip", "zlib library error.");
|
||||
break;
|
||||
case OpenFailed:
|
||||
return QCoreApplication::translate("Zip", "Unable to create or open file.");
|
||||
break;
|
||||
case NoOpenArchive:
|
||||
return QCoreApplication::translate("Zip", "No archive has been created yet.");
|
||||
break;
|
||||
case FileNotFound:
|
||||
return QCoreApplication::translate("Zip", "File or directory does not exist.");
|
||||
break;
|
||||
case ReadFailed:
|
||||
return QCoreApplication::translate("Zip", "File read error.");
|
||||
break;
|
||||
case WriteFailed:
|
||||
return QCoreApplication::translate("Zip", "File write error.");
|
||||
break;
|
||||
case SeekFailed:
|
||||
return QCoreApplication::translate("Zip", "File seek error.");
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
|
||||
return QCoreApplication::translate("Zip", "Unknown error.");
|
||||
|
|
|
|||
72
cockatrice/src/utility/external/zip/zip.h
vendored
Executable file → Normal file
72
cockatrice/src/utility/external/zip/zip.h
vendored
Executable file → Normal file
|
|
@ -32,7 +32,6 @@
|
|||
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QtGlobal>
|
||||
|
||||
#include <zlib/zlib.h>
|
||||
|
||||
class QIODevice;
|
||||
|
|
@ -66,9 +65,18 @@ public:
|
|||
enum CompressionLevel
|
||||
{
|
||||
Store,
|
||||
Deflate1 = 1, Deflate2, Deflate3, Deflate4,
|
||||
Deflate5, Deflate6, Deflate7, Deflate8, Deflate9,
|
||||
AutoCPU, AutoMIME, AutoFull
|
||||
Deflate1 = 1,
|
||||
Deflate2,
|
||||
Deflate3,
|
||||
Deflate4,
|
||||
Deflate5,
|
||||
Deflate6,
|
||||
Deflate7,
|
||||
Deflate8,
|
||||
Deflate9,
|
||||
AutoCPU,
|
||||
AutoMIME,
|
||||
AutoFull
|
||||
};
|
||||
|
||||
enum CompressionOption
|
||||
|
|
@ -103,52 +111,46 @@ public:
|
|||
|
||||
bool isOpen() const;
|
||||
|
||||
void setPassword(const QString& pwd);
|
||||
void setPassword(const QString &pwd);
|
||||
void clearPassword();
|
||||
QString password() const;
|
||||
|
||||
ErrorCode createArchive(const QString& file, bool overwrite = true);
|
||||
ErrorCode createArchive(QIODevice* device);
|
||||
ErrorCode createArchive(const QString &file, bool overwrite = true);
|
||||
ErrorCode createArchive(QIODevice *device);
|
||||
|
||||
QString archiveComment() const;
|
||||
void setArchiveComment(const QString& comment);
|
||||
void setArchiveComment(const QString &comment);
|
||||
|
||||
ErrorCode addDirectoryContents(const QString& path,
|
||||
CompressionLevel level = AutoFull);
|
||||
ErrorCode addDirectoryContents(const QString& path, const QString& root,
|
||||
CompressionLevel level = AutoFull);
|
||||
ErrorCode addDirectoryContents(const QString &path, CompressionLevel level = AutoFull);
|
||||
ErrorCode addDirectoryContents(const QString &path, const QString &root, CompressionLevel level = AutoFull);
|
||||
|
||||
ErrorCode addDirectory(const QString& path,
|
||||
CompressionLevel level = AutoFull);
|
||||
ErrorCode addDirectory(const QString& path, const QString& root,
|
||||
CompressionLevel level = AutoFull);
|
||||
ErrorCode addDirectory(const QString& path, const QString& root,
|
||||
CompressionOptions options, CompressionLevel level = AutoFull,
|
||||
int* addedFiles = 0);
|
||||
|
||||
ErrorCode addFile(const QString& path,
|
||||
CompressionLevel level = AutoFull);
|
||||
ErrorCode addFile(const QString& path, const QString& root,
|
||||
CompressionLevel level = AutoFull);
|
||||
ErrorCode addFile(const QString& path, const QString& root,
|
||||
CompressionOptions options,
|
||||
CompressionLevel level = AutoFull);
|
||||
|
||||
ErrorCode addFiles(const QStringList& paths,
|
||||
CompressionLevel level = AutoFull);
|
||||
ErrorCode addFiles(const QStringList& paths, const QString& root,
|
||||
CompressionLevel level = AutoFull);
|
||||
ErrorCode addFiles(const QStringList& paths, const QString& root,
|
||||
ErrorCode addDirectory(const QString &path, CompressionLevel level = AutoFull);
|
||||
ErrorCode addDirectory(const QString &path, const QString &root, CompressionLevel level = AutoFull);
|
||||
ErrorCode addDirectory(const QString &path,
|
||||
const QString &root,
|
||||
CompressionOptions options,
|
||||
CompressionLevel level = AutoFull,
|
||||
int* addedFiles = 0);
|
||||
int *addedFiles = 0);
|
||||
|
||||
ErrorCode addFile(const QString &path, CompressionLevel level = AutoFull);
|
||||
ErrorCode addFile(const QString &path, const QString &root, CompressionLevel level = AutoFull);
|
||||
ErrorCode
|
||||
addFile(const QString &path, const QString &root, CompressionOptions options, CompressionLevel level = AutoFull);
|
||||
|
||||
ErrorCode addFiles(const QStringList &paths, CompressionLevel level = AutoFull);
|
||||
ErrorCode addFiles(const QStringList &paths, const QString &root, CompressionLevel level = AutoFull);
|
||||
ErrorCode addFiles(const QStringList &paths,
|
||||
const QString &root,
|
||||
CompressionOptions options,
|
||||
CompressionLevel level = AutoFull,
|
||||
int *addedFiles = 0);
|
||||
|
||||
ErrorCode closeArchive();
|
||||
|
||||
QString formatError(ErrorCode c) const;
|
||||
|
||||
private:
|
||||
ZipPrivate* d;
|
||||
ZipPrivate *d;
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(Zip::CompressionOptions)
|
||||
|
|
|
|||
75
cockatrice/src/utility/external/zip/zip_p.h
vendored
Executable file → Normal file
75
cockatrice/src/utility/external/zip/zip_p.h
vendored
Executable file → Normal file
|
|
@ -45,14 +45,13 @@
|
|||
#include <QtCore/QFileInfo>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QtGlobal>
|
||||
|
||||
#include <zlib/zconf.h>
|
||||
|
||||
/*!
|
||||
zLib authors suggest using larger buffers (128K or 256K) for (de)compression (especially for inflate())
|
||||
we use a 256K buffer here - if you want to use this code on a pre-iceage mainframe please change it ;)
|
||||
*/
|
||||
#define ZIP_READ_BUFFER (256*1024)
|
||||
#define ZIP_READ_BUFFER (256 * 1024)
|
||||
|
||||
OSDAB_BEGIN_NAMESPACE(Zip)
|
||||
|
||||
|
|
@ -67,64 +66,74 @@ public:
|
|||
ZipPrivate();
|
||||
virtual ~ZipPrivate();
|
||||
|
||||
QMap<QString,ZipEntryP*>* headers;
|
||||
QMap<QString, ZipEntryP *> *headers;
|
||||
|
||||
QIODevice* device;
|
||||
QFile* file;
|
||||
QIODevice *device;
|
||||
QFile *file;
|
||||
|
||||
char buffer1[ZIP_READ_BUFFER];
|
||||
char buffer2[ZIP_READ_BUFFER];
|
||||
|
||||
unsigned char* uBuffer;
|
||||
unsigned char *uBuffer;
|
||||
|
||||
const crc_t* crcTable;
|
||||
const crc_t *crcTable;
|
||||
|
||||
QString comment;
|
||||
QString password;
|
||||
|
||||
Zip::ErrorCode createArchive(QIODevice* device);
|
||||
Zip::ErrorCode createArchive(QIODevice *device);
|
||||
Zip::ErrorCode closeArchive();
|
||||
void reset();
|
||||
|
||||
bool zLibInit();
|
||||
|
||||
bool containsEntry(const QFileInfo& info) const;
|
||||
bool containsEntry(const QFileInfo &info) const;
|
||||
|
||||
Zip::ErrorCode addDirectory(const QString& path, const QString& root,
|
||||
Zip::CompressionOptions options, Zip::CompressionLevel level,
|
||||
int hierarchyLevel, int* addedFiles = 0);
|
||||
Zip::ErrorCode addFiles(const QStringList& paths, const QString& root,
|
||||
Zip::CompressionOptions options, Zip::CompressionLevel level,
|
||||
int* addedFiles);
|
||||
Zip::ErrorCode addDirectory(const QString &path,
|
||||
const QString &root,
|
||||
Zip::CompressionOptions options,
|
||||
Zip::CompressionLevel level,
|
||||
int hierarchyLevel,
|
||||
int *addedFiles = 0);
|
||||
Zip::ErrorCode addFiles(const QStringList &paths,
|
||||
const QString &root,
|
||||
Zip::CompressionOptions options,
|
||||
Zip::CompressionLevel level,
|
||||
int *addedFiles);
|
||||
|
||||
Zip::ErrorCode createEntry(const QFileInfo& file, const QString& root,
|
||||
Zip::CompressionLevel level);
|
||||
Zip::CompressionLevel detectCompressionByMime(const QString& ext);
|
||||
Zip::ErrorCode createEntry(const QFileInfo &file, const QString &root, Zip::CompressionLevel level);
|
||||
Zip::CompressionLevel detectCompressionByMime(const QString &ext);
|
||||
|
||||
inline quint32 updateChecksum(const quint32& crc, const quint32& val) const;
|
||||
inline quint32 updateChecksum(const quint32 &crc, const quint32 &val) const;
|
||||
|
||||
inline void encryptBytes(quint32* keys, char* buffer, qint64 read);
|
||||
inline void encryptBytes(quint32 *keys, char *buffer, qint64 read);
|
||||
|
||||
inline void setULong(quint32 v, char* buffer, unsigned int offset);
|
||||
inline void updateKeys(quint32* keys, int c) const;
|
||||
inline void initKeys(quint32* keys) const;
|
||||
inline void setULong(quint32 v, char *buffer, unsigned int offset);
|
||||
inline void updateKeys(quint32 *keys, int c) const;
|
||||
inline void initKeys(quint32 *keys) const;
|
||||
inline int decryptByte(quint32 key2) const;
|
||||
|
||||
inline QString extractRoot(const QString& p, Zip::CompressionOptions o);
|
||||
inline QString extractRoot(const QString &p, Zip::CompressionOptions o);
|
||||
|
||||
private slots:
|
||||
void deviceDestroyed(QObject*);
|
||||
void deviceDestroyed(QObject *);
|
||||
|
||||
private:
|
||||
int compressionStrategy(const QString& path, QIODevice& file) const;
|
||||
Zip::ErrorCode deflateFile(const QFileInfo& fileInfo,
|
||||
quint32& crc, qint64& written, const Zip::CompressionLevel& level, quint32** keys);
|
||||
Zip::ErrorCode storeFile(const QString& path, QIODevice& file,
|
||||
quint32& crc, qint64& written, quint32** keys);
|
||||
Zip::ErrorCode compressFile(const QString& path, QIODevice& file,
|
||||
quint32& crc, qint64& written, const Zip::CompressionLevel& level, quint32** keys);
|
||||
int compressionStrategy(const QString &path, QIODevice &file) const;
|
||||
Zip::ErrorCode deflateFile(const QFileInfo &fileInfo,
|
||||
quint32 &crc,
|
||||
qint64 &written,
|
||||
const Zip::CompressionLevel &level,
|
||||
quint32 **keys);
|
||||
Zip::ErrorCode storeFile(const QString &path, QIODevice &file, quint32 &crc, qint64 &written, quint32 **keys);
|
||||
Zip::ErrorCode compressFile(const QString &path,
|
||||
QIODevice &file,
|
||||
quint32 &crc,
|
||||
qint64 &written,
|
||||
const Zip::CompressionLevel &level,
|
||||
quint32 **keys);
|
||||
Zip::ErrorCode do_closeArchive();
|
||||
Zip::ErrorCode writeEntry(const QString& fileName, const ZipEntryP* h, quint32& szCentralDir);
|
||||
Zip::ErrorCode writeEntry(const QString &fileName, const ZipEntryP *h, quint32 &szCentralDir);
|
||||
Zip::ErrorCode writeCentralDir(quint32 offCentralDir, quint32 szCentralDir);
|
||||
};
|
||||
|
||||
|
|
|
|||
26
cockatrice/src/utility/external/zip/zipentry_p.h
vendored
Executable file → Normal file
26
cockatrice/src/utility/external/zip/zipentry_p.h
vendored
Executable file → Normal file
|
|
@ -47,19 +47,9 @@ OSDAB_BEGIN_NAMESPACE(Zip)
|
|||
class ZipEntryP
|
||||
{
|
||||
public:
|
||||
ZipEntryP() :
|
||||
lhOffset(0),
|
||||
dataOffset(0),
|
||||
gpFlag(),
|
||||
compMethod(0),
|
||||
modTime(),
|
||||
modDate(),
|
||||
crc(0),
|
||||
szComp(0),
|
||||
szUncomp(0),
|
||||
absolutePath(),
|
||||
fileSize(0),
|
||||
lhEntryChecked(false)
|
||||
ZipEntryP()
|
||||
: lhOffset(0), dataOffset(0), gpFlag(), compMethod(0), modTime(), modDate(), crc(0), szComp(0), szUncomp(0),
|
||||
absolutePath(), fileSize(0), lhEntryChecked(false)
|
||||
{
|
||||
gpFlag[0] = gpFlag[1] = 0;
|
||||
modTime[0] = modTime[1] = 0;
|
||||
|
|
@ -82,8 +72,14 @@ public:
|
|||
|
||||
mutable bool lhEntryChecked; // Is true if the local header record for this entry has been parsed
|
||||
|
||||
inline bool isEncrypted() const { return gpFlag[0] & 0x01; }
|
||||
inline bool hasDataDescriptor() const { return gpFlag[0] & 0x08; }
|
||||
inline bool isEncrypted() const
|
||||
{
|
||||
return gpFlag[0] & 0x01;
|
||||
}
|
||||
inline bool hasDataDescriptor() const
|
||||
{
|
||||
return gpFlag[0] & 0x08;
|
||||
}
|
||||
};
|
||||
|
||||
OSDAB_END_NAMESPACE
|
||||
|
|
|
|||
26
cockatrice/src/utility/external/zip/zipglobal.h
vendored
Executable file → Normal file
26
cockatrice/src/utility/external/zip/zipglobal.h
vendored
Executable file → Normal file
|
|
@ -39,23 +39,29 @@
|
|||
*/
|
||||
|
||||
#ifndef OSDAB_ZIP_LIB
|
||||
# define OSDAB_ZIP_EXPORT
|
||||
#define OSDAB_ZIP_EXPORT
|
||||
#else
|
||||
# if defined(OSDAB_ZIP_BUILD_LIB)
|
||||
# define OSDAB_ZIP_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define OSDAB_ZIP_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
#if defined(OSDAB_ZIP_BUILD_LIB)
|
||||
#define OSDAB_ZIP_EXPORT Q_DECL_EXPORT
|
||||
#else
|
||||
#define OSDAB_ZIP_EXPORT Q_DECL_IMPORT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef OSDAB_NAMESPACE
|
||||
#define OSDAB_BEGIN_NAMESPACE(ModuleName) namespace Osdab { namespace ModuleName {
|
||||
#define OSDAB_BEGIN_NAMESPACE(ModuleName) \
|
||||
namespace Osdab \
|
||||
{ \
|
||||
namespace ModuleName \
|
||||
{
|
||||
#else
|
||||
#define OSDAB_BEGIN_NAMESPACE(ModuleName)
|
||||
#endif
|
||||
|
||||
#ifdef OSDAB_NAMESPACE
|
||||
#define OSDAB_END_NAMESPACE } }
|
||||
#define OSDAB_END_NAMESPACE \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define OSDAB_END_NAMESPACE
|
||||
#endif
|
||||
|
|
@ -69,8 +75,8 @@
|
|||
OSDAB_BEGIN_NAMESPACE(Zip)
|
||||
|
||||
OSDAB_ZIP_EXPORT int OSDAB_ZIP_MANGLE(currentUtcOffset)();
|
||||
OSDAB_ZIP_EXPORT QDateTime OSDAB_ZIP_MANGLE(fromFileTimestamp)(const QDateTime& dateTime);
|
||||
OSDAB_ZIP_EXPORT bool OSDAB_ZIP_MANGLE(setFileTimestamp)(const QString& fileName, const QDateTime& dateTime);
|
||||
OSDAB_ZIP_EXPORT QDateTime OSDAB_ZIP_MANGLE(fromFileTimestamp)(const QDateTime &dateTime);
|
||||
OSDAB_ZIP_EXPORT bool OSDAB_ZIP_MANGLE(setFileTimestamp)(const QString &fileName, const QDateTime &dateTime);
|
||||
|
||||
OSDAB_END_NAMESPACE
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue