summaryrefslogtreecommitdiff
path: root/utils/rbutilqt/quazip/quazipnewinfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/rbutilqt/quazip/quazipnewinfo.cpp')
-rw-r--r--utils/rbutilqt/quazip/quazipnewinfo.cpp290
1 files changed, 290 insertions, 0 deletions
diff --git a/utils/rbutilqt/quazip/quazipnewinfo.cpp b/utils/rbutilqt/quazip/quazipnewinfo.cpp
new file mode 100644
index 0000000000..98630e086a
--- /dev/null
+++ b/utils/rbutilqt/quazip/quazipnewinfo.cpp
@@ -0,0 +1,290 @@
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 <QtCore/QFileInfo>
26
27#include "quazipnewinfo.h"
28
29#include <string.h>
30
31static void QuaZipNewInfo_setPermissions(QuaZipNewInfo *info,
32 QFile::Permissions perm, bool isDir, bool isSymLink = false)
33{
34 quint32 uPerm = isDir ? 0040000 : 0100000;
35
36 if ( isSymLink ) {
37#ifdef Q_OS_WIN
38 uPerm = 0200000;
39#else
40 uPerm = 0120000;
41#endif
42 }
43
44 if ((perm & QFile::ReadOwner) != 0)
45 uPerm |= 0400;
46 if ((perm & QFile::WriteOwner) != 0)
47 uPerm |= 0200;
48 if ((perm & QFile::ExeOwner) != 0)
49 uPerm |= 0100;
50 if ((perm & QFile::ReadGroup) != 0)
51 uPerm |= 0040;
52 if ((perm & QFile::WriteGroup) != 0)
53 uPerm |= 0020;
54 if ((perm & QFile::ExeGroup) != 0)
55 uPerm |= 0010;
56 if ((perm & QFile::ReadOther) != 0)
57 uPerm |= 0004;
58 if ((perm & QFile::WriteOther) != 0)
59 uPerm |= 0002;
60 if ((perm & QFile::ExeOther) != 0)
61 uPerm |= 0001;
62 info->externalAttr = (info->externalAttr & ~0xFFFF0000u) | (uPerm << 16);
63}
64
65template<typename FileInfo>
66void QuaZipNewInfo_init(QuaZipNewInfo &self, const FileInfo &existing)
67{
68 self.name = existing.name;
69 self.dateTime = existing.dateTime;
70 self.internalAttr = existing.internalAttr;
71 self.externalAttr = existing.externalAttr;
72 self.comment = existing.comment;
73 self.extraLocal = existing.extra;
74 self.extraGlobal = existing.extra;
75 self.uncompressedSize = existing.uncompressedSize;
76}
77
78QuaZipNewInfo::QuaZipNewInfo(const QuaZipFileInfo &existing)
79{
80 QuaZipNewInfo_init(*this, existing);
81}
82
83QuaZipNewInfo::QuaZipNewInfo(const QuaZipFileInfo64 &existing)
84{
85 QuaZipNewInfo_init(*this, existing);
86}
87
88QuaZipNewInfo::QuaZipNewInfo(const QString& name):
89 name(name), dateTime(QDateTime::currentDateTime()), internalAttr(0), externalAttr(0),
90 uncompressedSize(0)
91{
92}
93
94QuaZipNewInfo::QuaZipNewInfo(const QString& name, const QString& file):
95 name(name), internalAttr(0), externalAttr(0), uncompressedSize(0)
96{
97 QFileInfo info(file);
98 QDateTime lm = info.lastModified();
99 if (!info.exists()) {
100 dateTime = QDateTime::currentDateTime();
101 } else {
102 dateTime = lm;
103 QuaZipNewInfo_setPermissions(this, info.permissions(), info.isDir(), info.isSymLink());
104 }
105}
106
107void QuaZipNewInfo::setFileDateTime(const QString& file)
108{
109 QFileInfo info(file);
110 QDateTime lm = info.lastModified();
111 if (info.exists())
112 dateTime = lm;
113}
114
115void QuaZipNewInfo::setFilePermissions(const QString &file)
116{
117 QFileInfo info = QFileInfo(file);
118 QFile::Permissions perm = info.permissions();
119 QuaZipNewInfo_setPermissions(this, perm, info.isDir(), info.isSymLink());
120}
121
122void QuaZipNewInfo::setPermissions(QFile::Permissions permissions)
123{
124 QuaZipNewInfo_setPermissions(this, permissions, name.endsWith(QLatin1String("/")));
125}
126
127void QuaZipNewInfo::setFileNTFSTimes(const QString &fileName)
128{
129 QFileInfo fi(fileName);
130 if (!fi.exists()) {
131 qWarning("QuaZipNewInfo::setFileNTFSTimes(): '%s' doesn't exist",
132 fileName.toUtf8().constData());
133 return;
134 }
135 setFileNTFSmTime(fi.lastModified());
136 setFileNTFSaTime(fi.lastRead());
137#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
138 setFileNTFScTime(fi.birthTime());
139#else
140 setFileNTFScTime(fi.created());
141#endif
142}
143
144static void setNTFSTime(QByteArray &extra, const QDateTime &time, int position,
145 int fineTicks) {
146 int ntfsPos = -1, timesPos = -1;
147 unsigned ntfsLength = 0, ntfsTimesLength = 0;
148 for (int i = 0; i <= extra.size() - 4; ) {
149 unsigned type = static_cast<unsigned>(static_cast<unsigned char>(
150 extra.at(i)))
151 | (static_cast<unsigned>(static_cast<unsigned char>(
152 extra.at(i + 1))) << 8);
153 i += 2;
154 unsigned length = static_cast<unsigned>(static_cast<unsigned char>(
155 extra.at(i)))
156 | (static_cast<unsigned>(static_cast<unsigned char>(
157 extra.at(i + 1))) << 8);
158 i += 2;
159 if (type == QUAZIP_EXTRA_NTFS_MAGIC) {
160 ntfsPos = i - 4; // the beginning of the NTFS record
161 ntfsLength = length;
162 if (length <= 4) {
163 break; // no times in the NTFS record
164 }
165 i += 4; // reserved
166 while (i <= extra.size() - 4) {
167 unsigned tag = static_cast<unsigned>(
168 static_cast<unsigned char>(extra.at(i)))
169 | (static_cast<unsigned>(
170 static_cast<unsigned char>(extra.at(i + 1)))
171 << 8);
172 i += 2;
173 unsigned tagsize = static_cast<unsigned>(
174 static_cast<unsigned char>(extra.at(i)))
175 | (static_cast<unsigned>(
176 static_cast<unsigned char>(extra.at(i + 1)))
177 << 8);
178 i += 2;
179 if (tag == QUAZIP_EXTRA_NTFS_TIME_MAGIC) {
180 timesPos = i - 4; // the beginning of the NTFS times tag
181 ntfsTimesLength = tagsize;
182 break;
183 } else {
184 i += tagsize;
185 }
186 }
187 break; // I ain't going to search for yet another NTFS record!
188 } else {
189 i += length;
190 }
191 }
192 if (ntfsPos == -1) {
193 // No NTFS record, need to create one.
194 ntfsPos = extra.size();
195 ntfsLength = 32;
196 extra.resize(extra.size() + 4 + ntfsLength);
197 // the NTFS record header
198 extra[ntfsPos] = static_cast<char>(QUAZIP_EXTRA_NTFS_MAGIC);
199 extra[ntfsPos + 1] = static_cast<char>(QUAZIP_EXTRA_NTFS_MAGIC >> 8);
200 extra[ntfsPos + 2] = 32; // the 2-byte size in LittleEndian
201 extra[ntfsPos + 3] = 0;
202 // zero the record
203 memset(extra.data() + ntfsPos + 4, 0, 32);
204 timesPos = ntfsPos + 8;
205 // now set the tag data
206 extra[timesPos] = static_cast<char>(QUAZIP_EXTRA_NTFS_TIME_MAGIC);
207 extra[timesPos + 1] = static_cast<char>(QUAZIP_EXTRA_NTFS_TIME_MAGIC
208 >> 8);
209 // the size:
210 extra[timesPos + 2] = 24;
211 extra[timesPos + 3] = 0;
212 ntfsTimesLength = 24;
213 }
214 if (timesPos == -1) {
215 // No time tag in the NTFS record, need to add one.
216 timesPos = ntfsPos + 4 + ntfsLength;
217 extra.resize(extra.size() + 28);
218 // Now we need to move the rest of the field
219 // (possibly zero bytes, but memmove() is OK with that).
220 // 0 ......... ntfsPos .. ntfsPos + 4 ... timesPos
221 // <some data> <header> <NTFS record> <need-to-move data> <end>
222 memmove(extra.data() + timesPos + 28, extra.data() + timesPos,
223 extra.size() - 28 - timesPos);
224 ntfsLength += 28;
225 // now set the tag data
226 extra[timesPos] = static_cast<char>(QUAZIP_EXTRA_NTFS_TIME_MAGIC);
227 extra[timesPos + 1] = static_cast<char>(QUAZIP_EXTRA_NTFS_TIME_MAGIC
228 >> 8);
229 // the size:
230 extra[timesPos + 2] = 24;
231 extra[timesPos + 3] = 0;
232 // zero the record
233 memset(extra.data() + timesPos + 4, 0, 24);
234 ntfsTimesLength = 24;
235 }
236 if (ntfsTimesLength < 24) {
237 // Broken times field. OK, this is really unlikely, but just in case...
238 size_t timesEnd = timesPos + 4 + ntfsTimesLength;
239 extra.resize(extra.size() + (24 - ntfsTimesLength));
240 // Move it!
241 // 0 ......... timesPos .... timesPos + 4 .. timesEnd
242 // <some data> <time header> <broken times> <need-to-move data> <end>
243 memmove(extra.data() + timesEnd + (24 - ntfsTimesLength),
244 extra.data() + timesEnd,
245 extra.size() - (24 - ntfsTimesLength) - timesEnd);
246 // Now we have to increase the NTFS record and time tag lengths.
247 ntfsLength += (24 - ntfsTimesLength);
248 ntfsTimesLength = 24;
249 extra[ntfsPos + 2] = static_cast<char>(ntfsLength);
250 extra[ntfsPos + 3] = static_cast<char>(ntfsLength >> 8);
251 extra[timesPos + 2] = static_cast<char>(ntfsTimesLength);
252 extra[timesPos + 3] = static_cast<char>(ntfsTimesLength >> 8);
253 }
254 QDateTime base(QDate(1601, 1, 1), QTime(0, 0), Qt::UTC);
255#if (QT_VERSION >= 0x040700)
256 quint64 ticks = base.msecsTo(time) * 10000 + fineTicks;
257#else
258 QDateTime utc = time.toUTC();
259 quint64 ticks = (static_cast<qint64>(base.date().daysTo(utc.date()))
260 * Q_INT64_C(86400000)
261 + static_cast<qint64>(base.time().msecsTo(utc.time())))
262 * Q_INT64_C(10000) + fineTicks;
263#endif
264 extra[timesPos + 4 + position] = static_cast<char>(ticks);
265 extra[timesPos + 5 + position] = static_cast<char>(ticks >> 8);
266 extra[timesPos + 6 + position] = static_cast<char>(ticks >> 16);
267 extra[timesPos + 7 + position] = static_cast<char>(ticks >> 24);
268 extra[timesPos + 8 + position] = static_cast<char>(ticks >> 32);
269 extra[timesPos + 9 + position] = static_cast<char>(ticks >> 40);
270 extra[timesPos + 10 + position] = static_cast<char>(ticks >> 48);
271 extra[timesPos + 11 + position] = static_cast<char>(ticks >> 56);
272}
273
274void QuaZipNewInfo::setFileNTFSmTime(const QDateTime &mTime, int fineTicks)
275{
276 setNTFSTime(extraLocal, mTime, 0, fineTicks);
277 setNTFSTime(extraGlobal, mTime, 0, fineTicks);
278}
279
280void QuaZipNewInfo::setFileNTFSaTime(const QDateTime &aTime, int fineTicks)
281{
282 setNTFSTime(extraLocal, aTime, 8, fineTicks);
283 setNTFSTime(extraGlobal, aTime, 8, fineTicks);
284}
285
286void QuaZipNewInfo::setFileNTFScTime(const QDateTime &cTime, int fineTicks)
287{
288 setNTFSTime(extraLocal, cTime, 16, fineTicks);
289 setNTFSTime(extraGlobal, cTime, 16, fineTicks);
290}