diff options
| author | Tomasz Sterna <tomek@xiaoka.com> | 2015-01-05 17:19:18 +0100 |
|---|---|---|
| committer | Tomasz Sterna <tomek@xiaoka.com> | 2015-01-05 17:19:18 +0100 |
| commit | a55f8f218ea9b52e97b9b7de1ac43502ce8c9994 (patch) | |
| tree | f9574bc9c52ba0e36916298942bbf958ddda1fb8 /daemon/quazip/quazipnewinfo.cpp | |
| parent | eac37967cc535a3ac43a712b52b4bf73b96ec19c (diff) | |
Imported QuaZIP library to daemon sources
Diffstat (limited to 'daemon/quazip/quazipnewinfo.cpp')
| -rw-r--r-- | daemon/quazip/quazipnewinfo.cpp | 277 |
1 files changed, 277 insertions, 0 deletions
diff --git a/daemon/quazip/quazipnewinfo.cpp b/daemon/quazip/quazipnewinfo.cpp new file mode 100644 index 0000000..db6c70a --- /dev/null +++ b/daemon/quazip/quazipnewinfo.cpp @@ -0,0 +1,277 @@ +/* +Copyright (C) 2005-2014 Sergey A. Tachenov + +This file is part of QuaZIP. + +QuaZIP is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +QuaZIP is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with QuaZIP. If not, see <http://www.gnu.org/licenses/>. + +See COPYING file for the full LGPL text. + +Original ZIP package is copyrighted by Gilles Vollant and contributors, +see quazip/(un)zip.h files for details. Basically it's the zlib license. +*/ + +#include <QFileInfo> + +#include "quazipnewinfo.h" + +#include <string.h> + +static void QuaZipNewInfo_setPermissions(QuaZipNewInfo *info, + QFile::Permissions perm, bool isDir) +{ + quint32 uPerm = isDir ? 0040000 : 0100000; + if ((perm & QFile::ReadOwner) != 0) + uPerm |= 0400; + if ((perm & QFile::WriteOwner) != 0) + uPerm |= 0200; + if ((perm & QFile::ExeOwner) != 0) + uPerm |= 0100; + if ((perm & QFile::ReadGroup) != 0) + uPerm |= 0040; + if ((perm & QFile::WriteGroup) != 0) + uPerm |= 0020; + if ((perm & QFile::ExeGroup) != 0) + uPerm |= 0010; + if ((perm & QFile::ReadOther) != 0) + uPerm |= 0004; + if ((perm & QFile::WriteOther) != 0) + uPerm |= 0002; + if ((perm & QFile::ExeOther) != 0) + uPerm |= 0001; + info->externalAttr = (info->externalAttr & ~0xFFFF0000u) | (uPerm << 16); +} + +template<typename FileInfo> +void QuaZipNewInfo_init(QuaZipNewInfo &self, const FileInfo &existing) +{ + self.name = existing.name; + self.dateTime = existing.dateTime; + self.internalAttr = existing.internalAttr; + self.externalAttr = existing.externalAttr; + self.comment = existing.comment; + self.extraLocal = existing.extra; + self.extraGlobal = existing.extra; + self.uncompressedSize = existing.uncompressedSize; +} + +QuaZipNewInfo::QuaZipNewInfo(const QuaZipFileInfo &existing) +{ + QuaZipNewInfo_init(*this, existing); +} + +QuaZipNewInfo::QuaZipNewInfo(const QuaZipFileInfo64 &existing) +{ + QuaZipNewInfo_init(*this, existing); +} + +QuaZipNewInfo::QuaZipNewInfo(const QString& name): + name(name), dateTime(QDateTime::currentDateTime()), internalAttr(0), externalAttr(0), + uncompressedSize(0) +{ +} + +QuaZipNewInfo::QuaZipNewInfo(const QString& name, const QString& file): + name(name), internalAttr(0), externalAttr(0), uncompressedSize(0) +{ + QFileInfo info(file); + QDateTime lm = info.lastModified(); + if (!info.exists()) { + dateTime = QDateTime::currentDateTime(); + } else { + dateTime = lm; + QuaZipNewInfo_setPermissions(this, info.permissions(), info.isDir()); + } +} + +void QuaZipNewInfo::setFileDateTime(const QString& file) +{ + QFileInfo info(file); + QDateTime lm = info.lastModified(); + if (info.exists()) + dateTime = lm; +} + +void QuaZipNewInfo::setFilePermissions(const QString &file) +{ + QFileInfo info = QFileInfo(file); + QFile::Permissions perm = info.permissions(); + QuaZipNewInfo_setPermissions(this, perm, info.isDir()); +} + +void QuaZipNewInfo::setPermissions(QFile::Permissions permissions) +{ + QuaZipNewInfo_setPermissions(this, permissions, name.endsWith('/')); +} + +void QuaZipNewInfo::setFileNTFSTimes(const QString &fileName) +{ + QFileInfo fi(fileName); + if (!fi.exists()) { + qWarning("QuaZipNewInfo::setFileNTFSTimes(): '%s' doesn't exist", + fileName.toUtf8().constData()); + return; + } + setFileNTFSmTime(fi.lastModified()); + setFileNTFSaTime(fi.lastRead()); + setFileNTFScTime(fi.created()); +} + +static void setNTFSTime(QByteArray &extra, const QDateTime &time, int position, + int fineTicks) { + int ntfsPos = -1, timesPos = -1; + unsigned ntfsLength = 0, ntfsTimesLength = 0; + for (int i = 0; i <= extra.size() - 4; ) { + unsigned type = static_cast<unsigned>(static_cast<unsigned char>( + extra.at(i))) + | (static_cast<unsigned>(static_cast<unsigned char>( + extra.at(i + 1))) << 8); + i += 2; + unsigned length = static_cast<unsigned>(static_cast<unsigned char>( + extra.at(i))) + | (static_cast<unsigned>(static_cast<unsigned char>( + extra.at(i + 1))) << 8); + i += 2; + if (type == QUAZIP_EXTRA_NTFS_MAGIC) { + ntfsPos = i - 4; // the beginning of the NTFS record + ntfsLength = length; + if (length <= 4) { + break; // no times in the NTFS record + } + i += 4; // reserved + while (i <= extra.size() - 4) { + unsigned tag = static_cast<unsigned>( + static_cast<unsigned char>(extra.at(i))) + | (static_cast<unsigned>( + static_cast<unsigned char>(extra.at(i + 1))) + << 8); + i += 2; + unsigned tagsize = static_cast<unsigned>( + static_cast<unsigned char>(extra.at(i))) + | (static_cast<unsigned>( + static_cast<unsigned char>(extra.at(i + 1))) + << 8); + i += 2; + if (tag == QUAZIP_EXTRA_NTFS_TIME_MAGIC) { + timesPos = i - 4; // the beginning of the NTFS times tag + ntfsTimesLength = tagsize; + break; + } else { + i += tagsize; + } + } + break; // I ain't going to search for yet another NTFS record! + } else { + i += length; + } + } + if (ntfsPos == -1) { + // No NTFS record, need to create one. + ntfsPos = extra.size(); + ntfsLength = 32; + extra.resize(extra.size() + 4 + ntfsLength); + // the NTFS record header + extra[ntfsPos] = static_cast<char>(QUAZIP_EXTRA_NTFS_MAGIC); + extra[ntfsPos + 1] = static_cast<char>(QUAZIP_EXTRA_NTFS_MAGIC >> 8); + extra[ntfsPos + 2] = 32; // the 2-byte size in LittleEndian + extra[ntfsPos + 3] = 0; + // zero the record + memset(extra.data() + ntfsPos + 4, 0, 32); + timesPos = ntfsPos + 8; + // now set the tag data + extra[timesPos] = static_cast<char>(QUAZIP_EXTRA_NTFS_TIME_MAGIC); + extra[timesPos + 1] = static_cast<char>(QUAZIP_EXTRA_NTFS_TIME_MAGIC + >> 8); + // the size: + extra[timesPos + 2] = 24; + extra[timesPos + 3] = 0; + ntfsTimesLength = 24; + } + if (timesPos == -1) { + // No time tag in the NTFS record, need to add one. + timesPos = ntfsPos + 4 + ntfsLength; + extra.resize(extra.size() + 28); + // Now we need to move the rest of the field + // (possibly zero bytes, but memmove() is OK with that). + // 0 ......... ntfsPos .. ntfsPos + 4 ... timesPos + // <some data> <header> <NTFS record> <need-to-move data> <end> + memmove(extra.data() + timesPos + 28, extra.data() + timesPos, + extra.size() - 28 - timesPos); + ntfsLength += 28; + // now set the tag data + extra[timesPos] = static_cast<char>(QUAZIP_EXTRA_NTFS_TIME_MAGIC); + extra[timesPos + 1] = static_cast<char>(QUAZIP_EXTRA_NTFS_TIME_MAGIC + >> 8); + // the size: + extra[timesPos + 2] = 24; + extra[timesPos + 3] = 0; + // zero the record + memset(extra.data() + timesPos + 4, 0, 24); + ntfsTimesLength = 24; + } + if (ntfsTimesLength < 24) { + // Broken times field. OK, this is really unlikely, but just in case... + size_t timesEnd = timesPos + 4 + ntfsTimesLength; + extra.resize(extra.size() + (24 - ntfsTimesLength)); + // Move it! + // 0 ......... timesPos .... timesPos + 4 .. timesEnd + // <some data> <time header> <broken times> <need-to-move data> <end> + memmove(extra.data() + timesEnd + (24 - ntfsTimesLength), + extra.data() + timesEnd, + extra.size() - (24 - ntfsTimesLength) - timesEnd); + // Now we have to increase the NTFS record and time tag lengths. + ntfsLength += (24 - ntfsTimesLength); + ntfsTimesLength = 24; + extra[ntfsPos + 2] = static_cast<char>(ntfsLength); + extra[ntfsPos + 3] = static_cast<char>(ntfsLength >> 8); + extra[timesPos + 2] = static_cast<char>(ntfsTimesLength); + extra[timesPos + 3] = static_cast<char>(ntfsTimesLength >> 8); + } + QDateTime base(QDate(1601, 1, 1), QTime(0, 0), Qt::UTC); +#if (QT_VERSION >= 0x040700) + quint64 ticks = base.msecsTo(time) * 10000 + fineTicks; +#else + QDateTime utc = time.toUTC(); + quint64 ticks = (static_cast<qint64>(base.date().daysTo(utc.date())) + * Q_INT64_C(86400000) + + static_cast<qint64>(base.time().msecsTo(utc.time()))) + * Q_INT64_C(10000) + fineTicks; +#endif + extra[timesPos + 4 + position] = static_cast<char>(ticks); + extra[timesPos + 5 + position] = static_cast<char>(ticks >> 8); + extra[timesPos + 6 + position] = static_cast<char>(ticks >> 16); + extra[timesPos + 7 + position] = static_cast<char>(ticks >> 24); + extra[timesPos + 8 + position] = static_cast<char>(ticks >> 32); + extra[timesPos + 9 + position] = static_cast<char>(ticks >> 40); + extra[timesPos + 10 + position] = static_cast<char>(ticks >> 48); + extra[timesPos + 11 + position] = static_cast<char>(ticks >> 56); +} + +void QuaZipNewInfo::setFileNTFSmTime(const QDateTime &mTime, int fineTicks) +{ + setNTFSTime(extraLocal, mTime, 0, fineTicks); + setNTFSTime(extraGlobal, mTime, 0, fineTicks); +} + +void QuaZipNewInfo::setFileNTFSaTime(const QDateTime &aTime, int fineTicks) +{ + setNTFSTime(extraLocal, aTime, 8, fineTicks); + setNTFSTime(extraGlobal, aTime, 8, fineTicks); +} + +void QuaZipNewInfo::setFileNTFScTime(const QDateTime &cTime, int fineTicks) +{ + setNTFSTime(extraLocal, cTime, 16, fineTicks); + setNTFSTime(extraGlobal, cTime, 16, fineTicks); +} |
