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
quazipdir.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 "quazipdir.h"
26 
27 #include <QSet>
28 #include <QSharedData>
29 
31 class QuaZipDirPrivate: public QSharedData {
32  friend class QuaZipDir;
33 private:
34  QuaZipDirPrivate(QuaZip *zip, const QString &dir = QString()):
35  zip(zip), dir(dir), caseSensitivity(QuaZip::csDefault),
36  filter(QDir::NoFilter), sorting(QDir::NoSort) {}
37  QuaZip *zip;
38  QString dir;
40  QDir::Filters filter;
41  QStringList nameFilters;
42  QDir::SortFlags sorting;
43  template<typename TFileInfoList>
44  bool entryInfoList(QStringList nameFilters, QDir::Filters filter,
45  QDir::SortFlags sort, TFileInfoList &result) const;
46  inline QString simplePath() const {return QDir::cleanPath(dir);}
47 };
49 
51  d(that.d)
52 {
53 }
54 
55 QuaZipDir::QuaZipDir(QuaZip *zip, const QString &dir):
56  d(new QuaZipDirPrivate(zip, dir))
57 {
58  if (d->dir.startsWith('/'))
59  d->dir = d->dir.mid(1);
60 }
61 
63 {
64 }
65 
67 {
68  return d->zip == that.d->zip && d->dir == that.d->dir;
69 }
70 
72 {
73  this->d = that.d;
74  return *this;
75 }
76 
77 QString QuaZipDir::operator[](int pos) const
78 {
79  return entryList().at(pos);
80 }
81 
83 {
84  return d->caseSensitivity;
85 }
86 
87 bool QuaZipDir::cd(const QString &directoryName)
88 {
89  if (directoryName == "/") {
90  d->dir = "";
91  return true;
92  }
93  QString dirName = directoryName;
94  if (dirName.endsWith('/'))
95  dirName.chop(1);
96  if (dirName.contains('/')) {
97  QuaZipDir dir(*this);
98  if (dirName.startsWith('/')) {
99 #ifdef QUAZIP_QUAZIPDIR_DEBUG
100  qDebug("QuaZipDir::cd(%s): going to /",
101  dirName.toUtf8().constData());
102 #endif
103  if (!dir.cd("/"))
104  return false;
105  }
106  QStringList path = dirName.split('/', QString::SkipEmptyParts);
107  for (QStringList::const_iterator i = path.constBegin();
108  i != path.end();
109  ++i) {
110  const QString &step = *i;
111 #ifdef QUAZIP_QUAZIPDIR_DEBUG
112  qDebug("QuaZipDir::cd(%s): going to %s",
113  dirName.toUtf8().constData(),
114  step.toUtf8().constData());
115 #endif
116  if (!dir.cd(step))
117  return false;
118  }
119  d->dir = dir.path();
120  return true;
121  } else { // no '/'
122  if (dirName == ".") {
123  return true;
124  } else if (dirName == "..") {
125  if (isRoot()) {
126  return false;
127  } else {
128  int slashPos = d->dir.lastIndexOf('/');
129  if (slashPos == -1) {
130  d->dir = "";
131  } else {
132  d->dir = d->dir.left(slashPos);
133  }
134  return true;
135  }
136  } else { // a simple subdirectory
137  if (exists(dirName)) {
138  if (isRoot())
139  d->dir = dirName;
140  else
141  d->dir += "/" + dirName;
142  return true;
143  } else {
144  return false;
145  }
146  }
147  }
148 }
149 
151 {
152  return cd("..");
153 }
154 
155 uint QuaZipDir::count() const
156 {
157  return entryList().count();
158 }
159 
160 QString QuaZipDir::dirName() const
161 {
162  return QDir(d->dir).dirName();
163 }
164 
166  const QString &relativeName,
167  bool isReal)
168 {
169  QuaZipFileInfo64 info;
170  if (isReal) {
171  *ok = zip->getCurrentFileInfo(&info);
172  } else {
173  *ok = true;
174  info.compressedSize = 0;
175  info.crc = 0;
176  info.diskNumberStart = 0;
177  info.externalAttr = 0;
178  info.flags = 0;
179  info.internalAttr = 0;
180  info.method = 0;
181  info.uncompressedSize = 0;
182  info.versionCreated = info.versionNeeded = 0;
183  }
184  info.name = relativeName;
185  return info;
186 }
187 
188 static void QuaZipDir_convertInfoList(const QList<QuaZipFileInfo64> &from,
189  QList<QuaZipFileInfo64> &to)
190 {
191  to = from;
192 }
193 
194 static void QuaZipDir_convertInfoList(const QList<QuaZipFileInfo64> &from,
195  QStringList &to)
196 {
197  to.clear();
198  for (QList<QuaZipFileInfo64>::const_iterator i = from.constBegin();
199  i != from.constEnd();
200  ++i) {
201  to.append(i->name);
202  }
203 }
204 
205 static void QuaZipDir_convertInfoList(const QList<QuaZipFileInfo64> &from,
206  QList<QuaZipFileInfo> &to)
207 {
208  to.clear();
209  for (QList<QuaZipFileInfo64>::const_iterator i = from.constBegin();
210  i != from.constEnd();
211  ++i) {
212  QuaZipFileInfo info32;
213  i->toQuaZipFileInfo(info32);
214  to.append(info32);
215  }
216 }
217 
219 
222 class QuaZipDirRestoreCurrent {
223 public:
224  inline QuaZipDirRestoreCurrent(QuaZip *zip):
225  zip(zip), currentFile(zip->getCurrentFileName()) {}
226  inline ~QuaZipDirRestoreCurrent()
227  {
228  zip->setCurrentFile(currentFile);
229  }
230 private:
231  QuaZip *zip;
232  QString currentFile;
233 };
235 
237 class QuaZipDirComparator
238 {
239  private:
240  QDir::SortFlags sort;
241  static QString getExtension(const QString &name);
242  int compareStrings(const QString &string1, const QString &string2);
243  public:
244  inline QuaZipDirComparator(QDir::SortFlags sort): sort(sort) {}
245  bool operator()(const QuaZipFileInfo64 &info1, const QuaZipFileInfo64 &info2);
246 };
247 
248 QString QuaZipDirComparator::getExtension(const QString &name)
249 {
250  if (name.endsWith('.') || name.indexOf('.', 1) == -1) {
251  return "";
252  } else {
253  return name.mid(name.lastIndexOf('.') + 1);
254  }
255 
256 }
257 
258 int QuaZipDirComparator::compareStrings(const QString &string1,
259  const QString &string2)
260 {
261  if (sort & QDir::LocaleAware) {
262  if (sort & QDir::IgnoreCase) {
263  return string1.toLower().localeAwareCompare(string2.toLower());
264  } else {
265  return string1.localeAwareCompare(string2);
266  }
267  } else {
268  return string1.compare(string2, (sort & QDir::IgnoreCase)
269  ? Qt::CaseInsensitive : Qt::CaseSensitive);
270  }
271 }
272 
273 bool QuaZipDirComparator::operator()(const QuaZipFileInfo64 &info1,
274  const QuaZipFileInfo64 &info2)
275 {
276  QDir::SortFlags order = sort
277  & (QDir::Name | QDir::Time | QDir::Size | QDir::Type);
278  if ((sort & QDir::DirsFirst) == QDir::DirsFirst
279  || (sort & QDir::DirsLast) == QDir::DirsLast) {
280  if (info1.name.endsWith('/') && !info2.name.endsWith('/'))
281  return (sort & QDir::DirsFirst) == QDir::DirsFirst;
282  else if (!info1.name.endsWith('/') && info2.name.endsWith('/'))
283  return (sort & QDir::DirsLast) == QDir::DirsLast;
284  }
285  bool result;
286  int extDiff;
287  switch (order) {
288  case QDir::Name:
289  result = compareStrings(info1.name, info2.name) < 0;
290  break;
291  case QDir::Type:
292  extDiff = compareStrings(getExtension(info1.name),
293  getExtension(info2.name));
294  if (extDiff == 0) {
295  result = compareStrings(info1.name, info2.name) < 0;
296  } else {
297  result = extDiff < 0;
298  }
299  break;
300  case QDir::Size:
301  if (info1.uncompressedSize == info2.uncompressedSize) {
302  result = compareStrings(info1.name, info2.name) < 0;
303  } else {
304  result = info1.uncompressedSize < info2.uncompressedSize;
305  }
306  break;
307  case QDir::Time:
308  if (info1.dateTime == info2.dateTime) {
309  result = compareStrings(info1.name, info2.name) < 0;
310  } else {
311  result = info1.dateTime < info2.dateTime;
312  }
313  break;
314  default:
315  qWarning("QuaZipDirComparator(): Invalid sort mode 0x%2X",
316  static_cast<unsigned>(sort));
317  return false;
318  }
319  return (sort & QDir::Reversed) ? !result : result;
320 }
321 
322 template<typename TFileInfoList>
323 bool QuaZipDirPrivate::entryInfoList(QStringList nameFilters,
324  QDir::Filters filter, QDir::SortFlags sort, TFileInfoList &result) const
325 {
326  QString basePath = simplePath();
327  if (!basePath.isEmpty())
328  basePath += "/";
329  int baseLength = basePath.length();
330  result.clear();
331  QuaZipDirRestoreCurrent saveCurrent(zip);
332  if (!zip->goToFirstFile()) {
333  return zip->getZipError() == UNZ_OK;
334  }
335  QDir::Filters fltr = filter;
336  if (fltr == QDir::NoFilter)
337  fltr = this->filter;
338  if (fltr == QDir::NoFilter)
339  fltr = QDir::AllEntries;
340  QStringList nmfltr = nameFilters;
341  if (nmfltr.isEmpty())
342  nmfltr = this->nameFilters;
343  QSet<QString> dirsFound;
344  QList<QuaZipFileInfo64> list;
345  do {
346  QString name = zip->getCurrentFileName();
347  if (!name.startsWith(basePath))
348  continue;
349  QString relativeName = name.mid(baseLength);
350  if (relativeName.isEmpty())
351  continue;
352  bool isDir = false;
353  bool isReal = true;
354  if (relativeName.contains('/')) {
355  int indexOfSlash = relativeName.indexOf('/');
356  // something like "subdir/"
357  isReal = indexOfSlash == relativeName.length() - 1;
358  relativeName = relativeName.left(indexOfSlash + 1);
359  if (dirsFound.contains(relativeName))
360  continue;
361  isDir = true;
362  }
363  dirsFound.insert(relativeName);
364  if ((fltr & QDir::Dirs) == 0 && isDir)
365  continue;
366  if ((fltr & QDir::Files) == 0 && !isDir)
367  continue;
368  if (!nmfltr.isEmpty() && !QDir::match(nmfltr, relativeName))
369  continue;
370  bool ok;
371  QuaZipFileInfo64 info = QuaZipDir_getFileInfo(zip, &ok, relativeName,
372  isReal);
373  if (!ok) {
374  return false;
375  }
376  list.append(info);
377  } while (zip->goToNextFile());
378  QDir::SortFlags srt = sort;
379  if (srt == QDir::NoSort)
380  srt = sorting;
381 #ifdef QUAZIP_QUAZIPDIR_DEBUG
382  qDebug("QuaZipDirPrivate::entryInfoList(): before sort:");
383  foreach (QuaZipFileInfo64 info, list) {
384  qDebug("%s\t%s", info.name.toUtf8().constData(),
385  info.dateTime.toString(Qt::ISODate).toUtf8().constData());
386  }
387 #endif
388  if (srt != QDir::NoSort && (srt & QDir::Unsorted) != QDir::Unsorted) {
389  if (QuaZip::convertCaseSensitivity(caseSensitivity)
390  == Qt::CaseInsensitive)
391  srt |= QDir::IgnoreCase;
392  QuaZipDirComparator lessThan(srt);
393  qSort(list.begin(), list.end(), lessThan);
394  }
395  QuaZipDir_convertInfoList(list, result);
396  return true;
397 }
398 
400 
401 QList<QuaZipFileInfo> QuaZipDir::entryInfoList(const QStringList &nameFilters,
402  QDir::Filters filters, QDir::SortFlags sort) const
403 {
404  QList<QuaZipFileInfo> result;
405  if (d->entryInfoList(nameFilters, filters, sort, result))
406  return result;
407  else
408  return QList<QuaZipFileInfo>();
409 }
410 
411 QList<QuaZipFileInfo> QuaZipDir::entryInfoList(QDir::Filters filters,
412  QDir::SortFlags sort) const
413 {
414  return entryInfoList(QStringList(), filters, sort);
415 }
416 
417 QList<QuaZipFileInfo64> QuaZipDir::entryInfoList64(const QStringList &nameFilters,
418  QDir::Filters filters, QDir::SortFlags sort) const
419 {
420  QList<QuaZipFileInfo64> result;
421  if (d->entryInfoList(nameFilters, filters, sort, result))
422  return result;
423  else
424  return QList<QuaZipFileInfo64>();
425 }
426 
427 QList<QuaZipFileInfo64> QuaZipDir::entryInfoList64(QDir::Filters filters,
428  QDir::SortFlags sort) const
429 {
430  return entryInfoList64(QStringList(), filters, sort);
431 }
432 
433 QStringList QuaZipDir::entryList(const QStringList &nameFilters,
434  QDir::Filters filters, QDir::SortFlags sort) const
435 {
436  QStringList result;
437  if (d->entryInfoList(nameFilters, filters, sort, result))
438  return result;
439  else
440  return QStringList();
441 }
442 
443 QStringList QuaZipDir::entryList(QDir::Filters filters,
444  QDir::SortFlags sort) const
445 {
446  return entryList(QStringList(), filters, sort);
447 }
448 
449 bool QuaZipDir::exists(const QString &filePath) const
450 {
451  if (filePath == "/" || filePath.isEmpty())
452  return true;
453  QString fileName = filePath;
454  if (fileName.endsWith('/'))
455  fileName.chop(1);
456  if (fileName.contains('/')) {
457  QFileInfo fileInfo(fileName);
458 #ifdef QUAZIP_QUAZIPDIR_DEBUG
459  qDebug("QuaZipDir::exists(): fileName=%s, fileInfo.fileName()=%s, "
460  "fileInfo.path()=%s", fileName.toUtf8().constData(),
461  fileInfo.fileName().toUtf8().constData(),
462  fileInfo.path().toUtf8().constData());
463 #endif
464  QuaZipDir dir(*this);
465  return dir.cd(fileInfo.path()) && dir.exists(fileInfo.fileName());
466  } else {
467  if (fileName == "..") {
468  return !isRoot();
469  } else if (fileName == ".") {
470  return true;
471  } else {
472  QStringList entries = entryList(QDir::AllEntries, QDir::NoSort);
473 #ifdef QUAZIP_QUAZIPDIR_DEBUG
474  qDebug("QuaZipDir::exists(): looking for %s",
475  fileName.toUtf8().constData());
476  for (QStringList::const_iterator i = entries.constBegin();
477  i != entries.constEnd();
478  ++i) {
479  qDebug("QuaZipDir::exists(): entry: %s",
480  i->toUtf8().constData());
481  }
482 #endif
483  Qt::CaseSensitivity cs = QuaZip::convertCaseSensitivity(
484  d->caseSensitivity);
485  if (filePath.endsWith('/')) {
486  return entries.contains(filePath, cs);
487  } else {
488  return entries.contains(fileName, cs)
489  || entries.contains(fileName + "/", cs);
490  }
491  }
492  }
493 }
494 
495 bool QuaZipDir::exists() const
496 {
497  return QuaZipDir(d->zip).exists(d->dir);
498 }
499 
500 QString QuaZipDir::filePath(const QString &fileName) const
501 {
502  return QDir(d->dir).filePath(fileName);
503 }
504 
505 QDir::Filters QuaZipDir::filter()
506 {
507  return d->filter;
508 }
509 
510 bool QuaZipDir::isRoot() const
511 {
512  return d->simplePath().isEmpty();
513 }
514 
515 QStringList QuaZipDir::nameFilters() const
516 {
517  return d->nameFilters;
518 }
519 
520 QString QuaZipDir::path() const
521 {
522  return d->dir;
523 }
524 
525 QString QuaZipDir::relativeFilePath(const QString &fileName) const
526 {
527  return QDir("/" + d->dir).relativeFilePath(fileName);
528 }
529 
531 {
532  d->caseSensitivity = caseSensitivity;
533 }
534 
535 void QuaZipDir::setFilter(QDir::Filters filters)
536 {
537  d->filter = filters;
538 }
539 
540 void QuaZipDir::setNameFilters(const QStringList &nameFilters)
541 {
542  d->nameFilters = nameFilters;
543 }
544 
545 void QuaZipDir::setPath(const QString &path)
546 {
547  QString newDir = path;
548  if (newDir == "/") {
549  d->dir = "";
550  } else {
551  if (newDir.endsWith('/'))
552  newDir.chop(1);
553  if (newDir.startsWith('/'))
554  newDir = newDir.mid(1);
555  d->dir = newDir;
556  }
557 }
558 
559 void QuaZipDir::setSorting(QDir::SortFlags sort)
560 {
561  d->sorting = sort;
562 }
563 
564 QDir::SortFlags QuaZipDir::sorting() const
565 {
566  return d->sorting;
567 }
~QuaZipDir()
Destructor.
Definition: quazipdir.cpp:62
static Qt::CaseSensitivity convertCaseSensitivity(CaseSensitivity cs)
Returns the actual case sensitivity for the specified QuaZIP one.
Definition: quazip.cpp:747
bool operator==(const QuaZipDir &that)
The assignment operator.
Definition: quazipdir.cpp:66
quint16 diskNumberStart
Disk number start.
QStringList nameFilters() const
Return the default name filter.
Definition: quazipdir.cpp:515
bool exists() const
Return true if the directory pointed by this QuaZipDir exists.
Definition: quazipdir.cpp:495
quint16 versionCreated
Version created by.
QList< QuaZipFileInfo64 > entryInfoList64(const QStringList &nameFilters, QDir::Filters filters=QDir::NoFilter, QDir::SortFlags sort=QDir::NoSort) const
Returns the list of the entries in the directory with zip64 support.
Definition: quazipdir.cpp:417
#define UNZ_OK
Definition: unzip.h:79
quint32 externalAttr
External file attributes.
bool cdUp()
Goes up.
Definition: quazipdir.cpp:150
quint16 versionNeeded
Version needed to extract.
QString operator[](int pos) const
Returns the name of the entry at the specified position.
Definition: quazipdir.cpp:77
QDir::Filters filter()
Returns the default filter.
Definition: quazipdir.cpp:505
QuaZipDir(const QuaZipDir &that)
The copy constructor.
Definition: quazipdir.cpp:50
Information about a file inside archive.
bool isRoot() const
Returns if the QuaZipDir points to the root of the archive.
Definition: quazipdir.cpp:510
QuaZipDir & operator=(const QuaZipDir &that)
operator==
Definition: quazipdir.cpp:71
QString relativeFilePath(const QString &fileName) const
Returns the path to the specified file relative to the current dir.
Definition: quazipdir.cpp:525
quint32 crc
CRC.
quint64 compressedSize
Compressed file size.
void setSorting(QDir::SortFlags sort)
Sets the default sorting mode.
Definition: quazipdir.cpp:559
static void QuaZipDir_convertInfoList(const QList< QuaZipFileInfo64 > &from, QList< QuaZipFileInfo64 > &to)
Definition: quazipdir.cpp:188
QString path() const
Returns the path to the current dir.
Definition: quazipdir.cpp:520
void setNameFilters(const QStringList &nameFilters)
Sets the default name filter.
Definition: quazipdir.cpp:540
QStringList entryList(const QStringList &nameFilters, QDir::Filters filters=QDir::NoFilter, QDir::SortFlags sort=QDir::NoSort) const
Returns the list of the entry names in the directory.
Definition: quazipdir.cpp:433
Information about a file inside archive (with zip64 support).
bool setCurrentFile(const QString &fileName, CaseSensitivity cs=csDefault)
Sets current file by its name.
Definition: quazip.cpp:408
quint16 method
Compression method.
void setFilter(QDir::Filters filters)
Sets the default filter.
Definition: quazipdir.cpp:535
quint64 uncompressedSize
Uncompressed file size.
ZIP archive.
Definition: quazip.h:84
bool cd(const QString &dirName)
Changes the 'current' directory.
Definition: quazipdir.cpp:87
QSharedDataPointer< QuaZipDirPrivate > d
Definition: quazipdir.h:56
void setCaseSensitivity(QuaZip::CaseSensitivity caseSensitivity)
Sets the default case sensitivity mode.
Definition: quazipdir.cpp:530
CaseSensitivity
Case sensitivity for the file names.
Definition: quazip.h:114
Provides ZIP archive navigation.
Definition: quazipdir.h:54
uint count() const
Returns the number of entries in the directory.
Definition: quazipdir.cpp:155
QDateTime dateTime
Last modification date and time.
quint16 flags
General purpose flags.
QString filePath(const QString &fileName) const
Returns the full path to the specified file.
Definition: quazipdir.cpp:500
QString name
File name.
QString dirName() const
Returns the current directory name.
Definition: quazipdir.cpp:160
QList< QuaZipFileInfo > entryInfoList(const QStringList &nameFilters, QDir::Filters filters=QDir::NoFilter, QDir::SortFlags sort=QDir::NoSort) const
Returns the list of the entries in the directory.
Definition: quazipdir.cpp:401
void setPath(const QString &path)
Goes to the specified path.
Definition: quazipdir.cpp:545
QuaZipFileInfo64 QuaZipDir_getFileInfo(QuaZip *zip, bool *ok, const QString &relativeName, bool isReal)
Definition: quazipdir.cpp:165
QuaZip::CaseSensitivity caseSensitivity() const
Returns the current case sensitivity mode.
Definition: quazipdir.cpp:82
QDir::SortFlags sorting() const
Returns the default sorting mode.
Definition: quazipdir.cpp:564
quint16 internalAttr
Internal file attributes.
bool getCurrentFileInfo(QuaZipFileInfo *info) const
Retrieves information about the current file.
Definition: quazip.cpp:492