diff options
Diffstat (limited to 'rbutil/rbutilqt/quazip/quazipfileinfo.cpp')
-rw-r--r-- | rbutil/rbutilqt/quazip/quazipfileinfo.cpp | 146 |
1 files changed, 83 insertions, 63 deletions
diff --git a/rbutil/rbutilqt/quazip/quazipfileinfo.cpp b/rbutil/rbutilqt/quazip/quazipfileinfo.cpp index 1961f116b3..d5798ea771 100644 --- a/rbutil/rbutilqt/quazip/quazipfileinfo.cpp +++ b/rbutil/rbutilqt/quazip/quazipfileinfo.cpp @@ -24,6 +24,8 @@ see quazip/(un)zip.h files for details. Basically it's the zlib license. #include "quazipfileinfo.h" +#include <QtCore/QDataStream> + static QFile::Permissions permissionsFromExternalAttr(quint32 externalAttr) { quint32 uPerm = (externalAttr & 0xFFFF0000u) >> 16; QFile::Permissions perm = QFile::Permissions(); @@ -93,69 +95,30 @@ static QDateTime getNTFSTime(const QByteArray &extra, int position, int *fineTicks) { QDateTime dateTime; - 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 && length >= 32) { - 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; - int 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 - && tagsize >= position + 8) { - i += position; - quint64 mtime = static_cast<quint64>( - static_cast<unsigned char>(extra.at(i))) - | (static_cast<quint64>(static_cast<unsigned char>( - extra.at(i + 1))) << 8) - | (static_cast<quint64>(static_cast<unsigned char>( - extra.at(i + 2))) << 16) - | (static_cast<quint64>(static_cast<unsigned char>( - extra.at(i + 3))) << 24) - | (static_cast<quint64>(static_cast<unsigned char>( - extra.at(i + 4))) << 32) - | (static_cast<quint64>(static_cast<unsigned char>( - extra.at(i + 5))) << 40) - | (static_cast<quint64>(static_cast<unsigned char>( - extra.at(i + 6))) << 48) - | (static_cast<quint64>(static_cast<unsigned char>( - extra.at(i + 7))) << 56); - // the NTFS time is measured from 1601 for whatever reason - QDateTime base(QDate(1601, 1, 1), QTime(0, 0), Qt::UTC); - dateTime = base.addMSecs(mtime / 10000); - if (fineTicks != NULL) { - *fineTicks = static_cast<int>(mtime % 10000); - } - i += tagsize - position; - } else { - i += tagsize; - } - - } - } else { - i += length; - } - } - if (fineTicks != NULL && dateTime.isNull()) { - *fineTicks = 0; + QuaExtraFieldHash extraHash = QuaZipFileInfo64::parseExtraField(extra); + QList<QByteArray> ntfsExtraFields = extraHash[QUAZIP_EXTRA_NTFS_MAGIC]; + if (ntfsExtraFields.isEmpty()) + return dateTime; + QByteArray ntfsExtraField = ntfsExtraFields.at(0); + if (ntfsExtraField.length() <= 4) + return dateTime; + QByteArray ntfsAttributes = ntfsExtraField.mid(4); + QuaExtraFieldHash ntfsHash = QuaZipFileInfo64::parseExtraField(ntfsAttributes); + QList<QByteArray> ntfsTimeAttributes = ntfsHash[QUAZIP_EXTRA_NTFS_TIME_MAGIC]; + if (ntfsTimeAttributes.isEmpty()) + return dateTime; + QByteArray ntfsTimes = ntfsTimeAttributes.at(0); + if (ntfsTimes.size() < 24) + return dateTime; + QDataStream timeReader(ntfsTimes); + timeReader.setByteOrder(QDataStream::LittleEndian); + timeReader.device()->seek(position); + quint64 time; + timeReader >> time; + QDateTime base(QDate(1601, 1, 1), QTime(0, 0), Qt::UTC); + dateTime = base.addMSecs(time / 10000); + if (fineTicks != NULL) { + *fineTicks = static_cast<int>(time % 10000); } return dateTime; } @@ -174,3 +137,60 @@ QDateTime QuaZipFileInfo64::getNTFScTime(int *fineTicks) const { return getNTFSTime(extra, 16, fineTicks); } + +QDateTime QuaZipFileInfo64::getExtTime(const QByteArray &extra, int flag) +{ + QDateTime dateTime; + QuaExtraFieldHash extraHash = QuaZipFileInfo64::parseExtraField(extra); + QList<QByteArray> extTimeFields = extraHash[QUAZIP_EXTRA_EXT_TIME_MAGIC]; + if (extTimeFields.isEmpty()) + return dateTime; + QByteArray extTimeField = extTimeFields.at(0); + if (extTimeField.length() < 1) + return dateTime; + QDataStream input(extTimeField); + input.setByteOrder(QDataStream::LittleEndian); + quint8 flags; + input >> flags; + int flagsRemaining = flags; + while (!input.atEnd()) { + int nextFlag = flagsRemaining & -flagsRemaining; + flagsRemaining &= flagsRemaining - 1; + qint32 time; + input >> time; + if (nextFlag == flag) { + QDateTime base(QDate(1970, 1, 1), QTime(0, 0), Qt::UTC); + dateTime = base.addSecs(time); + return dateTime; + } + } + return dateTime; +} + +QDateTime QuaZipFileInfo64::getExtModTime() const +{ + return getExtTime(extra, 1); +} + +QuaExtraFieldHash QuaZipFileInfo64::parseExtraField(const QByteArray &extraField) +{ + QDataStream input(extraField); + input.setByteOrder(QDataStream::LittleEndian); + QHash<quint16, QList<QByteArray> > result; + while (!input.atEnd()) { + quint16 id, size; + input >> id; + if (input.status() == QDataStream::ReadPastEnd) + return result; + input >> size; + if (input.status() == QDataStream::ReadPastEnd) + return result; + QByteArray data; + data.resize(size); + int read = input.readRawData(data.data(), data.size()); + if (read < data.size()) + return result; + result[id] << data; + } + return result; +} |