All Classes Namespaces Functions Variables Enumerations Properties Pages
qminiz.cpp
1 /*
2 
3 Pencil2D - Traditional Animation Software
4 Copyright (C) 2012-2020 Matthew Chiawen Chang
5 
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; version 2 of the License.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 
15 */
16 #include "qminiz.h"
17 
18 #include <QFileInfo>
19 #include <QDir>
20 #include <QDebug>
21 #include <QDirIterator>
22 #include "miniz.h"
23 #include "util.h"
24 
25 
26 bool MiniZ::isZip(const QString& sZipFilePath)
27 {
29  OnScopeExit(delete mz);
30  mz_zip_zero_struct(mz);
31 
32  mz_bool ok = mz_zip_reader_init_file(mz, sZipFilePath.toUtf8().data(), 0);
33  if (!ok) return false;
34 
35  int num = mz_zip_reader_get_num_files(mz);
36 
37  mz_zip_reader_end(mz);
38  return (num > 0);
39 }
40 
41 // ReSharper disable once CppInconsistentNaming
42 Status MiniZ::compressFolder(QString zipFilePath, QString srcFolderPath, const QStringList& fileList)
43 {
44  DebugDetails dd;
45  dd << QString("Creating Zip %1 from folder %2").arg(zipFilePath).arg(srcFolderPath);
46 
47  if (!srcFolderPath.endsWith("/"))
48  {
49  srcFolderPath.append("/");
50  }
51 
53  mz_zip_zero_struct(mz);
54 
55  mz_bool ok = mz_zip_writer_init_file(mz, zipFilePath.toUtf8().data(), 0);
56 
57  ScopeGuard mzScopeGuard([&] {
58  mz_zip_writer_end(mz);
59  delete mz;
60  });
61 
62  if (!ok)
63  {
64  mz_zip_error err = mz_zip_get_last_error(mz);
65  dd << QString("Miniz writer init failed: error %1, %2").arg(static_cast<int>(err)).arg(mz_zip_get_error_string(err));;
66  }
67 
68  //qDebug() << "SrcFolder=" << srcFolderPath;
69  for (const QString& filePath : fileList)
70  {
71  QString sRelativePath = filePath;
72  sRelativePath.replace(srcFolderPath, "");
73 
74  dd << QString("Add file to zip: ").append(sRelativePath);
75 
76  ok = mz_zip_writer_add_file(mz,
77  sRelativePath.toUtf8().data(),
78  filePath.toUtf8().data(),
79  "", 0, MZ_BEST_SPEED);
80  if (!ok)
81  {
82  mz_zip_error err = mz_zip_get_last_error(mz);
83  dd << QString("Cannot add %1: error %2, %3").arg(sRelativePath).arg(static_cast<int>(err)).arg(mz_zip_get_error_string(err));
84  }
85  }
86  ok &= mz_zip_writer_finalize_archive(mz);
87  if (!ok)
88  {
89  mz_zip_error err = mz_zip_get_last_error(mz);
90  dd << QString("Miniz finalize archive failed: error %1, %2").arg(static_cast<int>(err)).arg(mz_zip_get_error_string(err));
91  return Status(Status::FAIL, dd);
92  }
93 
94  ok &= mz_zip_writer_end(mz);
95 
96  mzScopeGuard.dismiss();
97  ScopeGuard mzScopeGuard2([&] { delete mz; });
98 
99  if (!ok)
100  {
101  mz_zip_error err = mz_zip_get_last_error(mz);
102  dd << QString("Miniz writer end failed: error %1, %2").arg(static_cast<int>(err)).arg(mz_zip_get_error_string(err));
103  return Status(Status::FAIL, dd);
104  }
105 
106  return Status::OK;
107 }
108 
109 Status MiniZ::uncompressFolder(QString zipFilePath, QString destPath)
110 {
111  DebugDetails dd;
112  dd << QString("Unzip file %1 to folder %2").arg(zipFilePath).arg(destPath);
113 
114  if (!QFile::exists(zipFilePath))
115  {
116  return Status::FILE_NOT_FOUND;
117  }
118 
119  QString sBaseDir = QFileInfo(destPath).absolutePath();
120  QDir baseDir(sBaseDir);
121  if (!baseDir.exists())
122  {
123  bool ok = baseDir.mkpath(".");
124  Q_ASSERT(ok);
125  }
126 
127  baseDir.makeAbsolute();
128 
129  mz_zip_archive* mz = new mz_zip_archive;
130  mz_zip_zero_struct(mz);
131 
132  mz_bool ok = mz_zip_reader_init_file(mz, zipFilePath.toUtf8().data(), 0);
133 
134  ScopeGuard mzScopeGuard([&] {
135  mz_zip_reader_end(mz);
136  delete mz;
137  });
138 
139  if (!ok)
140  return Status(Status::FAIL, dd);
141 
142  int num = mz_zip_reader_get_num_files(mz);
143 
145  OnScopeExit(delete stat);
146 
147  for (int i = 0; i < num; ++i)
148  {
149  ok &= mz_zip_reader_file_stat(mz, i, stat);
150 
151  if (stat->m_is_directory)
152  {
153  QString sFolderPath = QString::fromUtf8(stat->m_filename);
154  dd << QString("Make Dir: ").append(sFolderPath);
155 
156  bool mkDirOK = baseDir.mkpath(sFolderPath);
157  Q_ASSERT(mkDirOK);
158  if (!mkDirOK)
159  dd << "Make Dir failed.";
160  }
161  }
162 
163  for (int i = 0; i < num; ++i)
164  {
165  ok &= mz_zip_reader_file_stat(mz, i, stat);
166 
167  if (!stat->m_is_directory)
168  {
169  QString sFullPath = baseDir.filePath(QString::fromUtf8(stat->m_filename));
170  dd << QString("Unzip file: ").append(sFullPath);
171  bool b = QFileInfo(sFullPath).absoluteDir().mkpath(".");
172  Q_ASSERT(b);
173 
174  bool extractOK = mz_zip_reader_extract_to_file(mz, i, sFullPath.toUtf8(), 0);
175  if (!extractOK)
176  {
177  ok = false;
178  dd << "File extraction failed.";
179  }
180  }
181  }
182 
183  ok &= mz_zip_reader_end(mz);
184 
185  mzScopeGuard.dismiss();
186  ScopeGuard mzScopeGuard2([&] {
187  delete mz;
188  });
189 
190  if (!ok)
191  {
192  dd << "Unzip error!";
193  }
194  return Status::OK;
195 }
QString & append(QChar ch)
bool exists() const const
QString fromUtf8(const char *str, int size)
QDir absoluteDir() const const
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const const
QString & replace(int position, int n, QChar after)
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
char * data()
QString absolutePath() const const
bool mkpath(const QString &dirPath) const const
QByteArray toUtf8() const const