ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
JlCompress.cpp
Go to the documentation of this file.
1 /*
2 Copyright (C) 2010 Roberto Pompermaier
3 Copyright (C) 2005-2014 Sergey A. Tachenov
4 
5 This file is part of QuaZIP.
6 
7 QuaZIP is free software: you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation, either version 2.1 of the License, or
10 (at your option) any later version.
11 
12 QuaZIP is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU Lesser General Public License for more details.
16 
17 You should have received a copy of the GNU Lesser General Public License
18 along with QuaZIP. If not, see <http://www.gnu.org/licenses/>.
19 
20 See COPYING file for the full LGPL text.
21 
22 Original ZIP package is copyrighted by Gilles Vollant and contributors,
23 see quazip/(un)zip.h files for details. Basically it's the zlib license.
24 */
25 
26 #include "JlCompress.h"
27 
28 #include <QDebug>
29 
30 static bool copyData(QIODevice &inFile, QIODevice &outFile) {
31  while (!inFile.atEnd()) {
32  char buf[4096];
33  qint64 readLen = inFile.read(buf, 4096);
34  if (readLen <= 0) return false;
35  if (outFile.write(buf, readLen) != readLen) return false;
36  }
37  return true;
38 }
39 
40 bool JlCompress::compressFile(QuaZip *zip, QString fileName, QString fileDest) {
41  // zip: oggetto dove aggiungere il file
42  // fileName: nome del file reale
43  // fileDest: nome del file all'interno del file compresso
44 
45  // Controllo l'apertura dello zip
46  if (!zip) return false;
47  if (zip->getMode() != QuaZip::mdCreate &&
48  zip->getMode() != QuaZip::mdAppend && zip->getMode() != QuaZip::mdAdd)
49  return false;
50 
51  // Apro il file originale
52  QFile inFile;
53  inFile.setFileName(fileName);
54  if (!inFile.open(QIODevice::ReadOnly)) return false;
55 
56  // Apro il file risulato
57  QuaZipFile outFile(zip);
58  if (!outFile.open(QIODevice::WriteOnly,
59  QuaZipNewInfo(fileDest, inFile.fileName())))
60  return false;
61 
62  // Copio i dati
63  if (!copyData(inFile, outFile) || outFile.getZipError() != UNZ_OK) {
64  return false;
65  }
66 
67  // Chiudo i file
68  outFile.close();
69  if (outFile.getZipError() != UNZ_OK) return false;
70  inFile.close();
71 
72  return true;
73 }
74 
75 bool JlCompress::compressSubDir(QuaZip *zip,
76  QString dir,
77  QString origDir,
78  bool recursive,
79  QDir::Filters filters) {
80  // zip: oggetto dove aggiungere il file
81  // dir: cartella reale corrente
82  // origDir: cartella reale originale
83  // (path(dir)-path(origDir)) = path interno all'oggetto zip
84 
85  // Controllo l'apertura dello zip
86  if (!zip) return false;
87  if (zip->getMode() != QuaZip::mdCreate &&
88  zip->getMode() != QuaZip::mdAppend && zip->getMode() != QuaZip::mdAdd)
89  return false;
90 
91  // Controllo la cartella
92  QDir directory(dir);
93  if (!directory.exists()) return false;
94 
95  QDir origDirectory(origDir);
96  if (dir != origDir) {
97  QuaZipFile dirZipFile(zip);
98  if (!dirZipFile.open(
99  QIODevice::WriteOnly,
100  QuaZipNewInfo(origDirectory.relativeFilePath(dir) + "/",
101  dir),
102  0, 0, 0)) {
103  return false;
104  }
105  dirZipFile.close();
106  }
107 
108  // Se comprimo anche le sotto cartelle
109  if (recursive) {
110  // Per ogni sotto cartella
111  QFileInfoList files = directory.entryInfoList(
112  QDir::AllDirs | QDir::NoDotAndDotDot | filters);
113  Q_FOREACH (QFileInfo file, files) {
114  // Comprimo la sotto cartella
115  if (!compressSubDir(zip, file.absoluteFilePath(), origDir,
116  recursive, filters))
117  return false;
118  }
119  }
120 
121  // Per ogni file nella cartella
122  QFileInfoList files = directory.entryInfoList(QDir::Files | filters);
123  Q_FOREACH (QFileInfo file, files) {
124  // Se non e un file o e il file compresso che sto creando
125  if (!file.isFile() || file.absoluteFilePath() == zip->getZipName())
126  continue;
127 
128  // Creo il nome relativo da usare all'interno del file compresso
129  QString filename =
130  origDirectory.relativeFilePath(file.absoluteFilePath());
131 
132  // Comprimo il file
133  if (!compressFile(zip, file.absoluteFilePath(), filename)) return false;
134  }
135 
136  return true;
137 }
138 
139 bool JlCompress::extractFile(QuaZip *zip, QString fileName, QString fileDest) {
140  // zip: oggetto dove aggiungere il file
141  // filename: nome del file reale
142  // fileincompress: nome del file all'interno del file compresso
143 
144  // Controllo l'apertura dello zip
145  if (!zip) return false;
146  if (zip->getMode() != QuaZip::mdUnzip) return false;
147 
148  // Apro il file compresso
149  if (!fileName.isEmpty()) zip->setCurrentFile(fileName);
150  QuaZipFile inFile(zip);
151  if (!inFile.open(QIODevice::ReadOnly) || inFile.getZipError() != UNZ_OK)
152  return false;
153 
154  // Controllo esistenza cartella file risultato
155  QDir curDir;
156  if (fileDest.endsWith('/')) {
157  if (!curDir.mkpath(fileDest)) {
158  return false;
159  }
160  } else {
161  if (!curDir.mkpath(QFileInfo(fileDest).absolutePath())) {
162  return false;
163  }
164  }
165 
166  QuaZipFileInfo64 info;
167  if (!zip->getCurrentFileInfo(&info)) return false;
168 
169  QFile::Permissions srcPerm = info.getPermissions();
170  if (fileDest.endsWith('/') && QFileInfo(fileDest).isDir()) {
171  if (srcPerm != 0) {
172  QFile(fileDest).setPermissions(srcPerm);
173  }
174  return true;
175  }
176 
177  // Apro il file risultato
178  QFile outFile;
179  outFile.setFileName(fileDest);
180  if (!outFile.open(QIODevice::WriteOnly)) return false;
181 
182  // Copio i dati
183  if (!copyData(inFile, outFile) || inFile.getZipError() != UNZ_OK) {
184  outFile.close();
185  removeFile(QStringList(fileDest));
186  return false;
187  }
188  outFile.close();
189 
190  // Chiudo i file
191  inFile.close();
192  if (inFile.getZipError() != UNZ_OK) {
193  removeFile(QStringList(fileDest));
194  return false;
195  }
196 
197  if (srcPerm != 0) {
198  outFile.setPermissions(srcPerm);
199  }
200  return true;
201 }
202 
203 bool JlCompress::removeFile(QStringList listFile) {
204  bool ret = true;
205  // Per ogni file
206  for (int i = 0; i < listFile.count(); i++) {
207  // Lo elimino
208  ret = ret && QFile::remove(listFile.at(i));
209  }
210  return ret;
211 }
212 
213 bool JlCompress::compressFile(QString fileCompressed, QString file) {
214  // Creo lo zip
215  QuaZip zip(fileCompressed);
216  QDir().mkpath(QFileInfo(fileCompressed).absolutePath());
217  if (!zip.open(QuaZip::mdCreate)) {
218  QFile::remove(fileCompressed);
219  return false;
220  }
221 
222  // Aggiungo il file
223  if (!compressFile(&zip, file, QFileInfo(file).fileName())) {
224  QFile::remove(fileCompressed);
225  return false;
226  }
227 
228  // Chiudo il file zip
229  zip.close();
230  if (zip.getZipError() != 0) {
231  QFile::remove(fileCompressed);
232  return false;
233  }
234 
235  return true;
236 }
237 
238 bool JlCompress::compressFiles(QString fileCompressed, QStringList files) {
239  // Creo lo zip
240  QuaZip zip(fileCompressed);
241  QDir().mkpath(QFileInfo(fileCompressed).absolutePath());
242  if (!zip.open(QuaZip::mdCreate)) {
243  QFile::remove(fileCompressed);
244  return false;
245  }
246 
247  // Comprimo i file
248  QFileInfo info;
249  Q_FOREACH (QString file, files) {
250  info.setFile(file);
251  if (!info.exists() || !compressFile(&zip, file, info.fileName())) {
252  QFile::remove(fileCompressed);
253  return false;
254  }
255  }
256 
257  // Chiudo il file zip
258  zip.close();
259  if (zip.getZipError() != 0) {
260  QFile::remove(fileCompressed);
261  return false;
262  }
263 
264  return true;
265 }
266 
267 bool JlCompress::compressDir(QString fileCompressed,
268  QString dir,
269  bool recursive) {
270 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
271  return compressDir(fileCompressed, dir, recursive, QDir::NoFilter);
272 #else
273  return compressDir(fileCompressed, dir, recursive, 0);
274 #endif
275 }
276 
277 bool JlCompress::compressDir(QString fileCompressed,
278  QString dir,
279  bool recursive,
280  QDir::Filters filters) {
281  // Creo lo zip
282  QuaZip zip(fileCompressed);
283  QDir().mkpath(QFileInfo(fileCompressed).absolutePath());
284  if (!zip.open(QuaZip::mdCreate)) {
285  QFile::remove(fileCompressed);
286  return false;
287  }
288 
289  // Aggiungo i file e le sotto cartelle
290  if (!compressSubDir(&zip, dir, dir, recursive, filters)) {
291  QFile::remove(fileCompressed);
292  return false;
293  }
294 
295  // Chiudo il file zip
296  zip.close();
297  if (zip.getZipError() != 0) {
298  QFile::remove(fileCompressed);
299  return false;
300  }
301 
302  return true;
303 }
304 
305 QString JlCompress::extractFile(QString fileCompressed,
306  QString fileName,
307  QString fileDest) {
308  // Apro lo zip
309  QuaZip zip(fileCompressed);
310  return extractFile(zip, fileName, fileDest);
311 }
312 
313 QString JlCompress::extractFile(QuaZip &zip,
314  QString fileName,
315  QString fileDest) {
316  if (!zip.open(QuaZip::mdUnzip)) {
317  return QString();
318  }
319 
320  // Estraggo il file
321  if (fileDest.isEmpty()) fileDest = fileName;
322  if (!extractFile(&zip, fileName, fileDest)) {
323  return QString();
324  }
325 
326  // Chiudo il file zip
327  zip.close();
328  if (zip.getZipError() != 0) {
329  removeFile(QStringList(fileDest));
330  return QString();
331  }
332  return QFileInfo(fileDest).absoluteFilePath();
333 }
334 
335 QStringList JlCompress::extractFiles(QString fileCompressed,
336  QStringList files,
337  QString dir) {
338  // Creo lo zip
339  QuaZip zip(fileCompressed);
340  return extractFiles(zip, files, dir);
341 }
342 
343 QStringList JlCompress::extractFiles(QuaZip &zip,
344  const QStringList &files,
345  const QString &dir) {
346  if (!zip.open(QuaZip::mdUnzip)) {
347  return QStringList();
348  }
349 
350  // Estraggo i file
351  QStringList extracted;
352  for (int i = 0; i < files.count(); i++) {
353  QString absPath = QDir(dir).absoluteFilePath(files.at(i));
354  if (!extractFile(&zip, files.at(i), absPath)) {
355  removeFile(extracted);
356  return QStringList();
357  }
358  extracted.append(absPath);
359  }
360 
361  // Chiudo il file zip
362  zip.close();
363  if (zip.getZipError() != 0) {
364  removeFile(extracted);
365  return QStringList();
366  }
367 
368  return extracted;
369 }
370 
371 QStringList JlCompress::extractDir(QString fileCompressed, QString dir) {
372  // Apro lo zip
373  QuaZip zip(fileCompressed);
374  return extractDir(zip, dir);
375 }
376 
377 QStringList JlCompress::extractDir(QuaZip &zip, const QString &dir) {
378  if (!zip.open(QuaZip::mdUnzip)) {
379  return QStringList();
380  }
381 
382  QDir directory(dir);
383  QStringList extracted;
384  if (!zip.goToFirstFile()) {
385  return QStringList();
386  }
387  do {
388  QString name = zip.getCurrentFileName();
389  QString absFilePath = directory.absoluteFilePath(name);
390  if (!extractFile(&zip, "", absFilePath)) {
391  removeFile(extracted);
392  return QStringList();
393  }
394  extracted.append(absFilePath);
395  } while (zip.goToNextFile());
396 
397  // Chiudo il file zip
398  zip.close();
399  if (zip.getZipError() != 0) {
400  removeFile(extracted);
401  return QStringList();
402  }
403 
404  return extracted;
405 }
406 
407 QStringList JlCompress::getFileList(QString fileCompressed) {
408  // Apro lo zip
409  QuaZip *zip = new QuaZip(QFileInfo(fileCompressed).absoluteFilePath());
410  return getFileList(zip);
411 }
412 
413 QStringList JlCompress::getFileList(QuaZip *zip) {
414  if (!zip->open(QuaZip::mdUnzip)) {
415  delete zip;
416  return QStringList();
417  }
418 
419  // Estraggo i nomi dei file
420  QStringList lst;
421  QuaZipFileInfo64 info;
422  for (bool more = zip->goToFirstFile(); more; more = zip->goToNextFile()) {
423  if (!zip->getCurrentFileInfo(&info)) {
424  delete zip;
425  return QStringList();
426  }
427  lst << info.name;
428  // info.name.toLocal8Bit().constData()
429  }
430 
431  // Chiudo il file zip
432  zip->close();
433  if (zip->getZipError() != 0) {
434  delete zip;
435  return QStringList();
436  }
437  delete zip;
438  return lst;
439 }
440 
441 QStringList JlCompress::extractDir(QIODevice *ioDevice, QString dir) {
442  QuaZip zip(ioDevice);
443  return extractDir(zip, dir);
444 }
445 
446 QStringList JlCompress::getFileList(QIODevice *ioDevice) {
447  QuaZip *zip = new QuaZip(ioDevice);
448  return getFileList(zip);
449 }
450 
451 QString JlCompress::extractFile(QIODevice *ioDevice,
452  QString fileName,
453  QString fileDest) {
454  QuaZip zip(ioDevice);
455  return extractFile(zip, fileName, fileDest);
456 }
457 
458 QStringList JlCompress::extractFiles(QIODevice *ioDevice,
459  QStringList files,
460  QString dir) {
461  QuaZip zip(ioDevice);
462  return extractFiles(zip, files, dir);
463 }
std::string filename
std::string name
static bool copyData(QIODevice &inFile, QIODevice &outFile)
Definition: JlCompress.cpp:30
static bool compressDir(QString fileCompressed, QString dir=QString(), bool recursive=true)
Compress a whole directory.
Definition: JlCompress.cpp:267
static bool compressFiles(QString fileCompressed, QStringList files)
Compress a list of files.
Definition: JlCompress.cpp:238
A file inside ZIP archive.
Definition: quazipfile.h:74
ZIP archive.
Definition: quazip.h:128
QString getZipName() const
Returns the name of the ZIP file.
Definition: quazip.cpp:581
@ mdAdd
ZIP file was opened for adding files in the archive.
Definition: quazip.h:151
@ mdCreate
ZIP file was created with open() call.
Definition: quazip.h:142
@ mdUnzip
ZIP file is open for reading files inside it.
Definition: quazip.h:141
@ mdAppend
Definition: quazip.h:143
Mode getMode() const
Returns the mode in which ZIP file was opened.
Definition: quazip.cpp:589
bool setCurrentFile(const QString &fileName, CaseSensitivity cs=csDefault)
Sets current file by its name.
Definition: quazip.cpp:398
bool goToFirstFile()
Sets the current file to the first file in the archive.
Definition: quazip.cpp:454
void close()
Closes ZIP file.
Definition: quazip.cpp:314
QString getCurrentFileName() const
Returns the current file name.
Definition: quazip.cpp:539
int getZipError() const
Returns the error code of the last operation.
Definition: quazip.cpp:593
bool open(Mode mode, zlib_filefunc_def *ioApi=NULL)
Opens ZIP file.
Definition: quazip.cpp:208
bool getCurrentFileInfo(QuaZipFileInfo *info) const
Retrieves information about the current file.
Definition: quazip.cpp:477
bool goToNextFile()
Sets the current file to the next file in the archive.
Definition: quazip.cpp:465
Information about a file inside archive (with zip64 support).
QString name
File name.
QFile::Permissions getPermissions() const
Get the file permissions.
Information about a file to be created.
Definition: quazipnewinfo.h:49
#define UNZ_OK
Definition: unzip.h:83