source: Vago/quazip-0.7.2/quazip/quazipnewinfo.cpp@ 1089

Last change on this file since 1089 was 1049, checked in by s10k, 8 years ago
File size: 10.6 KB
RevLine 
[1049]1/*
2Copyright (C) 2005-2014 Sergey A. Tachenov
3
4This file is part of QuaZIP.
5
6QuaZIP is free software: you can redistribute it and/or modify
7it under the terms of the GNU Lesser General Public License as published by
8the Free Software Foundation, either version 2.1 of the License, or
9(at your option) any later version.
10
11QuaZIP is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU Lesser General Public License for more details.
15
16You should have received a copy of the GNU Lesser General Public License
17along with QuaZIP. If not, see <http://www.gnu.org/licenses/>.
18
19See COPYING file for the full LGPL text.
20
21Original ZIP package is copyrighted by Gilles Vollant and contributors,
22see quazip/(un)zip.h files for details. Basically it's the zlib license.
23*/
24
25#include <QFileInfo>
26
27#include "quazipnewinfo.h"
28
29#include <string.h>
30
31static void QuaZipNewInfo_setPermissions(QuaZipNewInfo *info,
32 QFile::Permissions perm, bool isDir)
33{
34 quint32 uPerm = isDir ? 0040000 : 0100000;
35 if ((perm & QFile::ReadOwner) != 0)
36 uPerm |= 0400;
37 if ((perm & QFile::WriteOwner) != 0)
38 uPerm |= 0200;
39 if ((perm & QFile::ExeOwner) != 0)
40 uPerm |= 0100;
41 if ((perm & QFile::ReadGroup) != 0)
42 uPerm |= 0040;
43 if ((perm & QFile::WriteGroup) != 0)
44 uPerm |= 0020;
45 if ((perm & QFile::ExeGroup) != 0)
46 uPerm |= 0010;
47 if ((perm & QFile::ReadOther) != 0)
48 uPerm |= 0004;
49 if ((perm & QFile::WriteOther) != 0)
50 uPerm |= 0002;
51 if ((perm & QFile::ExeOther) != 0)
52 uPerm |= 0001;
53 info->externalAttr = (info->externalAttr & ~0xFFFF0000u) | (uPerm << 16);
54}
55
56template<typename FileInfo>
57void QuaZipNewInfo_init(QuaZipNewInfo &self, const FileInfo &existing)
58{
59 self.name = existing.name;
60 self.dateTime = existing.dateTime;
61 self.internalAttr = existing.internalAttr;
62 self.externalAttr = existing.externalAttr;
63 self.comment = existing.comment;
64 self.extraLocal = existing.extra;
65 self.extraGlobal = existing.extra;
66 self.uncompressedSize = existing.uncompressedSize;
67}
68
69QuaZipNewInfo::QuaZipNewInfo(const QuaZipFileInfo &existing)
70{
71 QuaZipNewInfo_init(*this, existing);
72}
73
74QuaZipNewInfo::QuaZipNewInfo(const QuaZipFileInfo64 &existing)
75{
76 QuaZipNewInfo_init(*this, existing);
77}
78
79QuaZipNewInfo::QuaZipNewInfo(const QString& name):
80 name(name), dateTime(QDateTime::currentDateTime()), internalAttr(0), externalAttr(0),
81 uncompressedSize(0)
82{
83}
84
85QuaZipNewInfo::QuaZipNewInfo(const QString& name, const QString& file):
86 name(name), internalAttr(0), externalAttr(0), uncompressedSize(0)
87{
88 QFileInfo info(file);
89 QDateTime lm = info.lastModified();
90 if (!info.exists()) {
91 dateTime = QDateTime::currentDateTime();
92 } else {
93 dateTime = lm;
94 QuaZipNewInfo_setPermissions(this, info.permissions(), info.isDir());
95 }
96}
97
98void QuaZipNewInfo::setFileDateTime(const QString& file)
99{
100 QFileInfo info(file);
101 QDateTime lm = info.lastModified();
102 if (info.exists())
103 dateTime = lm;
104}
105
106void QuaZipNewInfo::setFilePermissions(const QString &file)
107{
108 QFileInfo info = QFileInfo(file);
109 QFile::Permissions perm = info.permissions();
110 QuaZipNewInfo_setPermissions(this, perm, info.isDir());
111}
112
113void QuaZipNewInfo::setPermissions(QFile::Permissions permissions)
114{
115 QuaZipNewInfo_setPermissions(this, permissions, name.endsWith('/'));
116}
117
118void QuaZipNewInfo::setFileNTFSTimes(const QString &fileName)
119{
120 QFileInfo fi(fileName);
121 if (!fi.exists()) {
122 qWarning("QuaZipNewInfo::setFileNTFSTimes(): '%s' doesn't exist",
123 fileName.toUtf8().constData());
124 return;
125 }
126 setFileNTFSmTime(fi.lastModified());
127 setFileNTFSaTime(fi.lastRead());
128 setFileNTFScTime(fi.created());
129}
130
131static void setNTFSTime(QByteArray &extra, const QDateTime &time, int position,
132 int fineTicks) {
133 int ntfsPos = -1, timesPos = -1;
134 unsigned ntfsLength = 0, ntfsTimesLength = 0;
135 for (int i = 0; i <= extra.size() - 4; ) {
136 unsigned type = static_cast<unsigned>(static_cast<unsigned char>(
137 extra.at(i)))
138 | (static_cast<unsigned>(static_cast<unsigned char>(
139 extra.at(i + 1))) << 8);
140 i += 2;
141 unsigned length = static_cast<unsigned>(static_cast<unsigned char>(
142 extra.at(i)))
143 | (static_cast<unsigned>(static_cast<unsigned char>(
144 extra.at(i + 1))) << 8);
145 i += 2;
146 if (type == QUAZIP_EXTRA_NTFS_MAGIC) {
147 ntfsPos = i - 4; // the beginning of the NTFS record
148 ntfsLength = length;
149 if (length <= 4) {
150 break; // no times in the NTFS record
151 }
152 i += 4; // reserved
153 while (i <= extra.size() - 4) {
154 unsigned tag = static_cast<unsigned>(
155 static_cast<unsigned char>(extra.at(i)))
156 | (static_cast<unsigned>(
157 static_cast<unsigned char>(extra.at(i + 1)))
158 << 8);
159 i += 2;
160 unsigned tagsize = static_cast<unsigned>(
161 static_cast<unsigned char>(extra.at(i)))
162 | (static_cast<unsigned>(
163 static_cast<unsigned char>(extra.at(i + 1)))
164 << 8);
165 i += 2;
166 if (tag == QUAZIP_EXTRA_NTFS_TIME_MAGIC) {
167 timesPos = i - 4; // the beginning of the NTFS times tag
168 ntfsTimesLength = tagsize;
169 break;
170 } else {
171 i += tagsize;
172 }
173 }
174 break; // I ain't going to search for yet another NTFS record!
175 } else {
176 i += length;
177 }
178 }
179 if (ntfsPos == -1) {
180 // No NTFS record, need to create one.
181 ntfsPos = extra.size();
182 ntfsLength = 32;
183 extra.resize(extra.size() + 4 + ntfsLength);
184 // the NTFS record header
185 extra[ntfsPos] = static_cast<char>(QUAZIP_EXTRA_NTFS_MAGIC);
186 extra[ntfsPos + 1] = static_cast<char>(QUAZIP_EXTRA_NTFS_MAGIC >> 8);
187 extra[ntfsPos + 2] = 32; // the 2-byte size in LittleEndian
188 extra[ntfsPos + 3] = 0;
189 // zero the record
190 memset(extra.data() + ntfsPos + 4, 0, 32);
191 timesPos = ntfsPos + 8;
192 // now set the tag data
193 extra[timesPos] = static_cast<char>(QUAZIP_EXTRA_NTFS_TIME_MAGIC);
194 extra[timesPos + 1] = static_cast<char>(QUAZIP_EXTRA_NTFS_TIME_MAGIC
195 >> 8);
196 // the size:
197 extra[timesPos + 2] = 24;
198 extra[timesPos + 3] = 0;
199 ntfsTimesLength = 24;
200 }
201 if (timesPos == -1) {
202 // No time tag in the NTFS record, need to add one.
203 timesPos = ntfsPos + 4 + ntfsLength;
204 extra.resize(extra.size() + 28);
205 // Now we need to move the rest of the field
206 // (possibly zero bytes, but memmove() is OK with that).
207 // 0 ......... ntfsPos .. ntfsPos + 4 ... timesPos
208 // <some data> <header> <NTFS record> <need-to-move data> <end>
209 memmove(extra.data() + timesPos + 28, extra.data() + timesPos,
210 extra.size() - 28 - timesPos);
211 ntfsLength += 28;
212 // now set the tag data
213 extra[timesPos] = static_cast<char>(QUAZIP_EXTRA_NTFS_TIME_MAGIC);
214 extra[timesPos + 1] = static_cast<char>(QUAZIP_EXTRA_NTFS_TIME_MAGIC
215 >> 8);
216 // the size:
217 extra[timesPos + 2] = 24;
218 extra[timesPos + 3] = 0;
219 // zero the record
220 memset(extra.data() + timesPos + 4, 0, 24);
221 ntfsTimesLength = 24;
222 }
223 if (ntfsTimesLength < 24) {
224 // Broken times field. OK, this is really unlikely, but just in case...
225 size_t timesEnd = timesPos + 4 + ntfsTimesLength;
226 extra.resize(extra.size() + (24 - ntfsTimesLength));
227 // Move it!
228 // 0 ......... timesPos .... timesPos + 4 .. timesEnd
229 // <some data> <time header> <broken times> <need-to-move data> <end>
230 memmove(extra.data() + timesEnd + (24 - ntfsTimesLength),
231 extra.data() + timesEnd,
232 extra.size() - (24 - ntfsTimesLength) - timesEnd);
233 // Now we have to increase the NTFS record and time tag lengths.
234 ntfsLength += (24 - ntfsTimesLength);
235 ntfsTimesLength = 24;
236 extra[ntfsPos + 2] = static_cast<char>(ntfsLength);
237 extra[ntfsPos + 3] = static_cast<char>(ntfsLength >> 8);
238 extra[timesPos + 2] = static_cast<char>(ntfsTimesLength);
239 extra[timesPos + 3] = static_cast<char>(ntfsTimesLength >> 8);
240 }
241 QDateTime base(QDate(1601, 1, 1), QTime(0, 0), Qt::UTC);
242#if (QT_VERSION >= 0x040700)
243 quint64 ticks = base.msecsTo(time) * 10000 + fineTicks;
244#else
245 QDateTime utc = time.toUTC();
246 quint64 ticks = (static_cast<qint64>(base.date().daysTo(utc.date()))
247 * Q_INT64_C(86400000)
248 + static_cast<qint64>(base.time().msecsTo(utc.time())))
249 * Q_INT64_C(10000) + fineTicks;
250#endif
251 extra[timesPos + 4 + position] = static_cast<char>(ticks);
252 extra[timesPos + 5 + position] = static_cast<char>(ticks >> 8);
253 extra[timesPos + 6 + position] = static_cast<char>(ticks >> 16);
254 extra[timesPos + 7 + position] = static_cast<char>(ticks >> 24);
255 extra[timesPos + 8 + position] = static_cast<char>(ticks >> 32);
256 extra[timesPos + 9 + position] = static_cast<char>(ticks >> 40);
257 extra[timesPos + 10 + position] = static_cast<char>(ticks >> 48);
258 extra[timesPos + 11 + position] = static_cast<char>(ticks >> 56);
259}
260
261void QuaZipNewInfo::setFileNTFSmTime(const QDateTime &mTime, int fineTicks)
262{
263 setNTFSTime(extraLocal, mTime, 0, fineTicks);
264 setNTFSTime(extraGlobal, mTime, 0, fineTicks);
265}
266
267void QuaZipNewInfo::setFileNTFSaTime(const QDateTime &aTime, int fineTicks)
268{
269 setNTFSTime(extraLocal, aTime, 8, fineTicks);
270 setNTFSTime(extraGlobal, aTime, 8, fineTicks);
271}
272
273void QuaZipNewInfo::setFileNTFScTime(const QDateTime &cTime, int fineTicks)
274{
275 setNTFSTime(extraLocal, cTime, 16, fineTicks);
276 setNTFSTime(extraGlobal, cTime, 16, fineTicks);
277}
Note: See TracBrowser for help on using the repository browser.