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);
90 bool exttimestamp_seen;
92 bool newinfounix_seen;
96 quint64 uncompressedSize = 0;
97 quint64 compressedSize = 0;
104 , exttimestamp_seen(false)
105 , newinfounix_seen(false)
107 ctime = mtime = atime = time(
nullptr);
119static bool parseExtTimestamp(
const char *buffer,
int size,
bool islocal, ParseFileInfo &pfi)
134 pfi.mtime = uint((uchar)buffer[0] | (uchar)buffer[1] << 8 | (uchar)buffer[2] << 16 | (uchar)buffer[3] << 24);
141 pfi.exttimestamp_seen =
true;
150 pfi.atime = uint((uchar)buffer[0] | (uchar)buffer[1] << 8 | (uchar)buffer[2] << 16 | (uchar)buffer[3] << 24);
160 pfi.ctime = uint((uchar)buffer[0] | (uchar)buffer[1] << 8 | (uchar)buffer[2] << 16 | (uchar)buffer[3] << 24);
164 pfi.exttimestamp_seen =
true;
176static bool parseInfoZipUnixOld(
const char *buffer,
int size,
bool islocal, ParseFileInfo &pfi)
179 if (pfi.exttimestamp_seen || pfi.newinfounix_seen) {
188 pfi.atime = uint((uchar)buffer[0] | (uchar)buffer[1] << 8 | (uchar)buffer[2] << 16 | (uchar)buffer[3] << 24);
190 pfi.mtime = uint((uchar)buffer[0] | (uchar)buffer[1] << 8 | (uchar)buffer[2] << 16 | (uchar)buffer[3] << 24);
192 if (islocal && size >= 12) {
193 pfi.uid = (uchar)buffer[0] | (uchar)buffer[1] << 8;
195 pfi.gid = (uchar)buffer[0] | (uchar)buffer[1] << 8;
210static bool parseInfoZipUnixNew(
const char *buffer,
int size,
bool islocal,
214 pfi.newinfounix =
true;
219 qCDebug(KArchiveLog) <<
"premature end of Info-ZIP unix extra field new";
223 pfi.uid = (uchar)buffer[0] | (uchar)buffer[1] << 8;
225 pfi.gid = (uchar)buffer[0] | (uchar)buffer[1] << 8;
228 pfi.newinfounix =
true;
241static bool parseExtraField(
const char *buffer,
int size,
bool islocal, ParseFileInfo &pfi)
250 int magic = (uchar)buffer[0] | (uchar)buffer[1] << 8;
252 int fieldsize = (uchar)buffer[0] | (uchar)buffer[1] << 8;
256 if (fieldsize > size) {
265 pfi.uncompressedSize = qFromLittleEndian(*
reinterpret_cast<const quint64 *
>(buffer));
268 pfi.compressedSize = qFromLittleEndian(*
reinterpret_cast<const quint64 *
>(buffer + 8));
272 if (!parseExtTimestamp(buffer, fieldsize, islocal, pfi)) {
277 if (!parseInfoZipUnixOld(buffer, fieldsize, islocal, pfi)) {
283 if (!parseInfoZipUnixNew(buffer, fieldsize, islocal, pfi)) {
311static bool handlePossibleHeaderBegin(
const char *buffer,
QIODevice *dev,
bool dataDescriptor)
320 if (buffer[0] ==
'K') {
321 if (buffer[1] == 7 && buffer[2] == 8) {
328 && ((buffer[1] == 1 && buffer[2] == 2)
329 || (buffer[1] == 3 && buffer[2] == 4))) {
346static bool seekToNextHeaderToken(
QIODevice *dev,
bool dataDescriptor)
348 bool headerTokenFound =
false;
351 while (!headerTokenFound) {
352 int n = dev->
read(buffer, 1);
358 if (buffer[0] !=
'P') {
362 n = dev->
read(buffer, 3);
368 if (handlePossibleHeaderBegin(buffer, dev, dataDescriptor)) {
369 headerTokenFound =
true;
371 for (
int i = 0; i < 3; ++i) {
372 if (buffer[i] ==
'P') {
387class Q_DECL_HIDDEN
KZip::KZipPrivate
392 , m_currentFile(nullptr)
393 , m_currentDev(nullptr)
395 , m_extraField(
KZip::NoExtraField)
437 d->m_fileList.clear();
455 bool startOfFile =
true;
460 int n = dev->
read(buffer, 4);
463 setErrorString(tr(
"Invalid ZIP file. Unexpected end of file. (Error code: %1)").arg(1));
467 if (!memcmp(buffer,
"PK\5\6", 4)) {
473 if (!memcmp(buffer,
"PK\3\4", 4)) {
480 n = dev->
read(buffer, 24);
482 setErrorString(tr(
"Invalid ZIP file. Unexpected end of file. (Error code: %1)").arg(4));
486 int gpf = (uchar)buffer[0];
487 int compression_mode = (uchar)buffer[2] | (uchar)buffer[3] << 8;
488 uint mtime = transformFromMsDos(buffer + 4);
490 const qint64 compr_size = uint(uchar(buffer[12])) | uint(uchar(buffer[13])) << 8 | uint(uchar(buffer[14])) << 16 | uint(uchar(buffer[15])) << 24;
491 const qint64 uncomp_size = uint(uchar(buffer[16])) | uint(uchar(buffer[17])) << 8 | uint(uchar(buffer[18])) << 16 | uint(uchar(buffer[19])) << 24;
492 const int namelen = uint(uchar(buffer[20])) | uint(uchar(buffer[21])) << 8;
493 const int extralen = uint(uchar(buffer[22])) | uint(uchar(buffer[23])) << 8;
511 setErrorString(tr(
"Invalid ZIP file. Name not completely read (#2)"));
520 unsigned int extraFieldEnd = dev->
pos() + extralen;
521 pfi.extralen = extralen;
522 int handledextralen = qMin(extralen, (
int)
sizeof buffer);
527 n = dev->
read(buffer, handledextralen);
529 if (!parseExtraField(buffer, n,
true, pfi)) {
535 dev->
seek(extraFieldEnd);
543 if (!seekToNextHeaderToken(dev,
true)) {
550 bool foundSignature =
false;
553 && uncomp_size <= max_path_len
554 && uncomp_size > 0) {
557 pfi.guessed_symlink = dev->
read(uncomp_size);
558 if (pfi.guessed_symlink.
size() < uncomp_size) {
559 setErrorString(tr(
"Invalid ZIP file. Unexpected end of file. (#5)"));
563 if (compr_size > dev->
size()) {
566 if (!seekToNextHeaderToken(dev,
false)) {
570 foundSignature =
true;
573 const bool success = dev->
seek(dev->
pos() + compr_size);
586 if (!foundSignature) {
589 n = dev->
read(buffer, 4);
591 setErrorString(tr(
"Invalid ZIP file. Unexpected end of file. (#1)"));
595 if (buffer[0] !=
'P' || !handlePossibleHeaderBegin(buffer + 1, dev,
false)) {
608 }
else if (!memcmp(buffer,
"PK\1\2", 4)) {
615 offset = dev->
pos() - 4;
618 if (d->m_offset == 0) {
619 d->m_offset = offset;
622 n = dev->
read(buffer + 4, 42);
624 setErrorString(tr(
"Invalid ZIP file, central entry too short (not long enough for valid entry)"));
631 int namelen = (uchar)buffer[29] << 8 | (uchar)buffer[28];
633 setErrorString(tr(
"Invalid ZIP file, file path name length smaller or equal to zero"));
637 if (bufferName.
size() < namelen) {
641 ParseFileInfo pfi = pfi_map.
value(bufferName, ParseFileInfo());
648 int extralen = (uchar)buffer[31] << 8 | (uchar)buffer[30];
650 int commlen = (uchar)buffer[33] << 8 | (uchar)buffer[32];
652 int cmethod = (uchar)buffer[11] << 8 | (uchar)buffer[10];
658 uint crc32 = (uchar)buffer[19] << 24 | (uchar)buffer[18] << 16 | (uchar)buffer[17] << 8 | (uchar)buffer[16];
661 quint64 ucsize = uint32_t((uchar)buffer[27] << 24 | (uchar)buffer[26] << 16 | (uchar)buffer[25] << 8 | (uchar)buffer[24]);
662 if (ucsize == 0xFFFFFFFF) {
663 ucsize = pfi.uncompressedSize;
666 quint64 csize = uint32_t((uchar)buffer[23] << 24 | (uchar)buffer[22] << 16 | (uchar)buffer[21] << 8 | (uchar)buffer[20]);
667 if (csize == 0xFFFFFFFF) {
668 csize = pfi.compressedSize;
672 uint localheaderoffset = (uchar)buffer[45] << 24 | (uchar)buffer[44] << 16 | (uchar)buffer[43] << 8 | (uchar)buffer[42];
678 int localextralen = pfi.extralen;
684 uint dataoffset = localheaderoffset + 30 + localextralen + namelen;
688 int os_madeby = (uchar)buffer[5];
690 int access = 0100644;
692 if (os_madeby == 3) {
693 access = (uchar)buffer[40] | (uchar)buffer[41] << 8;
701 if (os_madeby != 3) {
702 access = S_IFDIR | 0755;
704 access |= S_IFDIR | 0700;
712 entryName = name.
mid(pos + 1);
727 QDateTime mtime = KArchivePrivate::time_tToDateTime(pfi.mtime);
733 if ((access & QT_STAT_MASK) == QT_STAT_LNK) {
736 QDateTime mtime = KArchivePrivate::time_tToDateTime(pfi.mtime);
738 new KZipFileEntry(
this, entryName, access, mtime,
rootDir()->user(),
rootDir()->group(), symlink, name, dataoffset, ucsize, cmethod, csize);
739 static_cast<KZipFileEntry *
>(entry)->setHeaderStart(localheaderoffset);
756 setErrorString(tr(
"File %1 is in folder %2, but %3 is actually a file.").arg(entryName, path, path));
764 offset += 46 + commlen + extralen + namelen;
765 const bool b = dev->
seek(offset);
770 }
else if (startOfFile) {
775 bool foundSignature =
false;
777 while (!foundSignature) {
778 n = dev->
read(buffer, 1);
784 if (buffer[0] !=
'P') {
788 n = dev->
read(buffer, 3);
799 if (buffer[0] ==
'K' && buffer[1] == 3 && buffer[2] == 4) {
800 foundSignature =
true;
803 for (
int i = 0; i < 3; ++i) {
804 if (buffer[i] ==
'P') {
813 setErrorString(tr(
"Invalid ZIP file. Unrecognized header at offset %1").arg(dev->
pos() - 4));
833 uLong crc = crc32(0L,
nullptr, 0);
835 qint64 centraldiroffset =
device()->
pos();
837 qint64 atbackup = centraldiroffset;
840 if (!
device()->seek(entry->headerStart() + 14)) {
848 uLong mycrc = entry->
crc32();
849 buffer[0] = char(mycrc);
850 buffer[1] = char(mycrc >> 8);
851 buffer[2] = char(mycrc >> 16);
852 buffer[3] = char(mycrc >> 24);
854 int mysize1 = entry->compressedSize();
855 buffer[4] = char(mysize1);
856 buffer[5] = char(mysize1 >> 8);
857 buffer[6] = char(mysize1 >> 16);
858 buffer[7] = char(mysize1 >> 24);
860 int myusize = entry->
size();
861 buffer[8] = char(myusize);
862 buffer[9] = char(myusize >> 8);
863 buffer[10] = char(myusize >> 16);
864 buffer[11] = char(myusize >> 24);
866 if (
device()->write(buffer, 12) != 12) {
880 const int bufferSize = extra_field_len + path.
length() + 46;
881 char *buffer =
new char[bufferSize];
883 memset(buffer, 0, 46);
886 const char head[] = {
895 memmove(buffer, head,
sizeof(head));
897 buffer[10] = char(entry->encoding());
898 buffer[11] = char(entry->encoding() >> 8);
900 transformToMsDos(entry->
date(), &buffer[12]);
902 uLong mycrc = entry->
crc32();
903 buffer[16] = char(mycrc);
904 buffer[17] = char(mycrc >> 8);
905 buffer[18] = char(mycrc >> 16);
906 buffer[19] = char(mycrc >> 24);
908 int mysize1 = entry->compressedSize();
909 buffer[20] = char(mysize1);
910 buffer[21] = char(mysize1 >> 8);
911 buffer[22] = char(mysize1 >> 16);
912 buffer[23] = char(mysize1 >> 24);
914 int mysize = entry->
size();
915 buffer[24] = char(mysize);
916 buffer[25] = char(mysize >> 8);
917 buffer[26] = char(mysize >> 16);
918 buffer[27] = char(mysize >> 24);
920 buffer[28] = char(path.
length());
921 buffer[29] = char(path.
length() >> 8);
923 buffer[30] = char(extra_field_len);
924 buffer[31] = char(extra_field_len >> 8);
929 int myhst = entry->headerStart();
930 buffer[42] = char(myhst);
931 buffer[43] = char(myhst >> 8);
932 buffer[44] = char(myhst >> 16);
933 buffer[45] = char(myhst >> 24);
941 char *extfield = buffer + 46 + path.
length();
947 extfield[4] = 1 | 2 | 4;
951 extfield[5] = char(time);
952 extfield[6] = char(time >> 8);
953 extfield[7] = char(time >> 16);
954 extfield[8] = char(time >> 24);
957 crc = crc32(crc, (Bytef *)buffer, bufferSize);
958 bool ok = (
device()->
write(buffer, bufferSize) == bufferSize);
965 qint64 centraldirendoffset =
device()->
pos();
981 int count = d->m_fileList.count();
984 buffer[8] = char(count);
985 buffer[9] = char(count >> 8);
987 buffer[10] = buffer[8];
988 buffer[11] = buffer[9];
990 int cdsize = centraldirendoffset - centraldiroffset;
991 buffer[12] = char(cdsize);
992 buffer[13] = char(cdsize >> 8);
993 buffer[14] = char(cdsize >> 16);
994 buffer[15] = char(cdsize >> 24);
999 buffer[16] = char(centraldiroffset);
1000 buffer[17] = char(centraldiroffset >> 8);
1001 buffer[18] = char(centraldiroffset >> 16);
1002 buffer[19] = char(centraldiroffset >> 24);
1007 if (
device()->write(buffer, 22) != 22) {
1044 setErrorString(tr(
"Application error: ZIP file must be open before being written into"));
1045 qCWarning(KArchiveLog) <<
"doPrepareWriting failed: !isOpen()";
1050 setErrorString(tr(
"Application error: attempted to write into non-writable ZIP file"));
1051 qCWarning(KArchiveLog) <<
"doPrepareWriting failed: !(mode() & QIODevice::WriteOnly)";
1061 if (!
device()->seek(d->m_offset)) {
1086 for (
auto it = d->m_fileList.begin(); it != d->m_fileList.end();) {
1088 if (name == (*it)->path()) {
1093 it = d->m_fileList.erase(it);
1118 d->m_currentFile = e;
1119 d->m_fileList.append(e);
1121 int extra_field_len = 0;
1123 extra_field_len = 17;
1128 int bufferSize = extra_field_len + encodedName.
length() + 30;
1130 char *buffer =
new char[bufferSize];
1143 buffer[8] = char(e->encoding());
1144 buffer[9] = char(e->encoding() >> 8);
1146 transformToMsDos(e->
date(), &buffer[10]);
1163 buffer[26] = (uchar)(encodedName.
length());
1164 buffer[27] = (uchar)(encodedName.
length() >> 8);
1166 buffer[28] = (uchar)(extra_field_len);
1167 buffer[29] = (uchar)(extra_field_len >> 8);
1174 char *extfield = buffer + 30 + encodedName.
length();
1180 extfield[4] = 1 | 2 | 4;
1182 extfield[5] = char(mtime);
1183 extfield[6] = char(mtime >> 8);
1184 extfield[7] = char(mtime >> 16);
1185 extfield[8] = char(mtime >> 24);
1187 extfield[9] = char(atime);
1188 extfield[10] = char(atime >> 8);
1189 extfield[11] = char(atime >> 16);
1190 extfield[12] = char(atime >> 24);
1192 extfield[13] = char(ctime);
1193 extfield[14] = char(ctime >> 8);
1194 extfield[15] = char(ctime >> 16);
1195 extfield[16] = char(ctime >> 24);
1199 bool b = (
device()->
write(buffer, bufferSize) == bufferSize);
1204 setErrorString(tr(
"Could not write to the archive. Disk full?"));
1210 if (d->m_compression == 0) {
1211 d->m_currentDev =
device();
1216 d->m_currentDev = compressionDevice;
1217 compressionDevice->setSkipHeaders();
1223 setErrorString(tr(
"Could not open compression device: %1").arg(d->m_currentDev->errorString()));
1231 if (d->m_currentFile->encoding() == 8) {
1233 (void)d->m_currentDev->write(
nullptr, 0);
1234 delete d->m_currentDev;
1237 d->m_currentDev =
nullptr;
1239 Q_ASSERT(d->m_currentFile);
1242 d->m_currentFile->setSize(size);
1243 int extra_field_len = 0;
1245 extra_field_len = 17;
1249 int csize =
device()->
pos() - d->m_currentFile->headerStart() - 30 - encodedName.
length() - extra_field_len;
1250 d->m_currentFile->setCompressedSize(csize);
1256 d->m_currentFile->setCRC32(d->m_crc);
1258 d->m_currentFile =
nullptr;
1276 perm |= QT_STAT_LNK;
1300void KZip::virtual_hook(
int id,
void *data)
1302 KArchive::virtual_hook(
id, data);
1307 Q_ASSERT(d->m_currentFile);
1308 Q_ASSERT(d->m_currentDev);
1309 if (!d->m_currentFile || !d->m_currentDev) {
1316 d->m_crc = crc32(d->m_crc, (
const Bytef *)data, size);
1318 qint64 written = d->m_currentDev->write(data, size);
1320 const bool ok = written == size;
1323 setErrorString(tr(
"Error writing data: %1").arg(d->m_currentDev->errorString()));
1341 d->m_extraField = ef;
1346 return d->m_extraField;
1355 KZipFileEntryPrivate()
1363 qint64 compressedSize;
1378 qint64 uncompressedSize,
1380 qint64 compressedSize)
1381 :
KArchiveFile(zip, name, access, date, user, group, symlink,
start, uncompressedSize)
1382 , d(new KZipFileEntryPrivate)
1385 d->encoding = encoding;
1386 d->compressedSize = compressedSize;
1394int KZipFileEntry::encoding()
const
1399qint64 KZipFileEntry::compressedSize()
const
1401 return d->compressedSize;
1406 d->compressedSize = compressedSize;
1411 d->headerStart = headerstart;
1414qint64 KZipFileEntry::headerStart()
const
1416 return d->headerStart;
1424void KZipFileEntry::setCRC32(
unsigned long crc32)
1449 KLimitedIODevice *limitedDev =
new KLimitedIODevice(archive()->device(),
position(), compressedSize());
1450 if (encoding() == 0 || compressedSize() == 0) {
1454 if (encoding() == 8) {
1468 qCCritical(KArchiveLog) <<
"This zip file contains files compressed with method" << encoding() <<
", this method is currently not supported by KZip,"
1469 <<
"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