1 /*
2 Copyright (C) 2005-2014 Sergey A. Tachenov
3 
4 This file is part of QuaZIP.
5 
6 QuaZIP is free software: you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation, either version 2.1 of the License, or
9 (at your option) any later version.
10 
11 QuaZIP is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU Lesser General Public License for more details.
15 
16 You should have received a copy of the GNU Lesser General Public License
17 along with QuaZIP.  If not, see <http://www.gnu.org/licenses/>.
18 
19 See COPYING file for the full LGPL text.
20 
21 Original ZIP package is copyrighted by Gilles Vollant and contributors,
22 see quazip/(un)zip.h files for details. Basically it's the zlib license.
23 */
24 
25 #include "quazipfileinfo.h"
26 
permissionsFromExternalAttr(quint32 externalAttr)27 static QFile::Permissions permissionsFromExternalAttr(quint32 externalAttr) {
28     quint32 uPerm = (externalAttr & 0xFFFF0000u) >> 16;
29     QFile::Permissions perm = 0;
30     if ((uPerm & 0400) != 0)
31         perm |= QFile::ReadOwner;
32     if ((uPerm & 0200) != 0)
33         perm |= QFile::WriteOwner;
34     if ((uPerm & 0100) != 0)
35         perm |= QFile::ExeOwner;
36     if ((uPerm & 0040) != 0)
37         perm |= QFile::ReadGroup;
38     if ((uPerm & 0020) != 0)
39         perm |= QFile::WriteGroup;
40     if ((uPerm & 0010) != 0)
41         perm |= QFile::ExeGroup;
42     if ((uPerm & 0004) != 0)
43         perm |= QFile::ReadOther;
44     if ((uPerm & 0002) != 0)
45         perm |= QFile::WriteOther;
46     if ((uPerm & 0001) != 0)
47         perm |= QFile::ExeOther;
48     return perm;
49 
50 }
51 
getPermissions() const52 QFile::Permissions QuaZipFileInfo::getPermissions() const
53 {
54     return permissionsFromExternalAttr(externalAttr);
55 }
56 
getPermissions() const57 QFile::Permissions QuaZipFileInfo64::getPermissions() const
58 {
59     return permissionsFromExternalAttr(externalAttr);
60 }
61 
toQuaZipFileInfo(QuaZipFileInfo & info) const62 bool QuaZipFileInfo64::toQuaZipFileInfo(QuaZipFileInfo &info) const
63 {
64     bool noOverflow = true;
65     info.name = name;
66     info.versionCreated = versionCreated;
67     info.versionNeeded = versionNeeded;
68     info.flags = flags;
69     info.method = method;
70     info.dateTime = dateTime;
71     info.crc = crc;
72     if (compressedSize > 0xFFFFFFFFu) {
73         info.compressedSize = 0xFFFFFFFFu;
74         noOverflow = false;
75     } else {
76         info.compressedSize = compressedSize;
77     }
78     if (uncompressedSize > 0xFFFFFFFFu) {
79         info.uncompressedSize = 0xFFFFFFFFu;
80         noOverflow = false;
81     } else {
82         info.uncompressedSize = uncompressedSize;
83     }
84     info.diskNumberStart = diskNumberStart;
85     info.internalAttr = internalAttr;
86     info.externalAttr = externalAttr;
87     info.comment = comment;
88     info.extra = extra;
89     return noOverflow;
90 }
91 
getNTFSTime(const QByteArray & extra,int position,int * fineTicks)92 static QDateTime getNTFSTime(const QByteArray &extra, int position,
93                              int *fineTicks)
94 {
95     QDateTime dateTime;
96     for (int i = 0; i <= extra.size() - 4; ) {
97         unsigned type = static_cast<unsigned>(static_cast<unsigned char>(
98                                                   extra.at(i)))
99                 | (static_cast<unsigned>(static_cast<unsigned char>(
100                                                   extra.at(i + 1))) << 8);
101         i += 2;
102         unsigned length = static_cast<unsigned>(static_cast<unsigned char>(
103                                                   extra.at(i)))
104                 | (static_cast<unsigned>(static_cast<unsigned char>(
105                                                   extra.at(i + 1))) << 8);
106         i += 2;
107         if (type == QUAZIP_EXTRA_NTFS_MAGIC && length >= 32) {
108             i += 4; // reserved
109             while (i <= extra.size() - 4) {
110                 unsigned tag = static_cast<unsigned>(
111                             static_cast<unsigned char>(extra.at(i)))
112                         | (static_cast<unsigned>(
113                                static_cast<unsigned char>(extra.at(i + 1)))
114                            << 8);
115                 i += 2;
116                 int tagsize = static_cast<unsigned>(
117                             static_cast<unsigned char>(extra.at(i)))
118                         | (static_cast<unsigned>(
119                                static_cast<unsigned char>(extra.at(i + 1)))
120                            << 8);
121                 i += 2;
122                 if (tag == QUAZIP_EXTRA_NTFS_TIME_MAGIC
123                         && tagsize >= position + 8) {
124                     i += position;
125                     quint64 mtime = static_cast<quint64>(
126                                 static_cast<unsigned char>(extra.at(i)))
127                         | (static_cast<quint64>(static_cast<unsigned char>(
128                                                  extra.at(i + 1))) << 8)
129                         | (static_cast<quint64>(static_cast<unsigned char>(
130                                                  extra.at(i + 2))) << 16)
131                         | (static_cast<quint64>(static_cast<unsigned char>(
132                                                  extra.at(i + 3))) << 24)
133                         | (static_cast<quint64>(static_cast<unsigned char>(
134                                                  extra.at(i + 4))) << 32)
135                         | (static_cast<quint64>(static_cast<unsigned char>(
136                                                  extra.at(i + 5))) << 40)
137                         | (static_cast<quint64>(static_cast<unsigned char>(
138                                                  extra.at(i + 6))) << 48)
139                         | (static_cast<quint64>(static_cast<unsigned char>(
140                                                  extra.at(i + 7))) << 56);
141                     // the NTFS time is measured from 1601 for whatever reason
142                     QDateTime base(QDate(1601, 1, 1), QTime(0, 0), Qt::UTC);
143                     dateTime = base.addMSecs(mtime / 10000);
144                     if (fineTicks != NULL) {
145                         *fineTicks = static_cast<int>(mtime % 10000);
146                     }
147                     i += tagsize - position;
148                 } else {
149                     i += tagsize;
150                 }
151 
152             }
153         } else {
154             i += length;
155         }
156     }
157     if (fineTicks != NULL && dateTime.isNull()) {
158         *fineTicks = 0;
159     }
160     return dateTime;
161 }
162 
getNTFSmTime(int * fineTicks) const163 QDateTime QuaZipFileInfo64::getNTFSmTime(int *fineTicks) const
164 {
165     return getNTFSTime(extra, 0, fineTicks);
166 }
167 
getNTFSaTime(int * fineTicks) const168 QDateTime QuaZipFileInfo64::getNTFSaTime(int *fineTicks) const
169 {
170     return getNTFSTime(extra, 8, fineTicks);
171 }
172 
getNTFScTime(int * fineTicks) const173 QDateTime QuaZipFileInfo64::getNTFScTime(int *fineTicks) const
174 {
175     return getNTFSTime(extra, 16, fineTicks);
176 }
177