1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
9 * Copyright (C) 2011 Dominik Riebeling
11 * All files in this archive are subject to the GNU General Public License.
12 * See the file COPYING in the source tree root for full license agreement.
14 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
15 * KIND, either express or implied.
17 ****************************************************************************/
22 #include "progressloggerinterface.h"
24 #include "quazip/quazip.h"
25 #include "quazip/quazipfile.h"
26 #include "quazip/quazipfileinfo.h"
29 ZipUtil::ZipUtil(QObject
* parent
) : QObject(parent
)
42 //! @brief open zip file.
43 //! @param zipfile path to zip file
44 //! @param mode open mode (see QuaZip::Mode)
45 //! @return true on success, false otherwise
46 bool ZipUtil::open(QString
& zipfile
, QuaZip::Mode mode
)
48 m_zip
= new QuaZip(zipfile
);
49 return m_zip
->open(mode
);
53 //! @brief close zip file.
54 //! @return true on success, false otherwise
55 bool ZipUtil::close(void)
64 error
= m_zip
->getZipError();
68 return (error
== UNZ_OK
) ? true : false;
72 //! @brief extract currently opened archive
73 //! @brief dest path to extract archive to, can be filename when extracting a
75 //! @brief file file to extract from archive, full archive if empty.
76 //! @return true on success, false otherwise
77 bool ZipUtil::extractArchive(QString
& dest
, QString file
)
79 qDebug() << "[ZipUtil] extractArchive" << dest
<< file
;
84 QuaZipFile
*currentFile
= new QuaZipFile(m_zip
);
85 int entries
= m_zip
->getEntriesCount();
87 // construct the filename when extracting a single file from an archive.
88 // if the given destination is a full path use it as output name,
89 // otherwise use it as path to place the file as named in the archive.
90 QString singleoutfile
;
91 if(!file
.isEmpty() && QFileInfo(dest
).isDir()) {
92 singleoutfile
= dest
+ "/" + file
;
94 else if(!file
.isEmpty()){
97 for(bool more
= m_zip
->goToFirstFile(); more
; more
= m_zip
->goToNextFile())
100 // if the entry is a path ignore it. Path existence is ensured separately.
101 if(m_zip
->getCurrentFileName().split("/").last() == "")
103 // some tools set the MS-DOS file attributes. Check those for D flag,
104 // since in some cases a folder entry does not end with a /
106 currentFile
->getFileInfo(&fi
);
107 if(fi
.externalAttr
& 0x10) // FAT entry bit 4 indicating directory
111 if(!singleoutfile
.isEmpty()
112 && QFileInfo(m_zip
->getCurrentFileName()).fileName() == file
) {
113 outfilename
= singleoutfile
;
115 else if(singleoutfile
.isEmpty()) {
116 outfilename
= dest
+ "/" + m_zip
->getCurrentFileName();
118 if(outfilename
.isEmpty())
120 QFile
outputFile(outfilename
);
121 // make sure the output path exists
122 if(!QDir().mkpath(QFileInfo(outfilename
).absolutePath())) {
124 emit
logItem(tr("Creating output path failed"), LOGERROR
);
125 qDebug() << "[ZipUtil] creating output path failed for:"
129 if(!outputFile
.open(QFile::WriteOnly
)) {
131 emit
logItem(tr("Creating output file failed"), LOGERROR
);
132 qDebug() << "[ZipUtil] creating output file failed:"
136 currentFile
->open(QIODevice::ReadOnly
);
137 outputFile
.write(currentFile
->readAll());
138 if(currentFile
->getZipError() != UNZ_OK
) {
140 emit
logItem(tr("Error during Zip operation"), LOGERROR
);
141 qDebug() << "[ZipUtil] QuaZip error:" << currentFile
->getZipError()
142 << "on file" << currentFile
->getFileName();
145 currentFile
->close();
148 emit
logProgress(current
, entries
);
151 emit
logProgress(1, 1);
157 //! @brief append a folder to current archive
158 //! @param source source folder
159 //! @param basedir base folder for archive. Will get stripped from zip paths.
160 //! @return true on success, false otherwise
161 bool ZipUtil::appendDirToArchive(QString
& source
, QString
& basedir
)
164 if(!m_zip
|| !m_zip
->isOpen()) {
165 qDebug() << "[ZipUtil] Zip file not open!";
168 // get a list of all files and folders. Needed for progress info and avoids
170 QDirIterator
iterator(source
, QDirIterator::Subdirectories
);
171 QStringList fileList
;
172 while(iterator
.hasNext()) {
174 // skip folders, we can't add them.
175 if(!QFileInfo(iterator
.filePath()).isDir()) {
176 fileList
.append(iterator
.filePath());
179 qDebug() << "[ZipUtil] Adding" << fileList
.size() << "files to archive";
181 int max
= fileList
.size();
182 for(int i
= 0; i
< max
; i
++) {
183 QString current
= fileList
.at(i
);
184 if(!appendFileToArchive(current
, basedir
)) {
185 qDebug() << "[ZipUtil] Error appending file" << current
186 << "to archive" << m_zip
->getZipName();
190 emit
logProgress(i
, max
);
196 //! @brief append a single file to current archive
198 bool ZipUtil::appendFileToArchive(QString
& file
, QString
& basedir
)
201 if(!m_zip
|| !m_zip
->isOpen()) {
202 qDebug() << "[ZipUtil] Zip file not open!";
205 // skip folders, we can't add them.
206 QFileInfo
fileinfo(file
);
207 if(fileinfo
.isDir()) {
210 QString infile
= fileinfo
.canonicalFilePath();
211 QString newfile
= infile
;
212 newfile
.remove(QDir(basedir
).canonicalPath() + "/");
214 QuaZipFile
fout(m_zip
);
217 if(!fin
.open(QFile::ReadOnly
)) {
218 qDebug() << "[ZipUtil] Could not open file for reading:" << file
;
221 if(!fout
.open(QIODevice::WriteOnly
, QuaZipNewInfo(newfile
, infile
))) {
223 qDebug() << "[ZipUtil] Could not open file for writing:" << newfile
;
227 result
= (fout
.write(fin
.readAll()) < 0) ? false : true;
234 //! @brief calculate total size of extracted files
235 qint64
ZipUtil::totalUncompressedSize(unsigned int clustersize
)
237 qint64 uncompressed
= 0;
239 QList
<QuaZipFileInfo
> items
= contentProperties();
240 if(items
.size() == 0) {
243 int max
= items
.size();
244 if(clustersize
> 0) {
245 for(int i
= 0; i
< max
; ++i
) {
246 qint64 item
= items
.at(i
).uncompressedSize
;
247 uncompressed
+= (item
+ clustersize
- (item
% clustersize
));
251 for(int i
= 0; i
< max
; ++i
) {
252 uncompressed
+= items
.at(i
).uncompressedSize
;
255 if(clustersize
> 0) {
256 qDebug() << "[ZipUtil] calculation rounded to cluster size for each file:"
259 qDebug() << "[ZipUtil] size of archive files uncompressed:"
265 QStringList
ZipUtil::files(void)
267 QList
<QuaZipFileInfo
> items
= contentProperties();
268 QStringList fileList
;
269 if(items
.size() == 0) {
272 int max
= items
.size();
273 for(int i
= 0; i
< max
; ++i
) {
274 fileList
.append(items
.at(i
).name
);
280 QList
<QuaZipFileInfo
> ZipUtil::contentProperties()
282 QList
<QuaZipFileInfo
> items
;
283 if(!m_zip
|| !m_zip
->isOpen()) {
284 qDebug() << "[ZipUtil] Zip file not open!";
288 QuaZipFile
currentFile(m_zip
);
289 for(bool more
= m_zip
->goToFirstFile(); more
; more
= m_zip
->goToNextFile())
291 currentFile
.getFileInfo(&info
);
292 if(currentFile
.getZipError() != UNZ_OK
) {
293 qDebug() << "[ZipUtil] QuaZip error:" << currentFile
.getZipError()
294 << "on file" << currentFile
.getFileName();
295 return QList
<QuaZipFileInfo
>();