ckb-next  v0.2.8 at branch master
ckb-next driver for corsair devices
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
quazipnewinfo.cpp
Go to the documentation of this file.
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 <QFileInfo>
26 
27 #include "quazipnewinfo.h"
28 
29 #include <string.h>
30 
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 
56 template<typename FileInfo>
57 void 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 
70 {
71  QuaZipNewInfo_init(*this, existing);
72 }
73 
75 {
76  QuaZipNewInfo_init(*this, existing);
77 }
78 
79 QuaZipNewInfo::QuaZipNewInfo(const QString& name):
80  name(name), dateTime(QDateTime::currentDateTime()), internalAttr(0), externalAttr(0),
81  uncompressedSize(0)
82 {
83 }
84 
85 QuaZipNewInfo::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 
98 void QuaZipNewInfo::setFileDateTime(const QString& file)
99 {
100  QFileInfo info(file);
101  QDateTime lm = info.lastModified();
102  if (info.exists())
103  dateTime = lm;
104 }
105 
106 void 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 
113 void QuaZipNewInfo::setPermissions(QFile::Permissions permissions)
114 {
115  QuaZipNewInfo_setPermissions(this, permissions, name.endsWith('/'));
116 }
117 
118 void 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 
131 static 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 
261 void QuaZipNewInfo::setFileNTFSmTime(const QDateTime &mTime, int fineTicks)
262 {
263  setNTFSTime(extraLocal, mTime, 0, fineTicks);
264  setNTFSTime(extraGlobal, mTime, 0, fineTicks);
265 }
266 
267 void QuaZipNewInfo::setFileNTFSaTime(const QDateTime &aTime, int fineTicks)
268 {
269  setNTFSTime(extraLocal, aTime, 8, fineTicks);
270  setNTFSTime(extraGlobal, aTime, 8, fineTicks);
271 }
272 
273 void QuaZipNewInfo::setFileNTFScTime(const QDateTime &cTime, int fineTicks)
274 {
275  setNTFSTime(extraLocal, cTime, 16, fineTicks);
276  setNTFSTime(extraGlobal, cTime, 16, fineTicks);
277 }
#define QUAZIP_EXTRA_NTFS_MAGIC
Definition: quazip_global.h:56
Information about a file to be created.
Definition: quazipnewinfo.h:50
QByteArray extraLocal
File local extra field.
Definition: quazipnewinfo.h:77
static void setNTFSTime(QByteArray &extra, const QDateTime &time, int position, int fineTicks)
void setFileNTFScTime(const QDateTime &cTime, int fineTicks=0)
Sets the NTFS creation time.
void setPermissions(QFile::Permissions permissions)
Sets the file permissions.
Information about a file inside archive.
static void QuaZipNewInfo_setPermissions(QuaZipNewInfo *info, QFile::Permissions perm, bool isDir)
#define QUAZIP_EXTRA_NTFS_TIME_MAGIC
Definition: quazip_global.h:57
QuaZipNewInfo(const QString &name)
Constructs QuaZipNewInfo instance.
QDateTime dateTime
File timestamp.
Definition: quazipnewinfo.h:62
QByteArray extraGlobal
File global extra field.
Definition: quazipnewinfo.h:79
Information about a file inside archive (with zip64 support).
quint32 externalAttr
File external attributes.
Definition: quazipnewinfo.h:71
QString name
File name.
Definition: quazipnewinfo.h:55
void setFilePermissions(const QString &file)
Sets the file permissions from the existing file.
void setFileNTFSTimes(const QString &fileName)
Sets the NTFS times from an existing file.
void QuaZipNewInfo_init(QuaZipNewInfo &self, const FileInfo &existing)
void setFileNTFSmTime(const QDateTime &mTime, int fineTicks=0)
Sets the NTFS modification time.
void setFileNTFSaTime(const QDateTime &aTime, int fineTicks=0)
Sets the NTFS access time.
void setFileDateTime(const QString &file)
Sets the file timestamp from the existing file.