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 quint64 parseUi64(
const char *buffer)
76 const uint a = uint((uchar)buffer[0] | (uchar)buffer[1] << 8 | (uchar)buffer[2] << 16 | (uchar)buffer[3] << 24);
77 const uint b = uint((uchar)buffer[4] | (uchar)buffer[5] << 8 | (uchar)buffer[6] << 16 | (uchar)buffer[7] << 24);
78 return (a | (quint64)b << 32);
97 bool exttimestamp_seen;
99 bool newinfounix_seen;
103 quint64 uncompressedSize = 0;
104 quint64 compressedSize = 0;
111 , exttimestamp_seen(false)
112 , newinfounix_seen(false)
114 ctime = mtime = atime = time(
nullptr);
126static bool parseExtTimestamp(
const char *buffer,
int size,
bool islocal, ParseFileInfo &pfi)
141 pfi.mtime = uint((uchar)buffer[0] | (uchar)buffer[1] << 8 | (uchar)buffer[2] << 16 | (uchar)buffer[3] << 24);
148 pfi.exttimestamp_seen =
true;
157 pfi.atime = uint((uchar)buffer[0] | (uchar)buffer[1] << 8 | (uchar)buffer[2] << 16 | (uchar)buffer[3] << 24);
167 pfi.ctime = uint((uchar)buffer[0] | (uchar)buffer[1] << 8 | (uchar)buffer[2] << 16 | (uchar)buffer[3] << 24);
171 pfi.exttimestamp_seen =
true;
183static bool parseInfoZipUnixOld(
const char *buffer,
int size,
bool islocal, ParseFileInfo &pfi)
186 if (pfi.exttimestamp_seen || pfi.newinfounix_seen) {
195 pfi.atime = uint((uchar)buffer[0] | (uchar)buffer[1] << 8 | (uchar)buffer[2] << 16 | (uchar)buffer[3] << 24);
197 pfi.mtime = uint((uchar)buffer[0] | (uchar)buffer[1] << 8 | (uchar)buffer[2] << 16 | (uchar)buffer[3] << 24);
199 if (islocal && size >= 12) {
200 pfi.uid = (uchar)buffer[0] | (uchar)buffer[1] << 8;
202 pfi.gid = (uchar)buffer[0] | (uchar)buffer[1] << 8;
217static bool parseInfoZipUnixNew(
const char *buffer,
int size,
bool islocal,
221 pfi.newinfounix =
true;
226 qCDebug(KArchiveLog) <<
"premature end of Info-ZIP unix extra field new";
230 pfi.uid = (uchar)buffer[0] | (uchar)buffer[1] << 8;
232 pfi.gid = (uchar)buffer[0] | (uchar)buffer[1] << 8;
235 pfi.newinfounix =
true;
248static bool parseExtraField(
const char *buffer,
int size,
bool islocal, 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);
279 if (!parseExtTimestamp(buffer, fieldsize, islocal, pfi)) {
284 if (!parseInfoZipUnixOld(buffer, fieldsize, islocal, pfi)) {
290 if (!parseInfoZipUnixNew(buffer, fieldsize, islocal, pfi)) {
318static bool handlePossibleHeaderBegin(
const char *buffer,
QIODevice *dev,
bool dataDescriptor)
327 if (buffer[0] ==
'K') {
328 if (buffer[1] == 7 && buffer[2] == 8) {
335 && ((buffer[1] == 1 && buffer[2] == 2)
336 || (buffer[1] == 3 && buffer[2] == 4))) {
353static bool seekToNextHeaderToken(
QIODevice *dev,
bool dataDescriptor)
355 bool headerTokenFound =
false;
358 while (!headerTokenFound) {
359 int n = dev->
read(buffer, 1);
365 if (buffer[0] !=
'P') {
369 n = dev->
read(buffer, 3);
375 if (handlePossibleHeaderBegin(buffer, dev, dataDescriptor)) {
376 headerTokenFound =
true;
378 for (
int i = 0; i < 3; ++i) {
379 if (buffer[i] ==
'P') {
394class Q_DECL_HIDDEN
KZip::KZipPrivate
399 , m_currentFile(nullptr)
400 , m_currentDev(nullptr)
402 , m_extraField(
KZip::NoExtraField)
444 d->m_fileList.clear();
462 bool startOfFile =
true;
467 int n = dev->
read(buffer, 4);
470 setErrorString(tr(
"Invalid ZIP file. Unexpected end of file. (Error code: %1)").arg(1));
474 if (!memcmp(buffer,
"PK\5\6", 4)) {
480 if (!memcmp(buffer,
"PK\3\4", 4)) {
487 n = dev->
read(buffer, 24);
489 setErrorString(tr(
"Invalid ZIP file. Unexpected end of file. (Error code: %1)").arg(4));
493 int gpf = (uchar)buffer[0];
494 int compression_mode = (uchar)buffer[2] | (uchar)buffer[3] << 8;
495 uint mtime = transformFromMsDos(buffer + 4);
497 const qint64 compr_size = uint(uchar(buffer[12])) | uint(uchar(buffer[13])) << 8 | uint(uchar(buffer[14])) << 16 | uint(uchar(buffer[15])) << 24;
498 const qint64 uncomp_size = uint(uchar(buffer[16])) | uint(uchar(buffer[17])) << 8 | uint(uchar(buffer[18])) << 16 | uint(uchar(buffer[19])) << 24;
499 const int namelen = uint(uchar(buffer[20])) | uint(uchar(buffer[21])) << 8;
500 const int extralen = uint(uchar(buffer[22])) | uint(uchar(buffer[23])) << 8;
518 setErrorString(tr(
"Invalid ZIP file. Name not completely read (#2)"));
527 unsigned int extraFieldEnd = dev->
pos() + extralen;
528 pfi.extralen = extralen;
529 int handledextralen = qMin(extralen, (
int)
sizeof buffer);
534 n = dev->
read(buffer, handledextralen);
536 if (!parseExtraField(buffer, n,
true, pfi)) {
542 dev->
seek(extraFieldEnd);
550 if (!seekToNextHeaderToken(dev,
true)) {
557 bool foundSignature =
false;
560 && uncomp_size <= max_path_len
561 && uncomp_size > 0) {
564 pfi.guessed_symlink = dev->
read(uncomp_size);
565 if (pfi.guessed_symlink.
size() < uncomp_size) {
566 setErrorString(tr(
"Invalid ZIP file. Unexpected end of file. (#5)"));
570 if (compr_size > dev->
size()) {
573 if (!seekToNextHeaderToken(dev,
false)) {
577 foundSignature =
true;
580 const bool success = dev->
seek(dev->
pos() + compr_size);
593 if (!foundSignature) {
596 n = dev->
read(buffer, 4);
598 setErrorString(tr(
"Invalid ZIP file. Unexpected end of file. (#1)"));
602 if (buffer[0] !=
'P' || !handlePossibleHeaderBegin(buffer + 1, dev,
false)) {
615 }
else if (!memcmp(buffer,
"PK\1\2", 4)) {
622 offset = dev->
pos() - 4;
625 if (d->m_offset == 0) {
626 d->m_offset = offset;
629 n = dev->
read(buffer + 4, 42);
631 setErrorString(tr(
"Invalid ZIP file, central entry too short (not long enough for valid entry)"));
638 int namelen = (uchar)buffer[29] << 8 | (uchar)buffer[28];
640 setErrorString(tr(
"Invalid ZIP file, file path name length smaller or equal to zero"));
644 if (bufferName.
size() < namelen) {
648 ParseFileInfo pfi = pfi_map.
value(bufferName, ParseFileInfo());
655 int extralen = (uchar)buffer[31] << 8 | (uchar)buffer[30];
657 int commlen = (uchar)buffer[33] << 8 | (uchar)buffer[32];
659 int cmethod = (uchar)buffer[11] << 8 | (uchar)buffer[10];
665 uint crc32 = (uchar)buffer[19] << 24 | (uchar)buffer[18] << 16 | (uchar)buffer[17] << 8 | (uchar)buffer[16];
668 quint64 ucsize = uint32_t((uchar)buffer[27] << 24 | (uchar)buffer[26] << 16 | (uchar)buffer[25] << 8 | (uchar)buffer[24]);
669 if (ucsize == 0xFFFFFFFF) {
670 ucsize = pfi.uncompressedSize;
673 quint64 csize = uint32_t((uchar)buffer[23] << 24 | (uchar)buffer[22] << 16 | (uchar)buffer[21] << 8 | (uchar)buffer[20]);
674 if (csize == 0xFFFFFFFF) {
675 csize = pfi.compressedSize;
679 uint localheaderoffset = (uchar)buffer[45] << 24 | (uchar)buffer[44] << 16 | (uchar)buffer[43] << 8 | (uchar)buffer[42];
685 int localextralen = pfi.extralen;
691 uint dataoffset = localheaderoffset + 30 + localextralen + namelen;
695 int os_madeby = (uchar)buffer[5];
697 int access = 0100644;
699 if (os_madeby == 3) {
700 access = (uchar)buffer[40] | (uchar)buffer[41] << 8;
708 if (os_madeby != 3) {
709 access = S_IFDIR | 0755;
711 access |= S_IFDIR | 0700;
719 entryName = name.
mid(pos + 1);
734 QDateTime mtime = KArchivePrivate::time_tToDateTime(pfi.mtime);
740 if ((access & QT_STAT_MASK) == QT_STAT_LNK) {
743 QDateTime mtime = KArchivePrivate::time_tToDateTime(pfi.mtime);
745 new KZipFileEntry(
this, entryName, access, mtime,
rootDir()->user(),
rootDir()->group(), symlink, name, dataoffset, ucsize, cmethod, csize);
746 static_cast<KZipFileEntry *
>(entry)->setHeaderStart(localheaderoffset);
763 setErrorString(tr(
"File %1 is in folder %2, but %3 is actually a file.").arg(entryName, path, path));
771 offset += 46 + commlen + extralen + namelen;
772 const bool b = dev->
seek(offset);
777 }
else if (startOfFile) {
782 bool foundSignature =
false;
784 while (!foundSignature) {
785 n = dev->
read(buffer, 1);
791 if (buffer[0] !=
'P') {
795 n = dev->
read(buffer, 3);
806 if (buffer[0] ==
'K' && buffer[1] == 3 && buffer[2] == 4) {
807 foundSignature =
true;
810 for (
int i = 0; i < 3; ++i) {
811 if (buffer[i] ==
'P') {
820 setErrorString(tr(
"Invalid ZIP file. Unrecognized header at offset %1").arg(dev->
pos() - 4));
840 uLong crc = crc32(0L,
nullptr, 0);
842 qint64 centraldiroffset =
device()->
pos();
844 qint64 atbackup = centraldiroffset;
847 if (!
device()->seek(entry->headerStart() + 14)) {
855 uLong mycrc = entry->
crc32();
856 buffer[0] = char(mycrc);
857 buffer[1] = char(mycrc >> 8);
858 buffer[2] = char(mycrc >> 16);
859 buffer[3] = char(mycrc >> 24);
861 int mysize1 = entry->compressedSize();
862 buffer[4] = char(mysize1);
863 buffer[5] = char(mysize1 >> 8);
864 buffer[6] = char(mysize1 >> 16);
865 buffer[7] = char(mysize1 >> 24);
867 int myusize = entry->
size();
868 buffer[8] = char(myusize);
869 buffer[9] = char(myusize >> 8);
870 buffer[10] = char(myusize >> 16);
871 buffer[11] = char(myusize >> 24);
873 if (
device()->write(buffer, 12) != 12) {
887 const int bufferSize = extra_field_len + path.
length() + 46;
888 char *buffer =
new char[bufferSize];
890 memset(buffer, 0, 46);
893 const char head[] = {
902 memmove(buffer, head,
sizeof(head));
904 buffer[10] = char(entry->encoding());
905 buffer[11] = char(entry->encoding() >> 8);
907 transformToMsDos(entry->
date(), &buffer[12]);
909 uLong mycrc = entry->
crc32();
910 buffer[16] = char(mycrc);
911 buffer[17] = char(mycrc >> 8);
912 buffer[18] = char(mycrc >> 16);
913 buffer[19] = char(mycrc >> 24);
915 int mysize1 = entry->compressedSize();
916 buffer[20] = char(mysize1);
917 buffer[21] = char(mysize1 >> 8);
918 buffer[22] = char(mysize1 >> 16);
919 buffer[23] = char(mysize1 >> 24);
921 int mysize = entry->
size();
922 buffer[24] = char(mysize);
923 buffer[25] = char(mysize >> 8);
924 buffer[26] = char(mysize >> 16);
925 buffer[27] = char(mysize >> 24);
927 buffer[28] = char(path.
length());
928 buffer[29] = char(path.
length() >> 8);
930 buffer[30] = char(extra_field_len);
931 buffer[31] = char(extra_field_len >> 8);
936 int myhst = entry->headerStart();
937 buffer[42] = char(myhst);
938 buffer[43] = char(myhst >> 8);
939 buffer[44] = char(myhst >> 16);
940 buffer[45] = char(myhst >> 24);
948 char *extfield = buffer + 46 + path.
length();
954 extfield[4] = 1 | 2 | 4;
958 extfield[5] = char(time);
959 extfield[6] = char(time >> 8);
960 extfield[7] = char(time >> 16);
961 extfield[8] = char(time >> 24);
964 crc = crc32(crc, (Bytef *)buffer, bufferSize);
965 bool ok = (
device()->
write(buffer, bufferSize) == bufferSize);
972 qint64 centraldirendoffset =
device()->
pos();
988 int count = d->m_fileList.count();
991 buffer[8] = char(count);
992 buffer[9] = char(count >> 8);
994 buffer[10] = buffer[8];
995 buffer[11] = buffer[9];
997 int cdsize = centraldirendoffset - centraldiroffset;
998 buffer[12] = char(cdsize);
999 buffer[13] = char(cdsize >> 8);
1000 buffer[14] = char(cdsize >> 16);
1001 buffer[15] = char(cdsize >> 24);
1006 buffer[16] = char(centraldiroffset);
1007 buffer[17] = char(centraldiroffset >> 8);
1008 buffer[18] = char(centraldiroffset >> 16);
1009 buffer[19] = char(centraldiroffset >> 24);
1014 if (
device()->write(buffer, 22) != 22) {
1051 setErrorString(tr(
"Application error: ZIP file must be open before being written into"));
1052 qCWarning(KArchiveLog) <<
"doPrepareWriting failed: !isOpen()";
1057 setErrorString(tr(
"Application error: attempted to write into non-writable ZIP file"));
1058 qCWarning(KArchiveLog) <<
"doPrepareWriting failed: !(mode() & QIODevice::WriteOnly)";
1068 if (!
device()->seek(d->m_offset)) {
1093 for (
auto it = d->m_fileList.begin(); it != d->m_fileList.end();) {
1095 if (name == (*it)->path()) {
1100 it = d->m_fileList.erase(it);
1125 d->m_currentFile = e;
1126 d->m_fileList.append(e);
1128 int extra_field_len = 0;
1130 extra_field_len = 17;
1135 int bufferSize = extra_field_len + encodedName.
length() + 30;
1137 char *buffer =
new char[bufferSize];
1150 buffer[8] = char(e->encoding());
1151 buffer[9] = char(e->encoding() >> 8);
1153 transformToMsDos(e->
date(), &buffer[10]);
1170 buffer[26] = (uchar)(encodedName.
length());
1171 buffer[27] = (uchar)(encodedName.
length() >> 8);
1173 buffer[28] = (uchar)(extra_field_len);
1174 buffer[29] = (uchar)(extra_field_len >> 8);
1181 char *extfield = buffer + 30 + encodedName.
length();
1187 extfield[4] = 1 | 2 | 4;
1189 extfield[5] = char(mtime);
1190 extfield[6] = char(mtime >> 8);
1191 extfield[7] = char(mtime >> 16);
1192 extfield[8] = char(mtime >> 24);
1194 extfield[9] = char(atime);
1195 extfield[10] = char(atime >> 8);
1196 extfield[11] = char(atime >> 16);
1197 extfield[12] = char(atime >> 24);
1199 extfield[13] = char(ctime);
1200 extfield[14] = char(ctime >> 8);
1201 extfield[15] = char(ctime >> 16);
1202 extfield[16] = char(ctime >> 24);
1206 bool b = (
device()->
write(buffer, bufferSize) == bufferSize);
1211 setErrorString(tr(
"Could not write to the archive. Disk full?"));
1217 if (d->m_compression == 0) {
1218 d->m_currentDev =
device();
1223 d->m_currentDev = compressionDevice;
1224 compressionDevice->setSkipHeaders();
1230 setErrorString(tr(
"Could not open compression device: %1").arg(d->m_currentDev->errorString()));
1238 if (d->m_currentFile->encoding() == 8) {
1240 (void)d->m_currentDev->write(
nullptr, 0);
1241 delete d->m_currentDev;
1244 d->m_currentDev =
nullptr;
1246 Q_ASSERT(d->m_currentFile);
1249 d->m_currentFile->setSize(size);
1250 int extra_field_len = 0;
1252 extra_field_len = 17;
1256 int csize =
device()->
pos() - d->m_currentFile->headerStart() - 30 - encodedName.
length() - extra_field_len;
1257 d->m_currentFile->setCompressedSize(csize);
1263 d->m_currentFile->setCRC32(d->m_crc);
1265 d->m_currentFile =
nullptr;
1283 perm |= QT_STAT_LNK;
1307void KZip::virtual_hook(
int id,
void *data)
1309 KArchive::virtual_hook(
id, data);
1314 Q_ASSERT(d->m_currentFile);
1315 Q_ASSERT(d->m_currentDev);
1316 if (!d->m_currentFile || !d->m_currentDev) {
1323 d->m_crc = crc32(d->m_crc, (
const Bytef *)data, size);
1325 qint64 written = d->m_currentDev->write(data, size);
1327 const bool ok = written == size;
1330 setErrorString(tr(
"Error writing data: %1").arg(d->m_currentDev->errorString()));
1348 d->m_extraField = ef;
1353 return d->m_extraField;
1362 KZipFileEntryPrivate()
1370 qint64 compressedSize;
1385 qint64 uncompressedSize,
1387 qint64 compressedSize)
1388 :
KArchiveFile(zip, name, access, date, user, group, symlink,
start, uncompressedSize)
1389 , d(new KZipFileEntryPrivate)
1392 d->encoding = encoding;
1393 d->compressedSize = compressedSize;
1401int KZipFileEntry::encoding()
const
1406qint64 KZipFileEntry::compressedSize()
const
1408 return d->compressedSize;
1413 d->compressedSize = compressedSize;
1418 d->headerStart = headerstart;
1421qint64 KZipFileEntry::headerStart()
const
1423 return d->headerStart;
1431void KZipFileEntry::setCRC32(
unsigned long crc32)
1456 KLimitedIODevice *limitedDev =
new KLimitedIODevice(archive()->device(),
position(), compressedSize());
1457 if (encoding() == 0 || compressedSize() == 0) {
1461 if (encoding() == 8) {
1475 qCCritical(KArchiveLog) <<
"This zip file contains files compressed with method" << encoding() <<
", this method is currently not supported by KZip,"
1476 <<
"please use a command-line tool to handle this file.";
Represents a directory entry in a KArchive.
void addEntry(KArchiveEntry *)
void removeEntry(KArchiveEntry *)
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.
virtual bool isDirectory() const
Checks whether the entry is a directory.
QDateTime date() const
Creation date of the file.
Represents a file entry in a KArchive.
qint64 size() const
Size of the data.
qint64 position() const
Position of the data in the [uncompressed] archive.
KArchive is a base class for reading and writing archives.
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.
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 Q_NOREPLY void start()
QString path(const QString &relativePath)
const char * constData() const const
qsizetype length() const const
qsizetype size() 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
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
qsizetype size() const const