10#include "kcompressiondevice.h"
11#include "klimitediodevice_p.h"
12#include "loggingcategory.h"
22#include <qplatformdefs.h>
29#define QT_STAT_LNK 0120000
32static const int max_path_len = 4095;
34static void transformToMsDos(
const QDateTime &_dt,
char *buffer)
38 const quint16 time = (dt.
time().hour() << 11)
39 | (dt.
time().minute() << 5)
40 | (dt.
time().second() >> 1);
43 buffer[0] = char(time);
44 buffer[1] = char(time >> 8);
47 const quint16 date = ((dt.
date().year() - 1980) << 9)
48 | (dt.
date().month() << 5)
52 buffer[2] = char(date);
53 buffer[3] = char(date >> 8);
56static uint transformFromMsDos(
const char *buffer)
58 quint16 time = (uchar)buffer[0] | ((uchar)buffer[1] << 8);
60 int m = (time & 0x7ff) >> 5;
61 int s = (time & 0x1f) * 2;
64 quint16 date = (uchar)buffer[2] | ((uchar)buffer[3] << 8);
65 int y = (date >> 9) + 1980;
66 int o = (date & 0x1ff) >> 5;
67 int d = (date & 0x1f);
74static uint parseUi32(
const char *buffer)
76 return uint((uchar)buffer[0] | (uchar)buffer[1] << 8 | (uchar)buffer[2] << 16 | (uchar)buffer[3] << 24);
79static quint64 parseUi64(
const char *buffer)
81 const uint a = uint((uchar)buffer[0] | (uchar)buffer[1] << 8 | (uchar)buffer[2] << 16 | (uchar)buffer[3] << 24);
82 const uint b = uint((uchar)buffer[4] | (uchar)buffer[5] << 8 | (uchar)buffer[6] << 16 | (uchar)buffer[7] << 24);
83 return (a | (quint64)b << 32);
98 QByteArray guessed_symlink;
102 bool exttimestamp_seen;
104 bool newinfounix_seen;
108 quint64 uncompressedSize = 0;
109 quint64 compressedSize = 0;
112 quint64 localheaderoffset = 0;
118 , exttimestamp_seen(false)
119 , newinfounix_seen(false)
121 ctime = mtime = atime = time(
nullptr);
133static bool parseExtTimestamp(
const char *buffer,
int size,
bool islocal, ParseFileInfo &pfi)
148 pfi.mtime = uint((uchar)buffer[0] | (uchar)buffer[1] << 8 | (uchar)buffer[2] << 16 | (uchar)buffer[3] << 24);
155 pfi.exttimestamp_seen =
true;
164 pfi.atime = uint((uchar)buffer[0] | (uchar)buffer[1] << 8 | (uchar)buffer[2] << 16 | (uchar)buffer[3] << 24);
174 pfi.ctime = uint((uchar)buffer[0] | (uchar)buffer[1] << 8 | (uchar)buffer[2] << 16 | (uchar)buffer[3] << 24);
178 pfi.exttimestamp_seen =
true;
190static bool parseInfoZipUnixOld(
const char *buffer,
int size,
bool islocal, ParseFileInfo &pfi)
193 if (pfi.exttimestamp_seen || pfi.newinfounix_seen) {
202 pfi.atime = uint((uchar)buffer[0] | (uchar)buffer[1] << 8 | (uchar)buffer[2] << 16 | (uchar)buffer[3] << 24);
204 pfi.mtime = uint((uchar)buffer[0] | (uchar)buffer[1] << 8 | (uchar)buffer[2] << 16 | (uchar)buffer[3] << 24);
206 if (islocal && size >= 12) {
207 pfi.uid = (uchar)buffer[0] | (uchar)buffer[1] << 8;
209 pfi.gid = (uchar)buffer[0] | (uchar)buffer[1] << 8;
224static bool parseInfoZipUnixNew(
const char *buffer,
int size,
bool islocal,
228 pfi.newinfounix =
true;
233 qCDebug(KArchiveLog) <<
"premature end of Info-ZIP unix extra field new";
237 pfi.uid = (uchar)buffer[0] | (uchar)buffer[1] << 8;
239 pfi.gid = (uchar)buffer[0] | (uchar)buffer[1] << 8;
242 pfi.newinfounix =
true;
254static bool parseExtraField(
const char *buffer,
int size, ParseFileInfo &pfi)
257 int magic = (uchar)buffer[0] | (uchar)buffer[1] << 8;
259 int fieldsize = (uchar)buffer[0] | (uchar)buffer[1] << 8;
263 if (fieldsize > size) {
272 pfi.uncompressedSize = parseUi64(buffer);
275 pfi.compressedSize = parseUi64(buffer + 8);
278 pfi.localheaderoffset = parseUi64(buffer + 16);
282 if (!parseExtTimestamp(buffer, fieldsize,
true, pfi)) {
287 if (!parseInfoZipUnixOld(buffer, fieldsize,
true, pfi)) {
293 if (!parseInfoZipUnixNew(buffer, fieldsize, islocal, pfi)) {
323 while (n >= minSize) {
326 if ((i + minSize) < n) {
331 n = dev->
peek(header.
data(), minSize);
336 dev->
seek(dev->
pos() + (n - 1));
352static bool seekPostDataDescriptor(
QIODevice *dev,
bool isZip64)
355 const qsizetype descriptorSize = isZip64 ? 24 : 16;
358 auto oldPos = dev->
pos();
360 while (seekAnyHeader(dev, header, descriptorSize)) {
363 qint64 compressedSize = isZip64 ? parseUi64(header.
constData() + 8)
364 : parseUi32(header.constData() + 8);
365 if (oldPos + compressedSize == dev->
pos()) {
366 dev->seek(dev->pos() + descriptorSize);
382static bool seekToNextHeaderToken(
QIODevice *dev)
386 while (seekAnyHeader(dev, header, 4)) {
403class Q_DECL_HIDDEN
KZip::KZipPrivate
408 , m_currentFile(nullptr)
409 , m_currentDev(nullptr)
411 , m_extraField(KZip::NoExtraField)
417 KZipFileEntry *m_currentFile;
418 QIODevice *m_currentDev;
419 QList<KZipFileEntry *> m_fileList;
428 quint64 m_startPos = 0;
455 d->m_fileList.clear();
472 bool startOfFile =
true;
474 qint64 expectedStartPos = 0;
479 int n = dev->
read(buffer, 4);
482 setErrorString(tr(
"Invalid ZIP file. Unexpected end of file. (Error code: %1)").arg(1));
486 if (!memcmp(buffer,
"PK\6\6", 4)) {
491 if (!memcmp(buffer,
"PK\5\6", 4)) {
497 if (!memcmp(buffer,
"PK\3\4", 4)) {
502 pfi.localheaderoffset = dev->
pos() - 4;
505 n = dev->
read(buffer, 26);
507 setErrorString(tr(
"Invalid ZIP file. Unexpected end of file. (Error code: %1)").arg(4));
510 int neededVersion = (uchar)buffer[0] | (uchar)buffer[1] << 8;
511 bool isZip64 = neededVersion >= 45;
513 int gpf = (uchar)buffer[2];
514 int compression_mode = (uchar)buffer[4] | (uchar)buffer[5] << 8;
515 uint mtime = transformFromMsDos(buffer + 6);
517 const qint64 compr_size = parseUi32(buffer + 14);
518 const qint64 uncomp_size = parseUi32(buffer + 18);
519 const int namelen = uint(uchar(buffer[22])) | uint(uchar(buffer[23])) << 8;
520 const int extralen = uint(uchar(buffer[24])) | uint(uchar(buffer[25])) << 8;
538 setErrorString(tr(
"Invalid ZIP file. Name not completely read (#2)"));
543 pfi.dataoffset = 30 + extralen + namelen;
547 unsigned int extraFieldEnd = dev->
pos() + extralen;
548 int handledextralen = qMin(extralen, (
int)
sizeof buffer);
553 n = dev->
read(buffer, handledextralen);
555 if (!parseExtraField(buffer, n, pfi)) {
561 dev->
seek(extraFieldEnd);
569 if (!seekPostDataDescriptor(dev, isZip64)) {
576 bool foundSignature =
false;
579 && uncomp_size <= max_path_len
580 && uncomp_size > 0) {
583 pfi.guessed_symlink = dev->
read(uncomp_size);
584 if (pfi.guessed_symlink.
size() < uncomp_size) {
585 setErrorString(tr(
"Invalid ZIP file. Unexpected end of file. (#5)"));
589 if (compr_size > dev->
size()) {
592 if (!seekToNextHeaderToken(dev)) {
596 foundSignature =
true;
599 const bool success = dev->
seek(dev->
pos() + compr_size);
612 if (!foundSignature) {
615 n = dev->
peek(buffer, 4);
617 setErrorString(tr(
"Invalid ZIP file. Unexpected end of file. (#1)"));
638 }
else if (!memcmp(buffer,
"PK\1\2", 4)) {
645 auto offset = dev->
pos() - 4;
648 if (d->m_offset == 0) {
649 d->m_offset = offset;
652 n = dev->
read(buffer + 4, 42);
654 setErrorString(tr(
"Invalid ZIP file, central entry too short (not long enough for valid entry)"));
659 int extralen = (uchar)buffer[31] << 8 | (uchar)buffer[30];
661 int commlen = (uchar)buffer[33] << 8 | (uchar)buffer[32];
663 int cmethod = (uchar)buffer[11] << 8 | (uchar)buffer[10];
667 int namelen = (uchar)buffer[29] << 8 | (uchar)buffer[28];
669 setErrorString(tr(
"Invalid ZIP file, file path name length is zero"));
674 ParseFileInfo extrafi;
676 parseExtraField(varData.
constData() + namelen, extralen, extrafi);
680 if (bufferName.
size() < namelen) {
684 ParseFileInfo pfi = pfi_map.
value(bufferName, ParseFileInfo());
694 uint crc32 = parseUi32(buffer + 16);
697 quint64 ucsize = parseUi32(buffer + 24);
698 if (ucsize == 0xFFFFFFFF) {
699 ucsize = extrafi.uncompressedSize;
702 quint64 csize = parseUi32(buffer + 20);
703 if (csize == 0xFFFFFFFF) {
704 csize = extrafi.compressedSize;
708 quint64 localheaderoffset = parseUi32(buffer + 42);
709 if (localheaderoffset == 0xFFFFFFFF) {
710 localheaderoffset = extrafi.localheaderoffset;
716 qint64 dataoffset = localheaderoffset + pfi.dataoffset;
717 if (pfi.localheaderoffset != expectedStartPos + localheaderoffset) {
718 if (pfi.localheaderoffset == d->m_startPos + localheaderoffset) {
719 qCDebug(KArchiveLog) <<
"warning:" << d->m_startPos <<
"extra bytes at beginning of zipfile";
720 expectedStartPos = d->m_startPos;
722 setErrorString(tr(
"Invalid ZIP file, inconsistent Local Header Offset in Central Directory at %1").arg(offset));
725 dataoffset = localheaderoffset + pfi.dataoffset + d->m_startPos;
730 int os_madeby = (uchar)buffer[5];
732 int access = 0100644;
734 if (os_madeby == 3) {
735 access = (uchar)buffer[40] | (uchar)buffer[41] << 8;
743 if (os_madeby != 3) {
744 access = S_IFDIR | 0755;
746 access |= S_IFDIR | 0700;
754 entryName = name.
mid(pos + 1);
769 QDateTime mtime = KArchivePrivate::time_tToDateTime(pfi.mtime);
775 if ((access & QT_STAT_MASK) == QT_STAT_LNK) {
778 QDateTime mtime = KArchivePrivate::time_tToDateTime(pfi.mtime);
780 new KZipFileEntry(
this, entryName, access, mtime,
rootDir()->user(),
rootDir()->group(), symlink, name, dataoffset, ucsize, cmethod, csize);
781 static_cast<KZipFileEntry *
>(entry)->setHeaderStart(localheaderoffset);
799 setErrorString(tr(
"File %1 is in folder %2, but %3 is actually a file.").arg(entryName, path, path));
807 offset += 46 + commlen + extralen + namelen;
808 const bool b = dev->
seek(offset);
813 }
else if (startOfFile) {
818 bool foundSignature =
false;
821 while (seekAnyHeader(dev, header, 4)) {
828 foundSignature =
true;
829 d->m_startPos = dev->
pos();
832 if (dev->
pos() > 4 * 1024 * 1024) {
838 if (!foundSignature) {
839 setErrorString(tr(
"Not a ZIP file, no Local File Header found."));
843 setErrorString(tr(
"Invalid ZIP file. Unrecognized header at offset %1").arg(dev->
pos() - 4));
863 uLong crc = crc32(0L,
nullptr, 0);
865 qint64 centraldiroffset =
device()->
pos();
867 qint64 atbackup = centraldiroffset;
870 if (!
device()->seek(entry->headerStart() + 14)) {
878 uLong mycrc = entry->
crc32();
879 buffer[0] = char(mycrc);
880 buffer[1] = char(mycrc >> 8);
881 buffer[2] = char(mycrc >> 16);
882 buffer[3] = char(mycrc >> 24);
884 int mysize1 = entry->compressedSize();
885 buffer[4] = char(mysize1);
886 buffer[5] = char(mysize1 >> 8);
887 buffer[6] = char(mysize1 >> 16);
888 buffer[7] = char(mysize1 >> 24);
890 int myusize = entry->
size();
891 buffer[8] = char(myusize);
892 buffer[9] = char(myusize >> 8);
893 buffer[10] = char(myusize >> 16);
894 buffer[11] = char(myusize >> 24);
896 if (
device()->write(buffer, 12) != 12) {
910 const int bufferSize = extra_field_len + path.
length() + 46;
911 char *buffer =
new char[bufferSize];
913 memset(buffer, 0, 46);
916 const char head[] = {
925 memmove(buffer, head,
sizeof(head));
927 buffer[10] = char(entry->encoding());
928 buffer[11] = char(entry->encoding() >> 8);
930 transformToMsDos(entry->
date(), &buffer[12]);
932 uLong mycrc = entry->
crc32();
933 buffer[16] = char(mycrc);
934 buffer[17] = char(mycrc >> 8);
935 buffer[18] = char(mycrc >> 16);
936 buffer[19] = char(mycrc >> 24);
938 int mysize1 = entry->compressedSize();
939 buffer[20] = char(mysize1);
940 buffer[21] = char(mysize1 >> 8);
941 buffer[22] = char(mysize1 >> 16);
942 buffer[23] = char(mysize1 >> 24);
944 int mysize = entry->
size();
945 buffer[24] = char(mysize);
946 buffer[25] = char(mysize >> 8);
947 buffer[26] = char(mysize >> 16);
948 buffer[27] = char(mysize >> 24);
950 buffer[28] = char(path.
length());
951 buffer[29] = char(path.
length() >> 8);
953 buffer[30] = char(extra_field_len);
954 buffer[31] = char(extra_field_len >> 8);
959 int myhst = entry->headerStart();
960 buffer[42] = char(myhst);
961 buffer[43] = char(myhst >> 8);
962 buffer[44] = char(myhst >> 16);
963 buffer[45] = char(myhst >> 24);
971 char *extfield = buffer + 46 + path.
length();
977 extfield[4] = 1 | 2 | 4;
981 extfield[5] = char(time);
982 extfield[6] = char(time >> 8);
983 extfield[7] = char(time >> 16);
984 extfield[8] = char(time >> 24);
987 crc = crc32(crc, (Bytef *)buffer, bufferSize);
988 bool ok = (
device()->
write(buffer, bufferSize) == bufferSize);
995 qint64 centraldirendoffset =
device()->
pos();
1011 int count = d->m_fileList.count();
1014 buffer[8] = char(count);
1015 buffer[9] = char(count >> 8);
1017 buffer[10] = buffer[8];
1018 buffer[11] = buffer[9];
1020 int cdsize = centraldirendoffset - centraldiroffset;
1021 buffer[12] = char(cdsize);
1022 buffer[13] = char(cdsize >> 8);
1023 buffer[14] = char(cdsize >> 16);
1024 buffer[15] = char(cdsize >> 24);
1029 buffer[16] = char(centraldiroffset);
1030 buffer[17] = char(centraldiroffset >> 8);
1031 buffer[18] = char(centraldiroffset >> 16);
1032 buffer[19] = char(centraldiroffset >> 24);
1037 if (
device()->write(buffer, 22) != 22) {
1074 setErrorString(tr(
"Application error: ZIP file must be open before being written into"));
1075 qCWarning(KArchiveLog) <<
"doPrepareWriting failed: !isOpen()";
1080 setErrorString(tr(
"Application error: attempted to write into non-writable ZIP file"));
1081 qCWarning(KArchiveLog) <<
"doPrepareWriting failed: !(mode() & QIODevice::WriteOnly)";
1091 if (!
device()->seek(d->m_offset)) {
1116 for (
auto it = d->m_fileList.begin(); it != d->m_fileList.end();) {
1118 if (name == (*it)->path()) {
1125 it = d->m_fileList.erase(it);
1150 d->m_currentFile = e;
1151 d->m_fileList.append(e);
1153 int extra_field_len = 0;
1155 extra_field_len = 17;
1160 int bufferSize = extra_field_len + encodedName.
length() + 30;
1162 char *buffer =
new char[bufferSize];
1175 buffer[8] = char(e->encoding());
1176 buffer[9] = char(e->encoding() >> 8);
1178 transformToMsDos(e->
date(), &buffer[10]);
1195 buffer[26] = (uchar)(encodedName.
length());
1196 buffer[27] = (uchar)(encodedName.
length() >> 8);
1198 buffer[28] = (uchar)(extra_field_len);
1199 buffer[29] = (uchar)(extra_field_len >> 8);
1206 char *extfield = buffer + 30 + encodedName.
length();
1212 extfield[4] = 1 | 2 | 4;
1214 extfield[5] = char(mtime);
1215 extfield[6] = char(mtime >> 8);
1216 extfield[7] = char(mtime >> 16);
1217 extfield[8] = char(mtime >> 24);
1219 extfield[9] = char(atime);
1220 extfield[10] = char(atime >> 8);
1221 extfield[11] = char(atime >> 16);
1222 extfield[12] = char(atime >> 24);
1224 extfield[13] = char(ctime);
1225 extfield[14] = char(ctime >> 8);
1226 extfield[15] = char(ctime >> 16);
1227 extfield[16] = char(ctime >> 24);
1231 bool b = (
device()->
write(buffer, bufferSize) == bufferSize);
1236 setErrorString(tr(
"Could not write to the archive. Disk full?"));
1242 if (d->m_compression == 0) {
1243 d->m_currentDev =
device();
1248 d->m_currentDev = compressionDevice;
1249 compressionDevice->setSkipHeaders();
1255 setErrorString(tr(
"Could not open compression device: %1").arg(d->m_currentDev->errorString()));
1263 if (d->m_currentFile->encoding() == 8) {
1265 (void)d->m_currentDev->write(
nullptr, 0);
1266 delete d->m_currentDev;
1269 d->m_currentDev =
nullptr;
1271 Q_ASSERT(d->m_currentFile);
1274 d->m_currentFile->setSize(size);
1275 int extra_field_len = 0;
1277 extra_field_len = 17;
1281 int csize =
device()->
pos() - d->m_currentFile->headerStart() - 30 - encodedName.
length() - extra_field_len;
1282 d->m_currentFile->setCompressedSize(csize);
1288 d->m_currentFile->setCRC32(d->m_crc);
1290 d->m_currentFile =
nullptr;
1308 perm |= QT_STAT_LNK;
1332void KZip::virtual_hook(
int id,
void *data)
1334 KArchive::virtual_hook(
id, data);
1339 Q_ASSERT(d->m_currentFile);
1340 Q_ASSERT(d->m_currentDev);
1341 if (!d->m_currentFile || !d->m_currentDev) {
1348 d->m_crc = crc32(d->m_crc, (
const Bytef *)data, size);
1350 qint64 written = d->m_currentDev->write(data, size);
1352 const bool ok = written == size;
1355 setErrorString(tr(
"Error writing data: %1").arg(d->m_currentDev->errorString()));
1373 d->m_extraField = ef;
1378 return d->m_extraField;
1387 KZipFileEntryPrivate()
1395 qint64 compressedSize;
1410 qint64 uncompressedSize,
1412 qint64 compressedSize)
1414 , d(new KZipFileEntryPrivate)
1417 d->encoding = encoding;
1418 d->compressedSize = compressedSize;
1426int KZipFileEntry::encoding()
const
1431qint64 KZipFileEntry::compressedSize()
const
1433 return d->compressedSize;
1438 d->compressedSize = compressedSize;
1443 d->headerStart = headerstart;
1446qint64 KZipFileEntry::headerStart()
const
1448 return d->headerStart;
1456void KZipFileEntry::setCRC32(
unsigned long crc32)
1481 KLimitedIODevice *limitedDev =
new KLimitedIODevice(archive()->device(),
position(), compressedSize());
1482 if (encoding() == 0 || compressedSize() == 0) {
1486 if (encoding() == 8) {
1500 qCCritical(KArchiveLog) <<
"This zip file contains files compressed with method" << encoding() <<
", this method is currently not supported by KZip,"
1501 <<
"please use a command-line tool to handle this file.";
Represents a directory entry in a KArchive.
bool removeEntryV2(KArchiveEntry *)
Removes an entry from the directory.
bool addEntryV2(KArchiveEntry *)
const KArchiveEntry * entry(const QString &name) const
Returns the entry in the archive with the given name.
A base class for entries in an KArchive.
mode_t permissions() const
The permissions and mode flags as returned by the stat() function in st_mode.
QString user() const
User who created the file.
virtual bool isDirectory() const
Checks whether the entry is a directory.
QDateTime date() const
Creation date of the file.
QString group() const
Group of the user who created the file.
QString name() const
Name of the file without path.
KArchiveFile(KArchive *archive, const QString &name, int access, const QDateTime &date, const QString &user, const QString &group, const QString &symlink, qint64 pos, qint64 size)
Creates a new file entry.
qint64 size() const
Size of the data.
qint64 position() const
Position of the data in the [uncompressed] archive.
QString errorString() const
Returns a description of the last error.
QIODevice * device() const
The underlying device.
virtual bool close()
Closes the archive.
virtual KArchiveDirectory * rootDir()
Retrieves or create the root directory.
bool finishWriting(qint64 size)
Call finishWriting after writing the data.
KArchive(const QString &fileName)
Base constructor (protected since this is a pure virtual class).
bool writeFile(const QString &name, QByteArrayView data, mode_t perm=0100644, const QString &user=QString(), const QString &group=QString(), const QDateTime &atime=QDateTime(), const QDateTime &mtime=QDateTime(), const QDateTime &ctime=QDateTime())
Writes a new file into the archive.
bool writeData(const char *data, qint64 size)
Write data into the current file - to be called after calling prepareWriting.
KArchiveDirectory * findOrCreate(const QString &path)
Ensures that path exists, create otherwise.
QIODevice::OpenMode mode() const
Returns the mode in which the archive was opened.
QString fileName() const
The name of the archive file, as passed to the constructor that takes a fileName, or an empty string ...
bool isOpen() const
Checks whether the archive is open.
void setErrorString(const QString &errorStr)
Sets error description.
A class for reading and writing compressed data onto a device (e.g.
void setSkipHeaders()
Call this let this device skip the gzip headers when reading/writing.
bool open(QIODevice::OpenMode mode) override
Open for reading or writing.
A KZipFileEntry represents a file in a zip archive.
KZipFileEntry(KZip *zip, const QString &name, int access, const QDateTime &date, const QString &user, const QString &group, const QString &symlink, const QString &path, qint64 start, qint64 uncompressedSize, int encoding, qint64 compressedSize)
Creates a new zip file entry.
~KZipFileEntry() override
Destructor.
void setCompressedSize(qint64 compressedSize)
Only used when writing.
unsigned long crc32() const
CRC: only used when writing.
const QString & path() const
Name with complete path - KArchiveFile::name() is the filename only (no path)
QIODevice * createDevice() const override
This method returns a QIODevice to read the file contents.
QByteArray data() const override
void setHeaderStart(qint64 headerstart)
Header start: only used when writing.
A class for reading / writing zip archives.
bool openArchive(QIODevice::OpenMode mode) override
Opens the archive for reading.
bool doWriteDir(const QString &name, const QString &user, const QString &group, mode_t perm, const QDateTime &atime, const QDateTime &mtime, const QDateTime &ctime) override
Reimplemented from KArchive.
void setCompression(Compression c)
Call this before writeFile or prepareWriting, to define whether the next files to be written should b...
ExtraField
Describes the contents of the "extra field" for a given file in the Zip archive.
@ ModificationTime
Modification time ("extended timestamp" header)
bool doPrepareWriting(const QString &name, const QString &user, const QString &group, qint64 size, mode_t perm, const QDateTime &atime, const QDateTime &mtime, const QDateTime &creationTime) override
Reimplemented from KArchive.
void setExtraField(ExtraField ef)
Call this before writeFile or prepareWriting, to define what the next file to be written should have ...
KZip(const QString &filename)
Creates an instance that operates on the given filename.
bool doFinishWriting(qint64 size) override
Write data to a file that has been created using prepareWriting().
~KZip() override
If the zip file is still opened, then it will be closed automatically by the destructor.
bool closeArchive() override
Closes the archive.
Compression
Describes the compression type for a given file in the Zip archive.
@ DeflateCompression
Deflate compression method.
@ NoCompression
Uncompressed.
Compression compression() const
The current compression mode that will be used for new files.
bool doWriteSymLink(const QString &name, const QString &target, const QString &user, const QString &group, mode_t perm, const QDateTime &atime, const QDateTime &mtime, const QDateTime &ctime) override
Reimplemented from KArchive.
bool doWriteData(const char *data, qint64 size) override
Write data to a file that has been created using prepareWriting().
ExtraField extraField() const
The current type of "extra field" that will be used for new files.
Q_SCRIPTABLE QString start(QString train="")
QString path(const QString &relativePath)
const char * constData() const const
qsizetype length() const const
QByteArray & remove(qsizetype pos, qsizetype len)
void resize(qsizetype newSize, char c)
qsizetype size() const const
bool startsWith(QByteArrayView bv) const const
qsizetype indexOf(QByteArrayView bv, qsizetype from) const const
bool startsWith(QByteArrayView bv) const const
QDateTime currentDateTime()
bool isValid() const const
qint64 toSecsSinceEpoch() const const
QString cleanPath(const QString &path)
QString decodeName(const QByteArray &localFileName)
QByteArray encodeName(const QString &fileName)
iterator insert(const Key &key, const T &value)
T value(const Key &key) const const
QByteArray peek(qint64 maxSize)
virtual qint64 pos() const const
QByteArray read(qint64 maxSize)
virtual bool seek(qint64 pos)
virtual qint64 size() const const
qint64 write(const QByteArray &data)
QString & append(QChar ch)
const QChar * constData() const const
bool endsWith(QChar c, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
qsizetype lastIndexOf(QChar ch, Qt::CaseSensitivity cs) const const
QString left(qsizetype n) const const
qsizetype length() const const
QString mid(qsizetype position, qsizetype n) const const