summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDominik Riebeling <Dominik.Riebeling@gmail.com>2011-03-25 22:16:12 +0000
committerDominik Riebeling <Dominik.Riebeling@gmail.com>2011-03-25 22:16:12 +0000
commit8c1d114dcfcc8b3d47505e3139151eec43ebbdc4 (patch)
tree4925e1900520b0c89001c95c9da83f3533903d1e
parent0258895faa9a18c0b620ae0a63ee3768ba62747a (diff)
downloadrockbox-8c1d114dcfcc8b3d47505e3139151eec43ebbdc4.tar.gz
rockbox-8c1d114dcfcc8b3d47505e3139151eec43ebbdc4.zip
Rockbox Utility: Replace OSDaB Zip with QuaZip.
This change fixes problems with zip files created with newer zip utilities (a known issue is the iLike theme). QuaZip also allows better feedback during operations without changing the imported code. Additionally Rockbox Utility and the Theme Editor are now both using QuaZip; currently Rockbox Utility uses a copy of the sources, merging them later is planned. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29645 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--rbutil/rbutilqt/base/rbunzip.cpp66
-rw-r--r--rbutil/rbutilqt/base/rbunzip.h47
-rw-r--r--rbutil/rbutilqt/base/rbzip.cpp65
-rw-r--r--rbutil/rbutilqt/base/rbzip.h45
-rw-r--r--rbutil/rbutilqt/base/zipinstaller.cpp35
-rw-r--r--rbutil/rbutilqt/base/ziputil.cpp261
-rw-r--r--rbutil/rbutilqt/base/ziputil.h54
-rw-r--r--rbutil/rbutilqt/installwindow.cpp31
-rw-r--r--rbutil/rbutilqt/quazip/LICENSE.GPL (renamed from rbutil/rbutilqt/zip/LICENSE.GPL)0
-rw-r--r--rbutil/rbutilqt/quazip/README.ROCKBOX6
-rw-r--r--rbutil/rbutilqt/quazip/crypt.h133
-rw-r--r--rbutil/rbutilqt/quazip/ioapi.c184
-rw-r--r--rbutil/rbutilqt/quazip/ioapi.h75
-rw-r--r--rbutil/rbutilqt/quazip/quazip.cpp285
-rw-r--r--rbutil/rbutilqt/quazip/quazip.h346
-rw-r--r--rbutil/rbutilqt/quazip/quazipfile.cpp377
-rw-r--r--rbutil/rbutilqt/quazip/quazipfile.h442
-rw-r--r--rbutil/rbutilqt/quazip/quazipfileinfo.h73
-rw-r--r--rbutil/rbutilqt/quazip/quazipnewinfo.cpp59
-rw-r--r--rbutil/rbutilqt/quazip/quazipnewinfo.h109
-rw-r--r--rbutil/rbutilqt/quazip/unzip.c1601
-rw-r--r--rbutil/rbutilqt/quazip/unzip.h354
-rw-r--r--rbutil/rbutilqt/quazip/zip.c1221
-rw-r--r--rbutil/rbutilqt/quazip/zip.h235
-rw-r--r--rbutil/rbutilqt/rbutilqt.cpp25
-rw-r--r--rbutil/rbutilqt/rbutilqt.pri28
-rw-r--r--rbutil/rbutilqt/rbutilqt.pro2
-rw-r--r--rbutil/rbutilqt/zip/README69
-rw-r--r--rbutil/rbutilqt/zip/README.ROCKBOX8
-rw-r--r--rbutil/rbutilqt/zip/unzip.cpp1366
-rw-r--r--rbutil/rbutilqt/zip/unzip.h144
-rw-r--r--rbutil/rbutilqt/zip/unzip_p.h112
-rw-r--r--rbutil/rbutilqt/zip/zip.cpp1221
-rw-r--r--rbutil/rbutilqt/zip/zip.h115
-rw-r--r--rbutil/rbutilqt/zip/zip_p.h93
-rw-r--r--rbutil/rbutilqt/zip/zipentry_p.h78
36 files changed, 5880 insertions, 3485 deletions
diff --git a/rbutil/rbutilqt/base/rbunzip.cpp b/rbutil/rbutilqt/base/rbunzip.cpp
deleted file mode 100644
index f71db5377e..0000000000
--- a/rbutil/rbutilqt/base/rbunzip.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2008 by Dominik Riebeling
10 * $Id$
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include "rbunzip.h"
21#include <QtCore>
22
23
24//! @brief extract archive to destination
25UnZip::ErrorCode RbUnZip::extractArchive(const QString& dest)
26{
27 qDebug() << "[UNZIP] extracting archive to" << dest;
28 QStringList files = this->fileList();
29 UnZip::ErrorCode error = Ok;
30 m_abortunzip = false;
31
32 int total = files.size();
33 for(int i = 0; i < total; i++) {
34 error = this->extractFile(files.at(i), dest, UnZip::ExtractPaths);
35 emit unzipProgress(i + 1, total);
36 QCoreApplication::processEvents(); // update UI
37 if(m_abortunzip)
38 error = SkipAll;
39 if(error != Ok)
40 break;
41 }
42 return error;
43}
44
45
46//! @brief abort an extractArchive() operation.
47void RbUnZip::abortUnzip(void)
48{
49 m_abortunzip = true;
50}
51
52
53//! @brief return total size of extracted files in archive.
54qulonglong RbUnZip::totalSize(void)
55{
56 QList<ZipEntry> l = this->entryList();
57 qulonglong total = 0;
58
59 int i = l.size();
60 while(i--)
61 total += l.at(i).uncompressedSize;
62
63 return total;
64
65}
66
diff --git a/rbutil/rbutilqt/base/rbunzip.h b/rbutil/rbutilqt/base/rbunzip.h
deleted file mode 100644
index c0b7215b6a..0000000000
--- a/rbutil/rbutilqt/base/rbunzip.h
+++ /dev/null
@@ -1,47 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2008 by Dominik Riebeling
10 * $Id$
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#ifndef RBUNZIP_H
23#define RBUNZIP_H
24
25#include <QtCore>
26#include "zip/unzip.h"
27#include "zip/zip.h"
28
29class RbUnZip : public QObject, public UnZip
30{
31 Q_OBJECT
32 public:
33 UnZip::ErrorCode extractArchive(const QString&);
34 qulonglong totalSize(void);
35
36 signals:
37 void unzipProgress(int, int);
38
39 public slots:
40 void abortUnzip(void);
41
42 private:
43 bool m_abortunzip;
44};
45
46#endif
47
diff --git a/rbutil/rbutilqt/base/rbzip.cpp b/rbutil/rbutilqt/base/rbzip.cpp
deleted file mode 100644
index c011c0ccbc..0000000000
--- a/rbutil/rbutilqt/base/rbzip.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2008 by Dominik Wenger
10 * $Id$
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include "rbzip.h"
21#include <QtCore>
22
23
24Zip::ErrorCode RbZip::createZip(QString zip,QString dir)
25{
26 Zip::ErrorCode error = Ok;
27 m_curEntry = 1;
28 m_numEntrys=0;
29
30 QCoreApplication::processEvents();
31
32 // get number of entrys in dir
33 QDirIterator it(dir, QDirIterator::Subdirectories);
34 while (it.hasNext())
35 {
36 it.next();
37 m_numEntrys++;
38 QCoreApplication::processEvents();
39 }
40
41
42 //! create zip
43 error = Zip::createArchive(zip);
44 if(error != Ok)
45 return error;
46
47 //! add the content
48 error = Zip::addDirectory(dir);
49 if(error != Ok)
50 return error;
51
52 //! close zip
53 error = Zip::closeArchive();
54
55 return error;
56}
57
58void RbZip::progress()
59{
60 m_curEntry++;
61 emit zipProgress(m_curEntry,m_numEntrys);
62 QCoreApplication::processEvents(); // update UI
63}
64
65
diff --git a/rbutil/rbutilqt/base/rbzip.h b/rbutil/rbutilqt/base/rbzip.h
deleted file mode 100644
index d2681ec097..0000000000
--- a/rbutil/rbutilqt/base/rbzip.h
+++ /dev/null
@@ -1,45 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2008 by Dominik Wenger
10 * $Id$
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#ifndef RBZIP_H
23#define RBZIP_H
24
25#include <QtCore>
26#include "zip/zip.h"
27
28class RbZip : public QObject, public Zip
29{
30 Q_OBJECT
31 public:
32 Zip::ErrorCode createZip(QString zip,QString dir);
33
34 virtual void progress();
35
36 signals:
37 void zipProgress(int, int);
38
39 private:
40 int m_curEntry;
41 int m_numEntrys;
42};
43
44#endif
45
diff --git a/rbutil/rbutilqt/base/zipinstaller.cpp b/rbutil/rbutilqt/base/zipinstaller.cpp
index 1822d3c9ed..07a901ddf4 100644
--- a/rbutil/rbutilqt/base/zipinstaller.cpp
+++ b/rbutil/rbutilqt/base/zipinstaller.cpp
@@ -19,8 +19,8 @@
19 19
20#include <QtCore> 20#include <QtCore>
21#include "zipinstaller.h" 21#include "zipinstaller.h"
22#include "rbunzip.h"
23#include "utils.h" 22#include "utils.h"
23#include "ziputil.h"
24 24
25ZipInstaller::ZipInstaller(QObject* parent): QObject(parent) 25ZipInstaller::ZipInstaller(QObject* parent): QObject(parent)
26{ 26{
@@ -132,39 +132,28 @@ void ZipInstaller::downloadDone(bool error)
132 emit logItem(tr("Extracting file."), LOGINFO); 132 emit logItem(tr("Extracting file."), LOGINFO);
133 QCoreApplication::processEvents(); 133 QCoreApplication::processEvents();
134 134
135 UnZip::ErrorCode ec; 135 ZipUtil zip(this);
136 RbUnZip uz; 136 connect(&zip, SIGNAL(logProgress(int, int)), this, SIGNAL(logProgress(int, int)));
137 connect(&uz, SIGNAL(unzipProgress(int, int)), this, SIGNAL(logProgress(int, int))); 137 connect(&zip, SIGNAL(logItem(QString, int)), this, SIGNAL(logItem(QString, int)));
138 connect(this, SIGNAL(internalAborted()), &uz, SLOT(abortUnzip())); 138 zip.open(m_file, QuaZip::mdUnzip);
139 ec = uz.openArchive(m_file);
140 if(ec != UnZip::Ok) {
141 emit logItem(tr("Opening archive failed: %1.")
142 .arg(uz.formatError(ec)),LOGERROR);
143 emit logProgress(1, 1);
144 emit done(true);
145 return;
146 }
147
148 // check for free space. Make sure after installation will still be 139 // check for free space. Make sure after installation will still be
149 // some room for operating (also includes calculation mistakes due to 140 // some room for operating (also includes calculation mistakes due to
150 // cluster sizes on the player). 141 // cluster sizes on the player).
151 if(Utils::filesystemFree(m_mountpoint) < (uz.totalSize() + 1000000)) { 142 if(Utils::filesystemFree(m_mountpoint)
143 < (zip.totalUncompressedSize() + 1000000)) {
152 emit logItem(tr("Not enough disk space! Aborting."), LOGERROR); 144 emit logItem(tr("Not enough disk space! Aborting."), LOGERROR);
153 emit logProgress(1, 1); 145 emit logProgress(1, 1);
154 emit done(true); 146 emit done(true);
155 return; 147 return;
156 } 148 }
157 ec = uz.extractArchive(m_mountpoint); 149 zipContents = zip.files();
158 // TODO: better handling of aborted unzip operation. 150 if(!zip.extractArchive(m_mountpoint)) {
159 if(ec != UnZip::Ok) { 151 emit logItem(tr("Extraction failed!"), LOGERROR);
160 emit logItem(tr("Extracting failed: %1.")
161 .arg(uz.formatError(ec)),LOGERROR);
162 emit logProgress(1, 1); 152 emit logProgress(1, 1);
163 emit done(true); 153 emit done(true);
164 return; 154 return;
165 } 155 }
166 // prepare file list for log 156 zip.close();
167 zipContents = uz.fileList();
168 } 157 }
169 else { 158 else {
170 // only copy the downloaded file to the output location / name 159 // only copy the downloaded file to the output location / name
@@ -185,7 +174,7 @@ void ZipInstaller::downloadDone(bool error)
185 } 174 }
186 175
187 // add file to log 176 // add file to log
188 zipContents.append( m_target); 177 zipContents.append(m_target);
189 } 178 }
190 179
191 emit logItem(tr("Creating installation log"),LOGINFO); 180 emit logItem(tr("Creating installation log"),LOGINFO);
diff --git a/rbutil/rbutilqt/base/ziputil.cpp b/rbutil/rbutilqt/base/ziputil.cpp
new file mode 100644
index 0000000000..ed8f17eefe
--- /dev/null
+++ b/rbutil/rbutilqt/base/ziputil.cpp
@@ -0,0 +1,261 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2011 Dominik Riebeling
10 * $Id$
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include <QtCore>
21#include <QDebug>
22#include "ziputil.h"
23#include "progressloggerinterface.h"
24
25#include "quazip.h"
26#include "quazipfile.h"
27#include "quazipfileinfo.h"
28
29
30ZipUtil::ZipUtil(QObject* parent) : QObject(parent)
31{
32 m_zip = NULL;
33}
34
35
36ZipUtil::~ZipUtil()
37{
38 if(m_zip) {
39 delete m_zip;
40 }
41}
42
43//! @brief open zip file.
44//! @param zipfile path to zip file
45//! @param mode open mode (see QuaZip::Mode)
46//! @return true on success, false otherwise
47bool ZipUtil::open(QString& zipfile, QuaZip::Mode mode)
48{
49 m_zip = new QuaZip(zipfile);
50 return m_zip->open(mode);
51}
52
53
54//! @brief close zip file.
55//! @return true on success, false otherwise
56bool ZipUtil::close(void)
57{
58 if(!m_zip) {
59 return false;
60 }
61
62 int error = UNZ_OK;
63 if(m_zip->isOpen()) {
64 m_zip->close();
65 error = m_zip->getZipError();
66 }
67 delete m_zip;
68 m_zip = NULL;
69 return (error == UNZ_OK) ? true : false;
70}
71
72
73//! @brief extract currently opened archive
74//! @brief dest path to extract archive to
75//! @return true on success, false otherwise
76bool ZipUtil::extractArchive(QString& dest)
77{
78 bool result = true;
79 if(!m_zip) {
80 return false;
81 }
82 QuaZipFile *currentFile = new QuaZipFile(m_zip);
83 int entries = m_zip->getEntriesCount();
84 int current = 0;
85 for(bool more = m_zip->goToFirstFile(); more; more = m_zip->goToNextFile())
86 {
87 ++current;
88 // if the entry is a path ignore it. Path existence is ensured separately.
89 if(m_zip->getCurrentFileName().split("/").last() == "")
90 continue;
91
92 QString outfilename = dest + "/" + m_zip->getCurrentFileName();
93 QFile outputFile(outfilename);
94 // make sure the output path exists
95 if(!QDir().mkpath(QFileInfo(outfilename).absolutePath())) {
96 result = false;
97 emit logItem(tr("Creating output path failed"), LOGERROR);
98 qDebug() << "[ZipUtil] creating output path failed for:"
99 << outfilename;
100 break;
101 }
102 if(!outputFile.open(QFile::WriteOnly)) {
103 result = false;
104 emit logItem(tr("Creating output file failed"), LOGERROR);
105 qDebug() << "[ZipUtil] creating output file failed:"
106 << outfilename;
107 break;
108 }
109 currentFile->open(QIODevice::ReadOnly);
110 outputFile.write(currentFile->readAll());
111 if(currentFile->getZipError() != UNZ_OK) {
112 result = false;
113 emit logItem(tr("Error during Zip operation"), LOGERROR);
114 qDebug() << "[ZipUtil] QuaZip error:" << currentFile->getZipError()
115 << "on file" << currentFile->getFileName();
116 break;
117 }
118 currentFile->close();
119 outputFile.close();
120
121 emit logProgress(current, entries);
122 }
123 delete currentFile;
124 emit logProgress(1, 1);
125
126 return result;
127}
128
129
130//! @brief append a folder to current archive
131//! @param source source folder
132//! @param basedir base folder for archive. Will get stripped from zip paths.
133//! @return true on success, false otherwise
134bool ZipUtil::appendDirToArchive(QString& source, QString& basedir)
135{
136 bool result = true;
137 if(!m_zip || !m_zip->isOpen()) {
138 qDebug() << "[ZipUtil] Zip file not open!";
139 return false;
140 }
141 // get a list of all files and folders. Needed for progress info and avoids
142 // recursive calls.
143 QDirIterator iterator(source, QDirIterator::Subdirectories);
144 QStringList fileList;
145 while(iterator.hasNext()) {
146 iterator.next();
147 // skip folders, we can't add them.
148 if(!QFileInfo(iterator.filePath()).isDir()) {
149 fileList.append(iterator.filePath());
150 }
151 }
152 qDebug() << "[ZipUtil] Adding" << fileList.size() << "files to archive";
153
154 int max = fileList.size();
155 for(int i = 0; i < max; i++) {
156 QString current = fileList.at(i);
157 if(!appendFileToArchive(current, basedir)) {
158 qDebug() << "[ZipUtil] Error appending file" << current
159 << "to archive" << m_zip->getZipName();
160 result = false;
161 break;
162 }
163 emit logProgress(i, max);
164 }
165 return result;
166}
167
168
169//! @brief append a single file to current archive
170//!
171bool ZipUtil::appendFileToArchive(QString& file, QString& basedir)
172{
173 bool result = true;
174 if(!m_zip || !m_zip->isOpen()) {
175 qDebug() << "[ZipUtil] Zip file not open!";
176 return false;
177 }
178 // skip folders, we can't add them.
179 QFileInfo fileinfo(file);
180 if(fileinfo.isDir()) {
181 return false;
182 }
183 QString infile = fileinfo.canonicalFilePath();
184 QString newfile = infile;
185 newfile.remove(QDir(basedir).canonicalPath() + "/");
186
187 QuaZipFile fout(m_zip);
188 QFile fin(file);
189
190 if(!fin.open(QFile::ReadOnly)) {
191 qDebug() << "[ZipUtil] Could not open file for reading:" << file;
192 return false;
193 }
194 if(!fout.open(QIODevice::WriteOnly, QuaZipNewInfo(newfile, infile))) {
195 fin.close();
196 qDebug() << "[ZipUtil] Could not open file for writing:" << newfile;
197 return false;
198 }
199
200 result = (fout.write(fin.readAll()) < 0) ? false : true;
201 fin.close();
202 fout.close();
203 return result;
204}
205
206
207//! @brief calculate total size of extracted files
208qint64 ZipUtil::totalUncompressedSize(void)
209{
210 qint64 uncompressed = 0;
211
212 QList<QuaZipFileInfo> items = contentProperties();
213 if(items.size() == 0) {
214 return -1;
215 }
216 int max = items.size();
217 for(int i = 0; i < max; ++i) {
218 uncompressed += items.at(i).uncompressedSize;
219 }
220 qDebug() << "[ZipUtil] size of archive files uncompressed:" << uncompressed;
221 return uncompressed;
222}
223
224
225QStringList ZipUtil::files(void)
226{
227 QList<QuaZipFileInfo> items = contentProperties();
228 QStringList fileList;
229 if(items.size() == 0) {
230 return fileList;
231 }
232 int max = items.size();
233 for(int i = 0; i < max; ++i) {
234 fileList.append(items.at(i).name);
235 }
236 return fileList;
237}
238
239
240QList<QuaZipFileInfo> ZipUtil::contentProperties()
241{
242 QList<QuaZipFileInfo> items;
243 if(!m_zip || !m_zip->isOpen()) {
244 qDebug() << "[ZipUtil] Zip file not open!";
245 return items;
246 }
247 QuaZipFileInfo info;
248 QuaZipFile currentFile(m_zip);
249 for(bool more = m_zip->goToFirstFile(); more; more = m_zip->goToNextFile())
250 {
251 currentFile.getFileInfo(&info);
252 if(currentFile.getZipError() != UNZ_OK) {
253 qDebug() << "[ZipUtil] QuaZip error:" << currentFile.getZipError()
254 << "on file" << currentFile.getFileName();
255 return QList<QuaZipFileInfo>();
256 }
257 items.append(info);
258 }
259 return items;
260}
261
diff --git a/rbutil/rbutilqt/base/ziputil.h b/rbutil/rbutilqt/base/ziputil.h
new file mode 100644
index 0000000000..cfafb96566
--- /dev/null
+++ b/rbutil/rbutilqt/base/ziputil.h
@@ -0,0 +1,54 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2011 Dominik Riebeling
10 * $Id$
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#ifndef ZIPUTIL_H
21#define ZIPUTIL_H
22
23#include <QtCore>
24#include "quazip.h"
25#include "quazipfile.h"
26#include "quazipfileinfo.h"
27
28class ZipUtil : public QObject
29{
30 Q_OBJECT
31
32 public:
33 ZipUtil(QObject* parent);
34 ~ZipUtil();
35 bool open(QString& zipfile, QuaZip::Mode mode);
36 bool close(void);
37 bool extractArchive(QString& dest);
38 bool appendDirToArchive(QString& source, QString& basedir);
39 bool appendFileToArchive(QString& file, QString& basedir);
40 qint64 totalUncompressedSize(void);
41 QStringList files(void);
42
43 signals:
44 void logProgress(int, int);
45 void logItem(QString, int);
46
47 private:
48 QList<QuaZipFileInfo> contentProperties();
49 QuaZip* m_zip;
50 QuaZipFile* m_file;
51
52};
53#endif
54
diff --git a/rbutil/rbutilqt/installwindow.cpp b/rbutil/rbutilqt/installwindow.cpp
index 7b12303b96..c619bb5208 100644
--- a/rbutil/rbutilqt/installwindow.cpp
+++ b/rbutil/rbutilqt/installwindow.cpp
@@ -19,13 +19,13 @@
19 19
20#include "installwindow.h" 20#include "installwindow.h"
21#include "ui_installwindowfrm.h" 21#include "ui_installwindowfrm.h"
22#include "rbzip.h"
23#include "system.h" 22#include "system.h"
24#include "rbsettings.h" 23#include "rbsettings.h"
25#include "serverinfo.h" 24#include "serverinfo.h"
26#include "systeminfo.h" 25#include "systeminfo.h"
27#include "utils.h" 26#include "utils.h"
28#include "rockboxinfo.h" 27#include "rockboxinfo.h"
28#include "ziputil.h"
29 29
30InstallWindow::InstallWindow(QWidget *parent) : QDialog(parent) 30InstallWindow::InstallWindow(QWidget *parent) : QDialog(parent)
31{ 31{
@@ -55,8 +55,8 @@ InstallWindow::InstallWindow(QWidget *parent) : QDialog(parent)
55 ui.Backupgroup->hide(); 55 ui.Backupgroup->hide();
56 } 56 }
57 backupCheckboxChanged(Qt::Unchecked); 57 backupCheckboxChanged(Qt::Unchecked);
58 58
59 59
60 if(ServerInfo::value(ServerInfo::DailyRevision).toString().isEmpty()) { 60 if(ServerInfo::value(ServerInfo::DailyRevision).toString().isEmpty()) {
61 ui.radioArchived->setEnabled(false); 61 ui.radioArchived->setEnabled(false);
62 qDebug() << "[Install] no information about archived version available!"; 62 qDebug() << "[Install] no information about archived version available!";
@@ -89,7 +89,7 @@ InstallWindow::InstallWindow(QWidget *parent) : QDialog(parent)
89 font.setBold(true); 89 font.setBold(true);
90 ui.radioCurrent->setFont(font); 90 ui.radioCurrent->setFont(font);
91 } 91 }
92 92
93} 93}
94 94
95 95
@@ -186,6 +186,7 @@ void InstallWindow::accept()
186 if(ui.backup->isChecked()) 186 if(ui.backup->isChecked())
187 { 187 {
188 logger->addItem(tr("Beginning Backup..."),LOGINFO); 188 logger->addItem(tr("Beginning Backup..."),LOGINFO);
189 QCoreApplication::processEvents();
189 190
190 //! create dir, if it doesnt exist 191 //! create dir, if it doesnt exist
191 QFileInfo backupFile(m_backupName); 192 QFileInfo backupFile(m_backupName);
@@ -196,16 +197,20 @@ void InstallWindow::accept()
196 } 197 }
197 198
198 //! create backup 199 //! create backup
199 RbZip backup; 200 bool result = true;
200 connect(&backup,SIGNAL(zipProgress(int,int)),logger,SLOT(setProgress(int,int))); 201 ZipUtil zip(this);
201 if(backup.createZip(m_backupName, 202 connect(&zip, SIGNAL(logProgress(int, int)), logger, SLOT(setProgress(int, int)));
202 RbSettings::value(RbSettings::Mountpoint).toString() + "/.rockbox") == Zip::Ok) 203 connect(&zip, SIGNAL(logItem(QString, int)), logger, SLOT(addItem(QString, int)));
203 { 204 zip.open(m_backupName, QuaZip::mdCreate);
204 logger->addItem(tr("Backup successful"),LOGOK); 205 QString mp = RbSettings::value(RbSettings::Mountpoint).toString();
206 QString folder = mp + "/.rockbox";
207 result = zip.appendDirToArchive(folder, mp);
208 zip.close();
209 if(result) {
210 logger->addItem(tr("Backup finished."), LOGINFO);
205 } 211 }
206 else 212 else {
207 { 213 logger->addItem(tr("Backup failed!"), LOGERROR);
208 logger->addItem(tr("Backup failed!"),LOGERROR);
209 logger->setFinished(); 214 logger->setFinished();
210 return; 215 return;
211 } 216 }
diff --git a/rbutil/rbutilqt/zip/LICENSE.GPL b/rbutil/rbutilqt/quazip/LICENSE.GPL
index 04a7580109..04a7580109 100644
--- a/rbutil/rbutilqt/zip/LICENSE.GPL
+++ b/rbutil/rbutilqt/quazip/LICENSE.GPL
diff --git a/rbutil/rbutilqt/quazip/README.ROCKBOX b/rbutil/rbutilqt/quazip/README.ROCKBOX
new file mode 100644
index 0000000000..b95f80caee
--- /dev/null
+++ b/rbutil/rbutilqt/quazip/README.ROCKBOX
@@ -0,0 +1,6 @@
1This folder contains the quazip project for ZIP file compression/decompression.
2These files are distributed under the GPL v2 or later.
3The source files have been last synced with the projects release at
4http://sourceforge.net/projects/quazip/ on July 20, 2010
5
6
diff --git a/rbutil/rbutilqt/quazip/crypt.h b/rbutil/rbutilqt/quazip/crypt.h
new file mode 100644
index 0000000000..82748c5715
--- /dev/null
+++ b/rbutil/rbutilqt/quazip/crypt.h
@@ -0,0 +1,133 @@
1/* crypt.h -- base code for crypt/uncrypt ZIPfile
2
3
4 Version 1.01e, February 12th, 2005
5
6 Copyright (C) 1998-2005 Gilles Vollant
7
8 This code is a modified version of crypting code in Infozip distribution
9
10 The encryption/decryption parts of this source code (as opposed to the
11 non-echoing password parts) were originally written in Europe. The
12 whole source package can be freely distributed, including from the USA.
13 (Prior to January 2000, re-export from the US was a violation of US law.)
14
15 This encryption code is a direct transcription of the algorithm from
16 Roger Schlafly, described by Phil Katz in the file appnote.txt. This
17 file (appnote.txt) is distributed with the PKZIP program (even in the
18 version without encryption capabilities).
19
20 If you don't need crypting in your application, just define symbols
21 NOCRYPT and NOUNCRYPT.
22
23 This code support the "Traditional PKWARE Encryption".
24
25 The new AES encryption added on Zip format by Winzip (see the page
26 http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong
27 Encryption is not supported.
28*/
29
30#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8))
31
32/***********************************************************************
33 * Return the next byte in the pseudo-random sequence
34 */
35static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab)
36{
37 (void) pcrc_32_tab; /* avoid "unused parameter" warning */
38 unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an
39 * unpredictable manner on 16-bit systems; not a problem
40 * with any known compiler so far, though */
41
42 temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2;
43 return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
44}
45
46/***********************************************************************
47 * Update the encryption keys with the next byte of plain text
48 */
49static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c)
50{
51 (*(pkeys+0)) = CRC32((*(pkeys+0)), c);
52 (*(pkeys+1)) += (*(pkeys+0)) & 0xff;
53 (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1;
54 {
55 register int keyshift = (int)((*(pkeys+1)) >> 24);
56 (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift);
57 }
58 return c;
59}
60
61
62/***********************************************************************
63 * Initialize the encryption keys and the random header according to
64 * the given password.
65 */
66static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab)
67{
68 *(pkeys+0) = 305419896L;
69 *(pkeys+1) = 591751049L;
70 *(pkeys+2) = 878082192L;
71 while (*passwd != '\0') {
72 update_keys(pkeys,pcrc_32_tab,(int)*passwd);
73 passwd++;
74 }
75}
76
77#define zdecode(pkeys,pcrc_32_tab,c) \
78 (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab)))
79
80#define zencode(pkeys,pcrc_32_tab,c,t) \
81 (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c))
82
83#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED
84
85#define RAND_HEAD_LEN 12
86 /* "last resort" source for second part of crypt seed pattern */
87# ifndef ZCR_SEED2
88# define ZCR_SEED2 3141592654UL /* use PI as default pattern */
89# endif
90
91static int crypthead(passwd, buf, bufSize, pkeys, pcrc_32_tab, crcForCrypting)
92 const char *passwd; /* password string */
93 unsigned char *buf; /* where to write header */
94 int bufSize;
95 unsigned long* pkeys;
96 const unsigned long* pcrc_32_tab;
97 unsigned long crcForCrypting;
98{
99 int n; /* index in random header */
100 int t; /* temporary */
101 int c; /* random byte */
102 unsigned char header[RAND_HEAD_LEN-2]; /* random header */
103 static unsigned calls = 0; /* ensure different random header each time */
104
105 if (bufSize<RAND_HEAD_LEN)
106 return 0;
107
108 /* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the
109 * output of rand() to get less predictability, since rand() is
110 * often poorly implemented.
111 */
112 if (++calls == 1)
113 {
114 srand((unsigned)(time(NULL) ^ ZCR_SEED2));
115 }
116 init_keys(passwd, pkeys, pcrc_32_tab);
117 for (n = 0; n < RAND_HEAD_LEN-2; n++)
118 {
119 c = (rand() >> 7) & 0xff;
120 header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t);
121 }
122 /* Encrypt random header (last two bytes is high word of crc) */
123 init_keys(passwd, pkeys, pcrc_32_tab);
124 for (n = 0; n < RAND_HEAD_LEN-2; n++)
125 {
126 buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t);
127 }
128 buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t);
129 buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t);
130 return n;
131}
132
133#endif
diff --git a/rbutil/rbutilqt/quazip/ioapi.c b/rbutil/rbutilqt/quazip/ioapi.c
new file mode 100644
index 0000000000..cf29a317fd
--- /dev/null
+++ b/rbutil/rbutilqt/quazip/ioapi.c
@@ -0,0 +1,184 @@
1/* ioapi.c -- IO base function header for compress/uncompress .zip
2 files using zlib + zip or unzip API
3
4 Version 1.01e, February 12th, 2005
5
6 Copyright (C) 1998-2005 Gilles Vollant
7*/
8
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12
13#include "zlib.h"
14#include "ioapi.h"
15
16
17
18/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
19
20#ifndef SEEK_CUR
21#define SEEK_CUR 1
22#endif
23
24#ifndef SEEK_END
25#define SEEK_END 2
26#endif
27
28#ifndef SEEK_SET
29#define SEEK_SET 0
30#endif
31
32voidpf ZCALLBACK fopen_file_func OF((
33 voidpf opaque,
34 const char* filename,
35 int mode));
36
37uLong ZCALLBACK fread_file_func OF((
38 voidpf opaque,
39 voidpf stream,
40 void* buf,
41 uLong size));
42
43uLong ZCALLBACK fwrite_file_func OF((
44 voidpf opaque,
45 voidpf stream,
46 const void* buf,
47 uLong size));
48
49long ZCALLBACK ftell_file_func OF((
50 voidpf opaque,
51 voidpf stream));
52
53long ZCALLBACK fseek_file_func OF((
54 voidpf opaque,
55 voidpf stream,
56 uLong offset,
57 int origin));
58
59int ZCALLBACK fclose_file_func OF((
60 voidpf opaque,
61 voidpf stream));
62
63int ZCALLBACK ferror_file_func OF((
64 voidpf opaque,
65 voidpf stream));
66
67
68voidpf ZCALLBACK fopen_file_func (opaque, filename, mode)
69 voidpf opaque;
70 const char* filename;
71 int mode;
72{
73 (void) opaque; /* avoid "unused parameter" warning */
74 FILE* file = NULL;
75 const char* mode_fopen = NULL;
76 if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
77 mode_fopen = "rb";
78 else
79 if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
80 mode_fopen = "r+b";
81 else
82 if (mode & ZLIB_FILEFUNC_MODE_CREATE)
83 mode_fopen = "wb";
84
85 if ((filename!=NULL) && (mode_fopen != NULL))
86 file = fopen(filename, mode_fopen);
87 return file;
88}
89
90
91uLong ZCALLBACK fread_file_func (opaque, stream, buf, size)
92 voidpf opaque;
93 voidpf stream;
94 void* buf;
95 uLong size;
96{
97 (void) opaque; /* avoid "unused parameter" warning */
98 uLong ret;
99 ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream);
100 return ret;
101}
102
103
104uLong ZCALLBACK fwrite_file_func (opaque, stream, buf, size)
105 voidpf opaque;
106 voidpf stream;
107 const void* buf;
108 uLong size;
109{
110 (void) opaque; /* avoid "unused parameter" warning */
111 uLong ret;
112 ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream);
113 return ret;
114}
115
116long ZCALLBACK ftell_file_func (opaque, stream)
117 voidpf opaque;
118 voidpf stream;
119{
120 (void) opaque; /* avoid "unused parameter" warning */
121 long ret;
122 ret = ftell((FILE *)stream);
123 return ret;
124}
125
126long ZCALLBACK fseek_file_func (opaque, stream, offset, origin)
127 voidpf opaque;
128 voidpf stream;
129 uLong offset;
130 int origin;
131{
132 (void) opaque; /* avoid "unused parameter" warning */
133 int fseek_origin=0;
134 long ret;
135 switch (origin)
136 {
137 case ZLIB_FILEFUNC_SEEK_CUR :
138 fseek_origin = SEEK_CUR;
139 break;
140 case ZLIB_FILEFUNC_SEEK_END :
141 fseek_origin = SEEK_END;
142 break;
143 case ZLIB_FILEFUNC_SEEK_SET :
144 fseek_origin = SEEK_SET;
145 break;
146 default: return -1;
147 }
148 ret = 0;
149 fseek((FILE *)stream, offset, fseek_origin);
150 return ret;
151}
152
153int ZCALLBACK fclose_file_func (opaque, stream)
154 voidpf opaque;
155 voidpf stream;
156{
157 (void) opaque; /* avoid "unused parameter" warning */
158 int ret;
159 ret = fclose((FILE *)stream);
160 return ret;
161}
162
163int ZCALLBACK ferror_file_func (opaque, stream)
164 voidpf opaque;
165 voidpf stream;
166{
167 (void) opaque; /* avoid "unused parameter" warning */
168 int ret;
169 ret = ferror((FILE *)stream);
170 return ret;
171}
172
173void fill_fopen_filefunc (pzlib_filefunc_def)
174 zlib_filefunc_def* pzlib_filefunc_def;
175{
176 pzlib_filefunc_def->zopen_file = fopen_file_func;
177 pzlib_filefunc_def->zread_file = fread_file_func;
178 pzlib_filefunc_def->zwrite_file = fwrite_file_func;
179 pzlib_filefunc_def->ztell_file = ftell_file_func;
180 pzlib_filefunc_def->zseek_file = fseek_file_func;
181 pzlib_filefunc_def->zclose_file = fclose_file_func;
182 pzlib_filefunc_def->zerror_file = ferror_file_func;
183 pzlib_filefunc_def->opaque = NULL;
184}
diff --git a/rbutil/rbutilqt/quazip/ioapi.h b/rbutil/rbutilqt/quazip/ioapi.h
new file mode 100644
index 0000000000..7d457baab3
--- /dev/null
+++ b/rbutil/rbutilqt/quazip/ioapi.h
@@ -0,0 +1,75 @@
1/* ioapi.h -- IO base function header for compress/uncompress .zip
2 files using zlib + zip or unzip API
3
4 Version 1.01e, February 12th, 2005
5
6 Copyright (C) 1998-2005 Gilles Vollant
7*/
8
9#ifndef _ZLIBIOAPI_H
10#define _ZLIBIOAPI_H
11
12
13#define ZLIB_FILEFUNC_SEEK_CUR (1)
14#define ZLIB_FILEFUNC_SEEK_END (2)
15#define ZLIB_FILEFUNC_SEEK_SET (0)
16
17#define ZLIB_FILEFUNC_MODE_READ (1)
18#define ZLIB_FILEFUNC_MODE_WRITE (2)
19#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3)
20
21#define ZLIB_FILEFUNC_MODE_EXISTING (4)
22#define ZLIB_FILEFUNC_MODE_CREATE (8)
23
24
25#ifndef ZCALLBACK
26
27#if (defined(WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK)
28#define ZCALLBACK CALLBACK
29#else
30#define ZCALLBACK
31#endif
32#endif
33
34#ifdef __cplusplus
35extern "C" {
36#endif
37
38typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode));
39typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size));
40typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size));
41typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream));
42typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin));
43typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream));
44typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream));
45
46typedef struct zlib_filefunc_def_s
47{
48 open_file_func zopen_file;
49 read_file_func zread_file;
50 write_file_func zwrite_file;
51 tell_file_func ztell_file;
52 seek_file_func zseek_file;
53 close_file_func zclose_file;
54 testerror_file_func zerror_file;
55 voidpf opaque;
56} zlib_filefunc_def;
57
58
59
60void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));
61
62#define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size))
63#define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size))
64#define ZTELL(filefunc,filestream) ((*((filefunc).ztell_file))((filefunc).opaque,filestream))
65#define ZSEEK(filefunc,filestream,pos,mode) ((*((filefunc).zseek_file))((filefunc).opaque,filestream,pos,mode))
66#define ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream))
67#define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream))
68
69
70#ifdef __cplusplus
71}
72#endif
73
74#endif
75
diff --git a/rbutil/rbutilqt/quazip/quazip.cpp b/rbutil/rbutilqt/quazip/quazip.cpp
new file mode 100644
index 0000000000..3f7314a433
--- /dev/null
+++ b/rbutil/rbutilqt/quazip/quazip.cpp
@@ -0,0 +1,285 @@
1/*
2-- A kind of "standard" GPL license statement --
3QuaZIP - a Qt/C++ wrapper for the ZIP/UNZIP package
4Copyright (C) 2005-2007 Sergey A. Tachenov
5
6This program is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2 of the License, or (at your
9option) any later version.
10
11This program is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
14Public License for more details.
15
16You should have received a copy of the GNU General Public License along
17with this program; if not, write to the Free Software Foundation, Inc.,
1859 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
20-- A kind of "standard" GPL license statement ends here --
21
22See COPYING file for GPL.
23
24You are also permitted to use QuaZIP under the terms of LGPL (see
25COPYING.LGPL). You are free to choose either license, but please note
26that QuaZIP makes use of Qt, which is not licensed under LGPL. So if
27you are using Open Source edition of Qt, you therefore MUST use GPL for
28your code based on QuaZIP, since it would be also based on Qt in this
29case. If you are Qt commercial license owner, then you are free to use
30QuaZIP as long as you respect either GPL or LGPL for QuaZIP code.
31 **/
32
33#include <QFile>
34
35#include "quazip.h"
36
37QuaZip::QuaZip():
38 fileNameCodec(QTextCodec::codecForLocale()),
39 commentCodec(QTextCodec::codecForLocale()),
40 mode(mdNotOpen), hasCurrentFile_f(false), zipError(UNZ_OK)
41{
42}
43
44QuaZip::QuaZip(const QString& zipName):
45 fileNameCodec(QTextCodec::codecForLocale()),
46 commentCodec(QTextCodec::codecForLocale()),
47 zipName(zipName),
48 mode(mdNotOpen), hasCurrentFile_f(false), zipError(UNZ_OK)
49{
50}
51
52QuaZip::~QuaZip()
53{
54 if(isOpen()) close();
55}
56
57bool QuaZip::open(Mode mode, zlib_filefunc_def* ioApi)
58{
59 zipError=UNZ_OK;
60 if(isOpen()) {
61 qWarning("QuaZip::open(): ZIP already opened");
62 return false;
63 }
64 switch(mode) {
65 case mdUnzip:
66 unzFile_f=unzOpen2(QFile::encodeName(zipName).constData(), ioApi);
67 if(unzFile_f!=NULL) {
68 this->mode=mode;
69 return true;
70 } else {
71 zipError=UNZ_OPENERROR;
72 return false;
73 }
74 case mdCreate:
75 case mdAppend:
76 case mdAdd:
77 zipFile_f=zipOpen2(QFile::encodeName(zipName).constData(),
78 mode==mdCreate?APPEND_STATUS_CREATE:
79 mode==mdAppend?APPEND_STATUS_CREATEAFTER:
80 APPEND_STATUS_ADDINZIP,
81 NULL,
82 ioApi);
83 if(zipFile_f!=NULL) {
84 this->mode=mode;
85 return true;
86 } else {
87 zipError=UNZ_OPENERROR;
88 return false;
89 }
90 default:
91 qWarning("QuaZip::open(): unknown mode: %d", (int)mode);
92 return false;
93 break;
94 }
95}
96
97void QuaZip::close()
98{
99 zipError=UNZ_OK;
100 switch(mode) {
101 case mdNotOpen:
102 qWarning("QuaZip::close(): ZIP is not open");
103 return;
104 case mdUnzip:
105 zipError=unzClose(unzFile_f);
106 break;
107 case mdCreate:
108 case mdAppend:
109 case mdAdd:
110 zipError=zipClose(zipFile_f, commentCodec->fromUnicode(comment).constData());
111 break;
112 default:
113 qWarning("QuaZip::close(): unknown mode: %d", (int)mode);
114 return;
115 }
116 if(zipError==UNZ_OK) mode=mdNotOpen;
117}
118
119void QuaZip::setZipName(const QString& zipName)
120{
121 if(isOpen()) {
122 qWarning("QuaZip::setZipName(): ZIP is already open!");
123 return;
124 }
125 this->zipName=zipName;
126}
127
128int QuaZip::getEntriesCount()const
129{
130 QuaZip *fakeThis=(QuaZip*)this; // non-const
131 fakeThis->zipError=UNZ_OK;
132 if(mode!=mdUnzip) {
133 qWarning("QuaZip::getEntriesCount(): ZIP is not open in mdUnzip mode");
134 return -1;
135 }
136 unz_global_info globalInfo;
137 if((fakeThis->zipError=unzGetGlobalInfo(unzFile_f, &globalInfo))!=UNZ_OK)
138 return zipError;
139 return (int)globalInfo.number_entry;
140}
141
142QString QuaZip::getComment()const
143{
144 QuaZip *fakeThis=(QuaZip*)this; // non-const
145 fakeThis->zipError=UNZ_OK;
146 if(mode!=mdUnzip) {
147 qWarning("QuaZip::getComment(): ZIP is not open in mdUnzip mode");
148 return QString();
149 }
150 unz_global_info globalInfo;
151 QByteArray comment;
152 if((fakeThis->zipError=unzGetGlobalInfo(unzFile_f, &globalInfo))!=UNZ_OK)
153 return QString();
154 comment.resize(globalInfo.size_comment);
155 if((fakeThis->zipError=unzGetGlobalComment(unzFile_f, comment.data(), comment.size()))!=UNZ_OK)
156 return QString();
157 return commentCodec->toUnicode(comment);
158}
159
160bool QuaZip::setCurrentFile(const QString& fileName, CaseSensitivity cs)
161{
162 zipError=UNZ_OK;
163 if(mode!=mdUnzip) {
164 qWarning("QuaZip::setCurrentFile(): ZIP is not open in mdUnzip mode");
165 return false;
166 }
167 if(fileName.isNull()) {
168 hasCurrentFile_f=false;
169 return true;
170 }
171 // Unicode-aware reimplementation of the unzLocateFile function
172 if(unzFile_f==NULL) {
173 zipError=UNZ_PARAMERROR;
174 return false;
175 }
176 if(fileName.length()>MAX_FILE_NAME_LENGTH) {
177 zipError=UNZ_PARAMERROR;
178 return false;
179 }
180 bool sens;
181 if(cs==csDefault) {
182#ifdef Q_WS_WIN
183 sens=false;
184#else
185 sens=true;
186#endif
187 } else sens=cs==csSensitive;
188 QString lower, current;
189 if(!sens) lower=fileName.toLower();
190 hasCurrentFile_f=false;
191 for(bool more=goToFirstFile(); more; more=goToNextFile()) {
192 current=getCurrentFileName();
193 if(current.isNull()) return false;
194 if(sens) {
195 if(current==fileName) break;
196 } else {
197 if(current.toLower()==lower) break;
198 }
199 }
200 return hasCurrentFile_f;
201}
202
203bool QuaZip::goToFirstFile()
204{
205 zipError=UNZ_OK;
206 if(mode!=mdUnzip) {
207 qWarning("QuaZip::goToFirstFile(): ZIP is not open in mdUnzip mode");
208 return false;
209 }
210 zipError=unzGoToFirstFile(unzFile_f);
211 hasCurrentFile_f=zipError==UNZ_OK;
212 return hasCurrentFile_f;
213}
214
215bool QuaZip::goToNextFile()
216{
217 zipError=UNZ_OK;
218 if(mode!=mdUnzip) {
219 qWarning("QuaZip::goToFirstFile(): ZIP is not open in mdUnzip mode");
220 return false;
221 }
222 zipError=unzGoToNextFile(unzFile_f);
223 hasCurrentFile_f=zipError==UNZ_OK;
224 if(zipError==UNZ_END_OF_LIST_OF_FILE) zipError=UNZ_OK;
225 return hasCurrentFile_f;
226}
227
228bool QuaZip::getCurrentFileInfo(QuaZipFileInfo *info)const
229{
230 QuaZip *fakeThis=(QuaZip*)this; // non-const
231 fakeThis->zipError=UNZ_OK;
232 if(mode!=mdUnzip) {
233 qWarning("QuaZip::getCurrentFileInfo(): ZIP is not open in mdUnzip mode");
234 return false;
235 }
236 unz_file_info info_z;
237 QByteArray fileName;
238 QByteArray extra;
239 QByteArray comment;
240 if(info==NULL) return false;
241 if(!isOpen()||!hasCurrentFile()) return false;
242 if((fakeThis->zipError=unzGetCurrentFileInfo(unzFile_f, &info_z, NULL, 0, NULL, 0, NULL, 0))!=UNZ_OK)
243 return false;
244 fileName.resize(info_z.size_filename);
245 extra.resize(info_z.size_file_extra);
246 comment.resize(info_z.size_file_comment);
247 if((fakeThis->zipError=unzGetCurrentFileInfo(unzFile_f, NULL,
248 fileName.data(), fileName.size(),
249 extra.data(), extra.size(),
250 comment.data(), comment.size()))!=UNZ_OK)
251 return false;
252 info->versionCreated=info_z.version;
253 info->versionNeeded=info_z.version_needed;
254 info->flags=info_z.flag;
255 info->method=info_z.compression_method;
256 info->crc=info_z.crc;
257 info->compressedSize=info_z.compressed_size;
258 info->uncompressedSize=info_z.uncompressed_size;
259 info->diskNumberStart=info_z.disk_num_start;
260 info->internalAttr=info_z.internal_fa;
261 info->externalAttr=info_z.external_fa;
262 info->name=fileNameCodec->toUnicode(fileName);
263 info->comment=commentCodec->toUnicode(comment);
264 info->extra=extra;
265 info->dateTime=QDateTime(
266 QDate(info_z.tmu_date.tm_year, info_z.tmu_date.tm_mon+1, info_z.tmu_date.tm_mday),
267 QTime(info_z.tmu_date.tm_hour, info_z.tmu_date.tm_min, info_z.tmu_date.tm_sec));
268 return true;
269}
270
271QString QuaZip::getCurrentFileName()const
272{
273 QuaZip *fakeThis=(QuaZip*)this; // non-const
274 fakeThis->zipError=UNZ_OK;
275 if(mode!=mdUnzip) {
276 qWarning("QuaZip::getCurrentFileName(): ZIP is not open in mdUnzip mode");
277 return QString();
278 }
279 if(!isOpen()||!hasCurrentFile()) return QString();
280 QByteArray fileName(MAX_FILE_NAME_LENGTH, 0);
281 if((fakeThis->zipError=unzGetCurrentFileInfo(unzFile_f, NULL, fileName.data(), fileName.size(),
282 NULL, 0, NULL, 0))!=UNZ_OK)
283 return QString();
284 return fileNameCodec->toUnicode(fileName.constData());
285}
diff --git a/rbutil/rbutilqt/quazip/quazip.h b/rbutil/rbutilqt/quazip/quazip.h
new file mode 100644
index 0000000000..ced1ea0f1a
--- /dev/null
+++ b/rbutil/rbutilqt/quazip/quazip.h
@@ -0,0 +1,346 @@
1#ifndef QUA_ZIP_H
2#define QUA_ZIP_H
3
4/*
5-- A kind of "standard" GPL license statement --
6QuaZIP - a Qt/C++ wrapper for the ZIP/UNZIP package
7Copyright (C) 2005-2007 Sergey A. Tachenov
8
9This program is free software; you can redistribute it and/or modify it
10under the terms of the GNU General Public License as published by the
11Free Software Foundation; either version 2 of the License, or (at your
12option) any later version.
13
14This program is distributed in the hope that it will be useful, but
15WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17Public License for more details.
18
19You should have received a copy of the GNU General Public License along
20with this program; if not, write to the Free Software Foundation, Inc.,
2159 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
23-- A kind of "standard" GPL license statement ends here --
24
25See COPYING file for GPL.
26
27You are also permitted to use QuaZIP under the terms of LGPL (see
28COPYING.LGPL). You are free to choose either license, but please note
29that QuaZIP makes use of Qt, which is not licensed under LGPL. So if
30you are using Open Source edition of Qt, you therefore MUST use GPL for
31your code based on QuaZIP, since it would be also based on Qt in this
32case. If you are Qt commercial license owner, then you are free to use
33QuaZIP as long as you respect either GPL or LGPL for QuaZIP code.
34 **/
35
36#include <QString>
37#include <QTextCodec>
38
39#include "zip.h"
40#include "unzip.h"
41
42#include "quazipfileinfo.h"
43
44// just in case it will be defined in the later versions of the ZIP/UNZIP
45#ifndef UNZ_OPENERROR
46// define additional error code
47#define UNZ_OPENERROR -1000
48#endif
49
50/// ZIP archive.
51/** \class QuaZip quazip.h <quazip/quazip.h>
52 * This class implements basic interface to the ZIP archive. It can be
53 * used to read table contents of the ZIP archive and retreiving
54 * information about the files inside it.
55 *
56 * You can also use this class to open files inside archive by passing
57 * pointer to the instance of this class to the constructor of the
58 * QuaZipFile class. But see QuaZipFile::QuaZipFile(QuaZip*, QObject*)
59 * for the possible pitfalls.
60 *
61 * This class is indended to provide interface to the ZIP subpackage of
62 * the ZIP/UNZIP package as well as to the UNZIP subpackage. But
63 * currently it supports only UNZIP.
64 *
65 * The use of this class is simple - just create instance using
66 * constructor, then set ZIP archive file name using setFile() function
67 * (if you did not passed the name to the constructor), then open() and
68 * then use different functions to work with it! Well, if you are
69 * paranoid, you may also wish to call close before destructing the
70 * instance, to check for errors on close.
71 *
72 * You may also use getUnzFile() and getZipFile() functions to get the
73 * ZIP archive handle and use it with ZIP/UNZIP package API directly.
74 *
75 * This class supports localized file names inside ZIP archive, but you
76 * have to set up proper codec with setCodec() function. By default,
77 * locale codec will be used, which is probably ok for UNIX systems, but
78 * will almost certainly fail with ZIP archives created in Windows. This
79 * is because Windows ZIP programs have strange habit of using DOS
80 * encoding for file names in ZIP archives. For example, ZIP archive
81 * with cyrillic names created in Windows will have file names in \c
82 * IBM866 encoding instead of \c WINDOWS-1251. I think that calling one
83 * function is not much trouble, but for true platform independency it
84 * would be nice to have some mechanism for file name encoding auto
85 * detection using locale information. Does anyone know a good way to do
86 * it?
87 **/
88class QuaZip {
89 public:
90 /// Useful constants.
91 enum Constants {
92 MAX_FILE_NAME_LENGTH=256 /**< Maximum file name length. Taken from
93 \c UNZ_MAXFILENAMEINZIP constant in
94 unzip.c. */
95 };
96 /// Open mode of the ZIP file.
97 enum Mode {
98 mdNotOpen, ///< ZIP file is not open. This is the initial mode.
99 mdUnzip, ///< ZIP file is open for reading files inside it.
100 mdCreate, ///< ZIP file was created with open() call.
101 mdAppend, /**< ZIP file was opened in append mode. This refers to
102 * \c APPEND_STATUS_CREATEAFTER mode in ZIP/UNZIP package
103 * and means that zip is appended to some existing file
104 * what is useful when that file contains
105 * self-extractor code. This is obviously \em not what
106 * you whant to use to add files to the existing ZIP
107 * archive.
108 **/
109 mdAdd ///< ZIP file was opened for adding files in the archive.
110 };
111 /// Case sensitivity for the file names.
112 /** This is what you specify when accessing files in the archive.
113 * Works perfectly fine with any characters thanks to Qt's great
114 * unicode support. This is different from ZIP/UNZIP API, where
115 * only US-ASCII characters was supported.
116 **/
117 enum CaseSensitivity {
118 csDefault=0, ///< Default for platform. Case sensitive for UNIX, not for Windows.
119 csSensitive=1, ///< Case sensitive.
120 csInsensitive=2 ///< Case insensitive.
121 };
122 private:
123 QTextCodec *fileNameCodec, *commentCodec;
124 QString zipName;
125 QString comment;
126 Mode mode;
127 union {
128 unzFile unzFile_f;
129 zipFile zipFile_f;
130 };
131 bool hasCurrentFile_f;
132 int zipError;
133 // not (and will not be) implemented
134 QuaZip(const QuaZip& that);
135 // not (and will not be) implemented
136 QuaZip& operator=(const QuaZip& that);
137 public:
138 /// Constructs QuaZip object.
139 /** Call setName() before opening constructed object. */
140 QuaZip();
141 /// Constructs QuaZip object associated with ZIP file \a zipName.
142 QuaZip(const QString& zipName);
143 /// Destroys QuaZip object.
144 /** Calls close() if necessary. */
145 ~QuaZip();
146 /// Opens ZIP file.
147 /** Argument \a ioApi specifies IO function set for ZIP/UNZIP
148 * package to use. See unzip.h, zip.h and ioapi.h for details. By
149 * passing NULL (the default) you just tell package to use the
150 * default API which works just fine on UNIX platforms. I have tried
151 * it on win32-g++ platform too and it seems it works fine there
152 * too, so I see no reason to use win32 IO API included in original
153 * ZIP/UNZIP package.
154 *
155 * ZIP archive file name will be converted to 8-bit encoding using
156 * Qt's QFile::encodeName() function before passing it to the
157 * ZIP/UNZIP package API.
158 *
159 * Returns \c true if successful, \c false otherwise.
160 *
161 * Argument \a mode specifies open mode of the ZIP archive. See Mode
162 * for details. Note that there is zipOpen2() function in the
163 * ZIP/UNZIP API which accepts \a globalcomment argument, but it
164 * does not use it anywhere, so this open() function does not have this
165 * argument. See setComment() if you need to set global comment.
166 *
167 * \note ZIP/UNZIP API open calls do not return error code - they
168 * just return \c NULL indicating an error. But to make things
169 * easier, quazip.h header defines additional error code \c
170 * UNZ_ERROROPEN and getZipError() will return it if the open call
171 * of the ZIP/UNZIP API returns \c NULL.
172 **/
173 bool open(Mode mode, zlib_filefunc_def *ioApi =NULL);
174 /// Closes ZIP file.
175 /** Call getZipError() to determine if the close was successful. */
176 void close();
177 /// Sets the codec used to encode/decode file names inside archive.
178 /** This is necessary to access files in the ZIP archive created
179 * under Windows with non-latin characters in file names. For
180 * example, file names with cyrillic letters will be in \c IBM866
181 * encoding.
182 **/
183 void setFileNameCodec(QTextCodec *fileNameCodec)
184 {this->fileNameCodec=fileNameCodec;}
185 /// Sets the codec used to encode/decode file names inside archive.
186 /** \overload
187 * Equivalent to calling setFileNameCodec(QTextCodec::codecForName(codecName));
188 **/
189 void setFileNameCodec(const char *fileNameCodecName)
190 {fileNameCodec=QTextCodec::codecForName(fileNameCodecName);}
191 /// Returns the codec used to encode/decode comments inside archive.
192 QTextCodec* getFileNameCodec()const {return fileNameCodec;}
193 /// Sets the codec used to encode/decode comments inside archive.
194 /** This codec defaults to locale codec, which is probably ok.
195 **/
196 void setCommentCodec(QTextCodec *commentCodec)
197 {this->commentCodec=commentCodec;}
198 /// Sets the codec used to encode/decode comments inside archive.
199 /** \overload
200 * Equivalent to calling setCommentCodec(QTextCodec::codecForName(codecName));
201 **/
202 void setCommentCodec(const char *commentCodecName)
203 {commentCodec=QTextCodec::codecForName(commentCodecName);}
204 /// Returns the codec used to encode/decode comments inside archive.
205 QTextCodec* getCommentCodec()const {return commentCodec;}
206 /// Returns the name of the ZIP file.
207 /** Returns null string if no ZIP file name has been set.
208 * \sa setZipName()
209 **/
210 QString getZipName()const {return zipName;}
211 /// Sets the name of the ZIP file.
212 /** Does nothing if the ZIP file is open.
213 *
214 * Does not reset error code returned by getZipError().
215 **/
216 void setZipName(const QString& zipName);
217 /// Returns the mode in which ZIP file was opened.
218 Mode getMode()const {return mode;}
219 /// Returns \c true if ZIP file is open, \c false otherwise.
220 bool isOpen()const {return mode!=mdNotOpen;}
221 /// Returns the error code of the last operation.
222 /** Returns \c UNZ_OK if the last operation was successful.
223 *
224 * Error code resets to \c UNZ_OK every time you call any function
225 * that accesses something inside ZIP archive, even if it is \c
226 * const (like getEntriesCount()). open() and close() calls reset
227 * error code too. See documentation for the specific functions for
228 * details on error detection.
229 **/
230 int getZipError()const {return zipError;}
231 /// Returns number of the entries in the ZIP central directory.
232 /** Returns negative error code in the case of error. The same error
233 * code will be returned by subsequent getZipError() call.
234 **/
235 int getEntriesCount()const;
236 /// Returns global comment in the ZIP file.
237 QString getComment()const;
238 /// Sets global comment in the ZIP file.
239 /** Comment will be written to the archive on close operation.
240 *
241 * \sa open()
242 **/
243 void setComment(const QString& comment) {this->comment=comment;}
244 /// Sets the current file to the first file in the archive.
245 /** Returns \c true on success, \c false otherwise. Call
246 * getZipError() to get the error code.
247 **/
248 bool goToFirstFile();
249 /// Sets the current file to the next file in the archive.
250 /** Returns \c true on success, \c false otherwise. Call
251 * getZipError() to determine if there was an error.
252 *
253 * Should be used only in QuaZip::mdUnzip mode.
254 *
255 * \note If the end of file was reached, getZipError() will return
256 * \c UNZ_OK instead of \c UNZ_END_OF_LIST_OF_FILE. This is to make
257 * things like this easier:
258 * \code
259 * for(bool more=zip.goToFirstFile(); more; more=zip.goToNextFile()) {
260 * // do something
261 * }
262 * if(zip.getZipError()==UNZ_OK) {
263 * // ok, there was no error
264 * }
265 * \endcode
266 **/
267 bool goToNextFile();
268 /// Sets current file by its name.
269 /** Returns \c true if successful, \c false otherwise. Argument \a
270 * cs specifies case sensitivity of the file name. Call
271 * getZipError() in the case of a failure to get error code.
272 *
273 * This is not a wrapper to unzLocateFile() function. That is
274 * because I had to implement locale-specific case-insensitive
275 * comparison.
276 *
277 * Here are the differences from the original implementation:
278 *
279 * - If the file was not found, error code is \c UNZ_OK, not \c
280 * UNZ_END_OF_LIST_OF_FILE (see also goToNextFile()).
281 * - If this function fails, it unsets the current file rather than
282 * resetting it back to what it was before the call.
283 *
284 * If \a fileName is null string then this function unsets the
285 * current file and return \c true. Note that you should close the
286 * file first if it is open! See
287 * QuaZipFile::QuaZipFile(QuaZip*,QObject*) for the details.
288 *
289 * Should be used only in QuaZip::mdUnzip mode.
290 *
291 * \sa setFileNameCodec(), CaseSensitivity
292 **/
293 bool setCurrentFile(const QString& fileName, CaseSensitivity cs =csDefault);
294 /// Returns \c true if the current file has been set.
295 bool hasCurrentFile()const {return hasCurrentFile_f;}
296 /// Retrieves information about the current file.
297 /** Fills the structure pointed by \a info. Returns \c true on
298 * success, \c false otherwise. In the latter case structure pointed
299 * by \a info remains untouched. If there was an error,
300 * getZipError() returns error code.
301 *
302 * Should be used only in QuaZip::mdUnzip mode.
303 *
304 * Does nothing and returns \c false in any of the following cases.
305 * - ZIP is not open;
306 * - ZIP does not have current file;
307 * - \a info is \c NULL;
308 *
309 * In all these cases getZipError() returns \c UNZ_OK since there
310 * is no ZIP/UNZIP API call.
311 **/
312 bool getCurrentFileInfo(QuaZipFileInfo* info)const;
313 /// Returns the current file name.
314 /** Equivalent to calling getCurrentFileInfo() and then getting \c
315 * name field of the QuaZipFileInfo structure, but faster and more
316 * convenient.
317 *
318 * Should be used only in QuaZip::mdUnzip mode.
319 **/
320 QString getCurrentFileName()const;
321 /// Returns \c unzFile handle.
322 /** You can use this handle to directly call UNZIP part of the
323 * ZIP/UNZIP package functions (see unzip.h).
324 *
325 * \warning When using the handle returned by this function, please
326 * keep in mind that QuaZip class is unable to detect any changes
327 * you make in the ZIP file state (e. g. changing current file, or
328 * closing the handle). So please do not do anything with this
329 * handle that is possible to do with the functions of this class.
330 * Or at least return the handle in the original state before
331 * calling some another function of this class (including implicit
332 * destructor calls and calls from the QuaZipFile objects that refer
333 * to this QuaZip instance!). So if you have changed the current
334 * file in the ZIP archive - then change it back or you may
335 * experience some strange behavior or even crashes.
336 **/
337 unzFile getUnzFile() {return unzFile_f;}
338 /// Returns \c zipFile handle.
339 /** You can use this handle to directly call ZIP part of the
340 * ZIP/UNZIP package functions (see zip.h). Warnings about the
341 * getUnzFile() function also apply to this function.
342 **/
343 zipFile getZipFile() {return zipFile_f;}
344};
345
346#endif
diff --git a/rbutil/rbutilqt/quazip/quazipfile.cpp b/rbutil/rbutilqt/quazip/quazipfile.cpp
new file mode 100644
index 0000000000..0399d1dbd0
--- /dev/null
+++ b/rbutil/rbutilqt/quazip/quazipfile.cpp
@@ -0,0 +1,377 @@
1/*
2-- A kind of "standard" GPL license statement --
3QuaZIP - a Qt/C++ wrapper for the ZIP/UNZIP package
4Copyright (C) 2005-2007 Sergey A. Tachenov
5
6This program is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2 of the License, or (at your
9option) any later version.
10
11This program is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
14Public License for more details.
15
16You should have received a copy of the GNU General Public License along
17with this program; if not, write to the Free Software Foundation, Inc.,
1859 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
20-- A kind of "standard" GPL license statement ends here --
21
22See COPYING file for GPL.
23
24You are also permitted to use QuaZIP under the terms of LGPL (see
25COPYING.LGPL). You are free to choose either license, but please note
26that QuaZIP makes use of Qt, which is not licensed under LGPL. So if
27you are using Open Source edition of Qt, you therefore MUST use GPL for
28your code based on QuaZIP, since it would be also based on Qt in this
29case. If you are Qt commercial license owner, then you are free to use
30QuaZIP as long as you respect either GPL or LGPL for QuaZIP code.
31 **/
32
33#include "quazipfile.h"
34
35using namespace std;
36
37QuaZipFile::QuaZipFile():
38 zip(NULL), internal(true), zipError(UNZ_OK)
39{
40}
41
42QuaZipFile::QuaZipFile(QObject *parent):
43 QIODevice(parent), zip(NULL), internal(true), zipError(UNZ_OK)
44{
45}
46
47QuaZipFile::QuaZipFile(const QString& zipName, QObject *parent):
48 QIODevice(parent), internal(true), zipError(UNZ_OK)
49{
50 zip=new QuaZip(zipName);
51 Q_CHECK_PTR(zip);
52}
53
54QuaZipFile::QuaZipFile(const QString& zipName, const QString& fileName,
55 QuaZip::CaseSensitivity cs, QObject *parent):
56 QIODevice(parent), internal(true), zipError(UNZ_OK)
57{
58 zip=new QuaZip(zipName);
59 Q_CHECK_PTR(zip);
60 this->fileName=fileName;
61 this->caseSensitivity=cs;
62}
63
64QuaZipFile::QuaZipFile(QuaZip *zip, QObject *parent):
65 QIODevice(parent),
66 zip(zip), internal(false),
67 zipError(UNZ_OK)
68{
69}
70
71QuaZipFile::~QuaZipFile()
72{
73 if(isOpen()) close();
74 if(internal) delete zip;
75}
76
77QString QuaZipFile::getZipName()const
78{
79 return zip==NULL?QString():zip->getZipName();
80}
81
82QString QuaZipFile::getActualFileName()const
83{
84 setZipError(UNZ_OK);
85 if(zip==NULL||(openMode()&WriteOnly)) return QString();
86 QString name=zip->getCurrentFileName();
87 if(name.isNull())
88 setZipError(zip->getZipError());
89 return name;
90}
91
92void QuaZipFile::setZipName(const QString& zipName)
93{
94 if(isOpen()) {
95 qWarning("QuaZipFile::setZipName(): file is already open - can not set ZIP name");
96 return;
97 }
98 if(zip!=NULL&&internal) delete zip;
99 zip=new QuaZip(zipName);
100 Q_CHECK_PTR(zip);
101 internal=true;
102}
103
104void QuaZipFile::setZip(QuaZip *zip)
105{
106 if(isOpen()) {
107 qWarning("QuaZipFile::setZip(): file is already open - can not set ZIP");
108 return;
109 }
110 if(this->zip!=NULL&&internal) delete this->zip;
111 this->zip=zip;
112 this->fileName=QString();
113 internal=false;
114}
115
116void QuaZipFile::setFileName(const QString& fileName, QuaZip::CaseSensitivity cs)
117{
118 if(zip==NULL) {
119 qWarning("QuaZipFile::setFileName(): call setZipName() first");
120 return;
121 }
122 if(!internal) {
123 qWarning("QuaZipFile::setFileName(): should not be used when not using internal QuaZip");
124 return;
125 }
126 if(isOpen()) {
127 qWarning("QuaZipFile::setFileName(): can not set file name for already opened file");
128 return;
129 }
130 this->fileName=fileName;
131 this->caseSensitivity=cs;
132}
133
134void QuaZipFile::setZipError(int zipError)const
135{
136 QuaZipFile *fakeThis=(QuaZipFile*)this; // non-const
137 fakeThis->zipError=zipError;
138 if(zipError==UNZ_OK)
139 fakeThis->setErrorString(QString());
140 else
141 fakeThis->setErrorString(tr("ZIP/UNZIP API error %1").arg(zipError));
142}
143
144bool QuaZipFile::open(OpenMode mode)
145{
146 return open(mode, NULL);
147}
148
149bool QuaZipFile::open(OpenMode mode, int *method, int *level, bool raw, const char *password)
150{
151 resetZipError();
152 if(isOpen()) {
153 qWarning("QuaZipFile::open(): already opened");
154 return false;
155 }
156 if(mode&Unbuffered) {
157 qWarning("QuaZipFile::open(): Unbuffered mode is not supported");
158 return false;
159 }
160 if((mode&ReadOnly)&&!(mode&WriteOnly)) {
161 if(internal) {
162 if(!zip->open(QuaZip::mdUnzip)) {
163 setZipError(zip->getZipError());
164 return false;
165 }
166 if(!zip->setCurrentFile(fileName, caseSensitivity)) {
167 setZipError(zip->getZipError());
168 zip->close();
169 return false;
170 }
171 } else {
172 if(zip==NULL) {
173 qWarning("QuaZipFile::open(): zip is NULL");
174 return false;
175 }
176 if(zip->getMode()!=QuaZip::mdUnzip) {
177 qWarning("QuaZipFile::open(): file open mode %d incompatible with ZIP open mode %d",
178 (int)mode, (int)zip->getMode());
179 return false;
180 }
181 if(!zip->hasCurrentFile()) {
182 qWarning("QuaZipFile::open(): zip does not have current file");
183 return false;
184 }
185 }
186 setZipError(unzOpenCurrentFile3(zip->getUnzFile(), method, level, (int)raw, password));
187 if(zipError==UNZ_OK) {
188 setOpenMode(mode);
189 this->raw=raw;
190 return true;
191 } else
192 return false;
193 }
194 qWarning("QuaZipFile::open(): open mode %d not supported by this function", (int)mode);
195 return false;
196}
197
198bool QuaZipFile::open(OpenMode mode, const QuaZipNewInfo& info,
199 const char *password, quint32 crc,
200 int method, int level, bool raw,
201 int windowBits, int memLevel, int strategy)
202{
203 zip_fileinfo info_z;
204 resetZipError();
205 if(isOpen()) {
206 qWarning("QuaZipFile::open(): already opened");
207 return false;
208 }
209 if((mode&WriteOnly)&&!(mode&ReadOnly)) {
210 if(internal) {
211 qWarning("QuaZipFile::open(): write mode is incompatible with internal QuaZip approach");
212 return false;
213 }
214 if(zip==NULL) {
215 qWarning("QuaZipFile::open(): zip is NULL");
216 return false;
217 }
218 if(zip->getMode()!=QuaZip::mdCreate&&zip->getMode()!=QuaZip::mdAppend&&zip->getMode()!=QuaZip::mdAdd) {
219 qWarning("QuaZipFile::open(): file open mode %d incompatible with ZIP open mode %d",
220 (int)mode, (int)zip->getMode());
221 return false;
222 }
223 info_z.tmz_date.tm_year=info.dateTime.date().year();
224 info_z.tmz_date.tm_mon=info.dateTime.date().month() - 1;
225 info_z.tmz_date.tm_mday=info.dateTime.date().day();
226 info_z.tmz_date.tm_hour=info.dateTime.time().hour();
227 info_z.tmz_date.tm_min=info.dateTime.time().minute();
228 info_z.tmz_date.tm_sec=info.dateTime.time().second();
229 info_z.dosDate = 0;
230 info_z.internal_fa=(uLong)info.internalAttr;
231 info_z.external_fa=(uLong)info.externalAttr;
232 setZipError(zipOpenNewFileInZip3(zip->getZipFile(),
233 zip->getFileNameCodec()->fromUnicode(info.name).constData(), &info_z,
234 info.extraLocal.constData(), info.extraLocal.length(),
235 info.extraGlobal.constData(), info.extraGlobal.length(),
236 zip->getCommentCodec()->fromUnicode(info.comment).constData(),
237 method, level, (int)raw,
238 windowBits, memLevel, strategy,
239 password, (uLong)crc));
240 if(zipError==UNZ_OK) {
241 writePos=0;
242 setOpenMode(mode);
243 this->raw=raw;
244 if(raw) {
245 this->crc=crc;
246 this->uncompressedSize=info.uncompressedSize;
247 }
248 return true;
249 } else
250 return false;
251 }
252 qWarning("QuaZipFile::open(): open mode %d not supported by this function", (int)mode);
253 return false;
254}
255
256bool QuaZipFile::isSequential()const
257{
258 return true;
259}
260
261qint64 QuaZipFile::pos()const
262{
263 if(zip==NULL) {
264 qWarning("QuaZipFile::pos(): call setZipName() or setZip() first");
265 return -1;
266 }
267 if(!isOpen()) {
268 qWarning("QuaZipFile::pos(): file is not open");
269 return -1;
270 }
271 if(openMode()&ReadOnly)
272 return unztell(zip->getUnzFile());
273 else
274 return writePos;
275}
276
277bool QuaZipFile::atEnd()const
278{
279 if(zip==NULL) {
280 qWarning("QuaZipFile::atEnd(): call setZipName() or setZip() first");
281 return false;
282 }
283 if(!isOpen()) {
284 qWarning("QuaZipFile::atEnd(): file is not open");
285 return false;
286 }
287 if(openMode()&ReadOnly)
288 return unzeof(zip->getUnzFile())==1;
289 else
290 return true;
291}
292
293qint64 QuaZipFile::size()const
294{
295 if(!isOpen()) {
296 qWarning("QuaZipFile::atEnd(): file is not open");
297 return -1;
298 }
299 if(openMode()&ReadOnly)
300 return raw?csize():usize();
301 else
302 return writePos;
303}
304
305qint64 QuaZipFile::csize()const
306{
307 unz_file_info info_z;
308 setZipError(UNZ_OK);
309 if(zip==NULL||zip->getMode()!=QuaZip::mdUnzip) return -1;
310 setZipError(unzGetCurrentFileInfo(zip->getUnzFile(), &info_z, NULL, 0, NULL, 0, NULL, 0));
311 if(zipError!=UNZ_OK)
312 return -1;
313 return info_z.compressed_size;
314}
315
316qint64 QuaZipFile::usize()const
317{
318 unz_file_info info_z;
319 setZipError(UNZ_OK);
320 if(zip==NULL||zip->getMode()!=QuaZip::mdUnzip) return -1;
321 setZipError(unzGetCurrentFileInfo(zip->getUnzFile(), &info_z, NULL, 0, NULL, 0, NULL, 0));
322 if(zipError!=UNZ_OK)
323 return -1;
324 return info_z.uncompressed_size;
325}
326
327bool QuaZipFile::getFileInfo(QuaZipFileInfo *info)
328{
329 if(zip==NULL||zip->getMode()!=QuaZip::mdUnzip) return false;
330 zip->getCurrentFileInfo(info);
331 setZipError(zip->getZipError());
332 return zipError==UNZ_OK;
333}
334
335void QuaZipFile::close()
336{
337 resetZipError();
338 if(zip==NULL||!zip->isOpen()) return;
339 if(!isOpen()) {
340 qWarning("QuaZipFile::close(): file isn't open");
341 return;
342 }
343 if(openMode()&ReadOnly)
344 setZipError(unzCloseCurrentFile(zip->getUnzFile()));
345 else if(openMode()&WriteOnly)
346 if(isRaw()) setZipError(zipCloseFileInZipRaw(zip->getZipFile(), uncompressedSize, crc));
347 else setZipError(zipCloseFileInZip(zip->getZipFile()));
348 else {
349 qWarning("Wrong open mode: %d", (int)openMode());
350 return;
351 }
352 if(zipError==UNZ_OK) setOpenMode(QIODevice::NotOpen);
353 else return;
354 if(internal) {
355 zip->close();
356 setZipError(zip->getZipError());
357 }
358}
359
360qint64 QuaZipFile::readData(char *data, qint64 maxSize)
361{
362 setZipError(UNZ_OK);
363 qint64 bytesRead=unzReadCurrentFile(zip->getUnzFile(), data, (unsigned)maxSize);
364 if(bytesRead<0) setZipError((int)bytesRead);
365 return bytesRead;
366}
367
368qint64 QuaZipFile::writeData(const char* data, qint64 maxSize)
369{
370 setZipError(ZIP_OK);
371 setZipError(zipWriteInFileInZip(zip->getZipFile(), data, (uint)maxSize));
372 if(zipError!=ZIP_OK) return -1;
373 else {
374 writePos+=maxSize;
375 return maxSize;
376 }
377}
diff --git a/rbutil/rbutilqt/quazip/quazipfile.h b/rbutil/rbutilqt/quazip/quazipfile.h
new file mode 100644
index 0000000000..09af5bceca
--- /dev/null
+++ b/rbutil/rbutilqt/quazip/quazipfile.h
@@ -0,0 +1,442 @@
1#ifndef QUA_ZIPFILE_H
2#define QUA_ZIPFILE_H
3
4/*
5-- A kind of "standard" GPL license statement --
6QuaZIP - a Qt/C++ wrapper for the ZIP/UNZIP package
7Copyright (C) 2005-2008 Sergey A. Tachenov
8
9This program is free software; you can redistribute it and/or modify it
10under the terms of the GNU General Public License as published by the
11Free Software Foundation; either version 2 of the License, or (at your
12option) any later version.
13
14This program is distributed in the hope that it will be useful, but
15WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17Public License for more details.
18
19You should have received a copy of the GNU General Public License along
20with this program; if not, write to the Free Software Foundation, Inc.,
2159 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
23-- A kind of "standard" GPL license statement ends here --
24
25See COPYING file for GPL.
26
27You are also permitted to use QuaZIP under the terms of LGPL (see
28COPYING.LGPL). You are free to choose either license, but please note
29that QuaZIP makes use of Qt, which is not licensed under LGPL. So if
30you are using Open Source edition of Qt, you therefore MUST use GPL for
31your code based on QuaZIP, since it would be also based on Qt in this
32case. If you are Qt commercial license owner, then you are free to use
33QuaZIP as long as you respect either GPL or LGPL for QuaZIP code.
34 **/
35
36#include <QIODevice>
37
38#include "quazip.h"
39#include "quazipnewinfo.h"
40
41/// A file inside ZIP archive.
42/** \class QuaZipFile quazipfile.h <quazip/quazipfile.h>
43 * This is the most interesting class. Not only it provides C++
44 * interface to the ZIP/UNZIP package, but also integrates it with Qt by
45 * subclassing QIODevice. This makes possible to access files inside ZIP
46 * archive using QTextStream or QDataStream, for example. Actually, this
47 * is the main purpose of the whole QuaZIP library.
48 *
49 * You can either use existing QuaZip instance to create instance of
50 * this class or pass ZIP archive file name to this class, in which case
51 * it will create internal QuaZip object. See constructors' descriptions
52 * for details. Writing is only possible with the existing instance.
53 *
54 * \section quazipfile-sequential Sequential or random-access?
55 *
56 * At the first thought, QuaZipFile has fixed size, the start and the
57 * end and should be therefore considered random-access device. But
58 * there is one major obstacle to making it random-access: ZIP/UNZIP API
59 * does not support seek() operation and the only way to implement it is
60 * through reopening the file and re-reading to the required position,
61 * but this is prohibitely slow.
62 *
63 * Therefore, QuaZipFile is considered to be a sequential device. This
64 * has advantage of availability of the ungetChar() operation (QIODevice
65 * does not implement it properly for non-sequential devices unless they
66 * support seek()). Disadvantage is a somewhat strange behaviour of the
67 * size() and pos() functions. This should be kept in mind while using
68 * this class.
69 *
70 **/
71class QuaZipFile: public QIODevice {
72 Q_OBJECT
73 private:
74 QuaZip *zip;
75 QString fileName;
76 QuaZip::CaseSensitivity caseSensitivity;
77 bool raw;
78 qint64 writePos;
79 // these two are for writing raw files
80 ulong uncompressedSize;
81 quint32 crc;
82 bool internal;
83 int zipError;
84 // these are not supported nor implemented
85 QuaZipFile(const QuaZipFile& that);
86 QuaZipFile& operator=(const QuaZipFile& that);
87 void resetZipError()const {setZipError(UNZ_OK);}
88 // const, but sets zipError!
89 void setZipError(int zipError)const;
90 protected:
91 /// Implementation of the QIODevice::readData().
92 qint64 readData(char *data, qint64 maxSize);
93 /// Implementation of the QIODevice::writeData().
94 qint64 writeData(const char *data, qint64 maxSize);
95 public:
96 /// Constructs a QuaZipFile instance.
97 /** You should use setZipName() and setFileName() or setZip() before
98 * trying to call open() on the constructed object.
99 **/
100 QuaZipFile();
101 /// Constructs a QuaZipFile instance.
102 /** \a parent argument specifies this object's parent object.
103 *
104 * You should use setZipName() and setFileName() or setZip() before
105 * trying to call open() on the constructed object.
106 **/
107 QuaZipFile(QObject *parent);
108 /// Constructs a QuaZipFile instance.
109 /** \a parent argument specifies this object's parent object and \a
110 * zipName specifies ZIP archive file name.
111 *
112 * You should use setFileName() before trying to call open() on the
113 * constructed object.
114 *
115 * QuaZipFile constructed by this constructor can be used for read
116 * only access. Use QuaZipFile(QuaZip*,QObject*) for writing.
117 **/
118 QuaZipFile(const QString& zipName, QObject *parent =NULL);
119 /// Constructs a QuaZipFile instance.
120 /** \a parent argument specifies this object's parent object, \a
121 * zipName specifies ZIP archive file name and \a fileName and \a cs
122 * specify a name of the file to open inside archive.
123 *
124 * QuaZipFile constructed by this constructor can be used for read
125 * only access. Use QuaZipFile(QuaZip*,QObject*) for writing.
126 *
127 * \sa QuaZip::setCurrentFile()
128 **/
129 QuaZipFile(const QString& zipName, const QString& fileName,
130 QuaZip::CaseSensitivity cs =QuaZip::csDefault, QObject *parent =NULL);
131 /// Constructs a QuaZipFile instance.
132 /** \a parent argument specifies this object's parent object.
133 *
134 * \a zip is the pointer to the existing QuaZip object. This
135 * QuaZipFile object then can be used to read current file in the
136 * \a zip or to write to the file inside it.
137 *
138 * \warning Using this constructor for reading current file can be
139 * tricky. Let's take the following example:
140 * \code
141 * QuaZip zip("archive.zip");
142 * zip.open(QuaZip::mdUnzip);
143 * zip.setCurrentFile("file-in-archive");
144 * QuaZipFile file(&zip);
145 * file.open(QIODevice::ReadOnly);
146 * // ok, now we can read from the file
147 * file.read(somewhere, some);
148 * zip.setCurrentFile("another-file-in-archive"); // oops...
149 * QuaZipFile anotherFile(&zip);
150 * anotherFile.open(QIODevice::ReadOnly);
151 * anotherFile.read(somewhere, some); // this is still ok...
152 * file.read(somewhere, some); // and this is NOT
153 * \endcode
154 * So, what exactly happens here? When we change current file in the
155 * \c zip archive, \c file that references it becomes invalid
156 * (actually, as far as I understand ZIP/UNZIP sources, it becomes
157 * closed, but QuaZipFile has no means to detect it).
158 *
159 * Summary: do not close \c zip object or change its current file as
160 * long as QuaZipFile is open. Even better - use another constructors
161 * which create internal QuaZip instances, one per object, and
162 * therefore do not cause unnecessary trouble. This constructor may
163 * be useful, though, if you already have a QuaZip instance and do
164 * not want to access several files at once. Good example:
165 * \code
166 * QuaZip zip("archive.zip");
167 * zip.open(QuaZip::mdUnzip);
168 * // first, we need some information about archive itself
169 * QByteArray comment=zip.getComment();
170 * // and now we are going to access files inside it
171 * QuaZipFile file(&zip);
172 * for(bool more=zip.goToFirstFile(); more; more=zip.goToNextFile()) {
173 * file.open(QIODevice::ReadOnly);
174 * // do something cool with file here
175 * file.close(); // do not forget to close!
176 * }
177 * zip.close();
178 * \endcode
179 **/
180 QuaZipFile(QuaZip *zip, QObject *parent =NULL);
181 /// Destroys a QuaZipFile instance.
182 /** Closes file if open, destructs internal QuaZip object (if it
183 * exists and \em is internal, of course).
184 **/
185 virtual ~QuaZipFile();
186 /// Returns the ZIP archive file name.
187 /** If this object was created by passing QuaZip pointer to the
188 * constructor, this function will return that QuaZip's file name
189 * (or null string if that object does not have file name yet).
190 *
191 * Otherwise, returns associated ZIP archive file name or null
192 * string if there are no name set yet.
193 *
194 * \sa setZipName() getFileName()
195 **/
196 QString getZipName()const;
197 /// Returns a pointer to the associated QuaZip object.
198 /** Returns \c NULL if there is no associated QuaZip or it is
199 * internal (so you will not mess with it).
200 **/
201 QuaZip* getZip()const;
202 /// Returns file name.
203 /** This function returns file name you passed to this object either
204 * by using
205 * QuaZipFile(const QString&,const QString&,QuaZip::CaseSensitivity,QObject*)
206 * or by calling setFileName(). Real name of the file may differ in
207 * case if you used case-insensitivity.
208 *
209 * Returns null string if there is no file name set yet. This is the
210 * case when this QuaZipFile operates on the existing QuaZip object
211 * (constructor QuaZipFile(QuaZip*,QObject*) or setZip() was used).
212 *
213 * \sa getActualFileName
214 **/
215 QString getFileName()const {return fileName;}
216 /// Returns case sensitivity of the file name.
217 /** This function returns case sensitivity argument you passed to
218 * this object either by using
219 * QuaZipFile(const QString&,const QString&,QuaZip::CaseSensitivity,QObject*)
220 * or by calling setFileName().
221 *
222 * Returns unpredictable value if getFileName() returns null string
223 * (this is the case when you did not used setFileName() or
224 * constructor above).
225 *
226 * \sa getFileName
227 **/
228 QuaZip::CaseSensitivity getCaseSensitivity()const {return caseSensitivity;}
229 /// Returns the actual file name in the archive.
230 /** This is \em not a ZIP archive file name, but a name of file inside
231 * archive. It is not necessary the same name that you have passed
232 * to the
233 * QuaZipFile(const QString&,const QString&,QuaZip::CaseSensitivity,QObject*),
234 * setFileName() or QuaZip::setCurrentFile() - this is the real file
235 * name inside archive, so it may differ in case if the file name
236 * search was case-insensitive.
237 *
238 * Equivalent to calling getCurrentFileName() on the associated
239 * QuaZip object. Returns null string if there is no associated
240 * QuaZip object or if it does not have a current file yet. And this
241 * is the case if you called setFileName() but did not open the
242 * file yet. So this is perfectly fine:
243 * \code
244 * QuaZipFile file("somezip.zip");
245 * file.setFileName("somefile");
246 * QString name=file.getName(); // name=="somefile"
247 * QString actual=file.getActualFileName(); // actual is null string
248 * file.open(QIODevice::ReadOnly);
249 * QString actual=file.getActualFileName(); // actual can be "SoMeFiLe" on Windows
250 * \endcode
251 *
252 * \sa getZipName(), getFileName(), QuaZip::CaseSensitivity
253 **/
254 QString getActualFileName()const;
255 /// Sets the ZIP archive file name.
256 /** Automatically creates internal QuaZip object and destroys
257 * previously created internal QuaZip object, if any.
258 *
259 * Will do nothing if this file is already open. You must close() it
260 * first.
261 **/
262 void setZipName(const QString& zipName);
263 /// Returns \c true if the file was opened in raw mode.
264 /** If the file is not open, the returned value is undefined.
265 *
266 * \sa open(OpenMode,int*,int*,bool,const char*)
267 **/
268 bool isRaw()const {return raw;}
269 /// Binds to the existing QuaZip instance.
270 /** This function destroys internal QuaZip object, if any, and makes
271 * this QuaZipFile to use current file in the \a zip object for any
272 * further operations. See QuaZipFile(QuaZip*,QObject*) for the
273 * possible pitfalls.
274 *
275 * Will do nothing if the file is currently open. You must close()
276 * it first.
277 **/
278 void setZip(QuaZip *zip);
279 /// Sets the file name.
280 /** Will do nothing if at least one of the following conditions is
281 * met:
282 * - ZIP name has not been set yet (getZipName() returns null
283 * string).
284 * - This QuaZipFile is associated with external QuaZip. In this
285 * case you should call that QuaZip's setCurrentFile() function
286 * instead!
287 * - File is already open so setting the name is meaningless.
288 *
289 * \sa QuaZip::setCurrentFile
290 **/
291 void setFileName(const QString& fileName, QuaZip::CaseSensitivity cs =QuaZip::csDefault);
292 /// Opens a file for reading.
293 /** Returns \c true on success, \c false otherwise.
294 * Call getZipError() to get error code.
295 *
296 * \note Since ZIP/UNZIP API provides buffered reading only,
297 * QuaZipFile does not support unbuffered reading. So do not pass
298 * QIODevice::Unbuffered flag in \a mode, or open will fail.
299 **/
300 virtual bool open(OpenMode mode);
301 /// Opens a file for reading.
302 /** \overload
303 * Argument \a password specifies a password to decrypt the file. If
304 * it is NULL then this function behaves just like open(OpenMode).
305 **/
306 bool open(OpenMode mode, const char *password)
307 {return open(mode, NULL, NULL, false, password);}
308 /// Opens a file for reading.
309 /** \overload
310 * Argument \a password specifies a password to decrypt the file.
311 *
312 * An integers pointed by \a method and \a level will receive codes
313 * of the compression method and level used. See unzip.h.
314 *
315 * If raw is \c true then no decompression is performed.
316 *
317 * \a method should not be \c NULL. \a level can be \c NULL if you
318 * don't want to know the compression level.
319 **/
320 bool open(OpenMode mode, int *method, int *level, bool raw, const char *password =NULL);
321 /// Opens a file for writing.
322 /** \a info argument specifies information about file. It should at
323 * least specify a correct file name. Also, it is a good idea to
324 * specify correct timestamp (by default, current time will be
325 * used). See QuaZipNewInfo.
326 *
327 * Arguments \a password and \a crc provide necessary information
328 * for crypting. Note that you should specify both of them if you
329 * need crypting. If you do not, pass \c NULL as password, but you
330 * still need to specify \a crc if you are going to use raw mode
331 * (see below).
332 *
333 * Arguments \a method and \a level specify compression method and
334 * level.
335 *
336 * If \a raw is \c true, no compression is performed. In this case,
337 * \a crc and uncompressedSize field of the \a info are required.
338 *
339 * Arguments \a windowBits, \a memLevel, \a strategy provide zlib
340 * algorithms tuning. See deflateInit2() in zlib.
341 **/
342 bool open(OpenMode mode, const QuaZipNewInfo& info,
343 const char *password =NULL, quint32 crc =0,
344 int method =Z_DEFLATED, int level =Z_DEFAULT_COMPRESSION, bool raw =false,
345 int windowBits =-MAX_WBITS, int memLevel =DEF_MEM_LEVEL, int strategy =Z_DEFAULT_STRATEGY);
346 /// Returns \c true, but \ref quazipfile-sequential "beware"!
347 virtual bool isSequential()const;
348 /// Returns current position in the file.
349 /** Implementation of the QIODevice::pos(). When reading, this
350 * function is a wrapper to the ZIP/UNZIP unztell(), therefore it is
351 * unable to keep track of the ungetChar() calls (which is
352 * non-virtual and therefore is dangerous to reimplement). So if you
353 * are using ungetChar() feature of the QIODevice, this function
354 * reports incorrect value until you get back characters which you
355 * ungot.
356 *
357 * When writing, pos() returns number of bytes already written
358 * (uncompressed unless you use raw mode).
359 *
360 * \note Although
361 * \ref quazipfile-sequential "QuaZipFile is a sequential device"
362 * and therefore pos() should always return zero, it does not,
363 * because it would be misguiding. Keep this in mind.
364 *
365 * This function returns -1 if the file or archive is not open.
366 *
367 * Error code returned by getZipError() is not affected by this
368 * function call.
369 **/
370 virtual qint64 pos()const;
371 /// Returns \c true if the end of file was reached.
372 /** This function returns \c false in the case of error. This means
373 * that you called this function on either not open file, or a file
374 * in the not open archive or even on a QuaZipFile instance that
375 * does not even have QuaZip instance associated. Do not do that
376 * because there is no means to determine whether \c false is
377 * returned because of error or because end of file was reached.
378 * Well, on the other side you may interpret \c false return value
379 * as "there is no file open to check for end of file and there is
380 * no end of file therefore".
381 *
382 * When writing, this function always returns \c true (because you
383 * are always writing to the end of file).
384 *
385 * Error code returned by getZipError() is not affected by this
386 * function call.
387 **/
388 virtual bool atEnd()const;
389 /// Returns file size.
390 /** This function returns csize() if the file is open for reading in
391 * raw mode, usize() if it is open for reading in normal mode and
392 * pos() if it is open for writing.
393 *
394 * Returns -1 on error, call getZipError() to get error code.
395 *
396 * \note This function returns file size despite that
397 * \ref quazipfile-sequential "QuaZipFile is considered to be sequential device",
398 * for which size() should return bytesAvailable() instead. But its
399 * name would be very misguiding otherwise, so just keep in mind
400 * this inconsistence.
401 **/
402 virtual qint64 size()const;
403 /// Returns compressed file size.
404 /** Equivalent to calling getFileInfo() and then getting
405 * compressedSize field, but more convenient and faster.
406 *
407 * File must be open for reading before calling this function.
408 *
409 * Returns -1 on error, call getZipError() to get error code.
410 **/
411 qint64 csize()const;
412 /// Returns uncompressed file size.
413 /** Equivalent to calling getFileInfo() and then getting
414 * uncompressedSize field, but more convenient and faster. See
415 * getFileInfo() for a warning.
416 *
417 * File must be open for reading before calling this function.
418 *
419 * Returns -1 on error, call getZipError() to get error code.
420 **/
421 qint64 usize()const;
422 /// Gets information about current file.
423 /** This function does the same thing as calling
424 * QuaZip::getCurrentFileInfo() on the associated QuaZip object,
425 * but you can not call getCurrentFileInfo() if the associated
426 * QuaZip is internal (because you do not have access to it), while
427 * you still can call this function in that case.
428 *
429 * File must be open for reading before calling this function.
430 *
431 * Returns \c false in the case of an error.
432 **/
433 bool getFileInfo(QuaZipFileInfo *info);
434 /// Closes the file.
435 /** Call getZipError() to determine if the close was successful.
436 **/
437 virtual void close();
438 /// Returns the error code returned by the last ZIP/UNZIP API call.
439 int getZipError()const {return zipError;}
440};
441
442#endif
diff --git a/rbutil/rbutilqt/quazip/quazipfileinfo.h b/rbutil/rbutilqt/quazip/quazipfileinfo.h
new file mode 100644
index 0000000000..3216d776d5
--- /dev/null
+++ b/rbutil/rbutilqt/quazip/quazipfileinfo.h
@@ -0,0 +1,73 @@
1#ifndef QUA_ZIPFILEINFO_H
2#define QUA_ZIPFILEINFO_H
3
4/*
5-- A kind of "standard" GPL license statement --
6QuaZIP - a Qt/C++ wrapper for the ZIP/UNZIP package
7Copyright (C) 2005-2007 Sergey A. Tachenov
8
9This program is free software; you can redistribute it and/or modify it
10under the terms of the GNU General Public License as published by the
11Free Software Foundation; either version 2 of the License, or (at your
12option) any later version.
13
14This program is distributed in the hope that it will be useful, but
15WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17Public License for more details.
18
19You should have received a copy of the GNU General Public License along
20with this program; if not, write to the Free Software Foundation, Inc.,
2159 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
23-- A kind of "standard" GPL license statement ends here --
24
25See COPYING file for GPL.
26
27You are also permitted to use QuaZIP under the terms of LGPL (see
28COPYING.LGPL). You are free to choose either license, but please note
29that QuaZIP makes use of Qt, which is not licensed under LGPL. So if
30you are using Open Source edition of Qt, you therefore MUST use GPL for
31your code based on QuaZIP, since it would be also based on Qt in this
32case. If you are Qt commercial license owner, then you are free to use
33QuaZIP as long as you respect either GPL or LGPL for QuaZIP code.
34 **/
35
36#include <QByteArray>
37#include <QDateTime>
38
39/// Information about a file inside archive.
40/** Call QuaZip::getCurrentFileInfo() or QuaZipFile::getFileInfo() to
41 * fill this structure. */
42struct QuaZipFileInfo {
43 /// File name.
44 QString name;
45 /// Version created by.
46 quint16 versionCreated;
47 /// Version needed to extract.
48 quint16 versionNeeded;
49 /// General purpose flags.
50 quint16 flags;
51 /// Compression method.
52 quint16 method;
53 /// Last modification date and time.
54 QDateTime dateTime;
55 /// CRC.
56 quint32 crc;
57 /// Compressed file size.
58 quint32 compressedSize;
59 /// Uncompressed file size.
60 quint32 uncompressedSize;
61 /// Disk number start.
62 quint16 diskNumberStart;
63 /// Internal file attributes.
64 quint16 internalAttr;
65 /// External file attributes.
66 quint32 externalAttr;
67 /// Comment.
68 QString comment;
69 /// Extra field.
70 QByteArray extra;
71};
72
73#endif
diff --git a/rbutil/rbutilqt/quazip/quazipnewinfo.cpp b/rbutil/rbutilqt/quazip/quazipnewinfo.cpp
new file mode 100644
index 0000000000..17571f2fc8
--- /dev/null
+++ b/rbutil/rbutilqt/quazip/quazipnewinfo.cpp
@@ -0,0 +1,59 @@
1/* -- A kind of "standard" GPL license statement --
2QuaZIP - a Qt/C++ wrapper for the ZIP/UNZIP package
3Copyright (C) 2005-2007 Sergey A. Tachenov
4
5This program is free software; you can redistribute it and/or modify it
6under the terms of the GNU General Public License as published by the
7Free Software Foundation; either version 2 of the License, or (at your
8option) any later version.
9
10This program is distributed in the hope that it will be useful, but
11WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
13Public License for more details.
14
15You should have received a copy of the GNU General Public License along
16with this program; if not, write to the Free Software Foundation, Inc.,
1759 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19-- A kind of "standard" GPL license statement ends here --
20
21See COPYING file for GPL.
22
23You are also permitted to use QuaZIP under the terms of LGPL (see
24COPYING.LGPL). You are free to choose either license, but please note
25that QuaZIP makes use of Qt, which is not licensed under LGPL. So if
26you are using Open Source edition of Qt, you therefore MUST use GPL for
27your code based on QuaZIP, since it would be also based on Qt in this
28case. If you are Qt commercial license owner, then you are free to use
29QuaZIP as long as you respect either GPL or LGPL for QuaZIP code.
30*/
31
32#include <QFileInfo>
33
34#include "quazipnewinfo.h"
35
36
37QuaZipNewInfo::QuaZipNewInfo(const QString& name):
38 name(name), dateTime(QDateTime::currentDateTime()), internalAttr(0), externalAttr(0)
39{
40}
41
42QuaZipNewInfo::QuaZipNewInfo(const QString& name, const QString& file):
43 name(name), internalAttr(0), externalAttr(0)
44{
45 QFileInfo info(file);
46 QDateTime lm = info.lastModified();
47 if (!info.exists())
48 dateTime = QDateTime::currentDateTime();
49 else
50 dateTime = lm;
51}
52
53void QuaZipNewInfo::setFileDateTime(const QString& file)
54{
55 QFileInfo info(file);
56 QDateTime lm = info.lastModified();
57 if (info.exists())
58 dateTime = lm;
59}
diff --git a/rbutil/rbutilqt/quazip/quazipnewinfo.h b/rbutil/rbutilqt/quazip/quazipnewinfo.h
new file mode 100644
index 0000000000..93ff1a2fc0
--- /dev/null
+++ b/rbutil/rbutilqt/quazip/quazipnewinfo.h
@@ -0,0 +1,109 @@
1#ifndef QUA_ZIPNEWINFO_H
2#define QUA_ZIPNEWINFO_H
3
4/*
5-- A kind of "standard" GPL license statement --
6QuaZIP - a Qt/C++ wrapper for the ZIP/UNZIP package
7Copyright (C) 2005-2007 Sergey A. Tachenov
8
9This program is free software; you can redistribute it and/or modify it
10under the terms of the GNU General Public License as published by the
11Free Software Foundation; either version 2 of the License, or (at your
12option) any later version.
13
14This program is distributed in the hope that it will be useful, but
15WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17Public License for more details.
18
19You should have received a copy of the GNU General Public License along
20with this program; if not, write to the Free Software Foundation, Inc.,
2159 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
23-- A kind of "standard" GPL license statement ends here --
24
25See COPYING file for GPL.
26
27You are also permitted to use QuaZIP under the terms of LGPL (see
28COPYING.LGPL). You are free to choose either license, but please note
29that QuaZIP makes use of Qt, which is not licensed under LGPL. So if
30you are using Open Source edition of Qt, you therefore MUST use GPL for
31your code based on QuaZIP, since it would be also based on Qt in this
32case. If you are Qt commercial license owner, then you are free to use
33QuaZIP as long as you respect either GPL or LGPL for QuaZIP code.
34 **/
35
36#include <QDateTime>
37#include <QString>
38
39/// Information about a file to be created.
40/** This structure holds information about a file to be created inside
41 * ZIP archive. At least name should be set to something correct before
42 * passing this structure to
43 * QuaZipFile::open(OpenMode,const QuaZipNewInfo&,int,int,bool).
44 **/
45struct QuaZipNewInfo {
46 /// File name.
47 /** This field holds file name inside archive, including path relative
48 * to archive root.
49 **/
50 QString name;
51 /// File timestamp.
52 /** This is the last file modification date and time. Will be stored
53 * in the archive central directory. It is a good practice to set it
54 * to the source file timestamp instead of archive creating time. Use
55 * setFileDateTime() or QuaZipNewInfo(const QString&, const QString&).
56 **/
57 QDateTime dateTime;
58 /// File internal attributes.
59 quint16 internalAttr;
60 /// File external attributes.
61 quint32 externalAttr;
62 /// File comment.
63 /** Will be encoded using QuaZip::getCommentCodec().
64 **/
65 QString comment;
66 /// File local extra field.
67 QByteArray extraLocal;
68 /// File global extra field.
69 QByteArray extraGlobal;
70 /// Uncompressed file size.
71 /** This is only needed if you are using raw file zipping mode, i. e.
72 * adding precompressed file in the zip archive.
73 **/
74 ulong uncompressedSize;
75 /// Constructs QuaZipNewInfo instance.
76 /** Initializes name with \a name, dateTime with current date and
77 * time. Attributes are initialized with zeros, comment and extra
78 * field with null values.
79 **/
80 QuaZipNewInfo(const QString& name);
81 /// Constructs QuaZipNewInfo instance.
82 /** Initializes name with \a name and dateTime with timestamp of the
83 * file named \a file. If the \a file does not exists or its timestamp
84 * is inaccessible (e. g. you do not have read permission for the
85 * directory file in), uses current date and time. Attributes are
86 * initialized with zeros, comment and extra field with null values.
87 *
88 * \sa setFileDateTime()
89 **/
90 QuaZipNewInfo(const QString& name, const QString& file);
91 /// Sets the file timestamp from the existing file.
92 /** Use this function to set the file timestamp from the existing
93 * file. Use it like this:
94 * \code
95 * QuaZipFile zipFile(&zip);
96 * QFile file("file-to-add");
97 * file.open(QIODevice::ReadOnly);
98 * QuaZipNewInfo info("file-name-in-archive");
99 * info.setFileDateTime("file-to-add"); // take the timestamp from file
100 * zipFile.open(QIODevice::WriteOnly, info);
101 * \endcode
102 *
103 * This function does not change dateTime if some error occured (e. g.
104 * file is inaccessible).
105 **/
106 void setFileDateTime(const QString& file);
107};
108
109#endif
diff --git a/rbutil/rbutilqt/quazip/unzip.c b/rbutil/rbutilqt/quazip/unzip.c
new file mode 100644
index 0000000000..ace7a08837
--- /dev/null
+++ b/rbutil/rbutilqt/quazip/unzip.c
@@ -0,0 +1,1601 @@
1/* unzip.c -- IO for uncompress .zip files using zlib
2 Version 1.01e, February 12th, 2005
3
4 Copyright (C) 1998-2005 Gilles Vollant
5
6 Read unzip.h for more info
7*/
8
9/* Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of
10compatibility with older software. The following is from the original crypt.c. Code
11woven in by Terry Thorsen 1/2003.
12*/
13/*
14 Copyright (c) 1990-2000 Info-ZIP. All rights reserved.
15
16 See the accompanying file LICENSE, version 2000-Apr-09 or later
17 (the contents of which are also included in zip.h) for terms of use.
18 If, for some reason, all these files are missing, the Info-ZIP license
19 also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
20*/
21/*
22 crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h]
23
24 The encryption/decryption parts of this source code (as opposed to the
25 non-echoing password parts) were originally written in Europe. The
26 whole source package can be freely distributed, including from the USA.
27 (Prior to January 2000, re-export from the US was a violation of US law.)
28 */
29
30/*
31 This encryption code is a direct transcription of the algorithm from
32 Roger Schlafly, described by Phil Katz in the file appnote.txt. This
33 file (appnote.txt) is distributed with the PKZIP program (even in the
34 version without encryption capabilities).
35 */
36
37
38#include <stdio.h>
39#include <stdlib.h>
40#include <string.h>
41#include "zlib.h"
42#include "unzip.h"
43
44#ifdef STDC
45# include <stddef.h>
46# include <string.h>
47# include <stdlib.h>
48#endif
49#ifdef NO_ERRNO_H
50 extern int errno;
51#else
52# include <errno.h>
53#endif
54
55
56#ifndef local
57# define local static
58#endif
59/* compile with -Dlocal if your debugger can't find static symbols */
60
61
62#ifndef CASESENSITIVITYDEFAULT_NO
63# if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES)
64# define CASESENSITIVITYDEFAULT_NO
65# endif
66#endif
67
68
69#ifndef UNZ_BUFSIZE
70#define UNZ_BUFSIZE (16384)
71#endif
72
73#ifndef UNZ_MAXFILENAMEINZIP
74#define UNZ_MAXFILENAMEINZIP (256)
75#endif
76
77#ifndef ALLOC
78# define ALLOC(size) (malloc(size))
79#endif
80#ifndef TRYFREE
81# define TRYFREE(p) {if (p) free(p);}
82#endif
83
84#define SIZECENTRALDIRITEM (0x2e)
85#define SIZEZIPLOCALHEADER (0x1e)
86
87
88
89
90const char unz_copyright[] =
91 " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
92
93/* unz_file_info_interntal contain internal info about a file in zipfile*/
94typedef struct unz_file_info_internal_s
95{
96 uLong offset_curfile;/* relative offset of local header 4 bytes */
97} unz_file_info_internal;
98
99
100/* file_in_zip_read_info_s contain internal information about a file in zipfile,
101 when reading and decompress it */
102typedef struct
103{
104 char *read_buffer; /* internal buffer for compressed data */
105 z_stream stream; /* zLib stream structure for inflate */
106
107 uLong pos_in_zipfile; /* position in byte on the zipfile, for fseek*/
108 uLong stream_initialised; /* flag set if stream structure is initialised*/
109
110 uLong offset_local_extrafield;/* offset of the local extra field */
111 uInt size_local_extrafield;/* size of the local extra field */
112 uLong pos_local_extrafield; /* position in the local extra field in read*/
113
114 uLong crc32; /* crc32 of all data uncompressed */
115 uLong crc32_wait; /* crc32 we must obtain after decompress all */
116 uLong rest_read_compressed; /* number of byte to be decompressed */
117 uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/
118 zlib_filefunc_def z_filefunc;
119 voidpf filestream; /* io structore of the zipfile */
120 uLong compression_method; /* compression method (0==store) */
121 uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
122 int raw;
123} file_in_zip_read_info_s;
124
125
126/* unz_s contain internal information about the zipfile
127*/
128typedef struct
129{
130 zlib_filefunc_def z_filefunc;
131 voidpf filestream; /* io structore of the zipfile */
132 unz_global_info gi; /* public global information */
133 uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
134 uLong num_file; /* number of the current file in the zipfile*/
135 uLong pos_in_central_dir; /* pos of the current file in the central dir*/
136 uLong current_file_ok; /* flag about the usability of the current file*/
137 uLong central_pos; /* position of the beginning of the central dir*/
138
139 uLong size_central_dir; /* size of the central directory */
140 uLong offset_central_dir; /* offset of start of central directory with
141 respect to the starting disk number */
142
143 unz_file_info cur_file_info; /* public info about the current file in zip*/
144 unz_file_info_internal cur_file_info_internal; /* private info about it*/
145 file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
146 file if we are decompressing it */
147 int encrypted;
148# ifndef NOUNCRYPT
149 unsigned long keys[3]; /* keys defining the pseudo-random sequence */
150 const unsigned long* pcrc_32_tab;
151# endif
152} unz_s;
153
154
155#ifndef NOUNCRYPT
156#include "crypt.h"
157#endif
158
159/* ===========================================================================
160 Read a byte from a gz_stream; update next_in and avail_in. Return EOF
161 for end of file.
162 IN assertion: the stream s has been sucessfully opened for reading.
163*/
164
165
166local int unzlocal_getByte OF((
167 const zlib_filefunc_def* pzlib_filefunc_def,
168 voidpf filestream,
169 int *pi));
170
171local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi)
172 const zlib_filefunc_def* pzlib_filefunc_def;
173 voidpf filestream;
174 int *pi;
175{
176 unsigned char c;
177 int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1);
178 if (err==1)
179 {
180 *pi = (int)c;
181 return UNZ_OK;
182 }
183 else
184 {
185 if (ZERROR(*pzlib_filefunc_def,filestream))
186 return UNZ_ERRNO;
187 else
188 return UNZ_EOF;
189 }
190}
191
192
193/* ===========================================================================
194 Reads a long in LSB order from the given gz_stream. Sets
195*/
196local int unzlocal_getShort OF((
197 const zlib_filefunc_def* pzlib_filefunc_def,
198 voidpf filestream,
199 uLong *pX));
200
201local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX)
202 const zlib_filefunc_def* pzlib_filefunc_def;
203 voidpf filestream;
204 uLong *pX;
205{
206 uLong x ;
207 int i;
208 int err;
209
210 err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
211 x = (uLong)i;
212
213 if (err==UNZ_OK)
214 err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
215 x += ((uLong)i)<<8;
216
217 if (err==UNZ_OK)
218 *pX = x;
219 else
220 *pX = 0;
221 return err;
222}
223
224local int unzlocal_getLong OF((
225 const zlib_filefunc_def* pzlib_filefunc_def,
226 voidpf filestream,
227 uLong *pX));
228
229local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX)
230 const zlib_filefunc_def* pzlib_filefunc_def;
231 voidpf filestream;
232 uLong *pX;
233{
234 uLong x ;
235 int i;
236 int err;
237
238 err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
239 x = (uLong)i;
240
241 if (err==UNZ_OK)
242 err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
243 x += ((uLong)i)<<8;
244
245 if (err==UNZ_OK)
246 err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
247 x += ((uLong)i)<<16;
248
249 if (err==UNZ_OK)
250 err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
251 x += ((uLong)i)<<24;
252
253 if (err==UNZ_OK)
254 *pX = x;
255 else
256 *pX = 0;
257 return err;
258}
259
260
261/* My own strcmpi / strcasecmp */
262local int strcmpcasenosensitive_internal (fileName1,fileName2)
263 const char* fileName1;
264 const char* fileName2;
265{
266 for (;;)
267 {
268 char c1=*(fileName1++);
269 char c2=*(fileName2++);
270 if ((c1>='a') && (c1<='z'))
271 c1 -= 0x20;
272 if ((c2>='a') && (c2<='z'))
273 c2 -= 0x20;
274 if (c1=='\0')
275 return ((c2=='\0') ? 0 : -1);
276 if (c2=='\0')
277 return 1;
278 if (c1<c2)
279 return -1;
280 if (c1>c2)
281 return 1;
282 }
283}
284
285
286#ifdef CASESENSITIVITYDEFAULT_NO
287#define CASESENSITIVITYDEFAULTVALUE 2
288#else
289#define CASESENSITIVITYDEFAULTVALUE 1
290#endif
291
292#ifndef STRCMPCASENOSENTIVEFUNCTION
293#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
294#endif
295
296/*
297 Compare two filename (fileName1,fileName2).
298 If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
299 If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
300 or strcasecmp)
301 If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
302 (like 1 on Unix, 2 on Windows)
303
304*/
305extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity)
306 const char* fileName1;
307 const char* fileName2;
308 int iCaseSensitivity;
309{
310 if (iCaseSensitivity==0)
311 iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
312
313 if (iCaseSensitivity==1)
314 return strcmp(fileName1,fileName2);
315
316 return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
317}
318
319#ifndef BUFREADCOMMENT
320#define BUFREADCOMMENT (0x400)
321#endif
322
323/*
324 Locate the Central directory of a zipfile (at the end, just before
325 the global comment)
326*/
327local uLong unzlocal_SearchCentralDir OF((
328 const zlib_filefunc_def* pzlib_filefunc_def,
329 voidpf filestream));
330
331local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream)
332 const zlib_filefunc_def* pzlib_filefunc_def;
333 voidpf filestream;
334{
335 unsigned char* buf;
336 uLong uSizeFile;
337 uLong uBackRead;
338 uLong uMaxBack=0xffff; /* maximum size of global comment */
339 uLong uPosFound=0;
340
341 if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
342 return 0;
343
344
345 uSizeFile = ZTELL(*pzlib_filefunc_def,filestream);
346
347 if (uMaxBack>uSizeFile)
348 uMaxBack = uSizeFile;
349
350 buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
351 if (buf==NULL)
352 return 0;
353
354 uBackRead = 4;
355 while (uBackRead<uMaxBack)
356 {
357 uLong uReadSize,uReadPos ;
358 int i;
359 if (uBackRead+BUFREADCOMMENT>uMaxBack)
360 uBackRead = uMaxBack;
361 else
362 uBackRead+=BUFREADCOMMENT;
363 uReadPos = uSizeFile-uBackRead ;
364
365 uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
366 (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
367 if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
368 break;
369
370 if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
371 break;
372
373 for (i=(int)uReadSize-3; (i--)>0;)
374 if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
375 ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
376 {
377 uPosFound = uReadPos+i;
378 break;
379 }
380
381 if (uPosFound!=0)
382 break;
383 }
384 TRYFREE(buf);
385 return uPosFound;
386}
387
388/*
389 Open a Zip file. path contain the full pathname (by example,
390 on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer
391 "zlib/zlib114.zip".
392 If the zipfile cannot be opened (file doesn't exist or in not valid), the
393 return value is NULL.
394 Else, the return value is a unzFile Handle, usable with other function
395 of this unzip package.
396*/
397extern unzFile ZEXPORT unzOpen2 (path, pzlib_filefunc_def)
398 const char *path;
399 zlib_filefunc_def* pzlib_filefunc_def;
400{
401 unz_s us;
402 unz_s *s;
403 uLong central_pos,uL;
404
405 uLong number_disk; /* number of the current dist, used for
406 spaning ZIP, unsupported, always 0*/
407 uLong number_disk_with_CD; /* number the the disk with central dir, used
408 for spaning ZIP, unsupported, always 0*/
409 uLong number_entry_CD; /* total number of entries in
410 the central dir
411 (same than number_entry on nospan) */
412
413 int err=UNZ_OK;
414
415 if (unz_copyright[0]!=' ')
416 return NULL;
417
418 if (pzlib_filefunc_def==NULL)
419 fill_fopen_filefunc(&us.z_filefunc);
420 else
421 us.z_filefunc = *pzlib_filefunc_def;
422
423 us.filestream= (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque,
424 path,
425 ZLIB_FILEFUNC_MODE_READ |
426 ZLIB_FILEFUNC_MODE_EXISTING);
427 if (us.filestream==NULL)
428 return NULL;
429
430 central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream);
431 if (central_pos==0)
432 err=UNZ_ERRNO;
433
434 if (ZSEEK(us.z_filefunc, us.filestream,
435 central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
436 err=UNZ_ERRNO;
437
438 /* the signature, already checked */
439 if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
440 err=UNZ_ERRNO;
441
442 /* number of this disk */
443 if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
444 err=UNZ_ERRNO;
445
446 /* number of the disk with the start of the central directory */
447 if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
448 err=UNZ_ERRNO;
449
450 /* total number of entries in the central dir on this disk */
451 if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK)
452 err=UNZ_ERRNO;
453
454 /* total number of entries in the central dir */
455 if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK)
456 err=UNZ_ERRNO;
457
458 if ((number_entry_CD!=us.gi.number_entry) ||
459 (number_disk_with_CD!=0) ||
460 (number_disk!=0))
461 err=UNZ_BADZIPFILE;
462
463 /* size of the central directory */
464 if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK)
465 err=UNZ_ERRNO;
466
467 /* offset of start of central directory with respect to the
468 starting disk number */
469 if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK)
470 err=UNZ_ERRNO;
471
472 /* zipfile comment length */
473 if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK)
474 err=UNZ_ERRNO;
475
476 if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
477 (err==UNZ_OK))
478 err=UNZ_BADZIPFILE;
479
480 if (err!=UNZ_OK)
481 {
482 ZCLOSE(us.z_filefunc, us.filestream);
483 return NULL;
484 }
485
486 us.byte_before_the_zipfile = central_pos -
487 (us.offset_central_dir+us.size_central_dir);
488 us.central_pos = central_pos;
489 us.pfile_in_zip_read = NULL;
490 us.encrypted = 0;
491
492
493 s=(unz_s*)ALLOC(sizeof(unz_s));
494 *s=us;
495 unzGoToFirstFile((unzFile)s);
496 return (unzFile)s;
497}
498
499
500extern unzFile ZEXPORT unzOpen (path)
501 const char *path;
502{
503 return unzOpen2(path, NULL);
504}
505
506/*
507 Close a ZipFile opened with unzipOpen.
508 If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
509 these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
510 return UNZ_OK if there is no problem. */
511extern int ZEXPORT unzClose (file)
512 unzFile file;
513{
514 unz_s* s;
515 if (file==NULL)
516 return UNZ_PARAMERROR;
517 s=(unz_s*)file;
518
519 if (s->pfile_in_zip_read!=NULL)
520 unzCloseCurrentFile(file);
521
522 ZCLOSE(s->z_filefunc, s->filestream);
523 TRYFREE(s);
524 return UNZ_OK;
525}
526
527
528/*
529 Write info about the ZipFile in the *pglobal_info structure.
530 No preparation of the structure is needed
531 return UNZ_OK if there is no problem. */
532extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info)
533 unzFile file;
534 unz_global_info *pglobal_info;
535{
536 unz_s* s;
537 if (file==NULL)
538 return UNZ_PARAMERROR;
539 s=(unz_s*)file;
540 *pglobal_info=s->gi;
541 return UNZ_OK;
542}
543
544
545/*
546 Translate date/time from Dos format to tm_unz (readable more easilty)
547*/
548local void unzlocal_DosDateToTmuDate (ulDosDate, ptm)
549 uLong ulDosDate;
550 tm_unz* ptm;
551{
552 uLong uDate;
553 uDate = (uLong)(ulDosDate>>16);
554 ptm->tm_mday = (uInt)(uDate&0x1f) ;
555 ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ;
556 ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
557
558 ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
559 ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ;
560 ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ;
561}
562
563/*
564 Get Info about the current file in the zipfile, with internal only info
565*/
566local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file,
567 unz_file_info *pfile_info,
568 unz_file_info_internal
569 *pfile_info_internal,
570 char *szFileName,
571 uLong fileNameBufferSize,
572 void *extraField,
573 uLong extraFieldBufferSize,
574 char *szComment,
575 uLong commentBufferSize));
576
577local int unzlocal_GetCurrentFileInfoInternal (file,
578 pfile_info,
579 pfile_info_internal,
580 szFileName, fileNameBufferSize,
581 extraField, extraFieldBufferSize,
582 szComment, commentBufferSize)
583 unzFile file;
584 unz_file_info *pfile_info;
585 unz_file_info_internal *pfile_info_internal;
586 char *szFileName;
587 uLong fileNameBufferSize;
588 void *extraField;
589 uLong extraFieldBufferSize;
590 char *szComment;
591 uLong commentBufferSize;
592{
593 unz_s* s;
594 unz_file_info file_info;
595 unz_file_info_internal file_info_internal;
596 int err=UNZ_OK;
597 uLong uMagic;
598 long lSeek=0;
599
600 if (file==NULL)
601 return UNZ_PARAMERROR;
602 s=(unz_s*)file;
603 if (ZSEEK(s->z_filefunc, s->filestream,
604 s->pos_in_central_dir+s->byte_before_the_zipfile,
605 ZLIB_FILEFUNC_SEEK_SET)!=0)
606 err=UNZ_ERRNO;
607
608
609 /* we check the magic */
610 if (err==UNZ_OK) {
611 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
612 err=UNZ_ERRNO;
613 else if (uMagic!=0x02014b50)
614 err=UNZ_BADZIPFILE;
615 }
616
617 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)
618 err=UNZ_ERRNO;
619
620 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)
621 err=UNZ_ERRNO;
622
623 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)
624 err=UNZ_ERRNO;
625
626 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)
627 err=UNZ_ERRNO;
628
629 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK)
630 err=UNZ_ERRNO;
631
632 unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
633
634 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK)
635 err=UNZ_ERRNO;
636
637 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
638 err=UNZ_ERRNO;
639
640 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
641 err=UNZ_ERRNO;
642
643 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK)
644 err=UNZ_ERRNO;
645
646 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK)
647 err=UNZ_ERRNO;
648
649 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK)
650 err=UNZ_ERRNO;
651
652 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
653 err=UNZ_ERRNO;
654
655 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK)
656 err=UNZ_ERRNO;
657
658 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK)
659 err=UNZ_ERRNO;
660
661 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
662 err=UNZ_ERRNO;
663
664 lSeek+=file_info.size_filename;
665 if ((err==UNZ_OK) && (szFileName!=NULL))
666 {
667 uLong uSizeRead ;
668 if (file_info.size_filename<fileNameBufferSize)
669 {
670 *(szFileName+file_info.size_filename)='\0';
671 uSizeRead = file_info.size_filename;
672 }
673 else
674 uSizeRead = fileNameBufferSize;
675
676 if ((file_info.size_filename>0) && (fileNameBufferSize>0))
677 if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)
678 err=UNZ_ERRNO;
679 lSeek -= uSizeRead;
680 }
681
682
683 if ((err==UNZ_OK) && (extraField!=NULL))
684 {
685 uLong uSizeRead ;
686 if (file_info.size_file_extra<extraFieldBufferSize)
687 uSizeRead = file_info.size_file_extra;
688 else
689 uSizeRead = extraFieldBufferSize;
690
691 if (lSeek!=0) {
692 if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
693 lSeek=0;
694 else
695 err=UNZ_ERRNO;
696 }
697 if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
698 if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead)
699 err=UNZ_ERRNO;
700 lSeek += file_info.size_file_extra - uSizeRead;
701 }
702 else
703 lSeek+=file_info.size_file_extra;
704
705
706 if ((err==UNZ_OK) && (szComment!=NULL))
707 {
708 uLong uSizeRead ;
709 if (file_info.size_file_comment<commentBufferSize)
710 {
711 *(szComment+file_info.size_file_comment)='\0';
712 uSizeRead = file_info.size_file_comment;
713 }
714 else
715 uSizeRead = commentBufferSize;
716
717 if (lSeek!=0) {
718 if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
719 lSeek=0;
720 else
721 err=UNZ_ERRNO;
722 }
723 if ((file_info.size_file_comment>0) && (commentBufferSize>0))
724 if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)
725 err=UNZ_ERRNO;
726 lSeek+=file_info.size_file_comment - uSizeRead;
727 }
728 else
729 lSeek+=file_info.size_file_comment;
730
731 if ((err==UNZ_OK) && (pfile_info!=NULL))
732 *pfile_info=file_info;
733
734 if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
735 *pfile_info_internal=file_info_internal;
736
737 return err;
738}
739
740
741
742/*
743 Write info about the ZipFile in the *pglobal_info structure.
744 No preparation of the structure is needed
745 return UNZ_OK if there is no problem.
746*/
747extern int ZEXPORT unzGetCurrentFileInfo (file,
748 pfile_info,
749 szFileName, fileNameBufferSize,
750 extraField, extraFieldBufferSize,
751 szComment, commentBufferSize)
752 unzFile file;
753 unz_file_info *pfile_info;
754 char *szFileName;
755 uLong fileNameBufferSize;
756 void *extraField;
757 uLong extraFieldBufferSize;
758 char *szComment;
759 uLong commentBufferSize;
760{
761 return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
762 szFileName,fileNameBufferSize,
763 extraField,extraFieldBufferSize,
764 szComment,commentBufferSize);
765}
766
767/*
768 Set the current file of the zipfile to the first file.
769 return UNZ_OK if there is no problem
770*/
771extern int ZEXPORT unzGoToFirstFile (file)
772 unzFile file;
773{
774 int err=UNZ_OK;
775 unz_s* s;
776 if (file==NULL)
777 return UNZ_PARAMERROR;
778 s=(unz_s*)file;
779 s->pos_in_central_dir=s->offset_central_dir;
780 s->num_file=0;
781 err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
782 &s->cur_file_info_internal,
783 NULL,0,NULL,0,NULL,0);
784 s->current_file_ok = (err == UNZ_OK);
785 return err;
786}
787
788/*
789 Set the current file of the zipfile to the next file.
790 return UNZ_OK if there is no problem
791 return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
792*/
793extern int ZEXPORT unzGoToNextFile (file)
794 unzFile file;
795{
796 unz_s* s;
797 int err;
798
799 if (file==NULL)
800 return UNZ_PARAMERROR;
801 s=(unz_s*)file;
802 if (!s->current_file_ok)
803 return UNZ_END_OF_LIST_OF_FILE;
804 if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */
805 if (s->num_file+1==s->gi.number_entry)
806 return UNZ_END_OF_LIST_OF_FILE;
807
808 s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
809 s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
810 s->num_file++;
811 err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
812 &s->cur_file_info_internal,
813 NULL,0,NULL,0,NULL,0);
814 s->current_file_ok = (err == UNZ_OK);
815 return err;
816}
817
818
819/*
820 Try locate the file szFileName in the zipfile.
821 For the iCaseSensitivity signification, see unzipStringFileNameCompare
822
823 return value :
824 UNZ_OK if the file is found. It becomes the current file.
825 UNZ_END_OF_LIST_OF_FILE if the file is not found
826*/
827extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity)
828 unzFile file;
829 const char *szFileName;
830 int iCaseSensitivity;
831{
832 unz_s* s;
833 int err;
834
835 /* We remember the 'current' position in the file so that we can jump
836 * back there if we fail.
837 */
838 unz_file_info cur_file_infoSaved;
839 unz_file_info_internal cur_file_info_internalSaved;
840 uLong num_fileSaved;
841 uLong pos_in_central_dirSaved;
842
843
844 if (file==NULL)
845 return UNZ_PARAMERROR;
846
847 if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
848 return UNZ_PARAMERROR;
849
850 s=(unz_s*)file;
851 if (!s->current_file_ok)
852 return UNZ_END_OF_LIST_OF_FILE;
853
854 /* Save the current state */
855 num_fileSaved = s->num_file;
856 pos_in_central_dirSaved = s->pos_in_central_dir;
857 cur_file_infoSaved = s->cur_file_info;
858 cur_file_info_internalSaved = s->cur_file_info_internal;
859
860 err = unzGoToFirstFile(file);
861
862 while (err == UNZ_OK)
863 {
864 char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
865 err = unzGetCurrentFileInfo(file,NULL,
866 szCurrentFileName,sizeof(szCurrentFileName)-1,
867 NULL,0,NULL,0);
868 if (err == UNZ_OK)
869 {
870 if (unzStringFileNameCompare(szCurrentFileName,
871 szFileName,iCaseSensitivity)==0)
872 return UNZ_OK;
873 err = unzGoToNextFile(file);
874 }
875 }
876
877 /* We failed, so restore the state of the 'current file' to where we
878 * were.
879 */
880 s->num_file = num_fileSaved ;
881 s->pos_in_central_dir = pos_in_central_dirSaved ;
882 s->cur_file_info = cur_file_infoSaved;
883 s->cur_file_info_internal = cur_file_info_internalSaved;
884 return err;
885}
886
887
888/*
889///////////////////////////////////////////
890// Contributed by Ryan Haksi (mailto://cryogen@infoserve.net)
891// I need random access
892//
893// Further optimization could be realized by adding an ability
894// to cache the directory in memory. The goal being a single
895// comprehensive file read to put the file I need in a memory.
896*/
897
898/*
899typedef struct unz_file_pos_s
900{
901 uLong pos_in_zip_directory; // offset in file
902 uLong num_of_file; // # of file
903} unz_file_pos;
904*/
905
906extern int ZEXPORT unzGetFilePos(file, file_pos)
907 unzFile file;
908 unz_file_pos* file_pos;
909{
910 unz_s* s;
911
912 if (file==NULL || file_pos==NULL)
913 return UNZ_PARAMERROR;
914 s=(unz_s*)file;
915 if (!s->current_file_ok)
916 return UNZ_END_OF_LIST_OF_FILE;
917
918 file_pos->pos_in_zip_directory = s->pos_in_central_dir;
919 file_pos->num_of_file = s->num_file;
920
921 return UNZ_OK;
922}
923
924extern int ZEXPORT unzGoToFilePos(file, file_pos)
925 unzFile file;
926 unz_file_pos* file_pos;
927{
928 unz_s* s;
929 int err;
930
931 if (file==NULL || file_pos==NULL)
932 return UNZ_PARAMERROR;
933 s=(unz_s*)file;
934
935 /* jump to the right spot */
936 s->pos_in_central_dir = file_pos->pos_in_zip_directory;
937 s->num_file = file_pos->num_of_file;
938
939 /* set the current file */
940 err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
941 &s->cur_file_info_internal,
942 NULL,0,NULL,0,NULL,0);
943 /* return results */
944 s->current_file_ok = (err == UNZ_OK);
945 return err;
946}
947
948/*
949// Unzip Helper Functions - should be here?
950///////////////////////////////////////////
951*/
952
953/*
954 Read the local header of the current zipfile
955 Check the coherency of the local header and info in the end of central
956 directory about this file
957 store in *piSizeVar the size of extra info in local header
958 (filename and size of extra field data)
959*/
960local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar,
961 poffset_local_extrafield,
962 psize_local_extrafield)
963 unz_s* s;
964 uInt* piSizeVar;
965 uLong *poffset_local_extrafield;
966 uInt *psize_local_extrafield;
967{
968 uLong uMagic,uData,uFlags;
969 uLong size_filename;
970 uLong size_extra_field;
971 int err=UNZ_OK;
972
973 *piSizeVar = 0;
974 *poffset_local_extrafield = 0;
975 *psize_local_extrafield = 0;
976
977 if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile +
978 s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
979 return UNZ_ERRNO;
980
981
982 if (err==UNZ_OK) {
983 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
984 err=UNZ_ERRNO;
985 else if (uMagic!=0x04034b50)
986 err=UNZ_BADZIPFILE;
987 }
988
989 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
990 err=UNZ_ERRNO;
991/*
992 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
993 err=UNZ_BADZIPFILE;
994*/
995 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK)
996 err=UNZ_ERRNO;
997
998 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
999 err=UNZ_ERRNO;
1000 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
1001 err=UNZ_BADZIPFILE;
1002
1003 if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
1004 (s->cur_file_info.compression_method!=Z_DEFLATED))
1005 err=UNZ_BADZIPFILE;
1006
1007 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */
1008 err=UNZ_ERRNO;
1009
1010 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */
1011 err=UNZ_ERRNO;
1012 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
1013 ((uFlags & 8)==0))
1014 err=UNZ_BADZIPFILE;
1015
1016 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */
1017 err=UNZ_ERRNO;
1018 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
1019 ((uFlags & 8)==0))
1020 err=UNZ_BADZIPFILE;
1021
1022 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */
1023 err=UNZ_ERRNO;
1024 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&
1025 ((uFlags & 8)==0))
1026 err=UNZ_BADZIPFILE;
1027
1028
1029 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK)
1030 err=UNZ_ERRNO;
1031 else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
1032 err=UNZ_BADZIPFILE;
1033
1034 *piSizeVar += (uInt)size_filename;
1035
1036 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK)
1037 err=UNZ_ERRNO;
1038 *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
1039 SIZEZIPLOCALHEADER + size_filename;
1040 *psize_local_extrafield = (uInt)size_extra_field;
1041
1042 *piSizeVar += (uInt)size_extra_field;
1043
1044 return err;
1045}
1046
1047/*
1048 Open for reading data the current file in the zipfile.
1049 If there is no error and the file is opened, the return value is UNZ_OK.
1050*/
1051extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password)
1052 unzFile file;
1053 int* method;
1054 int* level;
1055 int raw;
1056 const char* password;
1057{
1058 int err=UNZ_OK;
1059 uInt iSizeVar;
1060 unz_s* s;
1061 file_in_zip_read_info_s* pfile_in_zip_read_info;
1062 uLong offset_local_extrafield; /* offset of the local extra field */
1063 uInt size_local_extrafield; /* size of the local extra field */
1064# ifndef NOUNCRYPT
1065 char source[12];
1066# else
1067 if (password != NULL)
1068 return UNZ_PARAMERROR;
1069# endif
1070
1071 if (file==NULL)
1072 return UNZ_PARAMERROR;
1073 s=(unz_s*)file;
1074 if (!s->current_file_ok)
1075 return UNZ_PARAMERROR;
1076
1077 if (s->pfile_in_zip_read != NULL)
1078 unzCloseCurrentFile(file);
1079
1080 if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
1081 &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
1082 return UNZ_BADZIPFILE;
1083
1084 pfile_in_zip_read_info = (file_in_zip_read_info_s*)
1085 ALLOC(sizeof(file_in_zip_read_info_s));
1086 if (pfile_in_zip_read_info==NULL)
1087 return UNZ_INTERNALERROR;
1088
1089 pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
1090 pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
1091 pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
1092 pfile_in_zip_read_info->pos_local_extrafield=0;
1093 pfile_in_zip_read_info->raw=raw;
1094
1095 if (pfile_in_zip_read_info->read_buffer==NULL)
1096 {
1097 TRYFREE(pfile_in_zip_read_info);
1098 return UNZ_INTERNALERROR;
1099 }
1100
1101 pfile_in_zip_read_info->stream_initialised=0;
1102
1103 if (method!=NULL)
1104 *method = (int)s->cur_file_info.compression_method;
1105
1106 if (level!=NULL)
1107 {
1108 *level = 6;
1109 switch (s->cur_file_info.flag & 0x06)
1110 {
1111 case 6 : *level = 1; break;
1112 case 4 : *level = 2; break;
1113 case 2 : *level = 9; break;
1114 }
1115 }
1116
1117 if ((s->cur_file_info.compression_method!=0) &&
1118 (s->cur_file_info.compression_method!=Z_DEFLATED))
1119 err=UNZ_BADZIPFILE;
1120
1121 pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
1122 pfile_in_zip_read_info->crc32=0;
1123 pfile_in_zip_read_info->compression_method =
1124 s->cur_file_info.compression_method;
1125 pfile_in_zip_read_info->filestream=s->filestream;
1126 pfile_in_zip_read_info->z_filefunc=s->z_filefunc;
1127 pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
1128
1129 pfile_in_zip_read_info->stream.total_out = 0;
1130
1131 if ((s->cur_file_info.compression_method==Z_DEFLATED) &&
1132 (!raw))
1133 {
1134 pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
1135 pfile_in_zip_read_info->stream.zfree = (free_func)0;
1136 pfile_in_zip_read_info->stream.opaque = (voidpf)0;
1137 pfile_in_zip_read_info->stream.next_in = (voidpf)0;
1138 pfile_in_zip_read_info->stream.avail_in = 0;
1139
1140 err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
1141 if (err == Z_OK)
1142 pfile_in_zip_read_info->stream_initialised=1;
1143 else
1144 {
1145 TRYFREE(pfile_in_zip_read_info);
1146 return err;
1147 }
1148 /* windowBits is passed < 0 to tell that there is no zlib header.
1149 * Note that in this case inflate *requires* an extra "dummy" byte
1150 * after the compressed stream in order to complete decompression and
1151 * return Z_STREAM_END.
1152 * In unzip, i don't wait absolutely Z_STREAM_END because I known the
1153 * size of both compressed and uncompressed data
1154 */
1155 }
1156 pfile_in_zip_read_info->rest_read_compressed =
1157 s->cur_file_info.compressed_size ;
1158 pfile_in_zip_read_info->rest_read_uncompressed =
1159 s->cur_file_info.uncompressed_size ;
1160
1161
1162 pfile_in_zip_read_info->pos_in_zipfile =
1163 s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
1164 iSizeVar;
1165
1166 pfile_in_zip_read_info->stream.avail_in = (uInt)0;
1167
1168 s->pfile_in_zip_read = pfile_in_zip_read_info;
1169
1170# ifndef NOUNCRYPT
1171 if (password != NULL)
1172 {
1173 int i;
1174 s->pcrc_32_tab = get_crc_table();
1175 init_keys(password,s->keys,s->pcrc_32_tab);
1176 if (ZSEEK(s->z_filefunc, s->filestream,
1177 s->pfile_in_zip_read->pos_in_zipfile +
1178 s->pfile_in_zip_read->byte_before_the_zipfile,
1179 SEEK_SET)!=0)
1180 return UNZ_INTERNALERROR;
1181 if(ZREAD(s->z_filefunc, s->filestream,source, 12)<12)
1182 return UNZ_INTERNALERROR;
1183
1184 for (i = 0; i<12; i++)
1185 zdecode(s->keys,s->pcrc_32_tab,source[i]);
1186
1187 s->pfile_in_zip_read->pos_in_zipfile+=12;
1188 s->encrypted=1;
1189 }
1190# endif
1191
1192
1193 return UNZ_OK;
1194}
1195
1196extern int ZEXPORT unzOpenCurrentFile (file)
1197 unzFile file;
1198{
1199 return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
1200}
1201
1202extern int ZEXPORT unzOpenCurrentFilePassword (file, password)
1203 unzFile file;
1204 const char* password;
1205{
1206 return unzOpenCurrentFile3(file, NULL, NULL, 0, password);
1207}
1208
1209extern int ZEXPORT unzOpenCurrentFile2 (file,method,level,raw)
1210 unzFile file;
1211 int* method;
1212 int* level;
1213 int raw;
1214{
1215 return unzOpenCurrentFile3(file, method, level, raw, NULL);
1216}
1217
1218/*
1219 Read bytes from the current file.
1220 buf contain buffer where data must be copied
1221 len the size of buf.
1222
1223 return the number of byte copied if somes bytes are copied
1224 return 0 if the end of file was reached
1225 return <0 with error code if there is an error
1226 (UNZ_ERRNO for IO error, or zLib error for uncompress error)
1227*/
1228extern int ZEXPORT unzReadCurrentFile (file, buf, len)
1229 unzFile file;
1230 voidp buf;
1231 unsigned len;
1232{
1233 int err=UNZ_OK;
1234 uInt iRead = 0;
1235 unz_s* s;
1236 file_in_zip_read_info_s* pfile_in_zip_read_info;
1237 if (file==NULL)
1238 return UNZ_PARAMERROR;
1239 s=(unz_s*)file;
1240 pfile_in_zip_read_info=s->pfile_in_zip_read;
1241
1242 if (pfile_in_zip_read_info==NULL)
1243 return UNZ_PARAMERROR;
1244
1245
1246 if ((pfile_in_zip_read_info->read_buffer == NULL))
1247 return UNZ_END_OF_LIST_OF_FILE;
1248 if (len==0)
1249 return 0;
1250
1251 pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
1252
1253 pfile_in_zip_read_info->stream.avail_out = (uInt)len;
1254
1255 if ((len>pfile_in_zip_read_info->rest_read_uncompressed) &&
1256 (!(pfile_in_zip_read_info->raw)))
1257 pfile_in_zip_read_info->stream.avail_out =
1258 (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
1259
1260 if ((len>pfile_in_zip_read_info->rest_read_compressed+
1261 pfile_in_zip_read_info->stream.avail_in) &&
1262 (pfile_in_zip_read_info->raw))
1263 pfile_in_zip_read_info->stream.avail_out =
1264 (uInt)pfile_in_zip_read_info->rest_read_compressed+
1265 pfile_in_zip_read_info->stream.avail_in;
1266
1267 while (pfile_in_zip_read_info->stream.avail_out>0)
1268 {
1269 if ((pfile_in_zip_read_info->stream.avail_in==0) &&
1270 (pfile_in_zip_read_info->rest_read_compressed>0))
1271 {
1272 uInt uReadThis = UNZ_BUFSIZE;
1273 if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
1274 uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
1275 if (uReadThis == 0)
1276 return UNZ_EOF;
1277 if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
1278 pfile_in_zip_read_info->filestream,
1279 pfile_in_zip_read_info->pos_in_zipfile +
1280 pfile_in_zip_read_info->byte_before_the_zipfile,
1281 ZLIB_FILEFUNC_SEEK_SET)!=0)
1282 return UNZ_ERRNO;
1283 if (ZREAD(pfile_in_zip_read_info->z_filefunc,
1284 pfile_in_zip_read_info->filestream,
1285 pfile_in_zip_read_info->read_buffer,
1286 uReadThis)!=uReadThis)
1287 return UNZ_ERRNO;
1288
1289
1290# ifndef NOUNCRYPT
1291 if(s->encrypted)
1292 {
1293 uInt i;
1294 for(i=0;i<uReadThis;i++)
1295 pfile_in_zip_read_info->read_buffer[i] =
1296 zdecode(s->keys,s->pcrc_32_tab,
1297 pfile_in_zip_read_info->read_buffer[i]);
1298 }
1299# endif
1300
1301
1302 pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
1303
1304 pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
1305
1306 pfile_in_zip_read_info->stream.next_in =
1307 (Bytef*)pfile_in_zip_read_info->read_buffer;
1308 pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
1309 }
1310
1311 if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw))
1312 {
1313 uInt uDoCopy,i ;
1314
1315 if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
1316 (pfile_in_zip_read_info->rest_read_compressed == 0))
1317 return (iRead==0) ? UNZ_EOF : iRead;
1318
1319 if (pfile_in_zip_read_info->stream.avail_out <
1320 pfile_in_zip_read_info->stream.avail_in)
1321 uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
1322 else
1323 uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
1324
1325 for (i=0;i<uDoCopy;i++)
1326 *(pfile_in_zip_read_info->stream.next_out+i) =
1327 *(pfile_in_zip_read_info->stream.next_in+i);
1328
1329 pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
1330 pfile_in_zip_read_info->stream.next_out,
1331 uDoCopy);
1332 pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
1333 pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
1334 pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
1335 pfile_in_zip_read_info->stream.next_out += uDoCopy;
1336 pfile_in_zip_read_info->stream.next_in += uDoCopy;
1337 pfile_in_zip_read_info->stream.total_out += uDoCopy;
1338 iRead += uDoCopy;
1339 }
1340 else
1341 {
1342 uLong uTotalOutBefore,uTotalOutAfter;
1343 const Bytef *bufBefore;
1344 uLong uOutThis;
1345 int flush=Z_SYNC_FLUSH;
1346
1347 uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
1348 bufBefore = pfile_in_zip_read_info->stream.next_out;
1349
1350 /*
1351 if ((pfile_in_zip_read_info->rest_read_uncompressed ==
1352 pfile_in_zip_read_info->stream.avail_out) &&
1353 (pfile_in_zip_read_info->rest_read_compressed == 0))
1354 flush = Z_FINISH;
1355 */
1356 err=inflate(&pfile_in_zip_read_info->stream,flush);
1357
1358 if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL))
1359 err = Z_DATA_ERROR;
1360
1361 uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
1362 uOutThis = uTotalOutAfter-uTotalOutBefore;
1363
1364 pfile_in_zip_read_info->crc32 =
1365 crc32(pfile_in_zip_read_info->crc32,bufBefore,
1366 (uInt)(uOutThis));
1367
1368 pfile_in_zip_read_info->rest_read_uncompressed -=
1369 uOutThis;
1370
1371 iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
1372
1373 if (err==Z_STREAM_END)
1374 return (iRead==0) ? UNZ_EOF : iRead;
1375 if (err!=Z_OK)
1376 break;
1377 }
1378 }
1379
1380 if (err==Z_OK)
1381 return iRead;
1382 return err;
1383}
1384
1385
1386/*
1387 Give the current position in uncompressed data
1388*/
1389extern z_off_t ZEXPORT unztell (file)
1390 unzFile file;
1391{
1392 unz_s* s;
1393 file_in_zip_read_info_s* pfile_in_zip_read_info;
1394 if (file==NULL)
1395 return UNZ_PARAMERROR;
1396 s=(unz_s*)file;
1397 pfile_in_zip_read_info=s->pfile_in_zip_read;
1398
1399 if (pfile_in_zip_read_info==NULL)
1400 return UNZ_PARAMERROR;
1401
1402 return (z_off_t)pfile_in_zip_read_info->stream.total_out;
1403}
1404
1405
1406/*
1407 return 1 if the end of file was reached, 0 elsewhere
1408*/
1409extern int ZEXPORT unzeof (file)
1410 unzFile file;
1411{
1412 unz_s* s;
1413 file_in_zip_read_info_s* pfile_in_zip_read_info;
1414 if (file==NULL)
1415 return UNZ_PARAMERROR;
1416 s=(unz_s*)file;
1417 pfile_in_zip_read_info=s->pfile_in_zip_read;
1418
1419 if (pfile_in_zip_read_info==NULL)
1420 return UNZ_PARAMERROR;
1421
1422 if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1423 return 1;
1424 else
1425 return 0;
1426}
1427
1428
1429
1430/*
1431 Read extra field from the current file (opened by unzOpenCurrentFile)
1432 This is the local-header version of the extra field (sometimes, there is
1433 more info in the local-header version than in the central-header)
1434
1435 if buf==NULL, it return the size of the local extra field that can be read
1436
1437 if buf!=NULL, len is the size of the buffer, the extra header is copied in
1438 buf.
1439 the return value is the number of bytes copied in buf, or (if <0)
1440 the error code
1441*/
1442extern int ZEXPORT unzGetLocalExtrafield (file,buf,len)
1443 unzFile file;
1444 voidp buf;
1445 unsigned len;
1446{
1447 unz_s* s;
1448 file_in_zip_read_info_s* pfile_in_zip_read_info;
1449 uInt read_now;
1450 uLong size_to_read;
1451
1452 if (file==NULL)
1453 return UNZ_PARAMERROR;
1454 s=(unz_s*)file;
1455 pfile_in_zip_read_info=s->pfile_in_zip_read;
1456
1457 if (pfile_in_zip_read_info==NULL)
1458 return UNZ_PARAMERROR;
1459
1460 size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
1461 pfile_in_zip_read_info->pos_local_extrafield);
1462
1463 if (buf==NULL)
1464 return (int)size_to_read;
1465
1466 if (len>size_to_read)
1467 read_now = (uInt)size_to_read;
1468 else
1469 read_now = (uInt)len ;
1470
1471 if (read_now==0)
1472 return 0;
1473
1474 if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
1475 pfile_in_zip_read_info->filestream,
1476 pfile_in_zip_read_info->offset_local_extrafield +
1477 pfile_in_zip_read_info->pos_local_extrafield,
1478 ZLIB_FILEFUNC_SEEK_SET)!=0)
1479 return UNZ_ERRNO;
1480
1481 if (ZREAD(pfile_in_zip_read_info->z_filefunc,
1482 pfile_in_zip_read_info->filestream,
1483 buf,read_now)!=read_now)
1484 return UNZ_ERRNO;
1485
1486 return (int)read_now;
1487}
1488
1489/*
1490 Close the file in zip opened with unzipOpenCurrentFile
1491 Return UNZ_CRCERROR if all the file was read but the CRC is not good
1492*/
1493extern int ZEXPORT unzCloseCurrentFile (file)
1494 unzFile file;
1495{
1496 int err=UNZ_OK;
1497
1498 unz_s* s;
1499 file_in_zip_read_info_s* pfile_in_zip_read_info;
1500 if (file==NULL)
1501 return UNZ_PARAMERROR;
1502 s=(unz_s*)file;
1503 pfile_in_zip_read_info=s->pfile_in_zip_read;
1504
1505 if (pfile_in_zip_read_info==NULL)
1506 return UNZ_PARAMERROR;
1507
1508
1509 if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
1510 (!pfile_in_zip_read_info->raw))
1511 {
1512 if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
1513 err=UNZ_CRCERROR;
1514 }
1515
1516
1517 TRYFREE(pfile_in_zip_read_info->read_buffer);
1518 pfile_in_zip_read_info->read_buffer = NULL;
1519 if (pfile_in_zip_read_info->stream_initialised)
1520 inflateEnd(&pfile_in_zip_read_info->stream);
1521
1522 pfile_in_zip_read_info->stream_initialised = 0;
1523 TRYFREE(pfile_in_zip_read_info);
1524
1525 s->pfile_in_zip_read=NULL;
1526
1527 return err;
1528}
1529
1530
1531/*
1532 Get the global comment string of the ZipFile, in the szComment buffer.
1533 uSizeBuf is the size of the szComment buffer.
1534 return the number of byte copied or an error code <0
1535*/
1536extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf)
1537 unzFile file;
1538 char *szComment;
1539 uLong uSizeBuf;
1540{
1541 unz_s* s;
1542 uLong uReadThis ;
1543 if (file==NULL)
1544 return UNZ_PARAMERROR;
1545 s=(unz_s*)file;
1546
1547 uReadThis = uSizeBuf;
1548 if (uReadThis>s->gi.size_comment)
1549 uReadThis = s->gi.size_comment;
1550
1551 if (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0)
1552 return UNZ_ERRNO;
1553
1554 if (uReadThis>0)
1555 {
1556 *szComment='\0';
1557 if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis)
1558 return UNZ_ERRNO;
1559 }
1560
1561 if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
1562 *(szComment+s->gi.size_comment)='\0';
1563 return (int)uReadThis;
1564}
1565
1566/* Additions by RX '2004 */
1567extern uLong ZEXPORT unzGetOffset (file)
1568 unzFile file;
1569{
1570 unz_s* s;
1571
1572 if (file==NULL)
1573 return UNZ_PARAMERROR;
1574 s=(unz_s*)file;
1575 if (!s->current_file_ok)
1576 return 0;
1577 if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff)
1578 if (s->num_file==s->gi.number_entry)
1579 return 0;
1580 return s->pos_in_central_dir;
1581}
1582
1583extern int ZEXPORT unzSetOffset (file, pos)
1584 unzFile file;
1585 uLong pos;
1586{
1587 unz_s* s;
1588 int err;
1589
1590 if (file==NULL)
1591 return UNZ_PARAMERROR;
1592 s=(unz_s*)file;
1593
1594 s->pos_in_central_dir = pos;
1595 s->num_file = s->gi.number_entry; /* hack */
1596 err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
1597 &s->cur_file_info_internal,
1598 NULL,0,NULL,0,NULL,0);
1599 s->current_file_ok = (err == UNZ_OK);
1600 return err;
1601}
diff --git a/rbutil/rbutilqt/quazip/unzip.h b/rbutil/rbutilqt/quazip/unzip.h
new file mode 100644
index 0000000000..b247937c80
--- /dev/null
+++ b/rbutil/rbutilqt/quazip/unzip.h
@@ -0,0 +1,354 @@
1/* unzip.h -- IO for uncompress .zip files using zlib
2 Version 1.01e, February 12th, 2005
3
4 Copyright (C) 1998-2005 Gilles Vollant
5
6 This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g
7 WinZip, InfoZip tools and compatible.
8
9 Multi volume ZipFile (span) are not supported.
10 Encryption compatible with pkzip 2.04g only supported
11 Old compressions used by old PKZip 1.x are not supported
12
13
14 I WAIT FEEDBACK at mail info@winimage.com
15 Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution
16
17 Condition of use and distribution are the same than zlib :
18
19 This software is provided 'as-is', without any express or implied
20 warranty. In no event will the authors be held liable for any damages
21 arising from the use of this software.
22
23 Permission is granted to anyone to use this software for any purpose,
24 including commercial applications, and to alter it and redistribute it
25 freely, subject to the following restrictions:
26
27 1. The origin of this software must not be misrepresented; you must not
28 claim that you wrote the original software. If you use this software
29 in a product, an acknowledgment in the product documentation would be
30 appreciated but is not required.
31 2. Altered source versions must be plainly marked as such, and must not be
32 misrepresented as being the original software.
33 3. This notice may not be removed or altered from any source distribution.
34
35
36*/
37
38/* for more info about .ZIP format, see
39 http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip
40 http://www.info-zip.org/pub/infozip/doc/
41 PkWare has also a specification at :
42 ftp://ftp.pkware.com/probdesc.zip
43*/
44
45#ifndef _unz_H
46#define _unz_H
47
48#ifdef __cplusplus
49extern "C" {
50#endif
51
52#ifndef _ZLIB_H
53#include "zlib.h"
54#endif
55
56#ifndef _ZLIBIOAPI_H
57#include "ioapi.h"
58#endif
59
60#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
61/* like the STRICT of WIN32, we define a pointer that cannot be converted
62 from (void*) without cast */
63typedef struct TagunzFile__ { int unused; } unzFile__;
64typedef unzFile__ *unzFile;
65#else
66typedef voidp unzFile;
67#endif
68
69
70#define UNZ_OK (0)
71#define UNZ_END_OF_LIST_OF_FILE (-100)
72#define UNZ_ERRNO (Z_ERRNO)
73#define UNZ_EOF (0)
74#define UNZ_PARAMERROR (-102)
75#define UNZ_BADZIPFILE (-103)
76#define UNZ_INTERNALERROR (-104)
77#define UNZ_CRCERROR (-105)
78
79/* tm_unz contain date/time info */
80typedef struct tm_unz_s
81{
82 uInt tm_sec; /* seconds after the minute - [0,59] */
83 uInt tm_min; /* minutes after the hour - [0,59] */
84 uInt tm_hour; /* hours since midnight - [0,23] */
85 uInt tm_mday; /* day of the month - [1,31] */
86 uInt tm_mon; /* months since January - [0,11] */
87 uInt tm_year; /* years - [1980..2044] */
88} tm_unz;
89
90/* unz_global_info structure contain global data about the ZIPfile
91 These data comes from the end of central dir */
92typedef struct unz_global_info_s
93{
94 uLong number_entry; /* total number of entries in
95 the central dir on this disk */
96 uLong size_comment; /* size of the global comment of the zipfile */
97} unz_global_info;
98
99
100/* unz_file_info contain information about a file in the zipfile */
101typedef struct unz_file_info_s
102{
103 uLong version; /* version made by 2 bytes */
104 uLong version_needed; /* version needed to extract 2 bytes */
105 uLong flag; /* general purpose bit flag 2 bytes */
106 uLong compression_method; /* compression method 2 bytes */
107 uLong dosDate; /* last mod file date in Dos fmt 4 bytes */
108 uLong crc; /* crc-32 4 bytes */
109 uLong compressed_size; /* compressed size 4 bytes */
110 uLong uncompressed_size; /* uncompressed size 4 bytes */
111 uLong size_filename; /* filename length 2 bytes */
112 uLong size_file_extra; /* extra field length 2 bytes */
113 uLong size_file_comment; /* file comment length 2 bytes */
114
115 uLong disk_num_start; /* disk number start 2 bytes */
116 uLong internal_fa; /* internal file attributes 2 bytes */
117 uLong external_fa; /* external file attributes 4 bytes */
118
119 tm_unz tmu_date;
120} unz_file_info;
121
122extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1,
123 const char* fileName2,
124 int iCaseSensitivity));
125/*
126 Compare two filename (fileName1,fileName2).
127 If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
128 If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
129 or strcasecmp)
130 If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
131 (like 1 on Unix, 2 on Windows)
132*/
133
134
135extern unzFile ZEXPORT unzOpen OF((const char *path));
136/*
137 Open a Zip file. path contain the full pathname (by example,
138 on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer
139 "zlib/zlib113.zip".
140 If the zipfile cannot be opened (file don't exist or in not valid), the
141 return value is NULL.
142 Else, the return value is a unzFile Handle, usable with other function
143 of this unzip package.
144*/
145
146extern unzFile ZEXPORT unzOpen2 OF((const char *path,
147 zlib_filefunc_def* pzlib_filefunc_def));
148/*
149 Open a Zip file, like unzOpen, but provide a set of file low level API
150 for read/write the zip file (see ioapi.h)
151*/
152
153extern int ZEXPORT unzClose OF((unzFile file));
154/*
155 Close a ZipFile opened with unzipOpen.
156 If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
157 these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
158 return UNZ_OK if there is no problem. */
159
160extern int ZEXPORT unzGetGlobalInfo OF((unzFile file,
161 unz_global_info *pglobal_info));
162/*
163 Write info about the ZipFile in the *pglobal_info structure.
164 No preparation of the structure is needed
165 return UNZ_OK if there is no problem. */
166
167
168extern int ZEXPORT unzGetGlobalComment OF((unzFile file,
169 char *szComment,
170 uLong uSizeBuf));
171/*
172 Get the global comment string of the ZipFile, in the szComment buffer.
173 uSizeBuf is the size of the szComment buffer.
174 return the number of byte copied or an error code <0
175*/
176
177
178/***************************************************************************/
179/* Unzip package allow you browse the directory of the zipfile */
180
181extern int ZEXPORT unzGoToFirstFile OF((unzFile file));
182/*
183 Set the current file of the zipfile to the first file.
184 return UNZ_OK if there is no problem
185*/
186
187extern int ZEXPORT unzGoToNextFile OF((unzFile file));
188/*
189 Set the current file of the zipfile to the next file.
190 return UNZ_OK if there is no problem
191 return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
192*/
193
194extern int ZEXPORT unzLocateFile OF((unzFile file,
195 const char *szFileName,
196 int iCaseSensitivity));
197/*
198 Try locate the file szFileName in the zipfile.
199 For the iCaseSensitivity signification, see unzStringFileNameCompare
200
201 return value :
202 UNZ_OK if the file is found. It becomes the current file.
203 UNZ_END_OF_LIST_OF_FILE if the file is not found
204*/
205
206
207/* ****************************************** */
208/* Ryan supplied functions */
209/* unz_file_info contain information about a file in the zipfile */
210typedef struct unz_file_pos_s
211{
212 uLong pos_in_zip_directory; /* offset in zip file directory */
213 uLong num_of_file; /* # of file */
214} unz_file_pos;
215
216extern int ZEXPORT unzGetFilePos(
217 unzFile file,
218 unz_file_pos* file_pos);
219
220extern int ZEXPORT unzGoToFilePos(
221 unzFile file,
222 unz_file_pos* file_pos);
223
224/* ****************************************** */
225
226extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file,
227 unz_file_info *pfile_info,
228 char *szFileName,
229 uLong fileNameBufferSize,
230 void *extraField,
231 uLong extraFieldBufferSize,
232 char *szComment,
233 uLong commentBufferSize));
234/*
235 Get Info about the current file
236 if pfile_info!=NULL, the *pfile_info structure will contain somes info about
237 the current file
238 if szFileName!=NULL, the filemane string will be copied in szFileName
239 (fileNameBufferSize is the size of the buffer)
240 if extraField!=NULL, the extra field information will be copied in extraField
241 (extraFieldBufferSize is the size of the buffer).
242 This is the Central-header version of the extra field
243 if szComment!=NULL, the comment string of the file will be copied in szComment
244 (commentBufferSize is the size of the buffer)
245*/
246
247/***************************************************************************/
248/* for reading the content of the current zipfile, you can open it, read data
249 from it, and close it (you can close it before reading all the file)
250 */
251
252extern int ZEXPORT unzOpenCurrentFile OF((unzFile file));
253/*
254 Open for reading data the current file in the zipfile.
255 If there is no error, the return value is UNZ_OK.
256*/
257
258extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file,
259 const char* password));
260/*
261 Open for reading data the current file in the zipfile.
262 password is a crypting password
263 If there is no error, the return value is UNZ_OK.
264*/
265
266extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file,
267 int* method,
268 int* level,
269 int raw));
270/*
271 Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
272 if raw==1
273 *method will receive method of compression, *level will receive level of
274 compression
275 note : you can set level parameter as NULL (if you did not want known level,
276 but you CANNOT set method parameter as NULL
277*/
278
279extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file,
280 int* method,
281 int* level,
282 int raw,
283 const char* password));
284/*
285 Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
286 if raw==1
287 *method will receive method of compression, *level will receive level of
288 compression
289 note : you can set level parameter as NULL (if you did not want known level,
290 but you CANNOT set method parameter as NULL
291*/
292
293
294extern int ZEXPORT unzCloseCurrentFile OF((unzFile file));
295/*
296 Close the file in zip opened with unzOpenCurrentFile
297 Return UNZ_CRCERROR if all the file was read but the CRC is not good
298*/
299
300extern int ZEXPORT unzReadCurrentFile OF((unzFile file,
301 voidp buf,
302 unsigned len));
303/*
304 Read bytes from the current file (opened by unzOpenCurrentFile)
305 buf contain buffer where data must be copied
306 len the size of buf.
307
308 return the number of byte copied if somes bytes are copied
309 return 0 if the end of file was reached
310 return <0 with error code if there is an error
311 (UNZ_ERRNO for IO error, or zLib error for uncompress error)
312*/
313
314extern z_off_t ZEXPORT unztell OF((unzFile file));
315/*
316 Give the current position in uncompressed data
317*/
318
319extern int ZEXPORT unzeof OF((unzFile file));
320/*
321 return 1 if the end of file was reached, 0 elsewhere
322*/
323
324extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file,
325 voidp buf,
326 unsigned len));
327/*
328 Read extra field from the current file (opened by unzOpenCurrentFile)
329 This is the local-header version of the extra field (sometimes, there is
330 more info in the local-header version than in the central-header)
331
332 if buf==NULL, it return the size of the local extra field
333
334 if buf!=NULL, len is the size of the buffer, the extra header is copied in
335 buf.
336 the return value is the number of bytes copied in buf, or (if <0)
337 the error code
338*/
339
340/***************************************************************************/
341
342/* Get the current file offset */
343extern uLong ZEXPORT unzGetOffset (unzFile file);
344
345/* Set the current file offset */
346extern int ZEXPORT unzSetOffset (unzFile file, uLong pos);
347
348
349
350#ifdef __cplusplus
351}
352#endif
353
354#endif /* _unz_H */
diff --git a/rbutil/rbutilqt/quazip/zip.c b/rbutil/rbutilqt/quazip/zip.c
new file mode 100644
index 0000000000..13463fe336
--- /dev/null
+++ b/rbutil/rbutilqt/quazip/zip.c
@@ -0,0 +1,1221 @@
1/* zip.c -- IO on .zip files using zlib
2 Version 1.01e, February 12th, 2005
3
4 27 Dec 2004 Rolf Kalbermatter
5 Modification to zipOpen2 to support globalComment retrieval.
6
7 Copyright (C) 1998-2005 Gilles Vollant
8
9 Read zip.h for more info
10*/
11
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <time.h>
17#include "zlib.h"
18#include "zip.h"
19
20#ifdef STDC
21# include <stddef.h>
22# include <string.h>
23# include <stdlib.h>
24#endif
25#ifdef NO_ERRNO_H
26 extern int errno;
27#else
28# include <errno.h>
29#endif
30
31
32#ifndef local
33# define local static
34#endif
35/* compile with -Dlocal if your debugger can't find static symbols */
36
37#ifndef VERSIONMADEBY
38# define VERSIONMADEBY (0x0) /* platform depedent */
39#endif
40
41#ifndef Z_BUFSIZE
42#define Z_BUFSIZE (16384)
43#endif
44
45#ifndef Z_MAXFILENAMEINZIP
46#define Z_MAXFILENAMEINZIP (256)
47#endif
48
49#ifndef ALLOC
50# define ALLOC(size) (malloc(size))
51#endif
52#ifndef TRYFREE
53# define TRYFREE(p) {if (p) free(p);}
54#endif
55
56/*
57#define SIZECENTRALDIRITEM (0x2e)
58#define SIZEZIPLOCALHEADER (0x1e)
59*/
60
61/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
62
63#ifndef SEEK_CUR
64#define SEEK_CUR 1
65#endif
66
67#ifndef SEEK_END
68#define SEEK_END 2
69#endif
70
71#ifndef SEEK_SET
72#define SEEK_SET 0
73#endif
74
75#ifndef DEF_MEM_LEVEL
76#if MAX_MEM_LEVEL >= 8
77# define DEF_MEM_LEVEL 8
78#else
79# define DEF_MEM_LEVEL MAX_MEM_LEVEL
80#endif
81#endif
82const char zip_copyright[] =
83 " zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
84
85
86#define SIZEDATA_INDATABLOCK (4096-(4*4))
87
88#define LOCALHEADERMAGIC (0x04034b50)
89#define CENTRALHEADERMAGIC (0x02014b50)
90#define ENDHEADERMAGIC (0x06054b50)
91
92#define FLAG_LOCALHEADER_OFFSET (0x06)
93#define CRC_LOCALHEADER_OFFSET (0x0e)
94
95#define SIZECENTRALHEADER (0x2e) /* 46 */
96
97typedef struct linkedlist_datablock_internal_s
98{
99 struct linkedlist_datablock_internal_s* next_datablock;
100 uLong avail_in_this_block;
101 uLong filled_in_this_block;
102 uLong unused; /* for future use and alignement */
103 unsigned char data[SIZEDATA_INDATABLOCK];
104} linkedlist_datablock_internal;
105
106typedef struct linkedlist_data_s
107{
108 linkedlist_datablock_internal* first_block;
109 linkedlist_datablock_internal* last_block;
110} linkedlist_data;
111
112
113typedef struct
114{
115 z_stream stream; /* zLib stream structure for inflate */
116 int stream_initialised; /* 1 is stream is initialised */
117 uInt pos_in_buffered_data; /* last written byte in buffered_data */
118
119 uLong pos_local_header; /* offset of the local header of the file
120 currenty writing */
121 char* central_header; /* central header data for the current file */
122 uLong size_centralheader; /* size of the central header for cur file */
123 uLong flag; /* flag of the file currently writing */
124
125 int method; /* compression method of file currenty wr.*/
126 int raw; /* 1 for directly writing raw data */
127 Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/
128 uLong dosDate;
129 uLong crc32;
130 int encrypt;
131#ifndef NOCRYPT
132 unsigned long keys[3]; /* keys defining the pseudo-random sequence */
133 const unsigned long* pcrc_32_tab;
134 int crypt_header_size;
135#endif
136} curfile_info;
137
138typedef struct
139{
140 zlib_filefunc_def z_filefunc;
141 voidpf filestream; /* io structore of the zipfile */
142 linkedlist_data central_dir;/* datablock with central dir in construction*/
143 int in_opened_file_inzip; /* 1 if a file in the zip is currently writ.*/
144 curfile_info ci; /* info on the file curretly writing */
145
146 uLong begin_pos; /* position of the beginning of the zipfile */
147 uLong add_position_when_writting_offset;
148 uLong number_entry;
149#ifndef NO_ADDFILEINEXISTINGZIP
150 char *globalcomment;
151#endif
152} zip_internal;
153
154
155
156#ifndef NOCRYPT
157#define INCLUDECRYPTINGCODE_IFCRYPTALLOWED
158#include "crypt.h"
159#endif
160
161local linkedlist_datablock_internal* allocate_new_datablock()
162{
163 linkedlist_datablock_internal* ldi;
164 ldi = (linkedlist_datablock_internal*)
165 ALLOC(sizeof(linkedlist_datablock_internal));
166 if (ldi!=NULL)
167 {
168 ldi->next_datablock = NULL ;
169 ldi->filled_in_this_block = 0 ;
170 ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ;
171 }
172 return ldi;
173}
174
175local void free_datablock(ldi)
176 linkedlist_datablock_internal* ldi;
177{
178 while (ldi!=NULL)
179 {
180 linkedlist_datablock_internal* ldinext = ldi->next_datablock;
181 TRYFREE(ldi);
182 ldi = ldinext;
183 }
184}
185
186local void init_linkedlist(ll)
187 linkedlist_data* ll;
188{
189 ll->first_block = ll->last_block = NULL;
190}
191
192#if 0 // unused
193local void free_linkedlist(ll)
194 linkedlist_data* ll;
195{
196 free_datablock(ll->first_block);
197 ll->first_block = ll->last_block = NULL;
198}
199#endif
200
201local int add_data_in_datablock(ll,buf,len)
202 linkedlist_data* ll;
203 const void* buf;
204 uLong len;
205{
206 linkedlist_datablock_internal* ldi;
207 const unsigned char* from_copy;
208
209 if (ll==NULL)
210 return ZIP_INTERNALERROR;
211
212 if (ll->last_block == NULL)
213 {
214 ll->first_block = ll->last_block = allocate_new_datablock();
215 if (ll->first_block == NULL)
216 return ZIP_INTERNALERROR;
217 }
218
219 ldi = ll->last_block;
220 from_copy = (unsigned char*)buf;
221
222 while (len>0)
223 {
224 uInt copy_this;
225 uInt i;
226 unsigned char* to_copy;
227
228 if (ldi->avail_in_this_block==0)
229 {
230 ldi->next_datablock = allocate_new_datablock();
231 if (ldi->next_datablock == NULL)
232 return ZIP_INTERNALERROR;
233 ldi = ldi->next_datablock ;
234 ll->last_block = ldi;
235 }
236
237 if (ldi->avail_in_this_block < len)
238 copy_this = (uInt)ldi->avail_in_this_block;
239 else
240 copy_this = (uInt)len;
241
242 to_copy = &(ldi->data[ldi->filled_in_this_block]);
243
244 for (i=0;i<copy_this;i++)
245 *(to_copy+i)=*(from_copy+i);
246
247 ldi->filled_in_this_block += copy_this;
248 ldi->avail_in_this_block -= copy_this;
249 from_copy += copy_this ;
250 len -= copy_this;
251 }
252 return ZIP_OK;
253}
254
255
256
257/****************************************************************************/
258
259#ifndef NO_ADDFILEINEXISTINGZIP
260/* ===========================================================================
261 Inputs a long in LSB order to the given file
262 nbByte == 1, 2 or 4 (byte, short or long)
263*/
264
265local int ziplocal_putValue OF((const zlib_filefunc_def* pzlib_filefunc_def,
266 voidpf filestream, uLong x, int nbByte));
267local int ziplocal_putValue (pzlib_filefunc_def, filestream, x, nbByte)
268 const zlib_filefunc_def* pzlib_filefunc_def;
269 voidpf filestream;
270 uLong x;
271 int nbByte;
272{
273 unsigned char buf[4];
274 int n;
275 for (n = 0; n < nbByte; n++)
276 {
277 buf[n] = (unsigned char)(x & 0xff);
278 x >>= 8;
279 }
280 if (x != 0)
281 { /* data overflow - hack for ZIP64 (X Roche) */
282 for (n = 0; n < nbByte; n++)
283 {
284 buf[n] = 0xff;
285 }
286 }
287
288 if (ZWRITE(*pzlib_filefunc_def,filestream,buf,nbByte)!=(uLong)nbByte)
289 return ZIP_ERRNO;
290 else
291 return ZIP_OK;
292}
293
294local void ziplocal_putValue_inmemory OF((void* dest, uLong x, int nbByte));
295local void ziplocal_putValue_inmemory (dest, x, nbByte)
296 void* dest;
297 uLong x;
298 int nbByte;
299{
300 unsigned char* buf=(unsigned char*)dest;
301 int n;
302 for (n = 0; n < nbByte; n++) {
303 buf[n] = (unsigned char)(x & 0xff);
304 x >>= 8;
305 }
306
307 if (x != 0)
308 { /* data overflow - hack for ZIP64 */
309 for (n = 0; n < nbByte; n++)
310 {
311 buf[n] = 0xff;
312 }
313 }
314}
315
316/****************************************************************************/
317
318
319local uLong ziplocal_TmzDateToDosDate(ptm,dosDate)
320 const tm_zip* ptm;
321 uLong dosDate;
322{
323 (void) dosDate; /* avoid "unused parameter" warning */
324 uLong year = (uLong)ptm->tm_year;
325 if (year>1980)
326 year-=1980;
327 else if (year>80)
328 year-=80;
329 return
330 (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) |
331 ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour));
332}
333
334
335/****************************************************************************/
336
337local int ziplocal_getByte OF((
338 const zlib_filefunc_def* pzlib_filefunc_def,
339 voidpf filestream,
340 int *pi));
341
342local int ziplocal_getByte(pzlib_filefunc_def,filestream,pi)
343 const zlib_filefunc_def* pzlib_filefunc_def;
344 voidpf filestream;
345 int *pi;
346{
347 unsigned char c;
348 int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1);
349 if (err==1)
350 {
351 *pi = (int)c;
352 return ZIP_OK;
353 }
354 else
355 {
356 if (ZERROR(*pzlib_filefunc_def,filestream))
357 return ZIP_ERRNO;
358 else
359 return ZIP_EOF;
360 }
361}
362
363
364/* ===========================================================================
365 Reads a long in LSB order from the given gz_stream. Sets
366*/
367local int ziplocal_getShort OF((
368 const zlib_filefunc_def* pzlib_filefunc_def,
369 voidpf filestream,
370 uLong *pX));
371
372local int ziplocal_getShort (pzlib_filefunc_def,filestream,pX)
373 const zlib_filefunc_def* pzlib_filefunc_def;
374 voidpf filestream;
375 uLong *pX;
376{
377 uLong x ;
378 int i;
379 int err;
380
381 err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
382 x = (uLong)i;
383
384 if (err==ZIP_OK)
385 err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
386 x += ((uLong)i)<<8;
387
388 if (err==ZIP_OK)
389 *pX = x;
390 else
391 *pX = 0;
392 return err;
393}
394
395local int ziplocal_getLong OF((
396 const zlib_filefunc_def* pzlib_filefunc_def,
397 voidpf filestream,
398 uLong *pX));
399
400local int ziplocal_getLong (pzlib_filefunc_def,filestream,pX)
401 const zlib_filefunc_def* pzlib_filefunc_def;
402 voidpf filestream;
403 uLong *pX;
404{
405 uLong x ;
406 int i;
407 int err;
408
409 err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
410 x = (uLong)i;
411
412 if (err==ZIP_OK)
413 err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
414 x += ((uLong)i)<<8;
415
416 if (err==ZIP_OK)
417 err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
418 x += ((uLong)i)<<16;
419
420 if (err==ZIP_OK)
421 err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
422 x += ((uLong)i)<<24;
423
424 if (err==ZIP_OK)
425 *pX = x;
426 else
427 *pX = 0;
428 return err;
429}
430
431#ifndef BUFREADCOMMENT
432#define BUFREADCOMMENT (0x400)
433#endif
434/*
435 Locate the Central directory of a zipfile (at the end, just before
436 the global comment)
437*/
438local uLong ziplocal_SearchCentralDir OF((
439 const zlib_filefunc_def* pzlib_filefunc_def,
440 voidpf filestream));
441
442local uLong ziplocal_SearchCentralDir(pzlib_filefunc_def,filestream)
443 const zlib_filefunc_def* pzlib_filefunc_def;
444 voidpf filestream;
445{
446 unsigned char* buf;
447 uLong uSizeFile;
448 uLong uBackRead;
449 uLong uMaxBack=0xffff; /* maximum size of global comment */
450 uLong uPosFound=0;
451
452 if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
453 return 0;
454
455
456 uSizeFile = ZTELL(*pzlib_filefunc_def,filestream);
457
458 if (uMaxBack>uSizeFile)
459 uMaxBack = uSizeFile;
460
461 buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
462 if (buf==NULL)
463 return 0;
464
465 uBackRead = 4;
466 while (uBackRead<uMaxBack)
467 {
468 uLong uReadSize,uReadPos ;
469 int i;
470 if (uBackRead+BUFREADCOMMENT>uMaxBack)
471 uBackRead = uMaxBack;
472 else
473 uBackRead+=BUFREADCOMMENT;
474 uReadPos = uSizeFile-uBackRead ;
475
476 uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
477 (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
478 if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
479 break;
480
481 if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
482 break;
483
484 for (i=(int)uReadSize-3; (i--)>0;)
485 if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
486 ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
487 {
488 uPosFound = uReadPos+i;
489 break;
490 }
491
492 if (uPosFound!=0)
493 break;
494 }
495 TRYFREE(buf);
496 return uPosFound;
497}
498#endif /* !NO_ADDFILEINEXISTINGZIP*/
499
500/************************************************************/
501extern zipFile ZEXPORT zipOpen2 (pathname, append, globalcomment, pzlib_filefunc_def)
502 const char *pathname;
503 int append;
504 zipcharpc* globalcomment;
505 zlib_filefunc_def* pzlib_filefunc_def;
506{
507 zip_internal ziinit;
508 zip_internal* zi;
509 int err=ZIP_OK;
510
511
512 if (pzlib_filefunc_def==NULL)
513 fill_fopen_filefunc(&ziinit.z_filefunc);
514 else
515 ziinit.z_filefunc = *pzlib_filefunc_def;
516
517 ziinit.filestream = (*(ziinit.z_filefunc.zopen_file))
518 (ziinit.z_filefunc.opaque,
519 pathname,
520 (append == APPEND_STATUS_CREATE) ?
521 (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE) :
522 (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING));
523
524 if (ziinit.filestream == NULL)
525 return NULL;
526 ziinit.begin_pos = ZTELL(ziinit.z_filefunc,ziinit.filestream);
527 ziinit.in_opened_file_inzip = 0;
528 ziinit.ci.stream_initialised = 0;
529 ziinit.number_entry = 0;
530 ziinit.add_position_when_writting_offset = 0;
531 init_linkedlist(&(ziinit.central_dir));
532
533
534 zi = (zip_internal*)ALLOC(sizeof(zip_internal));
535 if (zi==NULL)
536 {
537 ZCLOSE(ziinit.z_filefunc,ziinit.filestream);
538 return NULL;
539 }
540
541 /* now we add file in a zipfile */
542# ifndef NO_ADDFILEINEXISTINGZIP
543 ziinit.globalcomment = NULL;
544 if (append == APPEND_STATUS_ADDINZIP)
545 {
546 uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
547
548 uLong size_central_dir; /* size of the central directory */
549 uLong offset_central_dir; /* offset of start of central directory */
550 uLong central_pos,uL;
551
552 uLong number_disk; /* number of the current dist, used for
553 spaning ZIP, unsupported, always 0*/
554 uLong number_disk_with_CD; /* number the the disk with central dir, used
555 for spaning ZIP, unsupported, always 0*/
556 uLong number_entry;
557 uLong number_entry_CD; /* total number of entries in
558 the central dir
559 (same than number_entry on nospan) */
560 uLong size_comment;
561
562 central_pos = ziplocal_SearchCentralDir(&ziinit.z_filefunc,ziinit.filestream);
563 if (central_pos==0)
564 err=ZIP_ERRNO;
565
566 if (ZSEEK(ziinit.z_filefunc, ziinit.filestream,
567 central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
568 err=ZIP_ERRNO;
569
570 /* the signature, already checked */
571 if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&uL)!=ZIP_OK)
572 err=ZIP_ERRNO;
573
574 /* number of this disk */
575 if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_disk)!=ZIP_OK)
576 err=ZIP_ERRNO;
577
578 /* number of the disk with the start of the central directory */
579 if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_disk_with_CD)!=ZIP_OK)
580 err=ZIP_ERRNO;
581
582 /* total number of entries in the central dir on this disk */
583 if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_entry)!=ZIP_OK)
584 err=ZIP_ERRNO;
585
586 /* total number of entries in the central dir */
587 if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_entry_CD)!=ZIP_OK)
588 err=ZIP_ERRNO;
589
590 if ((number_entry_CD!=number_entry) ||
591 (number_disk_with_CD!=0) ||
592 (number_disk!=0))
593 err=ZIP_BADZIPFILE;
594
595 /* size of the central directory */
596 if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&size_central_dir)!=ZIP_OK)
597 err=ZIP_ERRNO;
598
599 /* offset of start of central directory with respect to the
600 starting disk number */
601 if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&offset_central_dir)!=ZIP_OK)
602 err=ZIP_ERRNO;
603
604 /* zipfile global comment length */
605 if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&size_comment)!=ZIP_OK)
606 err=ZIP_ERRNO;
607
608 if ((central_pos<offset_central_dir+size_central_dir) &&
609 (err==ZIP_OK))
610 err=ZIP_BADZIPFILE;
611
612 if (err!=ZIP_OK)
613 {
614 ZCLOSE(ziinit.z_filefunc, ziinit.filestream);
615 return NULL;
616 }
617
618 if (size_comment>0)
619 {
620 ziinit.globalcomment = ALLOC(size_comment+1);
621 if (ziinit.globalcomment)
622 {
623 size_comment = ZREAD(ziinit.z_filefunc, ziinit.filestream,ziinit.globalcomment,size_comment);
624 ziinit.globalcomment[size_comment]=0;
625 }
626 }
627
628 byte_before_the_zipfile = central_pos -
629 (offset_central_dir+size_central_dir);
630 ziinit.add_position_when_writting_offset = byte_before_the_zipfile;
631
632 {
633 uLong size_central_dir_to_read = size_central_dir;
634 size_t buf_size = SIZEDATA_INDATABLOCK;
635 void* buf_read = (void*)ALLOC(buf_size);
636 if (ZSEEK(ziinit.z_filefunc, ziinit.filestream,
637 offset_central_dir + byte_before_the_zipfile,
638 ZLIB_FILEFUNC_SEEK_SET) != 0)
639 err=ZIP_ERRNO;
640
641 while ((size_central_dir_to_read>0) && (err==ZIP_OK))
642 {
643 uLong read_this = SIZEDATA_INDATABLOCK;
644 if (read_this > size_central_dir_to_read)
645 read_this = size_central_dir_to_read;
646 if (ZREAD(ziinit.z_filefunc, ziinit.filestream,buf_read,read_this) != read_this)
647 err=ZIP_ERRNO;
648
649 if (err==ZIP_OK)
650 err = add_data_in_datablock(&ziinit.central_dir,buf_read,
651 (uLong)read_this);
652 size_central_dir_to_read-=read_this;
653 }
654 TRYFREE(buf_read);
655 }
656 ziinit.begin_pos = byte_before_the_zipfile;
657 ziinit.number_entry = number_entry_CD;
658
659 if (ZSEEK(ziinit.z_filefunc, ziinit.filestream,
660 offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
661 err=ZIP_ERRNO;
662 }
663
664 if (globalcomment)
665 {
666 *globalcomment = ziinit.globalcomment;
667 }
668# endif /* !NO_ADDFILEINEXISTINGZIP*/
669
670 if (err != ZIP_OK)
671 {
672# ifndef NO_ADDFILEINEXISTINGZIP
673 TRYFREE(ziinit.globalcomment);
674# endif /* !NO_ADDFILEINEXISTINGZIP*/
675 TRYFREE(zi);
676 return NULL;
677 }
678 else
679 {
680 *zi = ziinit;
681 return (zipFile)zi;
682 }
683}
684
685extern zipFile ZEXPORT zipOpen (pathname, append)
686 const char *pathname;
687 int append;
688{
689 return zipOpen2(pathname,append,NULL,NULL);
690}
691
692extern int ZEXPORT zipOpenNewFileInZip3 (file, filename, zipfi,
693 extrafield_local, size_extrafield_local,
694 extrafield_global, size_extrafield_global,
695 comment, method, level, raw,
696 windowBits, memLevel, strategy,
697 password, crcForCrypting)
698 zipFile file;
699 const char* filename;
700 const zip_fileinfo* zipfi;
701 const void* extrafield_local;
702 uInt size_extrafield_local;
703 const void* extrafield_global;
704 uInt size_extrafield_global;
705 const char* comment;
706 int method;
707 int level;
708 int raw;
709 int windowBits;
710 int memLevel;
711 int strategy;
712 const char* password;
713 uLong crcForCrypting;
714{
715 zip_internal* zi;
716 uInt size_filename;
717 uInt size_comment;
718 uInt i;
719 int err = ZIP_OK;
720
721# ifdef NOCRYPT
722 if (password != NULL)
723 return ZIP_PARAMERROR;
724# endif
725
726 if (file == NULL)
727 return ZIP_PARAMERROR;
728 if ((method!=0) && (method!=Z_DEFLATED))
729 return ZIP_PARAMERROR;
730
731 zi = (zip_internal*)file;
732
733 if (zi->in_opened_file_inzip == 1)
734 {
735 err = zipCloseFileInZip (file);
736 if (err != ZIP_OK)
737 return err;
738 }
739
740
741 if (filename==NULL)
742 filename="-";
743
744 if (comment==NULL)
745 size_comment = 0;
746 else
747 size_comment = (uInt)strlen(comment);
748
749 size_filename = (uInt)strlen(filename);
750
751 if (zipfi == NULL)
752 zi->ci.dosDate = 0;
753 else
754 {
755 if (zipfi->dosDate != 0)
756 zi->ci.dosDate = zipfi->dosDate;
757 else zi->ci.dosDate = ziplocal_TmzDateToDosDate(&zipfi->tmz_date,zipfi->dosDate);
758 }
759
760 zi->ci.flag = 0;
761 if ((level==8) || (level==9))
762 zi->ci.flag |= 2;
763 if ((level==2))
764 zi->ci.flag |= 4;
765 if ((level==1))
766 zi->ci.flag |= 6;
767 if (password != NULL)
768 zi->ci.flag |= 1;
769
770 zi->ci.crc32 = 0;
771 zi->ci.method = method;
772 zi->ci.encrypt = 0;
773 zi->ci.stream_initialised = 0;
774 zi->ci.pos_in_buffered_data = 0;
775 zi->ci.raw = raw;
776 zi->ci.pos_local_header = ZTELL(zi->z_filefunc,zi->filestream) ;
777 zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename +
778 size_extrafield_global + size_comment;
779 zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader);
780
781 ziplocal_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4);
782 /* version info */
783 ziplocal_putValue_inmemory(zi->ci.central_header+4,(uLong)VERSIONMADEBY,2);
784 ziplocal_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2);
785 ziplocal_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2);
786 ziplocal_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2);
787 ziplocal_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4);
788 ziplocal_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/
789 ziplocal_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/
790 ziplocal_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/
791 ziplocal_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2);
792 ziplocal_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2);
793 ziplocal_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2);
794 ziplocal_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/
795
796 if (zipfi==NULL)
797 ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2);
798 else
799 ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2);
800
801 if (zipfi==NULL)
802 ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4);
803 else
804 ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4);
805
806 ziplocal_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header- zi->add_position_when_writting_offset,4);
807
808 for (i=0;i<size_filename;i++)
809 *(zi->ci.central_header+SIZECENTRALHEADER+i) = *(filename+i);
810
811 for (i=0;i<size_extrafield_global;i++)
812 *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+i) =
813 *(((const char*)extrafield_global)+i);
814
815 for (i=0;i<size_comment;i++)
816 *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+
817 size_extrafield_global+i) = *(comment+i);
818 if (zi->ci.central_header == NULL)
819 return ZIP_INTERNALERROR;
820
821 /* write the local header */
822 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)LOCALHEADERMAGIC,4);
823
824 if (err==ZIP_OK)
825 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)20,2);/* version needed to extract */
826 if (err==ZIP_OK)
827 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.flag,2);
828
829 if (err==ZIP_OK)
830 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.method,2);
831
832 if (err==ZIP_OK)
833 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.dosDate,4);
834
835 if (err==ZIP_OK)
836 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* crc 32, unknown */
837 if (err==ZIP_OK)
838 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* compressed size, unknown */
839 if (err==ZIP_OK)
840 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* uncompressed size, unknown */
841
842 if (err==ZIP_OK)
843 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_filename,2);
844
845 if (err==ZIP_OK)
846 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_extrafield_local,2);
847
848 if ((err==ZIP_OK) && (size_filename>0))
849 if (ZWRITE(zi->z_filefunc,zi->filestream,filename,size_filename)!=size_filename)
850 err = ZIP_ERRNO;
851
852 if ((err==ZIP_OK) && (size_extrafield_local>0))
853 if (ZWRITE(zi->z_filefunc,zi->filestream,extrafield_local,size_extrafield_local)
854 !=size_extrafield_local)
855 err = ZIP_ERRNO;
856
857 zi->ci.stream.avail_in = (uInt)0;
858 zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
859 zi->ci.stream.next_out = zi->ci.buffered_data;
860 zi->ci.stream.total_in = 0;
861 zi->ci.stream.total_out = 0;
862
863 if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
864 {
865 zi->ci.stream.zalloc = (alloc_func)0;
866 zi->ci.stream.zfree = (free_func)0;
867 zi->ci.stream.opaque = (voidpf)0;
868
869 if (windowBits>0)
870 windowBits = -windowBits;
871
872 err = deflateInit2(&zi->ci.stream, level,
873 Z_DEFLATED, windowBits, memLevel, strategy);
874
875 if (err==Z_OK)
876 zi->ci.stream_initialised = 1;
877 }
878# ifndef NOCRYPT
879 zi->ci.crypt_header_size = 0;
880 if ((err==Z_OK) && (password != NULL))
881 {
882 unsigned char bufHead[RAND_HEAD_LEN];
883 unsigned int sizeHead;
884 zi->ci.encrypt = 1;
885 zi->ci.pcrc_32_tab = get_crc_table();
886 /*init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab);*/
887
888 sizeHead=crypthead(password,bufHead,RAND_HEAD_LEN,zi->ci.keys,zi->ci.pcrc_32_tab,crcForCrypting);
889 zi->ci.crypt_header_size = sizeHead;
890
891 if (ZWRITE(zi->z_filefunc,zi->filestream,bufHead,sizeHead) != sizeHead)
892 err = ZIP_ERRNO;
893 }
894# endif
895
896 if (err==Z_OK)
897 zi->in_opened_file_inzip = 1;
898 return err;
899}
900
901extern int ZEXPORT zipOpenNewFileInZip2(file, filename, zipfi,
902 extrafield_local, size_extrafield_local,
903 extrafield_global, size_extrafield_global,
904 comment, method, level, raw)
905 zipFile file;
906 const char* filename;
907 const zip_fileinfo* zipfi;
908 const void* extrafield_local;
909 uInt size_extrafield_local;
910 const void* extrafield_global;
911 uInt size_extrafield_global;
912 const char* comment;
913 int method;
914 int level;
915 int raw;
916{
917 return zipOpenNewFileInZip3 (file, filename, zipfi,
918 extrafield_local, size_extrafield_local,
919 extrafield_global, size_extrafield_global,
920 comment, method, level, raw,
921 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
922 NULL, 0);
923}
924
925extern int ZEXPORT zipOpenNewFileInZip (file, filename, zipfi,
926 extrafield_local, size_extrafield_local,
927 extrafield_global, size_extrafield_global,
928 comment, method, level)
929 zipFile file;
930 const char* filename;
931 const zip_fileinfo* zipfi;
932 const void* extrafield_local;
933 uInt size_extrafield_local;
934 const void* extrafield_global;
935 uInt size_extrafield_global;
936 const char* comment;
937 int method;
938 int level;
939{
940 return zipOpenNewFileInZip2 (file, filename, zipfi,
941 extrafield_local, size_extrafield_local,
942 extrafield_global, size_extrafield_global,
943 comment, method, level, 0);
944}
945
946local int zipFlushWriteBuffer(zi)
947 zip_internal* zi;
948{
949 int err=ZIP_OK;
950
951 if (zi->ci.encrypt != 0)
952 {
953#ifndef NOCRYPT
954 uInt i;
955 int t;
956 for (i=0;i<zi->ci.pos_in_buffered_data;i++)
957 zi->ci.buffered_data[i] = zencode(zi->ci.keys, zi->ci.pcrc_32_tab,
958 zi->ci.buffered_data[i],t);
959#endif
960 }
961 if (ZWRITE(zi->z_filefunc,zi->filestream,zi->ci.buffered_data,zi->ci.pos_in_buffered_data)
962 !=zi->ci.pos_in_buffered_data)
963 err = ZIP_ERRNO;
964 zi->ci.pos_in_buffered_data = 0;
965 return err;
966}
967
968extern int ZEXPORT zipWriteInFileInZip (file, buf, len)
969 zipFile file;
970 const void* buf;
971 unsigned len;
972{
973 zip_internal* zi;
974 int err=ZIP_OK;
975
976 if (file == NULL)
977 return ZIP_PARAMERROR;
978 zi = (zip_internal*)file;
979
980 if (zi->in_opened_file_inzip == 0)
981 return ZIP_PARAMERROR;
982
983 zi->ci.stream.next_in = (void*)buf;
984 zi->ci.stream.avail_in = len;
985 zi->ci.crc32 = crc32(zi->ci.crc32,buf,len);
986
987 while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0))
988 {
989 if (zi->ci.stream.avail_out == 0)
990 {
991 if (zipFlushWriteBuffer(zi) == ZIP_ERRNO)
992 err = ZIP_ERRNO;
993 zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
994 zi->ci.stream.next_out = zi->ci.buffered_data;
995 }
996
997
998 if(err != ZIP_OK)
999 break;
1000
1001 if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
1002 {
1003 uLong uTotalOutBefore = zi->ci.stream.total_out;
1004 err=deflate(&zi->ci.stream, Z_NO_FLUSH);
1005 zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
1006
1007 }
1008 else
1009 {
1010 uInt copy_this,i;
1011 if (zi->ci.stream.avail_in < zi->ci.stream.avail_out)
1012 copy_this = zi->ci.stream.avail_in;
1013 else
1014 copy_this = zi->ci.stream.avail_out;
1015 for (i=0;i<copy_this;i++)
1016 *(((char*)zi->ci.stream.next_out)+i) =
1017 *(((const char*)zi->ci.stream.next_in)+i);
1018 {
1019 zi->ci.stream.avail_in -= copy_this;
1020 zi->ci.stream.avail_out-= copy_this;
1021 zi->ci.stream.next_in+= copy_this;
1022 zi->ci.stream.next_out+= copy_this;
1023 zi->ci.stream.total_in+= copy_this;
1024 zi->ci.stream.total_out+= copy_this;
1025 zi->ci.pos_in_buffered_data += copy_this;
1026 }
1027 }
1028 }
1029
1030 return err;
1031}
1032
1033extern int ZEXPORT zipCloseFileInZipRaw (file, uncompressed_size, crc32)
1034 zipFile file;
1035 uLong uncompressed_size;
1036 uLong crc32;
1037{
1038 zip_internal* zi;
1039 uLong compressed_size;
1040 int err=ZIP_OK;
1041
1042 if (file == NULL)
1043 return ZIP_PARAMERROR;
1044 zi = (zip_internal*)file;
1045
1046 if (zi->in_opened_file_inzip == 0)
1047 return ZIP_PARAMERROR;
1048 zi->ci.stream.avail_in = 0;
1049
1050 if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
1051 while (err==ZIP_OK)
1052 {
1053 uLong uTotalOutBefore;
1054 if (zi->ci.stream.avail_out == 0)
1055 {
1056 if (zipFlushWriteBuffer(zi) == ZIP_ERRNO)
1057 err = ZIP_ERRNO;
1058 zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
1059 zi->ci.stream.next_out = zi->ci.buffered_data;
1060 }
1061 uTotalOutBefore = zi->ci.stream.total_out;
1062 err=deflate(&zi->ci.stream, Z_FINISH);
1063 zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
1064 }
1065
1066 if (err==Z_STREAM_END)
1067 err=ZIP_OK; /* this is normal */
1068
1069 if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK))
1070 if (zipFlushWriteBuffer(zi)==ZIP_ERRNO)
1071 err = ZIP_ERRNO;
1072
1073 if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
1074 {
1075 err=deflateEnd(&zi->ci.stream);
1076 zi->ci.stream_initialised = 0;
1077 }
1078
1079 if (!zi->ci.raw)
1080 {
1081 crc32 = (uLong)zi->ci.crc32;
1082 uncompressed_size = (uLong)zi->ci.stream.total_in;
1083 }
1084 compressed_size = (uLong)zi->ci.stream.total_out;
1085# ifndef NOCRYPT
1086 compressed_size += zi->ci.crypt_header_size;
1087# endif
1088
1089 ziplocal_putValue_inmemory(zi->ci.central_header+16,crc32,4); /*crc*/
1090 ziplocal_putValue_inmemory(zi->ci.central_header+20,
1091 compressed_size,4); /*compr size*/
1092 if (zi->ci.stream.data_type == Z_ASCII)
1093 ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)Z_ASCII,2);
1094 ziplocal_putValue_inmemory(zi->ci.central_header+24,
1095 uncompressed_size,4); /*uncompr size*/
1096
1097 if (err==ZIP_OK)
1098 err = add_data_in_datablock(&zi->central_dir,zi->ci.central_header,
1099 (uLong)zi->ci.size_centralheader);
1100 free(zi->ci.central_header);
1101
1102 if (err==ZIP_OK)
1103 {
1104 long cur_pos_inzip = ZTELL(zi->z_filefunc,zi->filestream);
1105 if (ZSEEK(zi->z_filefunc,zi->filestream,
1106 zi->ci.pos_local_header + 14,ZLIB_FILEFUNC_SEEK_SET)!=0)
1107 err = ZIP_ERRNO;
1108
1109 if (err==ZIP_OK)
1110 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,crc32,4); /* crc 32, unknown */
1111
1112 if (err==ZIP_OK) /* compressed size, unknown */
1113 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,compressed_size,4);
1114
1115 if (err==ZIP_OK) /* uncompressed size, unknown */
1116 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,uncompressed_size,4);
1117
1118 if (ZSEEK(zi->z_filefunc,zi->filestream,
1119 cur_pos_inzip,ZLIB_FILEFUNC_SEEK_SET)!=0)
1120 err = ZIP_ERRNO;
1121 }
1122
1123 zi->number_entry ++;
1124 zi->in_opened_file_inzip = 0;
1125
1126 return err;
1127}
1128
1129extern int ZEXPORT zipCloseFileInZip (file)
1130 zipFile file;
1131{
1132 return zipCloseFileInZipRaw (file,0,0);
1133}
1134
1135extern int ZEXPORT zipClose (file, global_comment)
1136 zipFile file;
1137 const char* global_comment;
1138{
1139 zip_internal* zi;
1140 int err = 0;
1141 uLong size_centraldir = 0;
1142 uLong centraldir_pos_inzip;
1143 uInt size_global_comment;
1144 if (file == NULL)
1145 return ZIP_PARAMERROR;
1146 zi = (zip_internal*)file;
1147
1148 if (zi->in_opened_file_inzip == 1)
1149 {
1150 err = zipCloseFileInZip (file);
1151 }
1152
1153#ifndef NO_ADDFILEINEXISTINGZIP
1154 if (global_comment==NULL)
1155 global_comment = zi->globalcomment;
1156#endif
1157 if (global_comment==NULL)
1158 size_global_comment = 0;
1159 else
1160 size_global_comment = (uInt)strlen(global_comment);
1161
1162 centraldir_pos_inzip = ZTELL(zi->z_filefunc,zi->filestream);
1163 if (err==ZIP_OK)
1164 {
1165 linkedlist_datablock_internal* ldi = zi->central_dir.first_block ;
1166 while (ldi!=NULL)
1167 {
1168 if ((err==ZIP_OK) && (ldi->filled_in_this_block>0))
1169 if (ZWRITE(zi->z_filefunc,zi->filestream,
1170 ldi->data,ldi->filled_in_this_block)
1171 !=ldi->filled_in_this_block )
1172 err = ZIP_ERRNO;
1173
1174 size_centraldir += ldi->filled_in_this_block;
1175 ldi = ldi->next_datablock;
1176 }
1177 }
1178 free_datablock(zi->central_dir.first_block);
1179
1180 if (err==ZIP_OK) /* Magic End */
1181 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)ENDHEADERMAGIC,4);
1182
1183 if (err==ZIP_OK) /* number of this disk */
1184 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2);
1185
1186 if (err==ZIP_OK) /* number of the disk with the start of the central directory */
1187 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2);
1188
1189 if (err==ZIP_OK) /* total number of entries in the central dir on this disk */
1190 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2);
1191
1192 if (err==ZIP_OK) /* total number of entries in the central dir */
1193 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2);
1194
1195 if (err==ZIP_OK) /* size of the central directory */
1196 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_centraldir,4);
1197
1198 if (err==ZIP_OK) /* offset of start of central directory with respect to the
1199 starting disk number */
1200 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,
1201 (uLong)(centraldir_pos_inzip - zi->add_position_when_writting_offset),4);
1202
1203 if (err==ZIP_OK) /* zipfile comment length */
1204 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_global_comment,2);
1205
1206 if ((err==ZIP_OK) && (size_global_comment>0))
1207 if (ZWRITE(zi->z_filefunc,zi->filestream,
1208 global_comment,size_global_comment) != size_global_comment)
1209 err = ZIP_ERRNO;
1210
1211 if (ZCLOSE(zi->z_filefunc,zi->filestream) != 0)
1212 if (err == ZIP_OK)
1213 err = ZIP_ERRNO;
1214
1215#ifndef NO_ADDFILEINEXISTINGZIP
1216 TRYFREE(zi->globalcomment);
1217#endif
1218 TRYFREE(zi);
1219
1220 return err;
1221}
diff --git a/rbutil/rbutilqt/quazip/zip.h b/rbutil/rbutilqt/quazip/zip.h
new file mode 100644
index 0000000000..acacce83b9
--- /dev/null
+++ b/rbutil/rbutilqt/quazip/zip.h
@@ -0,0 +1,235 @@
1/* zip.h -- IO for compress .zip files using zlib
2 Version 1.01e, February 12th, 2005
3
4 Copyright (C) 1998-2005 Gilles Vollant
5
6 This unzip package allow creates .ZIP file, compatible with PKZip 2.04g
7 WinZip, InfoZip tools and compatible.
8 Multi volume ZipFile (span) are not supported.
9 Encryption compatible with pkzip 2.04g only supported
10 Old compressions used by old PKZip 1.x are not supported
11
12 For uncompress .zip file, look at unzip.h
13
14
15 I WAIT FEEDBACK at mail info@winimage.com
16 Visit also http://www.winimage.com/zLibDll/unzip.html for evolution
17
18 Condition of use and distribution are the same than zlib :
19
20 This software is provided 'as-is', without any express or implied
21 warranty. In no event will the authors be held liable for any damages
22 arising from the use of this software.
23
24 Permission is granted to anyone to use this software for any purpose,
25 including commercial applications, and to alter it and redistribute it
26 freely, subject to the following restrictions:
27
28 1. The origin of this software must not be misrepresented; you must not
29 claim that you wrote the original software. If you use this software
30 in a product, an acknowledgment in the product documentation would be
31 appreciated but is not required.
32 2. Altered source versions must be plainly marked as such, and must not be
33 misrepresented as being the original software.
34 3. This notice may not be removed or altered from any source distribution.
35
36
37*/
38
39/* for more info about .ZIP format, see
40 http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip
41 http://www.info-zip.org/pub/infozip/doc/
42 PkWare has also a specification at :
43 ftp://ftp.pkware.com/probdesc.zip
44*/
45
46#ifndef _zip_H
47#define _zip_H
48
49#ifdef __cplusplus
50extern "C" {
51#endif
52
53#ifndef _ZLIB_H
54#include "zlib.h"
55#endif
56
57#ifndef _ZLIBIOAPI_H
58#include "ioapi.h"
59#endif
60
61#if defined(STRICTZIP) || defined(STRICTZIPUNZIP)
62/* like the STRICT of WIN32, we define a pointer that cannot be converted
63 from (void*) without cast */
64typedef struct TagzipFile__ { int unused; } zipFile__;
65typedef zipFile__ *zipFile;
66#else
67typedef voidp zipFile;
68#endif
69
70#define ZIP_OK (0)
71#define ZIP_EOF (0)
72#define ZIP_ERRNO (Z_ERRNO)
73#define ZIP_PARAMERROR (-102)
74#define ZIP_BADZIPFILE (-103)
75#define ZIP_INTERNALERROR (-104)
76
77#ifndef DEF_MEM_LEVEL
78# if MAX_MEM_LEVEL >= 8
79# define DEF_MEM_LEVEL 8
80# else
81# define DEF_MEM_LEVEL MAX_MEM_LEVEL
82# endif
83#endif
84/* default memLevel */
85
86/* tm_zip contain date/time info */
87typedef struct tm_zip_s
88{
89 uInt tm_sec; /* seconds after the minute - [0,59] */
90 uInt tm_min; /* minutes after the hour - [0,59] */
91 uInt tm_hour; /* hours since midnight - [0,23] */
92 uInt tm_mday; /* day of the month - [1,31] */
93 uInt tm_mon; /* months since January - [0,11] */
94 uInt tm_year; /* years - [1980..2044] */
95} tm_zip;
96
97typedef struct
98{
99 tm_zip tmz_date; /* date in understandable format */
100 uLong dosDate; /* if dos_date == 0, tmu_date is used */
101/* uLong flag; */ /* general purpose bit flag 2 bytes */
102
103 uLong internal_fa; /* internal file attributes 2 bytes */
104 uLong external_fa; /* external file attributes 4 bytes */
105} zip_fileinfo;
106
107typedef const char* zipcharpc;
108
109
110#define APPEND_STATUS_CREATE (0)
111#define APPEND_STATUS_CREATEAFTER (1)
112#define APPEND_STATUS_ADDINZIP (2)
113
114extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append));
115/*
116 Create a zipfile.
117 pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on
118 an Unix computer "zlib/zlib113.zip".
119 if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip
120 will be created at the end of the file.
121 (useful if the file contain a self extractor code)
122 if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will
123 add files in existing zip (be sure you don't add file that doesn't exist)
124 If the zipfile cannot be opened, the return value is NULL.
125 Else, the return value is a zipFile Handle, usable with other function
126 of this zip package.
127*/
128
129/* Note : there is no delete function into a zipfile.
130 If you want delete file into a zipfile, you must open a zipfile, and create another
131 Of couse, you can use RAW reading and writing to copy the file you did not want delte
132*/
133
134extern zipFile ZEXPORT zipOpen2 OF((const char *pathname,
135 int append,
136 zipcharpc* globalcomment,
137 zlib_filefunc_def* pzlib_filefunc_def));
138
139extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file,
140 const char* filename,
141 const zip_fileinfo* zipfi,
142 const void* extrafield_local,
143 uInt size_extrafield_local,
144 const void* extrafield_global,
145 uInt size_extrafield_global,
146 const char* comment,
147 int method,
148 int level));
149/*
150 Open a file in the ZIP for writing.
151 filename : the filename in zip (if NULL, '-' without quote will be used
152 *zipfi contain supplemental information
153 if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local
154 contains the extrafield data the the local header
155 if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global
156 contains the extrafield data the the local header
157 if comment != NULL, comment contain the comment string
158 method contain the compression method (0 for store, Z_DEFLATED for deflate)
159 level contain the level of compression (can be Z_DEFAULT_COMPRESSION)
160*/
161
162
163extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file,
164 const char* filename,
165 const zip_fileinfo* zipfi,
166 const void* extrafield_local,
167 uInt size_extrafield_local,
168 const void* extrafield_global,
169 uInt size_extrafield_global,
170 const char* comment,
171 int method,
172 int level,
173 int raw));
174
175/*
176 Same than zipOpenNewFileInZip, except if raw=1, we write raw file
177 */
178
179extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file,
180 const char* filename,
181 const zip_fileinfo* zipfi,
182 const void* extrafield_local,
183 uInt size_extrafield_local,
184 const void* extrafield_global,
185 uInt size_extrafield_global,
186 const char* comment,
187 int method,
188 int level,
189 int raw,
190 int windowBits,
191 int memLevel,
192 int strategy,
193 const char* password,
194 uLong crcForCtypting));
195
196/*
197 Same than zipOpenNewFileInZip2, except
198 windowBits,memLevel,,strategy : see parameter strategy in deflateInit2
199 password : crypting password (NULL for no crypting)
200 crcForCtypting : crc of file to compress (needed for crypting)
201 */
202
203
204extern int ZEXPORT zipWriteInFileInZip OF((zipFile file,
205 const void* buf,
206 unsigned len));
207/*
208 Write data in the zipfile
209*/
210
211extern int ZEXPORT zipCloseFileInZip OF((zipFile file));
212/*
213 Close the current file in the zipfile
214*/
215
216extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file,
217 uLong uncompressed_size,
218 uLong crc32));
219/*
220 Close the current file in the zipfile, for fiel opened with
221 parameter raw=1 in zipOpenNewFileInZip2
222 uncompressed_size and crc32 are value for the uncompressed size
223*/
224
225extern int ZEXPORT zipClose OF((zipFile file,
226 const char* global_comment));
227/*
228 Close the zipfile
229*/
230
231#ifdef __cplusplus
232}
233#endif
234
235#endif /* _zip_H */
diff --git a/rbutil/rbutilqt/rbutilqt.cpp b/rbutil/rbutilqt/rbutilqt.cpp
index 328fb5d8c7..f7ae202ab0 100644
--- a/rbutil/rbutilqt/rbutilqt.cpp
+++ b/rbutil/rbutilqt/rbutilqt.cpp
@@ -32,13 +32,13 @@
32#include "uninstallwindow.h" 32#include "uninstallwindow.h"
33#include "utils.h" 33#include "utils.h"
34#include "rockboxinfo.h" 34#include "rockboxinfo.h"
35#include "rbzip.h"
36#include "sysinfo.h" 35#include "sysinfo.h"
37#include "system.h" 36#include "system.h"
38#include "systrace.h" 37#include "systrace.h"
39#include "rbsettings.h" 38#include "rbsettings.h"
40#include "serverinfo.h" 39#include "serverinfo.h"
41#include "systeminfo.h" 40#include "systeminfo.h"
41#include "ziputil.h"
42 42
43#include "progressloggerinterface.h" 43#include "progressloggerinterface.h"
44 44
@@ -578,6 +578,7 @@ bool RbUtilQt::installAuto()
578 tr("Rockbox installation detected. Do you want to backup first?"), 578 tr("Rockbox installation detected. Do you want to backup first?"),
579 QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) 579 QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes)
580 { 580 {
581 bool result;
581 logger->addItem(tr("Starting backup..."),LOGINFO); 582 logger->addItem(tr("Starting backup..."),LOGINFO);
582 QString backupName = RbSettings::value(RbSettings::Mountpoint).toString() 583 QString backupName = RbSettings::value(RbSettings::Mountpoint).toString()
583 + "/.backup/rockbox-backup-" + rbinfo.version() + ".zip"; 584 + "/.backup/rockbox-backup-" + rbinfo.version() + ".zip";
@@ -590,11 +591,19 @@ bool RbUtilQt::installAuto()
590 a.mkpath(backupFile.path()); 591 a.mkpath(backupFile.path());
591 } 592 }
592 593
594 logger->addItem(tr("Beginning Backup..."),LOGINFO);
595 QCoreApplication::processEvents();
596
593 //! create backup 597 //! create backup
594 RbZip backup; 598 ZipUtil zip(this);
595 connect(&backup,SIGNAL(zipProgress(int,int)),logger, SLOT(setProgress(int,int))); 599 connect(&zip, SIGNAL(logProgress(int, int)), logger, SLOT(setProgress(int, int)));
596 if(backup.createZip(backupName, 600 connect(&zip, SIGNAL(logItem(QString, int)), logger, SLOT(addItem(QString, int)));
597 RbSettings::value(RbSettings::Mountpoint).toString() + "/.rockbox") == Zip::Ok) 601 zip.open(backupName, QuaZip::mdCreate);
602 QString mp = RbSettings::value(RbSettings::Mountpoint).toString();
603 QString folder = mp + "/.rockbox";
604 result = zip.appendDirToArchive(folder, mp);
605 zip.close();
606 if(result)
598 { 607 {
599 logger->addItem(tr("Backup successful"),LOGOK); 608 logger->addItem(tr("Backup successful"),LOGOK);
600 } 609 }
@@ -1262,13 +1271,13 @@ void RbUtilQt::checkUpdate(void)
1262#elif defined(Q_OS_MACX) 1271#elif defined(Q_OS_MACX)
1263 url += "macosx/"; 1272 url += "macosx/";
1264#endif 1273#endif
1265 1274
1266 update = new HttpGet(this); 1275 update = new HttpGet(this);
1267 connect(update, SIGNAL(done(bool)), this, SLOT(downloadUpdateDone(bool))); 1276 connect(update, SIGNAL(done(bool)), this, SLOT(downloadUpdateDone(bool)));
1268 connect(qApp, SIGNAL(lastWindowClosed()), update, SLOT(abort())); 1277 connect(qApp, SIGNAL(lastWindowClosed()), update, SLOT(abort()));
1269 if(RbSettings::value(RbSettings::CacheOffline).toBool()) 1278 if(RbSettings::value(RbSettings::CacheOffline).toBool())
1270 update->setCache(true); 1279 update->setCache(true);
1271 1280
1272 ui.statusbar->showMessage(tr("Checking for update ...")); 1281 ui.statusbar->showMessage(tr("Checking for update ..."));
1273 update->getFile(QUrl(url)); 1282 update->getFile(QUrl(url));
1274} 1283}
@@ -1289,7 +1298,7 @@ void RbUtilQt::downloadUpdateDone(bool error)
1289 rbutilList << searchString.cap(1); 1298 rbutilList << searchString.cap(1);
1290 pos += searchString.matchedLength(); 1299 pos += searchString.matchedLength();
1291 } 1300 }
1292 qDebug() << "[Checkupdate] " << rbutilList; 1301 qDebug() << "[RbUtilQt] Checking for update";
1293 1302
1294 QString newVersion = ""; 1303 QString newVersion = "";
1295 QString foundVersion = ""; 1304 QString foundVersion = "";
diff --git a/rbutil/rbutilqt/rbutilqt.pri b/rbutil/rbutilqt/rbutilqt.pri
index 63d182a0ab..88977c1da3 100644
--- a/rbutil/rbutilqt/rbutilqt.pri
+++ b/rbutil/rbutilqt/rbutilqt.pri
@@ -22,8 +22,6 @@ SOURCES += \
22 installwindow.cpp \ 22 installwindow.cpp \
23 base/httpget.cpp \ 23 base/httpget.cpp \
24 configure.cpp \ 24 configure.cpp \
25 zip/zip.cpp \
26 zip/unzip.cpp \
27 base/zipinstaller.cpp \ 25 base/zipinstaller.cpp \
28 progressloggergui.cpp \ 26 progressloggergui.cpp \
29 installtalkwindow.cpp \ 27 installtalkwindow.cpp \
@@ -53,8 +51,6 @@ SOURCES += \
53 base/rbsettings.cpp \ 51 base/rbsettings.cpp \
54 base/serverinfo.cpp \ 52 base/serverinfo.cpp \
55 base/systeminfo.cpp \ 53 base/systeminfo.cpp \
56 base/rbunzip.cpp \
57 base/rbzip.cpp \
58 base/system.cpp \ 54 base/system.cpp \
59 sysinfo.cpp \ 55 sysinfo.cpp \
60 systrace.cpp \ 56 systrace.cpp \
@@ -71,6 +67,13 @@ SOURCES += \
71 base/rockboxinfo.cpp \ 67 base/rockboxinfo.cpp \
72 ../../tools/mkboot.c \ 68 ../../tools/mkboot.c \
73 ../../tools/iriver.c \ 69 ../../tools/iriver.c \
70 quazip/quazip.cpp \
71 quazip/quazipfile.cpp \
72 quazip/quazipnewinfo.cpp \
73 quazip/unzip.c \
74 quazip/zip.c \
75 quazip/ioapi.c \
76 base/ziputil.cpp \
74 77
75 78
76HEADERS += \ 79HEADERS += \
@@ -78,11 +81,6 @@ HEADERS += \
78 installwindow.h \ 81 installwindow.h \
79 base/httpget.h \ 82 base/httpget.h \
80 configure.h \ 83 configure.h \
81 zip/zip.h \
82 zip/unzip.h \
83 zip/zipentry_p.h \
84 zip/unzip_p.h \
85 zip/zip_p.h \
86 version.h \ 84 version.h \
87 base/zipinstaller.h \ 85 base/zipinstaller.h \
88 installtalkwindow.h \ 86 installtalkwindow.h \
@@ -120,8 +118,6 @@ HEADERS += \
120 base/rbsettings.h \ 118 base/rbsettings.h \
121 base/serverinfo.h \ 119 base/serverinfo.h \
122 base/systeminfo.h \ 120 base/systeminfo.h \
123 base/rbunzip.h \
124 base/rbzip.h \
125 sysinfo.h \ 121 sysinfo.h \
126 base/system.h \ 122 base/system.h \
127 systrace.h \ 123 systrace.h \
@@ -138,6 +134,16 @@ HEADERS += \
138 base/rockboxinfo.h \ 134 base/rockboxinfo.h \
139 ../../tools/mkboot.h \ 135 ../../tools/mkboot.h \
140 ../../tools/iriver.h \ 136 ../../tools/iriver.h \
137 quazip/crypt.h \
138 quazip/ioapi.h \
139 quazip/quazipfile.h \
140 quazip/quazipfileinfo.h \
141 quazip/quazip.h \
142 quazip/quazipnewinfo.h \
143 quazip/unzip.h \
144 quazip/zip.h \
145 base/ziputil.h \
146
141 147
142FORMS += \ 148FORMS += \
143 rbutilqtfrm.ui \ 149 rbutilqtfrm.ui \
diff --git a/rbutil/rbutilqt/rbutilqt.pro b/rbutil/rbutilqt/rbutilqt.pro
index 13667dd25b..c2e3c93f13 100644
--- a/rbutil/rbutilqt/rbutilqt.pro
+++ b/rbutil/rbutilqt/rbutilqt.pro
@@ -110,7 +110,7 @@ QMAKE_EXTRA_TARGETS += lrelease
110 110
111# Needed by QT on Win 111# Needed by QT on Win
112INCLUDEPATH = $$_PRO_FILE_PWD_ $$_PRO_FILE_PWD_/irivertools \ 112INCLUDEPATH = $$_PRO_FILE_PWD_ $$_PRO_FILE_PWD_/irivertools \
113 $$_PRO_FILE_PWD_/zip $$_PRO_FILE_PWD_/zlib $$_PRO_FILE_PWD_/base 113 $$_PRO_FILE_PWD_/quazip $$_PRO_FILE_PWD_/zlib $$_PRO_FILE_PWD_/base
114INCLUDEPATH += $$RBBASE_DIR/rbutil/ipodpatcher $$RBBASE_DIR/rbutil/sansapatcher \ 114INCLUDEPATH += $$RBBASE_DIR/rbutil/ipodpatcher $$RBBASE_DIR/rbutil/sansapatcher \
115 $$RBBASE_DIR/tools/rbspeex $$RBBASE_DIR/tools 115 $$RBBASE_DIR/tools/rbspeex $$RBBASE_DIR/tools
116 116
diff --git a/rbutil/rbutilqt/zip/README b/rbutil/rbutilqt/zip/README
deleted file mode 100644
index b5f88cb6ae..0000000000
--- a/rbutil/rbutilqt/zip/README
+++ /dev/null
@@ -1,69 +0,0 @@
1The *.cpp and *.h files in this archive are
2Copyright (C) 2007-2008 Angius Fabrizio (blue_death@users.sourceforge.net)
3
4You may use, distribute and copy the files under the terms of
5GNU General Public License version 2 (see the file LICENSE.GPL for details)
6
7-------------------------------------------------------------------------
8
9Website: http://osdab.sourceforge.net/
10SourceForge.net project page: https://sourceforge.net/projects/osdab/
11
12**************** ******* ******************************************************
13
14detailed description
15--------------------
16Meet a couple of pure-Qt/C++ classes capable of handling PKZIP 2.0 compatible zip archives.
17
18This is not a "port" of some other existing implementation, everything has been written from scratch (althought some code was actually inspired by existing public domain projects) and it's all pure C++/Qt. Please note that this is not a complete stand-alone library, it's just a bunch of classes. You will have to add them to your project and modify them to best fit your needs.
19
20It supports basic features like file extraction and compression (with optional password encryption) and archive comments. There are methods to extract single files or the whole archive and methods to compress the contents of a whole directory. Nevertheless, it should be quite trivial to add other features. The public API only has a few methods because this is what I was looking for. This does not mean you can't write a few more lines of code (it really shouldn't take more than a few lines!) to add more features.
21
22The classes are great if you only need to use the PKZIP format for loading/saving your application's data. Just remember that you will need to customize a few parts of the code, i.e. to add your own password retrieval method.
23
24zlib is used for actual compression and decompression.
25
26Please refer to the example application's main.cpp file or to the class comments in the source files for details and more usage examples.
27
28history
29-------
302008-09-97 - Bug fix: end of central directory was sometimes not being found when the archive had a comment.
312007-02-01 - New IgnorePaths compression option and two more "addDirectoryContents()" convenience methods to use this option.
322007-01-28 - Major changes:
33 - Bug fix: there was a big problem with directory names.
34 - API changes: the Zip::addDirectory() method is now easier to use.
35 The password can now be set using a setPassword() method and a new flag allows to preserve absolute paths.
36 - Added an "encrypted" flag to the Unzip::ZipEntry struct.
37 - Removed QObject inheritance. Internationalization is now achieved through QCoreApplication::translate().
382006-11-30 - A good part of the UnZip class has been rewritten. Zip entries with a Data Descriptor (like OpenOffice files) are now correctly parsed; some minor API changes and bug fixes; new features: comments, zip entry list, skip paths unzip option
392006-11-24 - Bug fix. An additional directory was being created for some files in the root directory
402006-10-23 - Minor API changes; QIODevice support added; better binary compatibility; "long long" issue with older compilers solved
412006-06-09 - Minor API changes
422005-10-03 - First public release
43
44features
45--------
46Pure C++/Qt based, clean & oo implementation.
47Retrieve archive contents information before extracting any file.
48Fast (but less robust with corrupt archives) parsing of the ZIP file format.
49Traditional PKWARE password encryption (strong encryption as introduced by PKZip versions 5.0 and later is NOT available).
50Support for archive comments.
51
52missing features and restrictions
53---------------------------------
54Needs to be modified to fit into an existing project (i.e.: you might need to add your own password handling routine).
55Weak support of corrupted archives (althought some files could be extracted even if the archive is corrupted).
56No support for filesystem specific features like unix symbolic links.
57No support for spanned archives.
58No support for strong encryption or features introduced after PKZIP version 2.0 (see the PKWARE specs for details).
59
60requirements
61------------
62Qt version 4.0.x or later
63zlib library
64
65
66**************** ******* ******************************************************
67BEFORE SENDING ANY EMAIL, CHECK OUT THE OSDAB WEBSITE HOSTED AT SOURCEFORGE.NET
68**************** ******* ******************************************************
69
diff --git a/rbutil/rbutilqt/zip/README.ROCKBOX b/rbutil/rbutilqt/zip/README.ROCKBOX
deleted file mode 100644
index 46bdd9a15e..0000000000
--- a/rbutil/rbutilqt/zip/README.ROCKBOX
+++ /dev/null
@@ -1,8 +0,0 @@
1This folder contains the zip extraction classes of the OSDaB project.
2These classes are distributed under the GPL license (see the file
3LICENSE.GPL in this folder).
4The source files have been last synced with the projects svn repo
5at http://osdab.googlecode.com/svn/trunk revision 7 on 2009-04-26.
6
7Details at http://code.google.com/p/osdab/
8
diff --git a/rbutil/rbutilqt/zip/unzip.cpp b/rbutil/rbutilqt/zip/unzip.cpp
deleted file mode 100644
index 8c4028b40c..0000000000
--- a/rbutil/rbutilqt/zip/unzip.cpp
+++ /dev/null
@@ -1,1366 +0,0 @@
1/****************************************************************************
2** Filename: unzip.cpp
3** Last updated [dd/mm/yyyy]: 07/09/2008
4**
5** pkzip 2.0 decompression.
6**
7** Some of the code has been inspired by other open source projects,
8** (mainly Info-Zip and Gilles Vollant's minizip).
9** Compression and decompression actually uses the zlib library.
10**
11** Copyright (C) 2007-2008 Angius Fabrizio. All rights reserved.
12**
13** This file is part of the OSDaB project (http://osdab.sourceforge.net/).
14**
15** This file may be distributed and/or modified under the terms of the
16** GNU General Public License version 2 as published by the Free Software
17** Foundation and appearing in the file LICENSE.GPL included in the
18** packaging of this file.
19**
20** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
21** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22**
23** See the file LICENSE.GPL that came with this software distribution or
24** visit http://www.gnu.org/copyleft/gpl.html for GPL licensing information.
25**
26**********************************************************************/
27
28#include "unzip.h"
29#include "unzip_p.h"
30#include "zipentry_p.h"
31
32#include <QString>
33#include <QStringList>
34#include <QDir>
35#include <QFile>
36#include <QCoreApplication>
37
38// You can remove this #include if you replace the qDebug() statements.
39#include <QtDebug>
40
41/*!
42 \class UnZip unzip.h
43
44 \brief PKZip 2.0 file decompression.
45 Compatibility with later versions is not ensured as they may use
46 unsupported compression algorithms.
47 Versions after 2.7 may have an incompatible header format and thus be
48 completely incompatible.
49*/
50
51/*! \enum UnZip::ErrorCode The result of a decompression operation.
52 \value UnZip::Ok No error occurred.
53 \value UnZip::ZlibInit Failed to init or load the zlib library.
54 \value UnZip::ZlibError The zlib library returned some error.
55 \value UnZip::OpenFailed Unable to create or open a device.
56 \value UnZip::PartiallyCorrupted Corrupted zip archive - some files could be extracted.
57 \value UnZip::Corrupted Corrupted or invalid zip archive.
58 \value UnZip::WrongPassword Unable to decrypt a password protected file.
59 \value UnZip::NoOpenArchive No archive has been opened yet.
60 \value UnZip::FileNotFound Unable to find the requested file in the archive.
61 \value UnZip::ReadFailed Reading of a file failed.
62 \value UnZip::WriteFailed Writing of a file failed.
63 \value UnZip::SeekFailed Seek failed.
64 \value UnZip::CreateDirFailed Could not create a directory.
65 \value UnZip::InvalidDevice A null device has been passed as parameter.
66 \value UnZip::InvalidArchive This is not a valid (or supported) ZIP archive.
67 \value UnZip::HeaderConsistencyError Local header record info does not match with the central directory record info. The archive may be corrupted.
68
69 \value UnZip::Skip Internal use only.
70 \value UnZip::SkipAll Internal use only.
71*/
72
73/*! \enum UnZip::ExtractionOptions Some options for the file extraction methods.
74 \value UnZip::ExtractPaths Default. Does not ignore the path of the zipped files.
75 \value UnZip::SkipPaths Default. Ignores the path of the zipped files and extracts them all to the same root directory.
76*/
77
78//! Local header size (excluding signature, excluding variable length fields)
79#define UNZIP_LOCAL_HEADER_SIZE 26
80//! Central Directory file entry size (excluding signature, excluding variable length fields)
81#define UNZIP_CD_ENTRY_SIZE_NS 42
82//! Data descriptor size (excluding signature)
83#define UNZIP_DD_SIZE 12
84//! End Of Central Directory size (including signature, excluding variable length fields)
85#define UNZIP_EOCD_SIZE 22
86//! Local header entry encryption header size
87#define UNZIP_LOCAL_ENC_HEADER_SIZE 12
88
89// Some offsets inside a CD record (excluding signature)
90#define UNZIP_CD_OFF_VERSION 0
91#define UNZIP_CD_OFF_GPFLAG 4
92#define UNZIP_CD_OFF_CMETHOD 6
93#define UNZIP_CD_OFF_MODT 8
94#define UNZIP_CD_OFF_MODD 10
95#define UNZIP_CD_OFF_CRC32 12
96#define UNZIP_CD_OFF_CSIZE 16
97#define UNZIP_CD_OFF_USIZE 20
98#define UNZIP_CD_OFF_NAMELEN 24
99#define UNZIP_CD_OFF_XLEN 26
100#define UNZIP_CD_OFF_COMMLEN 28
101#define UNZIP_CD_OFF_LHOFFSET 38
102
103// Some offsets inside a local header record (excluding signature)
104#define UNZIP_LH_OFF_VERSION 0
105#define UNZIP_LH_OFF_GPFLAG 2
106#define UNZIP_LH_OFF_CMETHOD 4
107#define UNZIP_LH_OFF_MODT 6
108#define UNZIP_LH_OFF_MODD 8
109#define UNZIP_LH_OFF_CRC32 10
110#define UNZIP_LH_OFF_CSIZE 14
111#define UNZIP_LH_OFF_USIZE 18
112#define UNZIP_LH_OFF_NAMELEN 22
113#define UNZIP_LH_OFF_XLEN 24
114
115// Some offsets inside a data descriptor record (excluding signature)
116#define UNZIP_DD_OFF_CRC32 0
117#define UNZIP_DD_OFF_CSIZE 4
118#define UNZIP_DD_OFF_USIZE 8
119
120// Some offsets inside a EOCD record
121#define UNZIP_EOCD_OFF_ENTRIES 6
122#define UNZIP_EOCD_OFF_CDOFF 12
123#define UNZIP_EOCD_OFF_COMMLEN 16
124
125/*!
126 Max version handled by this API.
127 0x1B = 2.7 --> full compatibility only up to version 2.0 (0x14)
128 versions from 2.1 to 2.7 may use unsupported compression methods
129 versions after 2.7 may have an incompatible header format
130*/
131/* NOTE: changed to 0x1e as info-zip 3.0 uses that header type which breaks
132 * usage. Extraction seems to work fine with the value increased.
133 * No guarantees though.
134 */
135//#define UNZIP_VERSION 0x1B
136#define UNZIP_VERSION 0x1e
137//! Full compatibility granted until this version
138#define UNZIP_VERSION_STRICT 0x14
139
140//! CRC32 routine
141#define CRC32(c, b) crcTable[((int)c^b) & 0xff] ^ (c >> 8)
142
143//! Checks if some file has been already extracted.
144#define UNZIP_CHECK_FOR_VALID_DATA \
145 {\
146 if (headers != 0)\
147 {\
148 qDebug() << "Corrupted zip archive. Some files might be extracted.";\
149 ec = headers->size() != 0 ? UnZip::PartiallyCorrupted : UnZip::Corrupted;\
150 break;\
151 }\
152 else\
153 {\
154 delete device;\
155 device = 0;\
156 qDebug() << "Corrupted or invalid zip archive";\
157 ec = UnZip::Corrupted;\
158 break;\
159 }\
160 }
161
162
163/************************************************************************
164 Public interface
165*************************************************************************/
166
167/*!
168 Creates a new Zip file decompressor.
169*/
170UnZip::UnZip()
171{
172 d = new UnzipPrivate;
173}
174
175/*!
176 Closes any open archive and releases used resources.
177*/
178UnZip::~UnZip()
179{
180 closeArchive();
181 delete d;
182}
183
184/*!
185 Returns true if there is an open archive.
186*/
187bool UnZip::isOpen() const
188{
189 return d->device != 0;
190}
191
192/*!
193 Opens a zip archive and reads the files list. Closes any previously opened archive.
194*/
195UnZip::ErrorCode UnZip::openArchive(const QString& filename)
196{
197 QFile* file = new QFile(filename);
198
199 if (!file->exists()) {
200 delete file;
201 return UnZip::FileNotFound;
202 }
203
204 if (!file->open(QIODevice::ReadOnly)) {
205 delete file;
206 return UnZip::OpenFailed;
207 }
208
209 return openArchive(file);
210}
211
212/*!
213 Opens a zip archive and reads the entries list.
214 Closes any previously opened archive.
215 \warning The class takes ownership of the device so don't delete it!
216*/
217UnZip::ErrorCode UnZip::openArchive(QIODevice* device)
218{
219 if (device == 0)
220 {
221 qDebug() << "Invalid device.";
222 return UnZip::InvalidDevice;
223 }
224
225 return d->openArchive(device);
226}
227
228/*!
229 Closes the archive and releases all the used resources (like cached passwords).
230*/
231void UnZip::closeArchive()
232{
233 d->closeArchive();
234}
235
236QString UnZip::archiveComment() const
237{
238 if (d->device == 0)
239 return QString();
240 return d->comment;
241}
242
243/*!
244 Returns a locale translated error string for a given error code.
245*/
246QString UnZip::formatError(UnZip::ErrorCode c) const
247{
248 switch (c)
249 {
250 case Ok: return QCoreApplication::translate("UnZip", "ZIP operation completed successfully."); break;
251 case ZlibInit: return QCoreApplication::translate("UnZip", "Failed to initialize or load zlib library."); break;
252 case ZlibError: return QCoreApplication::translate("UnZip", "zlib library error."); break;
253 case OpenFailed: return QCoreApplication::translate("UnZip", "Unable to create or open file."); break;
254 case PartiallyCorrupted: return QCoreApplication::translate("UnZip", "Partially corrupted archive. Some files might be extracted."); break;
255 case Corrupted: return QCoreApplication::translate("UnZip", "Corrupted archive."); break;
256 case WrongPassword: return QCoreApplication::translate("UnZip", "Wrong password."); break;
257 case NoOpenArchive: return QCoreApplication::translate("UnZip", "No archive has been created yet."); break;
258 case FileNotFound: return QCoreApplication::translate("UnZip", "File or directory does not exist."); break;
259 case ReadFailed: return QCoreApplication::translate("UnZip", "File read error."); break;
260 case WriteFailed: return QCoreApplication::translate("UnZip", "File write error."); break;
261 case SeekFailed: return QCoreApplication::translate("UnZip", "File seek error."); break;
262 case CreateDirFailed: return QCoreApplication::translate("UnZip", "Unable to create a directory."); break;
263 case InvalidDevice: return QCoreApplication::translate("UnZip", "Invalid device."); break;
264 case InvalidArchive: return QCoreApplication::translate("UnZip", "Invalid or incompatible zip archive."); break;
265 case HeaderConsistencyError: return QCoreApplication::translate("UnZip", "Inconsistent headers. Archive might be corrupted."); break;
266 default: ;
267 }
268
269 return QCoreApplication::translate("UnZip", "Unknown error.");
270}
271
272/*!
273 Returns true if the archive contains a file with the given path and name.
274*/
275bool UnZip::contains(const QString& file) const
276{
277 if (d->headers == 0)
278 return false;
279
280 return d->headers->contains(file);
281}
282
283/*!
284 Returns complete paths of files and directories in this archive.
285*/
286QStringList UnZip::fileList() const
287{
288 return d->headers == 0 ? QStringList() : d->headers->keys();
289}
290
291/*!
292 Returns information for each (correctly parsed) entry of this archive.
293*/
294QList<UnZip::ZipEntry> UnZip::entryList() const
295{
296 QList<UnZip::ZipEntry> list;
297
298 if (d->headers != 0)
299 {
300 for (QMap<QString,ZipEntryP*>::ConstIterator it = d->headers->constBegin(); it != d->headers->constEnd(); ++it)
301 {
302 const ZipEntryP* entry = it.value();
303 Q_ASSERT(entry != 0);
304
305 ZipEntry z;
306
307 z.filename = it.key();
308 if (!entry->comment.isEmpty())
309 z.comment = entry->comment;
310 z.compressedSize = entry->szComp;
311 z.uncompressedSize = entry->szUncomp;
312 z.crc32 = entry->crc;
313 z.lastModified = d->convertDateTime(entry->modDate, entry->modTime);
314
315 z.compression = entry->compMethod == 0 ? NoCompression : entry->compMethod == 8 ? Deflated : UnknownCompression;
316 z.type = z.filename.endsWith("/") ? Directory : File;
317
318 z.encrypted = entry->isEncrypted();
319
320 list.append(z);
321 }
322 }
323
324 return list;
325}
326
327/*!
328 Extracts the whole archive to a directory.
329*/
330UnZip::ErrorCode UnZip::extractAll(const QString& dirname, ExtractionOptions options)
331{
332 return extractAll(QDir(dirname), options);
333}
334
335/*!
336 Extracts the whole archive to a directory.
337*/
338UnZip::ErrorCode UnZip::extractAll(const QDir& dir, ExtractionOptions options)
339{
340 // this should only happen if we didn't call openArchive() yet
341 if (d->device == 0)
342 return NoOpenArchive;
343
344 if (d->headers == 0)
345 return Ok;
346
347 bool end = false;
348 for (QMap<QString,ZipEntryP*>::Iterator itr = d->headers->begin(); itr != d->headers->end(); ++itr)
349 {
350 ZipEntryP* entry = itr.value();
351 Q_ASSERT(entry != 0);
352
353 if ((entry->isEncrypted()) && d->skipAllEncrypted)
354 continue;
355
356 switch (d->extractFile(itr.key(), *entry, dir, options))
357 {
358 case Corrupted:
359 qDebug() << "Removing corrupted entry" << itr.key();
360 d->headers->erase(itr++);
361 if (itr == d->headers->end())
362 end = true;
363 break;
364 case CreateDirFailed:
365 break;
366 case Skip:
367 break;
368 case SkipAll:
369 d->skipAllEncrypted = true;
370 break;
371 default:
372 ;
373 }
374
375 if (end)
376 break;
377 }
378
379 return Ok;
380}
381
382/*!
383 Extracts a single file to a directory.
384*/
385UnZip::ErrorCode UnZip::extractFile(const QString& filename, const QString& dirname, ExtractionOptions options)
386{
387 return extractFile(filename, QDir(dirname), options);
388}
389
390/*!
391 Extracts a single file to a directory.
392*/
393UnZip::ErrorCode UnZip::extractFile(const QString& filename, const QDir& dir, ExtractionOptions options)
394{
395 QMap<QString,ZipEntryP*>::Iterator itr = d->headers->find(filename);
396 if (itr != d->headers->end())
397 {
398 ZipEntryP* entry = itr.value();
399 Q_ASSERT(entry != 0);
400 return d->extractFile(itr.key(), *entry, dir, options);
401 }
402
403 return FileNotFound;
404}
405
406/*!
407 Extracts a single file to a directory.
408*/
409UnZip::ErrorCode UnZip::extractFile(const QString& filename, QIODevice* dev, ExtractionOptions options)
410{
411 if (dev == 0)
412 return InvalidDevice;
413
414 QMap<QString,ZipEntryP*>::Iterator itr = d->headers->find(filename);
415 if (itr != d->headers->end()) {
416 ZipEntryP* entry = itr.value();
417 Q_ASSERT(entry != 0);
418 return d->extractFile(itr.key(), *entry, dev, options);
419 }
420
421 return FileNotFound;
422}
423
424/*!
425 Extracts a list of files.
426 Stops extraction at the first error (but continues if a file does not exist in the archive).
427 */
428UnZip::ErrorCode UnZip::extractFiles(const QStringList& filenames, const QString& dirname, ExtractionOptions options)
429{
430 QDir dir(dirname);
431 ErrorCode ec;
432
433 for (QStringList::ConstIterator itr = filenames.constBegin(); itr != filenames.constEnd(); ++itr)
434 {
435 ec = extractFile(*itr, dir, options);
436 if (ec == FileNotFound)
437 continue;
438 if (ec != Ok)
439 return ec;
440 }
441
442 return Ok;
443}
444
445/*!
446 Extracts a list of files.
447 Stops extraction at the first error (but continues if a file does not exist in the archive).
448 */
449UnZip::ErrorCode UnZip::extractFiles(const QStringList& filenames, const QDir& dir, ExtractionOptions options)
450{
451 ErrorCode ec;
452
453 for (QStringList::ConstIterator itr = filenames.constBegin(); itr != filenames.constEnd(); ++itr)
454 {
455 ec = extractFile(*itr, dir, options);
456 if (ec == FileNotFound)
457 continue;
458 if (ec != Ok)
459 return ec;
460 }
461
462 return Ok;
463}
464
465/*!
466 Remove/replace this method to add your own password retrieval routine.
467*/
468void UnZip::setPassword(const QString& pwd)
469{
470 d->password = pwd;
471}
472
473/*!
474 ZipEntry constructor - initialize data. Type is set to File.
475*/
476UnZip::ZipEntry::ZipEntry()
477{
478 compressedSize = uncompressedSize = crc32 = 0;
479 compression = NoCompression;
480 type = File;
481 encrypted = false;
482}
483
484
485/************************************************************************
486 Private interface
487*************************************************************************/
488
489//! \internal
490UnzipPrivate::UnzipPrivate()
491{
492 skipAllEncrypted = false;
493 headers = 0;
494 device = 0;
495
496 uBuffer = (unsigned char*) buffer1;
497 crcTable = (quint32*) get_crc_table();
498
499 cdOffset = eocdOffset = 0;
500 cdEntryCount = 0;
501 unsupportedEntryCount = 0;
502}
503
504//! \internal Parses a Zip archive.
505UnZip::ErrorCode UnzipPrivate::openArchive(QIODevice* dev)
506{
507 Q_ASSERT(dev != 0);
508
509 if (device != 0)
510 closeArchive();
511
512 device = dev;
513
514 if (!(device->isOpen() || device->open(QIODevice::ReadOnly)))
515 {
516 delete device;
517 device = 0;
518
519 qDebug() << "Unable to open device for reading";
520 return UnZip::OpenFailed;
521 }
522
523 UnZip::ErrorCode ec;
524
525 ec = seekToCentralDirectory();
526 if (ec != UnZip::Ok)
527 {
528 closeArchive();
529 return ec;
530 }
531
532 //! \todo Ignore CD entry count? CD may be corrupted.
533 if (cdEntryCount == 0)
534 {
535 return UnZip::Ok;
536 }
537
538 bool continueParsing = true;
539
540 while (continueParsing)
541 {
542 if (device->read(buffer1, 4) != 4)
543 UNZIP_CHECK_FOR_VALID_DATA
544
545 if (! (buffer1[0] == 'P' && buffer1[1] == 'K' && buffer1[2] == 0x01 && buffer1[3] == 0x02) )
546 break;
547
548 if ( (ec = parseCentralDirectoryRecord()) != UnZip::Ok )
549 break;
550 }
551
552 if (ec != UnZip::Ok)
553 closeArchive();
554
555 return ec;
556}
557
558/*
559 \internal Parses a local header record and makes some consistency check
560 with the information stored in the Central Directory record for this entry
561 that has been previously parsed.
562 \todo Optional consistency check (as a ExtractionOptions flag)
563
564 local file header signature 4 bytes (0x04034b50)
565 version needed to extract 2 bytes
566 general purpose bit flag 2 bytes
567 compression method 2 bytes
568 last mod file time 2 bytes
569 last mod file date 2 bytes
570 crc-32 4 bytes
571 compressed size 4 bytes
572 uncompressed size 4 bytes
573 file name length 2 bytes
574 extra field length 2 bytes
575
576 file name (variable size)
577 extra field (variable size)
578*/
579UnZip::ErrorCode UnzipPrivate::parseLocalHeaderRecord(const QString& path, ZipEntryP& entry)
580{
581 if (!device->seek(entry.lhOffset))
582 return UnZip::SeekFailed;
583
584 // Test signature
585 if (device->read(buffer1, 4) != 4)
586 return UnZip::ReadFailed;
587
588 if ((buffer1[0] != 'P') || (buffer1[1] != 'K') || (buffer1[2] != 0x03) || (buffer1[3] != 0x04))
589 return UnZip::InvalidArchive;
590
591 if (device->read(buffer1, UNZIP_LOCAL_HEADER_SIZE) != UNZIP_LOCAL_HEADER_SIZE)
592 return UnZip::ReadFailed;
593
594 /*
595 Check 3rd general purpose bit flag.
596
597 "bit 3: If this bit is set, the fields crc-32, compressed size
598 and uncompressed size are set to zero in the local
599 header. The correct values are put in the data descriptor
600 immediately following the compressed data."
601 */
602 bool hasDataDescriptor = entry.hasDataDescriptor();
603
604 bool checkFailed = false;
605
606 if (!checkFailed)
607 checkFailed = entry.compMethod != getUShort(uBuffer, UNZIP_LH_OFF_CMETHOD);
608 if (!checkFailed)
609 checkFailed = entry.gpFlag[0] != uBuffer[UNZIP_LH_OFF_GPFLAG];
610 if (!checkFailed)
611 checkFailed = entry.gpFlag[1] != uBuffer[UNZIP_LH_OFF_GPFLAG + 1];
612 if (!checkFailed)
613 checkFailed = entry.modTime[0] != uBuffer[UNZIP_LH_OFF_MODT];
614 if (!checkFailed)
615 checkFailed = entry.modTime[1] != uBuffer[UNZIP_LH_OFF_MODT + 1];
616 if (!checkFailed)
617 checkFailed = entry.modDate[0] != uBuffer[UNZIP_LH_OFF_MODD];
618 if (!checkFailed)
619 checkFailed = entry.modDate[1] != uBuffer[UNZIP_LH_OFF_MODD + 1];
620 if (!hasDataDescriptor)
621 {
622 if (!checkFailed)
623 checkFailed = entry.crc != getULong(uBuffer, UNZIP_LH_OFF_CRC32);
624 if (!checkFailed)
625 checkFailed = entry.szComp != getULong(uBuffer, UNZIP_LH_OFF_CSIZE);
626 if (!checkFailed)
627 checkFailed = entry.szUncomp != getULong(uBuffer, UNZIP_LH_OFF_USIZE);
628 }
629
630 if (checkFailed)
631 return UnZip::HeaderConsistencyError;
632
633 // Check filename
634 quint16 szName = getUShort(uBuffer, UNZIP_LH_OFF_NAMELEN);
635 if (szName == 0)
636 return UnZip::HeaderConsistencyError;
637
638 if (device->read(buffer2, szName) != szName)
639 return UnZip::ReadFailed;
640
641 QString filename = QString::fromAscii(buffer2, szName);
642 if (filename != path)
643 {
644 qDebug() << "Filename in local header mismatches.";
645 return UnZip::HeaderConsistencyError;
646 }
647
648 // Skip extra field
649 quint16 szExtra = getUShort(uBuffer, UNZIP_LH_OFF_XLEN);
650 if (szExtra != 0)
651 {
652 if (!device->seek(device->pos() + szExtra))
653 return UnZip::SeekFailed;
654 }
655
656 entry.dataOffset = device->pos();
657
658 if (hasDataDescriptor)
659 {
660 /*
661 The data descriptor has this OPTIONAL signature: PK\7\8
662 We try to skip the compressed data relying on the size set in the
663 Central Directory record.
664 */
665 if (!device->seek(device->pos() + entry.szComp))
666 return UnZip::SeekFailed;
667
668 // Read 4 bytes and check if there is a data descriptor signature
669 if (device->read(buffer2, 4) != 4)
670 return UnZip::ReadFailed;
671
672 bool hasSignature = buffer2[0] == 'P' && buffer2[1] == 'K' && buffer2[2] == 0x07 && buffer2[3] == 0x08;
673 if (hasSignature)
674 {
675 if (device->read(buffer2, UNZIP_DD_SIZE) != UNZIP_DD_SIZE)
676 return UnZip::ReadFailed;
677 }
678 else
679 {
680 if (device->read(buffer2 + 4, UNZIP_DD_SIZE - 4) != UNZIP_DD_SIZE - 4)
681 return UnZip::ReadFailed;
682 }
683
684 // DD: crc, compressed size, uncompressed size
685 if (
686 entry.crc != getULong((unsigned char*)buffer2, UNZIP_DD_OFF_CRC32) ||
687 entry.szComp != getULong((unsigned char*)buffer2, UNZIP_DD_OFF_CSIZE) ||
688 entry.szUncomp != getULong((unsigned char*)buffer2, UNZIP_DD_OFF_USIZE)
689 )
690 return UnZip::HeaderConsistencyError;
691 }
692
693 return UnZip::Ok;
694}
695
696/*! \internal Attempts to find the start of the central directory record.
697
698 We seek the file back until we reach the "End Of Central Directory"
699 signature PK\5\6.
700
701 end of central dir signature 4 bytes (0x06054b50)
702 number of this disk 2 bytes
703 number of the disk with the
704 start of the central directory 2 bytes
705 total number of entries in the
706 central directory on this disk 2 bytes
707 total number of entries in
708 the central directory 2 bytes
709 size of the central directory 4 bytes
710 offset of start of central
711 directory with respect to
712 the starting disk number 4 bytes
713 .ZIP file comment length 2 bytes
714 --- SIZE UNTIL HERE: UNZIP_EOCD_SIZE ---
715 .ZIP file comment (variable size)
716*/
717UnZip::ErrorCode UnzipPrivate::seekToCentralDirectory()
718{
719 qint64 length = device->size();
720 qint64 offset = length - UNZIP_EOCD_SIZE;
721
722 if (length < UNZIP_EOCD_SIZE)
723 return UnZip::InvalidArchive;
724
725 if (!device->seek( offset ))
726 return UnZip::SeekFailed;
727
728 if (device->read(buffer1, UNZIP_EOCD_SIZE) != UNZIP_EOCD_SIZE)
729 return UnZip::ReadFailed;
730
731 bool eocdFound = (buffer1[0] == 'P' && buffer1[1] == 'K' && buffer1[2] == 0x05 && buffer1[3] == 0x06);
732
733 if (eocdFound)
734 {
735 // Zip file has no comment (the only variable length field in the EOCD record)
736 eocdOffset = offset;
737 }
738 else
739 {
740 qint64 read;
741 char* p = 0;
742
743 offset -= UNZIP_EOCD_SIZE;
744
745 if (offset <= 0)
746 return UnZip::InvalidArchive;
747
748 if (!device->seek( offset ))
749 return UnZip::SeekFailed;
750
751 while ((read = device->read(buffer1, UNZIP_EOCD_SIZE)) >= 0)
752 {
753 if ( (p = strstr(buffer1, "PK\5\6")) != 0)
754 {
755 // Seek to the start of the EOCD record so we can read it fully
756 // Yes... we could simply read the missing bytes and append them to the buffer
757 // but this is far easier so heck it!
758 device->seek( offset + (p - buffer1) );
759 eocdFound = true;
760 eocdOffset = offset + (p - buffer1);
761
762 // Read EOCD record
763 if (device->read(buffer1, UNZIP_EOCD_SIZE) != UNZIP_EOCD_SIZE)
764 return UnZip::ReadFailed;
765
766 break;
767 }
768
769 // TODO: This is very slow and only a temporary bug fix. Need some pattern matching algorithm here.
770 offset -= 1 /*UNZIP_EOCD_SIZE*/;
771 if (offset <= 0)
772 return UnZip::InvalidArchive;
773
774 if (!device->seek( offset ))
775 return UnZip::SeekFailed;
776 }
777 }
778
779 if (!eocdFound)
780 return UnZip::InvalidArchive;
781
782 // Parse EOCD to locate CD offset
783 offset = getULong((const unsigned char*)buffer1, UNZIP_EOCD_OFF_CDOFF + 4);
784
785 cdOffset = offset;
786
787 cdEntryCount = getUShort((const unsigned char*)buffer1, UNZIP_EOCD_OFF_ENTRIES + 4);
788
789 quint16 commentLength = getUShort((const unsigned char*)buffer1, UNZIP_EOCD_OFF_COMMLEN + 4);
790 if (commentLength != 0)
791 {
792 QByteArray c = device->read(commentLength);
793 if (c.count() != commentLength)
794 return UnZip::ReadFailed;
795
796 comment = c;
797 }
798
799 // Seek to the start of the CD record
800 if (!device->seek( cdOffset ))
801 return UnZip::SeekFailed;
802
803 return UnZip::Ok;
804}
805
806/*!
807 \internal Parses a central directory record.
808
809 Central Directory record structure:
810
811 [file header 1]
812 .
813 .
814 .
815 [file header n]
816 [digital signature] // PKZip 6.2 or later only
817
818 File header:
819
820 central file header signature 4 bytes (0x02014b50)
821 version made by 2 bytes
822 version needed to extract 2 bytes
823 general purpose bit flag 2 bytes
824 compression method 2 bytes
825 last mod file time 2 bytes
826 last mod file date 2 bytes
827 crc-32 4 bytes
828 compressed size 4 bytes
829 uncompressed size 4 bytes
830 file name length 2 bytes
831 extra field length 2 bytes
832 file comment length 2 bytes
833 disk number start 2 bytes
834 internal file attributes 2 bytes
835 external file attributes 4 bytes
836 relative offset of local header 4 bytes
837
838 file name (variable size)
839 extra field (variable size)
840 file comment (variable size)
841*/
842UnZip::ErrorCode UnzipPrivate::parseCentralDirectoryRecord()
843{
844 // Read CD record
845 if (device->read(buffer1, UNZIP_CD_ENTRY_SIZE_NS) != UNZIP_CD_ENTRY_SIZE_NS)
846 return UnZip::ReadFailed;
847
848 bool skipEntry = false;
849
850 // Get compression type so we can skip non compatible algorithms
851 quint16 compMethod = getUShort(uBuffer, UNZIP_CD_OFF_CMETHOD);
852
853 // Get variable size fields length so we can skip the whole record
854 // if necessary
855 quint16 szName = getUShort(uBuffer, UNZIP_CD_OFF_NAMELEN);
856 quint16 szExtra = getUShort(uBuffer, UNZIP_CD_OFF_XLEN);
857 quint16 szComment = getUShort(uBuffer, UNZIP_CD_OFF_COMMLEN);
858
859 quint32 skipLength = szName + szExtra + szComment;
860
861 UnZip::ErrorCode ec = UnZip::Ok;
862
863 if ((compMethod != 0) && (compMethod != 8))
864 {
865 qDebug() << "Unsupported compression method. Skipping file.";
866 skipEntry = true;
867 }
868
869 // Header parsing may be a problem if version is bigger than UNZIP_VERSION
870 if (!skipEntry && buffer1[UNZIP_CD_OFF_VERSION] > UNZIP_VERSION)
871 {
872 qDebug() << "Unsupported PKZip version. Skipping file.";
873 skipEntry = true;
874 }
875
876 if (!skipEntry && szName == 0)
877 {
878 qDebug() << "Skipping file with no name.";
879 skipEntry = true;
880 }
881
882 if (!skipEntry && device->read(buffer2, szName) != szName)
883 {
884 ec = UnZip::ReadFailed;
885 skipEntry = true;
886 }
887
888 if (skipEntry)
889 {
890 if (ec == UnZip::Ok)
891 {
892 if (!device->seek( device->pos() + skipLength ))
893 ec = UnZip::SeekFailed;
894
895 unsupportedEntryCount++;
896 }
897
898 return ec;
899 }
900
901 QString filename = QString::fromAscii(buffer2, szName);
902
903 ZipEntryP* h = new ZipEntryP;
904 h->compMethod = compMethod;
905
906 h->gpFlag[0] = buffer1[UNZIP_CD_OFF_GPFLAG];
907 h->gpFlag[1] = buffer1[UNZIP_CD_OFF_GPFLAG + 1];
908
909 h->modTime[0] = buffer1[UNZIP_CD_OFF_MODT];
910 h->modTime[1] = buffer1[UNZIP_CD_OFF_MODT + 1];
911
912 h->modDate[0] = buffer1[UNZIP_CD_OFF_MODD];
913 h->modDate[1] = buffer1[UNZIP_CD_OFF_MODD + 1];
914
915 h->crc = getULong(uBuffer, UNZIP_CD_OFF_CRC32);
916 h->szComp = getULong(uBuffer, UNZIP_CD_OFF_CSIZE);
917 h->szUncomp = getULong(uBuffer, UNZIP_CD_OFF_USIZE);
918
919 // Skip extra field (if any)
920 if (szExtra != 0)
921 {
922 if (!device->seek( device->pos() + szExtra ))
923 {
924 delete h;
925 return UnZip::SeekFailed;
926 }
927 }
928
929 // Read comment field (if any)
930 if (szComment != 0)
931 {
932 if (device->read(buffer2, szComment) != szComment)
933 {
934 delete h;
935 return UnZip::ReadFailed;
936 }
937
938 h->comment = QString::fromAscii(buffer2, szComment);
939 }
940
941 h->lhOffset = getULong(uBuffer, UNZIP_CD_OFF_LHOFFSET);
942
943 if (headers == 0)
944 headers = new QMap<QString, ZipEntryP*>();
945 headers->insert(filename, h);
946
947 return UnZip::Ok;
948}
949
950//! \internal Closes the archive and resets the internal status.
951void UnzipPrivate::closeArchive()
952{
953 if (device == 0)
954 return;
955
956 skipAllEncrypted = false;
957
958 if (headers != 0)
959 {
960 qDeleteAll(*headers);
961 delete headers;
962 headers = 0;
963 }
964
965 delete device; device = 0;
966
967 cdOffset = eocdOffset = 0;
968 cdEntryCount = 0;
969 unsupportedEntryCount = 0;
970
971 comment.clear();
972}
973
974//! \internal
975UnZip::ErrorCode UnzipPrivate::extractFile(const QString& path, ZipEntryP& entry, const QDir& dir, UnZip::ExtractionOptions options)
976{
977 QString name(path);
978 QString dirname;
979 QString directory;
980
981 int pos = name.lastIndexOf('/');
982
983 // This entry is for a directory
984 if (pos == name.length() - 1)
985 {
986 if (options.testFlag(UnZip::SkipPaths))
987 return UnZip::Ok;
988
989 directory = QString("%1/%2").arg(dir.absolutePath()).arg(QDir::cleanPath(name));
990 if (!createDirectory(directory))
991 {
992 qDebug() << QString("Unable to create directory: %1").arg(directory);
993 return UnZip::CreateDirFailed;
994 }
995
996 return UnZip::Ok;
997 }
998
999 // Extract path from entry
1000 if (pos > 0)
1001 {
1002 // get directory part
1003 dirname = name.left(pos);
1004 if (options.testFlag(UnZip::SkipPaths))
1005 {
1006 directory = dir.absolutePath();
1007 }
1008 else
1009 {
1010 directory = QString("%1/%2").arg(dir.absolutePath()).arg(QDir::cleanPath(dirname));
1011 if (!createDirectory(directory))
1012 {
1013 qDebug() << QString("Unable to create directory: %1").arg(directory);
1014 return UnZip::CreateDirFailed;
1015 }
1016 }
1017 name = name.right(name.length() - pos - 1);
1018 } else directory = dir.absolutePath();
1019
1020 name = QString("%1/%2").arg(directory).arg(name);
1021
1022 QFile outFile(name);
1023
1024 if (!outFile.open(QIODevice::WriteOnly))
1025 {
1026 qDebug() << QString("Unable to open %1 for writing").arg(name);
1027 return UnZip::OpenFailed;
1028 }
1029
1030 //! \todo Set creation/last_modified date/time
1031
1032 UnZip::ErrorCode ec = extractFile(path, entry, &outFile, options);
1033
1034 outFile.close();
1035
1036 if (ec != UnZip::Ok)
1037 {
1038 if (!outFile.remove())
1039 qDebug() << QString("Unable to remove corrupted file: %1").arg(name);
1040 }
1041
1042 return ec;
1043}
1044
1045//! \internal
1046UnZip::ErrorCode UnzipPrivate::extractFile(const QString& path, ZipEntryP& entry, QIODevice* dev, UnZip::ExtractionOptions options)
1047{
1048 Q_UNUSED(options);
1049 Q_ASSERT(dev != 0);
1050
1051 if (!entry.lhEntryChecked)
1052 {
1053 UnZip::ErrorCode ec = parseLocalHeaderRecord(path, entry);
1054 entry.lhEntryChecked = true;
1055
1056 if (ec != UnZip::Ok)
1057 return ec;
1058 }
1059
1060 if (!device->seek(entry.dataOffset))
1061 return UnZip::SeekFailed;
1062
1063 // Encryption keys
1064 quint32 keys[3];
1065
1066 if (entry.isEncrypted())
1067 {
1068 UnZip::ErrorCode e = testPassword(keys, path, entry);
1069 if (e != UnZip::Ok)
1070 {
1071 qDebug() << QString("Unable to decrypt %1").arg(path);
1072 return e;
1073 }//! Encryption header size
1074 entry.szComp -= UNZIP_LOCAL_ENC_HEADER_SIZE; // remove encryption header size
1075 }
1076
1077 if (entry.szComp == 0)
1078 {
1079 if (entry.crc != 0)
1080 return UnZip::Corrupted;
1081
1082 return UnZip::Ok;
1083 }
1084
1085 uInt rep = entry.szComp / UNZIP_READ_BUFFER;
1086 uInt rem = entry.szComp % UNZIP_READ_BUFFER;
1087 uInt cur = 0;
1088
1089 // extract data
1090 qint64 read;
1091 quint64 tot = 0;
1092
1093 quint32 myCRC = crc32(0L, Z_NULL, 0);
1094
1095 if (entry.compMethod == 0)
1096 {
1097 while ( (read = device->read(buffer1, cur < rep ? UNZIP_READ_BUFFER : rem)) > 0 )
1098 {
1099 if (entry.isEncrypted())
1100 decryptBytes(keys, buffer1, read);
1101
1102 myCRC = crc32(myCRC, uBuffer, read);
1103
1104 if (dev->write(buffer1, read) != read)
1105 return UnZip::WriteFailed;
1106
1107 cur++;
1108 tot += read;
1109
1110 if (tot == entry.szComp)
1111 break;
1112 }
1113
1114 if (read < 0)
1115 return UnZip::ReadFailed;
1116 }
1117 else if (entry.compMethod == 8)
1118 {
1119 /* Allocate inflate state */
1120 z_stream zstr;
1121 zstr.zalloc = Z_NULL;
1122 zstr.zfree = Z_NULL;
1123 zstr.opaque = Z_NULL;
1124 zstr.next_in = Z_NULL;
1125 zstr.avail_in = 0;
1126
1127 int zret;
1128
1129 // Use inflateInit2 with negative windowBits to get raw decompression
1130 if ( (zret = inflateInit2_(&zstr, -MAX_WBITS, ZLIB_VERSION, sizeof(z_stream))) != Z_OK )
1131 return UnZip::ZlibError;
1132
1133 int szDecomp;
1134
1135 // Decompress until deflate stream ends or end of file
1136 do
1137 {
1138 read = device->read(buffer1, cur < rep ? UNZIP_READ_BUFFER : rem);
1139 if (read == 0)
1140 break;
1141 if (read < 0)
1142 {
1143 (void)inflateEnd(&zstr);
1144 return UnZip::ReadFailed;
1145 }
1146
1147 if (entry.isEncrypted())
1148 decryptBytes(keys, buffer1, read);
1149
1150 cur++;
1151 tot += read;
1152
1153 zstr.avail_in = (uInt) read;
1154 zstr.next_in = (Bytef*) buffer1;
1155
1156
1157 // Run inflate() on input until output buffer not full
1158 do {
1159 zstr.avail_out = UNZIP_READ_BUFFER;
1160 zstr.next_out = (Bytef*) buffer2;;
1161
1162 zret = inflate(&zstr, Z_NO_FLUSH);
1163
1164 switch (zret) {
1165 case Z_NEED_DICT:
1166 case Z_DATA_ERROR:
1167 case Z_MEM_ERROR:
1168 inflateEnd(&zstr);
1169 return UnZip::WriteFailed;
1170 default:
1171 ;
1172 }
1173
1174 szDecomp = UNZIP_READ_BUFFER - zstr.avail_out;
1175 if (dev->write(buffer2, szDecomp) != szDecomp)
1176 {
1177 inflateEnd(&zstr);
1178 return UnZip::ZlibError;
1179 }
1180
1181 myCRC = crc32(myCRC, (const Bytef*) buffer2, szDecomp);
1182
1183 } while (zstr.avail_out == 0);
1184
1185 }
1186 while (zret != Z_STREAM_END);
1187
1188 inflateEnd(&zstr);
1189 }
1190
1191 if (myCRC != entry.crc)
1192 return UnZip::Corrupted;
1193
1194 return UnZip::Ok;
1195}
1196
1197//! \internal Creates a new directory and all the needed parent directories.
1198bool UnzipPrivate::createDirectory(const QString& path)
1199{
1200 QDir d(path);
1201 if (!d.exists())
1202 {
1203 int sep = path.lastIndexOf("/");
1204 if (sep <= 0) return true;
1205
1206 if (!createDirectory(path.left(sep)))
1207 return false;
1208
1209 if (!d.mkdir(path))
1210 {
1211 qDebug() << QString("Unable to create directory: %1").arg(path);
1212 return false;
1213 }
1214 }
1215
1216 return true;
1217}
1218
1219/*!
1220 \internal Reads an quint32 (4 bytes) from a byte array starting at given offset.
1221*/
1222quint32 UnzipPrivate::getULong(const unsigned char* data, quint32 offset) const
1223{
1224 quint32 res = (quint32) data[offset];
1225 res |= (((quint32)data[offset+1]) << 8);
1226 res |= (((quint32)data[offset+2]) << 16);
1227 res |= (((quint32)data[offset+3]) << 24);
1228
1229 return res;
1230}
1231
1232/*!
1233 \internal Reads an quint64 (8 bytes) from a byte array starting at given offset.
1234*/
1235quint64 UnzipPrivate::getULLong(const unsigned char* data, quint32 offset) const
1236{
1237 quint64 res = (quint64) data[offset];
1238 res |= (((quint64)data[offset+1]) << 8);
1239 res |= (((quint64)data[offset+2]) << 16);
1240 res |= (((quint64)data[offset+3]) << 24);
1241 res |= (((quint64)data[offset+1]) << 32);
1242 res |= (((quint64)data[offset+2]) << 40);
1243 res |= (((quint64)data[offset+3]) << 48);
1244 res |= (((quint64)data[offset+3]) << 56);
1245
1246 return res;
1247}
1248
1249/*!
1250 \internal Reads an quint16 (2 bytes) from a byte array starting at given offset.
1251*/
1252quint16 UnzipPrivate::getUShort(const unsigned char* data, quint32 offset) const
1253{
1254 return (quint16) data[offset] | (((quint16)data[offset+1]) << 8);
1255}
1256
1257/*!
1258 \internal Return the next byte in the pseudo-random sequence
1259 */
1260int UnzipPrivate::decryptByte(quint32 key2) const
1261{
1262 quint16 temp = ((quint16)(key2) & 0xffff) | 2;
1263 return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
1264}
1265
1266/*!
1267 \internal Update the encryption keys with the next byte of plain text
1268 */
1269void UnzipPrivate::updateKeys(quint32* keys, int c) const
1270{
1271 keys[0] = CRC32(keys[0], c);
1272 keys[1] += keys[0] & 0xff;
1273 keys[1] = keys[1] * 134775813L + 1;
1274 keys[2] = CRC32(keys[2], ((int)keys[1]) >> 24);
1275}
1276
1277/*!
1278 \internal Initialize the encryption keys and the random header according to
1279 the given password.
1280 */
1281void UnzipPrivate::initKeys(const QString& pwd, quint32* keys) const
1282{
1283 keys[0] = 305419896L;
1284 keys[1] = 591751049L;
1285 keys[2] = 878082192L;
1286
1287 QByteArray pwdBytes = pwd.toAscii();
1288 int sz = pwdBytes.size();
1289 const char* ascii = pwdBytes.data();
1290
1291 for (int i=0; i<sz; ++i)
1292 updateKeys(keys, (int)ascii[i]);
1293}
1294
1295/*!
1296 \internal Attempts to test a password without actually extracting a file.
1297 The \p file parameter can be used in the user interface or for debugging purposes
1298 as it is the name of the encrypted file for wich the password is being tested.
1299*/
1300UnZip::ErrorCode UnzipPrivate::testPassword(quint32* keys, const QString& file, const ZipEntryP& header)
1301{
1302 Q_UNUSED(file);
1303
1304 // read encryption keys
1305 if (device->read(buffer1, 12) != 12)
1306 return UnZip::Corrupted;
1307
1308 // Replace this code if you want to i.e. call some dialog and ask the user for a password
1309 initKeys(password, keys);
1310 if (testKeys(header, keys))
1311 return UnZip::Ok;
1312
1313 return UnZip::Skip;
1314}
1315
1316/*!
1317 \internal Tests a set of keys on the encryption header.
1318*/
1319bool UnzipPrivate::testKeys(const ZipEntryP& header, quint32* keys)
1320{
1321 char lastByte;
1322
1323 // decrypt encryption header
1324 for (int i=0; i<11; ++i)
1325 updateKeys(keys, lastByte = buffer1[i] ^ decryptByte(keys[2]));
1326 updateKeys(keys, lastByte = buffer1[11] ^ decryptByte(keys[2]));
1327
1328 // if there is an extended header (bit in the gp flag) buffer[11] is a byte from the file time
1329 // with no extended header we have to check the crc high-order byte
1330 char c = ((header.gpFlag[0] & 0x08) == 8) ? header.modTime[1] : header.crc >> 24;
1331
1332 return (lastByte == c);
1333}
1334
1335/*!
1336 \internal Decrypts an array of bytes long \p read.
1337*/
1338void UnzipPrivate::decryptBytes(quint32* keys, char* buffer, qint64 read)
1339{
1340 for (int i=0; i<(int)read; ++i)
1341 updateKeys(keys, buffer[i] ^= decryptByte(keys[2]));
1342}
1343
1344/*!
1345 \internal Converts date and time values from ZIP format to a QDateTime object.
1346*/
1347QDateTime UnzipPrivate::convertDateTime(const unsigned char date[2], const unsigned char time[2]) const
1348{
1349 QDateTime dt;
1350
1351 // Usual PKZip low-byte to high-byte order
1352
1353 // Date: 7 bits = years from 1980, 4 bits = month, 5 bits = day
1354 quint16 year = (date[1] >> 1) & 127;
1355 quint16 month = ((date[1] << 3) & 14) | ((date[0] >> 5) & 7);
1356 quint16 day = date[0] & 31;
1357
1358 // Time: 5 bits hour, 6 bits minutes, 5 bits seconds with a 2sec precision
1359 quint16 hour = (time[1] >> 3) & 31;
1360 quint16 minutes = ((time[1] << 3) & 56) | ((time[0] >> 5) & 7);
1361 quint16 seconds = (time[0] & 31) * 2;
1362
1363 dt.setDate(QDate(1980 + year, month, day));
1364 dt.setTime(QTime(hour, minutes, seconds));
1365 return dt;
1366}
diff --git a/rbutil/rbutilqt/zip/unzip.h b/rbutil/rbutilqt/zip/unzip.h
deleted file mode 100644
index 4839e12027..0000000000
--- a/rbutil/rbutilqt/zip/unzip.h
+++ /dev/null
@@ -1,144 +0,0 @@
1/****************************************************************************
2** Filename: unzip.h
3** Last updated [dd/mm/yyyy]: 28/01/2007
4**
5** pkzip 2.0 decompression.
6**
7** Some of the code has been inspired by other open source projects,
8** (mainly Info-Zip and Gilles Vollant's minizip).
9** Compression and decompression actually uses the zlib library.
10**
11** Copyright (C) 2007-2008 Angius Fabrizio. All rights reserved.
12**
13** This file is part of the OSDaB project (http://osdab.sourceforge.net/).
14**
15** This file may be distributed and/or modified under the terms of the
16** GNU General Public License version 2 as published by the Free Software
17** Foundation and appearing in the file LICENSE.GPL included in the
18** packaging of this file.
19**
20** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
21** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22**
23** See the file LICENSE.GPL that came with this software distribution or
24** visit http://www.gnu.org/copyleft/gpl.html for GPL licensing information.
25**
26**********************************************************************/
27
28#ifndef OSDAB_UNZIP__H
29#define OSDAB_UNZIP__H
30
31#include <QtGlobal>
32#include <QMap>
33#include <QDateTime>
34
35#include <zlib/zlib.h>
36
37class UnzipPrivate;
38class QIODevice;
39class QFile;
40class QDir;
41class QStringList;
42class QString;
43
44
45class UnZip
46{
47public:
48 enum ErrorCode
49 {
50 Ok,
51 ZlibInit,
52 ZlibError,
53 OpenFailed,
54 PartiallyCorrupted,
55 Corrupted,
56 WrongPassword,
57 NoOpenArchive,
58 FileNotFound,
59 ReadFailed,
60 WriteFailed,
61 SeekFailed,
62 CreateDirFailed,
63 InvalidDevice,
64 InvalidArchive,
65 HeaderConsistencyError,
66
67 Skip, SkipAll // internal use only
68 };
69
70 enum ExtractionOption
71 {
72 //! Extracts paths (default)
73 ExtractPaths = 0x0001,
74 //! Ignores paths and extracts all the files to the same directory
75 SkipPaths = 0x0002
76 };
77 Q_DECLARE_FLAGS(ExtractionOptions, ExtractionOption)
78
79 enum CompressionMethod
80 {
81 NoCompression, Deflated, UnknownCompression
82 };
83
84 enum FileType
85 {
86 File, Directory
87 };
88
89 struct ZipEntry
90 {
91 ZipEntry();
92
93 QString filename;
94 QString comment;
95
96 quint32 compressedSize;
97 quint32 uncompressedSize;
98 quint32 crc32;
99
100 QDateTime lastModified;
101
102 CompressionMethod compression;
103 FileType type;
104
105 bool encrypted;
106 };
107
108 UnZip();
109 virtual ~UnZip();
110
111 bool isOpen() const;
112
113 ErrorCode openArchive(const QString& filename);
114 ErrorCode openArchive(QIODevice* device);
115 void closeArchive();
116
117 QString archiveComment() const;
118
119 QString formatError(UnZip::ErrorCode c) const;
120
121 bool contains(const QString& file) const;
122
123 QStringList fileList() const;
124 QList<ZipEntry> entryList() const;
125
126 ErrorCode extractAll(const QString& dirname, ExtractionOptions options = ExtractPaths);
127 ErrorCode extractAll(const QDir& dir, ExtractionOptions options = ExtractPaths);
128
129 ErrorCode extractFile(const QString& filename, const QString& dirname, ExtractionOptions options = ExtractPaths);
130 ErrorCode extractFile(const QString& filename, const QDir& dir, ExtractionOptions options = ExtractPaths);
131 ErrorCode extractFile(const QString& filename, QIODevice* device, ExtractionOptions options = ExtractPaths);
132
133 ErrorCode extractFiles(const QStringList& filenames, const QString& dirname, ExtractionOptions options = ExtractPaths);
134 ErrorCode extractFiles(const QStringList& filenames, const QDir& dir, ExtractionOptions options = ExtractPaths);
135
136 void setPassword(const QString& pwd);
137
138private:
139 UnzipPrivate* d;
140};
141
142Q_DECLARE_OPERATORS_FOR_FLAGS(UnZip::ExtractionOptions)
143
144#endif // OSDAB_UNZIP__H
diff --git a/rbutil/rbutilqt/zip/unzip_p.h b/rbutil/rbutilqt/zip/unzip_p.h
deleted file mode 100644
index 394c9d5346..0000000000
--- a/rbutil/rbutilqt/zip/unzip_p.h
+++ /dev/null
@@ -1,112 +0,0 @@
1/****************************************************************************
2** Filename: unzip_p.h
3** Last updated [dd/mm/yyyy]: 28/01/2007
4**
5** pkzip 2.0 decompression.
6**
7** Some of the code has been inspired by other open source projects,
8** (mainly Info-Zip and Gilles Vollant's minizip).
9** Compression and decompression actually uses the zlib library.
10**
11** Copyright (C) 2007-2008 Angius Fabrizio. All rights reserved.
12**
13** This file is part of the OSDaB project (http://osdab.sourceforge.net/).
14**
15** This file may be distributed and/or modified under the terms of the
16** GNU General Public License version 2 as published by the Free Software
17** Foundation and appearing in the file LICENSE.GPL included in the
18** packaging of this file.
19**
20** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
21** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22**
23** See the file LICENSE.GPL that came with this software distribution or
24** visit http://www.gnu.org/copyleft/gpl.html for GPL licensing information.
25**
26**********************************************************************/
27
28//
29// W A R N I N G
30// -------------
31//
32// This file is not part of the Zip/UnZip API. It exists purely as an
33// implementation detail. This header file may change from version to
34// version without notice, or even be removed.
35//
36// We mean it.
37//
38
39#ifndef OSDAB_UNZIP_P__H
40#define OSDAB_UNZIP_P__H
41
42#include "unzip.h"
43#include "zipentry_p.h"
44
45#include <QtGlobal>
46
47// zLib authors suggest using larger buffers (128K or 256K) for (de)compression (especially for inflate())
48// we use a 256K buffer here - if you want to use this code on a pre-iceage mainframe please change it ;)
49#define UNZIP_READ_BUFFER (256*1024)
50
51class UnzipPrivate
52{
53public:
54 UnzipPrivate();
55
56 // Replace this with whatever else you use to store/retrieve the password.
57 QString password;
58
59 bool skipAllEncrypted;
60
61 QMap<QString,ZipEntryP*>* headers;
62
63 QIODevice* device;
64
65 char buffer1[UNZIP_READ_BUFFER];
66 char buffer2[UNZIP_READ_BUFFER];
67
68 unsigned char* uBuffer;
69 const quint32* crcTable;
70
71 // Central Directory (CD) offset
72 quint32 cdOffset;
73 // End of Central Directory (EOCD) offset
74 quint32 eocdOffset;
75
76 // Number of entries in the Central Directory (as to the EOCD record)
77 quint16 cdEntryCount;
78
79 // The number of detected entries that have been skipped because of a non compatible format
80 quint16 unsupportedEntryCount;
81
82 QString comment;
83
84 UnZip::ErrorCode openArchive(QIODevice* device);
85
86 UnZip::ErrorCode seekToCentralDirectory();
87 UnZip::ErrorCode parseCentralDirectoryRecord();
88 UnZip::ErrorCode parseLocalHeaderRecord(const QString& path, ZipEntryP& entry);
89
90 void closeArchive();
91
92 UnZip::ErrorCode extractFile(const QString& path, ZipEntryP& entry, const QDir& dir, UnZip::ExtractionOptions options);
93 UnZip::ErrorCode extractFile(const QString& path, ZipEntryP& entry, QIODevice* device, UnZip::ExtractionOptions options);
94
95 UnZip::ErrorCode testPassword(quint32* keys, const QString& file, const ZipEntryP& header);
96 bool testKeys(const ZipEntryP& header, quint32* keys);
97
98 bool createDirectory(const QString& path);
99
100 inline void decryptBytes(quint32* keys, char* buffer, qint64 read);
101
102 inline quint32 getULong(const unsigned char* data, quint32 offset) const;
103 inline quint64 getULLong(const unsigned char* data, quint32 offset) const;
104 inline quint16 getUShort(const unsigned char* data, quint32 offset) const;
105 inline int decryptByte(quint32 key2) const;
106 inline void updateKeys(quint32* keys, int c) const;
107 inline void initKeys(const QString& pwd, quint32* keys) const;
108
109 inline QDateTime convertDateTime(const unsigned char date[2], const unsigned char time[2]) const;
110};
111
112#endif // OSDAB_UNZIP_P__H
diff --git a/rbutil/rbutilqt/zip/zip.cpp b/rbutil/rbutilqt/zip/zip.cpp
deleted file mode 100644
index 9ecd5531ef..0000000000
--- a/rbutil/rbutilqt/zip/zip.cpp
+++ /dev/null
@@ -1,1221 +0,0 @@
1/****************************************************************************
2** Filename: zip.cpp
3** Last updated [dd/mm/yyyy]: 01/02/2007
4**
5** pkzip 2.0 file compression.
6**
7** Some of the code has been inspired by other open source projects,
8** (mainly Info-Zip and Gilles Vollant's minizip).
9** Compression and decompression actually uses the zlib library.
10**
11** Copyright (C) 2007-2008 Angius Fabrizio. All rights reserved.
12**
13** This file is part of the OSDaB project (http://osdab.sourceforge.net/).
14**
15** This file may be distributed and/or modified under the terms of the
16** GNU General Public License version 2 as published by the Free Software
17** Foundation and appearing in the file LICENSE.GPL included in the
18** packaging of this file.
19**
20** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
21** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22**
23** See the file LICENSE.GPL that came with this software distribution or
24** visit http://www.gnu.org/copyleft/gpl.html for GPL licensing information.
25**
26**********************************************************************/
27
28#include "zip.h"
29#include "zip_p.h"
30#include "zipentry_p.h"
31
32// we only use this to seed the random number generator
33#include <time.h>
34
35#include <QMap>
36#include <QString>
37#include <QStringList>
38#include <QDir>
39#include <QFile>
40#include <QDateTime>
41#include <QCoreApplication>
42
43// You can remove this #include if you replace the qDebug() statements.
44#include <QtDebug>
45
46//! Local header size (including signature, excluding variable length fields)
47#define ZIP_LOCAL_HEADER_SIZE 30
48//! Encryption header size
49#define ZIP_LOCAL_ENC_HEADER_SIZE 12
50//! Data descriptor size (signature included)
51#define ZIP_DD_SIZE_WS 16
52//! Central Directory record size (signature included)
53#define ZIP_CD_SIZE 46
54//! End of Central Directory record size (signature included)
55#define ZIP_EOCD_SIZE 22
56
57// Some offsets inside a local header record (signature included)
58#define ZIP_LH_OFF_VERS 4
59#define ZIP_LH_OFF_GPFLAG 6
60#define ZIP_LH_OFF_CMET 8
61#define ZIP_LH_OFF_MODT 10
62#define ZIP_LH_OFF_MODD 12
63#define ZIP_LH_OFF_CRC 14
64#define ZIP_LH_OFF_CSIZE 18
65#define ZIP_LH_OFF_USIZE 22
66#define ZIP_LH_OFF_NAMELEN 26
67#define ZIP_LH_OFF_XLEN 28
68
69// Some offsets inside a data descriptor record (including signature)
70#define ZIP_DD_OFF_CRC32 4
71#define ZIP_DD_OFF_CSIZE 8
72#define ZIP_DD_OFF_USIZE 12
73
74// Some offsets inside a Central Directory record (including signature)
75#define ZIP_CD_OFF_MADEBY 4
76#define ZIP_CD_OFF_VERSION 6
77#define ZIP_CD_OFF_GPFLAG 8
78#define ZIP_CD_OFF_CMET 10
79#define ZIP_CD_OFF_MODT 12
80#define ZIP_CD_OFF_MODD 14
81#define ZIP_CD_OFF_CRC 16
82#define ZIP_CD_OFF_CSIZE 20
83#define ZIP_CD_OFF_USIZE 24
84#define ZIP_CD_OFF_NAMELEN 28
85#define ZIP_CD_OFF_XLEN 30
86#define ZIP_CD_OFF_COMMLEN 32
87#define ZIP_CD_OFF_DISKSTART 34
88#define ZIP_CD_OFF_IATTR 36
89#define ZIP_CD_OFF_EATTR 38
90#define ZIP_CD_OFF_LHOFF 42
91
92// Some offsets inside a EOCD record (including signature)
93#define ZIP_EOCD_OFF_DISKNUM 4
94#define ZIP_EOCD_OFF_CDDISKNUM 6
95#define ZIP_EOCD_OFF_ENTRIES 8
96#define ZIP_EOCD_OFF_CDENTRIES 10
97#define ZIP_EOCD_OFF_CDSIZE 12
98#define ZIP_EOCD_OFF_CDOFF 16
99#define ZIP_EOCD_OFF_COMMLEN 20
100
101//! PKZip version for archives created by this API
102#define ZIP_VERSION 0x14
103
104//! Do not store very small files as the compression headers overhead would be to big
105#define ZIP_COMPRESSION_THRESHOLD 60
106
107//! This macro updates a one-char-only CRC; it's the Info-Zip macro re-adapted
108#define CRC32(c, b) crcTable[((int)c^b) & 0xff] ^ (c >> 8)
109
110/*!
111 \class Zip zip.h
112
113 \brief Zip file compression.
114
115 Some quick usage examples.
116
117 \verbatim
118 Suppose you have this directory structure:
119
120 /root/dir1/
121 /root/dir1/file1.1
122 /root/dir1/file1.2
123 /root/dir1/dir1.1/
124 /root/dir1/dir1.2/file1.2.1
125
126 EXAMPLE 1:
127 myZipInstance.addDirectory("/root/dir1");
128
129 RESULT:
130 Beheaves like any common zip software and creates a zip file with this structure:
131
132 dir1/
133 dir1/file1.1
134 dir1/file1.2
135 dir1/dir1.1/
136 dir1/dir1.2/file1.2.1
137
138 EXAMPLE 2:
139 myZipInstance.addDirectory("/root/dir1", "myRoot/myFolder");
140
141 RESULT:
142 Adds a custom root to the paths and creates a zip file with this structure:
143
144 myRoot/myFolder/dir1/
145 myRoot/myFolder/dir1/file1.1
146 myRoot/myFolder/dir1/file1.2
147 myRoot/myFolder/dir1/dir1.1/
148 myRoot/myFolder/dir1/dir1.2/file1.2.1
149
150 EXAMPLE 3:
151 myZipInstance.addDirectory("/root/dir1", Zip::AbsolutePaths);
152
153 NOTE:
154 Same as calling addDirectory(SOME_PATH, PARENT_PATH_of_SOME_PATH).
155
156 RESULT:
157 Preserves absolute paths and creates a zip file with this structure:
158
159 /root/dir1/
160 /root/dir1/file1.1
161 /root/dir1/file1.2
162 /root/dir1/dir1.1/
163 /root/dir1/dir1.2/file1.2.1
164
165 EXAMPLE 4:
166 myZipInstance.setPassword("hellopass");
167 myZipInstance.addDirectory("/root/dir1", "/");
168
169 RESULT:
170 Adds and encrypts the files in /root/dir1, creating the following zip structure:
171
172 /dir1/
173 /dir1/file1.1
174 /dir1/file1.2
175 /dir1/dir1.1/
176 /dir1/dir1.2/file1.2.1
177
178 \endverbatim
179*/
180
181/*! \enum Zip::ErrorCode The result of a compression operation.
182 \value Zip::Ok No error occurred.
183 \value Zip::ZlibInit Failed to init or load the zlib library.
184 \value Zip::ZlibError The zlib library returned some error.
185 \value Zip::FileExists The file already exists and will not be overwritten.
186 \value Zip::OpenFailed Unable to create or open a device.
187 \value Zip::NoOpenArchive CreateArchive() has not been called yet.
188 \value Zip::FileNotFound File or directory does not exist.
189 \value Zip::ReadFailed Reading of a file failed.
190 \value Zip::WriteFailed Writing of a file failed.
191 \value Zip::SeekFailed Seek failed.
192*/
193
194/*! \enum Zip::CompressionLevel Returns the result of a decompression operation.
195 \value Zip::Store No compression.
196 \value Zip::Deflate1 Deflate compression level 1(lowest compression).
197 \value Zip::Deflate1 Deflate compression level 2.
198 \value Zip::Deflate1 Deflate compression level 3.
199 \value Zip::Deflate1 Deflate compression level 4.
200 \value Zip::Deflate1 Deflate compression level 5.
201 \value Zip::Deflate1 Deflate compression level 6.
202 \value Zip::Deflate1 Deflate compression level 7.
203 \value Zip::Deflate1 Deflate compression level 8.
204 \value Zip::Deflate1 Deflate compression level 9 (maximum compression).
205 \value Zip::AutoCPU Adapt compression level to CPU speed (faster CPU => better compression).
206 \value Zip::AutoMIME Adapt compression level to MIME type of the file being compressed.
207 \value Zip::AutoFull Use both CPU and MIME type detection.
208*/
209
210
211/************************************************************************
212 Public interface
213*************************************************************************/
214
215/*!
216 Creates a new Zip file compressor.
217*/
218Zip::Zip()
219{
220 d = new ZipPrivate;
221}
222
223/*!
224 Closes any open archive and releases used resources.
225*/
226Zip::~Zip()
227{
228 closeArchive();
229 delete d;
230}
231
232/*!
233 Returns true if there is an open archive.
234*/
235bool Zip::isOpen() const
236{
237 return d->device != 0;
238}
239
240/*!
241 Sets the password to be used for the next files being added!
242 Files added before calling this method will use the previously
243 set password (if any).
244 Closing the archive won't clear the password!
245*/
246void Zip::setPassword(const QString& pwd)
247{
248 d->password = pwd;
249}
250
251//! Convenience method, clears the current password.
252void Zip::clearPassword()
253{
254 d->password.clear();
255}
256
257//! Returns the currently used password.
258QString Zip::password() const
259{
260 return d->password;
261}
262
263/*!
264 Attempts to create a new Zip archive. If \p overwrite is true and the file
265 already exist it will be overwritten.
266 Any open archive will be closed.
267 */
268Zip::ErrorCode Zip::createArchive(const QString& filename, bool overwrite)
269{
270 QFile* file = new QFile(filename);
271
272 if (file->exists() && !overwrite) {
273 delete file;
274 return Zip::FileExists;
275 }
276
277 if (!file->open(QIODevice::WriteOnly)) {
278 delete file;
279 return Zip::OpenFailed;
280 }
281
282 Zip::ErrorCode ec = createArchive(file);
283 if (ec != Zip::Ok) {
284 file->remove();
285 }
286
287 return ec;
288}
289
290/*!
291 Attempts to create a new Zip archive. If there is another open archive this will be closed.
292 \warning The class takes ownership of the device!
293 */
294Zip::ErrorCode Zip::createArchive(QIODevice* device)
295{
296 if (device == 0)
297 {
298 qDebug() << "Invalid device.";
299 return Zip::OpenFailed;
300 }
301
302 return d->createArchive(device);
303}
304
305/*!
306 Returns the current archive comment.
307*/
308QString Zip::archiveComment() const
309{
310 return d->comment;
311}
312
313/*!
314 Sets the comment for this archive. Note: createArchive() should have been
315 called before.
316*/
317void Zip::setArchiveComment(const QString& comment)
318{
319 if (d->device != 0)
320 d->comment = comment;
321}
322
323/*!
324 Convenience method, same as calling
325 Zip::addDirectory(const QString&,const QString&,CompressionLevel)
326 with an empty \p root parameter (or with the parent directory of \p path if the
327 AbsolutePaths options is set).
328
329 The ExtractionOptions are checked in the order they are defined in the zip.h heaser file.
330 This means that the last one overwrites the previous one (if some conflict occurs), i.e.
331 Zip::IgnorePaths | Zip::AbsolutePaths would be interpreted as Zip::IgnorePaths.
332 */
333Zip::ErrorCode Zip::addDirectory(const QString& path, CompressionOptions options, CompressionLevel level)
334{
335 return addDirectory(path, QString(), options, level);
336}
337
338/*!
339 Convenience method, same as calling Zip::addDirectory(const QString&,const QString&,CompressionOptions,CompressionLevel)
340 with the Zip::RelativePaths flag as compression option.
341 */
342Zip::ErrorCode Zip::addDirectory(const QString& path, const QString& root, CompressionLevel level)
343{
344 return addDirectory(path, root, Zip::RelativePaths, level);
345}
346
347/*!
348 Convenience method, same as calling Zip::addDirectory(const QString&,const QString&,CompressionOptions,CompressionLevel)
349 with the Zip::IgnorePaths flag as compression option and an empty \p root parameter.
350*/
351Zip::ErrorCode Zip::addDirectoryContents(const QString& path, CompressionLevel level)
352{
353 return addDirectory(path, QString(), IgnorePaths, level);
354}
355
356/*!
357 Convenience method, same as calling Zip::addDirectory(const QString&,const QString&,CompressionOptions,CompressionLevel)
358 with the Zip::IgnorePaths flag as compression option.
359*/
360Zip::ErrorCode Zip::addDirectoryContents(const QString& path, const QString& root, CompressionLevel level)
361{
362 return addDirectory(path, root, IgnorePaths, level);
363}
364
365/*!
366 Recursively adds files contained in \p dir to the archive, using \p root as name for the root folder.
367 Stops adding files if some error occurs.
368
369 The ExtractionOptions are checked in the order they are defined in the zip.h heaser file.
370 This means that the last one overwrites the previous one (if some conflict occurs), i.e.
371 Zip::IgnorePaths | Zip::AbsolutePaths would be interpreted as Zip::IgnorePaths.
372
373 The \p root parameter is ignored with the Zip::IgnorePaths parameter and used as path prefix (a trailing /
374 is always added as directory separator!) otherwise (even with Zip::AbsolutePaths set!).
375*/
376Zip::ErrorCode Zip::addDirectory(const QString& path, const QString& root, CompressionOptions options, CompressionLevel level)
377{
378 // qDebug() << QString("addDir(path=%1, root=%2)").arg(path, root);
379
380 // Bad boy didn't call createArchive() yet :)
381 if (d->device == 0)
382 return Zip::NoOpenArchive;
383
384 QDir dir(path);
385 if (!dir.exists())
386 return Zip::FileNotFound;
387
388 // Remove any trailing separator
389 QString actualRoot = root.trimmed();
390
391 // Preserve Unix root
392 if (actualRoot != "/")
393 {
394 while (actualRoot.endsWith("/") || actualRoot.endsWith("\\"))
395 actualRoot.truncate(actualRoot.length() - 1);
396 }
397
398 // QDir::cleanPath() fixes some issues with QDir::dirName()
399 QFileInfo current(QDir::cleanPath(path));
400
401 if (!actualRoot.isEmpty() && actualRoot != "/")
402 actualRoot.append("/");
403
404 /* This part is quite confusing and needs some test or check */
405 /* An attempt to compress the / root directory evtl. using a root prefix should be a good test */
406 if (options.testFlag(AbsolutePaths) && !options.testFlag(IgnorePaths))
407 {
408 QString absolutePath = d->extractRoot(path);
409 if (!absolutePath.isEmpty() && absolutePath != "/")
410 absolutePath.append("/");
411 actualRoot.append(absolutePath);
412 }
413
414 if (!options.testFlag(IgnorePaths))
415 {
416 actualRoot = actualRoot.append(QDir(current.absoluteFilePath()).dirName());
417 actualRoot.append("/");
418 }
419
420 // actualRoot now contains the path of the file relative to the zip archive
421 // with a trailing /
422
423 QFileInfoList list = dir.entryInfoList(
424 QDir::Files |
425 QDir::Dirs |
426 QDir::NoDotAndDotDot |
427 QDir::NoSymLinks);
428
429 ErrorCode ec = Zip::Ok;
430 bool filesAdded = false;
431
432 CompressionOptions recursionOptions;
433 if (options.testFlag(IgnorePaths))
434 recursionOptions |= IgnorePaths;
435 else recursionOptions |= RelativePaths;
436
437 for (int i = 0; i < list.size() && ec == Zip::Ok; ++i)
438 {
439 QFileInfo info = list.at(i);
440
441 if (info.isDir())
442 {
443 // Recursion :)
444 progress();
445 ec = addDirectory(info.absoluteFilePath(), actualRoot, recursionOptions, level);
446 }
447 else
448 {
449 progress();
450 ec = d->createEntry(info, actualRoot, level);
451 filesAdded = true;
452 }
453 }
454
455
456 // We need an explicit record for this dir
457 // Non-empty directories don't need it because they have a path component in the filename
458 if (!filesAdded && !options.testFlag(IgnorePaths))
459 ec = d->createEntry(current, actualRoot, level);
460
461 return ec;
462}
463
464/*!
465 Closes the archive and writes any pending data.
466*/
467Zip::ErrorCode Zip::closeArchive()
468{
469 Zip::ErrorCode ec = d->closeArchive();
470 d->reset();
471 return ec;
472}
473
474/*!
475 Returns a locale translated error string for a given error code.
476*/
477QString Zip::formatError(Zip::ErrorCode c) const
478{
479 switch (c)
480 {
481 case Ok: return QCoreApplication::translate("Zip", "ZIP operation completed successfully."); break;
482 case ZlibInit: return QCoreApplication::translate("Zip", "Failed to initialize or load zlib library."); break;
483 case ZlibError: return QCoreApplication::translate("Zip", "zlib library error."); break;
484 case OpenFailed: return QCoreApplication::translate("Zip", "Unable to create or open file."); break;
485 case NoOpenArchive: return QCoreApplication::translate("Zip", "No archive has been created yet."); break;
486 case FileNotFound: return QCoreApplication::translate("Zip", "File or directory does not exist."); break;
487 case ReadFailed: return QCoreApplication::translate("Zip", "File read error."); break;
488 case WriteFailed: return QCoreApplication::translate("Zip", "File write error."); break;
489 case SeekFailed: return QCoreApplication::translate("Zip", "File seek error."); break;
490 default: ;
491 }
492
493 return QCoreApplication::translate("Zip", "Unknown error.");
494}
495
496
497/************************************************************************
498 Private interface
499*************************************************************************/
500
501//! \internal
502ZipPrivate::ZipPrivate()
503{
504 headers = 0;
505 device = 0;
506
507 // keep an unsigned pointer so we avoid to over bloat the code with casts
508 uBuffer = (unsigned char*) buffer1;
509 crcTable = (quint32*) get_crc_table();
510}
511
512//! \internal
513ZipPrivate::~ZipPrivate()
514{
515 closeArchive();
516}
517
518//! \internal
519Zip::ErrorCode ZipPrivate::createArchive(QIODevice* dev)
520{
521 Q_ASSERT(dev != 0);
522
523 if (device != 0)
524 closeArchive();
525
526 device = dev;
527
528 if (!device->isOpen())
529 {
530 if (!device->open(QIODevice::ReadOnly)) {
531 delete device;
532 device = 0;
533 qDebug() << "Unable to open device for writing.";
534 return Zip::OpenFailed;
535 }
536 }
537
538 headers = new QMap<QString,ZipEntryP*>;
539 return Zip::Ok;
540}
541
542//! \internal Writes a new entry in the zip file.
543Zip::ErrorCode ZipPrivate::createEntry(const QFileInfo& file, const QString& root, Zip::CompressionLevel level)
544{
545 //! \todo Automatic level detection (cpu, extension & file size)
546
547 // Directories and very small files are always stored
548 // (small files would get bigger due to the compression headers overhead)
549
550 // Need this for zlib
551 bool isPNGFile = false;
552 bool dirOnly = file.isDir();
553
554 QString entryName = root;
555
556 // Directory entry
557 if (dirOnly)
558 level = Zip::Store;
559 else
560 {
561 entryName.append(file.fileName());
562
563 QString ext = file.completeSuffix().toLower();
564 isPNGFile = ext == "png";
565
566 if (file.size() < ZIP_COMPRESSION_THRESHOLD)
567 level = Zip::Store;
568 else
569 switch (level)
570 {
571 case Zip::AutoCPU:
572 level = Zip::Deflate5;
573 break;
574 case Zip::AutoMIME:
575 level = detectCompressionByMime(ext);
576 break;
577 case Zip::AutoFull:
578 level = detectCompressionByMime(ext);
579 break;
580 default:
581 ;
582 }
583 }
584
585 // entryName contains the path as it should be written
586 // in the zip file records
587 // qDebug() << QString("addDir(file=%1, root=%2, entry=%3)").arg(file.absoluteFilePath(), root, entryName);
588
589 // create header and store it to write a central directory later
590 ZipEntryP* h = new ZipEntryP;
591
592 h->compMethod = (level == Zip::Store) ? 0 : 0x0008;
593
594 // Set encryption bit and set the data descriptor bit
595 // so we can use mod time instead of crc for password check
596 bool encrypt = !dirOnly && !password.isEmpty();
597 if (encrypt)
598 h->gpFlag[0] |= 9;
599
600 QDateTime dt = file.lastModified();
601 QDate d = dt.date();
602 h->modDate[1] = ((d.year() - 1980) << 1) & 254;
603 h->modDate[1] |= ((d.month() >> 3) & 1);
604 h->modDate[0] = ((d.month() & 7) << 5) & 224;
605 h->modDate[0] |= d.day();
606
607 QTime t = dt.time();
608 h->modTime[1] = (t.hour() << 3) & 248;
609 h->modTime[1] |= ((t.minute() >> 3) & 7);
610 h->modTime[0] = ((t.minute() & 7) << 5) & 224;
611 h->modTime[0] |= t.second() / 2;
612
613 h->szUncomp = dirOnly ? 0 : file.size();
614
615 // **** Write local file header ****
616
617 // signature
618 buffer1[0] = 'P'; buffer1[1] = 'K';
619 buffer1[2] = 0x3; buffer1[3] = 0x4;
620
621 // version needed to extract
622 buffer1[ZIP_LH_OFF_VERS] = ZIP_VERSION;
623 buffer1[ZIP_LH_OFF_VERS + 1] = 0;
624
625 // general purpose flag
626 buffer1[ZIP_LH_OFF_GPFLAG] = h->gpFlag[0];
627 buffer1[ZIP_LH_OFF_GPFLAG + 1] = h->gpFlag[1];
628
629 // compression method
630 buffer1[ZIP_LH_OFF_CMET] = h->compMethod & 0xFF;
631 buffer1[ZIP_LH_OFF_CMET + 1] = (h->compMethod>>8) & 0xFF;
632
633 // last mod file time
634 buffer1[ZIP_LH_OFF_MODT] = h->modTime[0];
635 buffer1[ZIP_LH_OFF_MODT + 1] = h->modTime[1];
636
637 // last mod file date
638 buffer1[ZIP_LH_OFF_MODD] = h->modDate[0];
639 buffer1[ZIP_LH_OFF_MODD + 1] = h->modDate[1];
640
641 // skip crc (4bytes) [14,15,16,17]
642
643 // skip compressed size but include evtl. encryption header (4bytes: [18,19,20,21])
644 buffer1[ZIP_LH_OFF_CSIZE] =
645 buffer1[ZIP_LH_OFF_CSIZE + 1] =
646 buffer1[ZIP_LH_OFF_CSIZE + 2] =
647 buffer1[ZIP_LH_OFF_CSIZE + 3] = 0;
648
649 h->szComp = encrypt ? ZIP_LOCAL_ENC_HEADER_SIZE : 0;
650
651 // uncompressed size [22,23,24,25]
652 setULong(h->szUncomp, buffer1, ZIP_LH_OFF_USIZE);
653
654 // filename length
655 QByteArray entryNameBytes = entryName.toAscii();
656 int sz = entryNameBytes.size();
657
658 buffer1[ZIP_LH_OFF_NAMELEN] = sz & 0xFF;
659 buffer1[ZIP_LH_OFF_NAMELEN + 1] = (sz >> 8) & 0xFF;
660
661 // extra field length
662 buffer1[ZIP_LH_OFF_XLEN] = buffer1[ZIP_LH_OFF_XLEN + 1] = 0;
663
664 // Store offset to write crc and compressed size
665 h->lhOffset = device->pos();
666 quint32 crcOffset = h->lhOffset + ZIP_LH_OFF_CRC;
667
668 if (device->write(buffer1, ZIP_LOCAL_HEADER_SIZE) != ZIP_LOCAL_HEADER_SIZE)
669 {
670 delete h;
671 return Zip::WriteFailed;
672 }
673
674 // Write out filename
675 if (device->write(entryNameBytes) != sz)
676 {
677 delete h;
678 return Zip::WriteFailed;
679 }
680
681 // Encryption keys
682 quint32 keys[3] = { 0, 0, 0 };
683
684 if (encrypt)
685 {
686 // **** encryption header ****
687
688 // XOR with PI to ensure better random numbers
689 // with poorly implemented rand() as suggested by Info-Zip
690 srand(time(NULL) ^ 3141592654UL);
691 int randByte;
692
693 initKeys(keys);
694 for (int i=0; i<10; ++i)
695 {
696 randByte = (rand() >> 7) & 0xff;
697 buffer1[i] = decryptByte(keys[2]) ^ randByte;
698 updateKeys(keys, randByte);
699 }
700
701 // Encrypt encryption header
702 initKeys(keys);
703 for (int i=0; i<10; ++i)
704 {
705 randByte = decryptByte(keys[2]);
706 updateKeys(keys, buffer1[i]);
707 buffer1[i] ^= randByte;
708 }
709
710 // We don't know the CRC at this time, so we use the modification time
711 // as the last two bytes
712 randByte = decryptByte(keys[2]);
713 updateKeys(keys, h->modTime[0]);
714 buffer1[10] ^= randByte;
715
716 randByte = decryptByte(keys[2]);
717 updateKeys(keys, h->modTime[1]);
718 buffer1[11] ^= randByte;
719
720 // Write out encryption header
721 if (device->write(buffer1, ZIP_LOCAL_ENC_HEADER_SIZE) != ZIP_LOCAL_ENC_HEADER_SIZE)
722 {
723 delete h;
724 return Zip::WriteFailed;
725 }
726 }
727
728 qint64 written = 0;
729 quint32 crc = crc32(0L, Z_NULL, 0);
730
731 if (!dirOnly)
732 {
733 QFile actualFile(file.absoluteFilePath());
734 if (!actualFile.open(QIODevice::ReadOnly))
735 {
736 qDebug() << QString("An error occurred while opening %1").arg(file.absoluteFilePath());
737 return Zip::OpenFailed;
738 }
739
740 // Write file data
741 qint64 read = 0;
742 qint64 totRead = 0;
743 qint64 toRead = actualFile.size();
744
745 if (level == Zip::Store)
746 {
747 while ( (read = actualFile.read(buffer1, ZIP_READ_BUFFER)) > 0 )
748 {
749 crc = crc32(crc, uBuffer, read);
750
751 if (password != 0)
752 encryptBytes(keys, buffer1, read);
753
754 if ( (written = device->write(buffer1, read)) != read )
755 {
756 actualFile.close();
757 delete h;
758 return Zip::WriteFailed;
759 }
760 }
761 }
762 else
763 {
764 z_stream zstr;
765
766 // Initialize zalloc, zfree and opaque before calling the init function
767 zstr.zalloc = Z_NULL;
768 zstr.zfree = Z_NULL;
769 zstr.opaque = Z_NULL;
770
771 int zret;
772
773 // Use deflateInit2 with negative windowBits to get raw compression
774 if ((zret = deflateInit2_(
775 &zstr,
776 (int)level,
777 Z_DEFLATED,
778 -MAX_WBITS,
779 8,
780 isPNGFile ? Z_RLE : Z_DEFAULT_STRATEGY,
781 ZLIB_VERSION,
782 sizeof(z_stream)
783 )) != Z_OK )
784 {
785 actualFile.close();
786 qDebug() << "Could not initialize zlib for compression";
787 delete h;
788 return Zip::ZlibError;
789 }
790
791 qint64 compressed;
792
793 int flush = Z_NO_FLUSH;
794
795 do
796 {
797 read = actualFile.read(buffer1, ZIP_READ_BUFFER);
798 totRead += read;
799
800 if (read == 0)
801 break;
802 if (read < 0)
803 {
804 actualFile.close();
805 deflateEnd(&zstr);
806 qDebug() << QString("Error while reading %1").arg(file.absoluteFilePath());
807 delete h;
808 return Zip::ReadFailed;
809 }
810
811 crc = crc32(crc, uBuffer, read);
812
813 zstr.next_in = (Bytef*) buffer1;
814 zstr.avail_in = (uInt)read;
815
816 // Tell zlib if this is the last chunk we want to encode
817 // by setting the flush parameter to Z_FINISH
818 flush = (totRead == toRead) ? Z_FINISH : Z_NO_FLUSH;
819
820 // Run deflate() on input until output buffer not full
821 // finish compression if all of source has been read in
822 do
823 {
824 zstr.next_out = (Bytef*) buffer2;
825 zstr.avail_out = ZIP_READ_BUFFER;
826
827 zret = deflate(&zstr, flush);
828 // State not clobbered
829 Q_ASSERT(zret != Z_STREAM_ERROR);
830
831 // Write compressed data to file and empty buffer
832 compressed = ZIP_READ_BUFFER - zstr.avail_out;
833
834 if (password != 0)
835 encryptBytes(keys, buffer2, compressed);
836
837 if (device->write(buffer2, compressed) != compressed)
838 {
839 deflateEnd(&zstr);
840 actualFile.close();
841 qDebug() << QString("Error while writing %1").arg(file.absoluteFilePath());
842 delete h;
843 return Zip::WriteFailed;
844 }
845
846 written += compressed;
847
848 } while (zstr.avail_out == 0);
849
850 // All input will be used
851 Q_ASSERT(zstr.avail_in == 0);
852
853 } while (flush != Z_FINISH);
854
855 // Stream will be complete
856 Q_ASSERT(zret == Z_STREAM_END);
857
858 deflateEnd(&zstr);
859
860 } // if (level != STORE)
861
862 actualFile.close();
863 }
864
865 // Store end of entry offset
866 quint32 current = device->pos();
867
868 // Update crc and compressed size in local header
869 if (!device->seek(crcOffset))
870 {
871 delete h;
872 return Zip::SeekFailed;
873 }
874
875 h->crc = dirOnly ? 0 : crc;
876 h->szComp += written;
877
878 setULong(h->crc, buffer1, 0);
879 setULong(h->szComp, buffer1, 4);
880 if ( device->write(buffer1, 8) != 8)
881 {
882 delete h;
883 return Zip::WriteFailed;
884 }
885
886 // Seek to end of entry
887 if (!device->seek(current))
888 {
889 delete h;
890 return Zip::SeekFailed;
891 }
892
893 if ((h->gpFlag[0] & 8) == 8)
894 {
895 // Write data descriptor
896
897 // Signature: PK\7\8
898 buffer1[0] = 'P';
899 buffer1[1] = 'K';
900 buffer1[2] = 0x07;
901 buffer1[3] = 0x08;
902
903 // CRC
904 setULong(h->crc, buffer1, ZIP_DD_OFF_CRC32);
905
906 // Compressed size
907 setULong(h->szComp, buffer1, ZIP_DD_OFF_CSIZE);
908
909 // Uncompressed size
910 setULong(h->szUncomp, buffer1, ZIP_DD_OFF_USIZE);
911
912 if (device->write(buffer1, ZIP_DD_SIZE_WS) != ZIP_DD_SIZE_WS)
913 {
914 delete h;
915 return Zip::WriteFailed;
916 }
917 }
918
919 headers->insert(entryName, h);
920 return Zip::Ok;
921}
922
923//! \internal
924int ZipPrivate::decryptByte(quint32 key2) const
925{
926 quint16 temp = ((quint16)(key2) & 0xffff) | 2;
927 return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
928}
929
930//! \internal Writes an quint32 (4 bytes) to a byte array at given offset.
931void ZipPrivate::setULong(quint32 v, char* buffer, unsigned int offset)
932{
933 buffer[offset+3] = ((v >> 24) & 0xFF);
934 buffer[offset+2] = ((v >> 16) & 0xFF);
935 buffer[offset+1] = ((v >> 8) & 0xFF);
936 buffer[offset] = (v & 0xFF);
937}
938
939//! \internal Initializes decryption keys using a password.
940void ZipPrivate::initKeys(quint32* keys) const
941{
942 // Encryption keys initialization constants are taken from the
943 // PKZip file format specification docs
944 keys[0] = 305419896L;
945 keys[1] = 591751049L;
946 keys[2] = 878082192L;
947
948 QByteArray pwdBytes = password.toAscii();
949 int sz = pwdBytes.size();
950 const char* ascii = pwdBytes.data();
951
952 for (int i=0; i<sz; ++i)
953 updateKeys(keys, (int)ascii[i]);
954}
955
956//! \internal Updates encryption keys.
957void ZipPrivate::updateKeys(quint32* keys, int c) const
958{
959 keys[0] = CRC32(keys[0], c);
960 keys[1] += keys[0] & 0xff;
961 keys[1] = keys[1] * 134775813L + 1;
962 keys[2] = CRC32(keys[2], ((int)keys[1]) >> 24);
963}
964
965//! \internal Encrypts a byte array.
966void ZipPrivate::encryptBytes(quint32* keys, char* buffer, qint64 read)
967{
968 char t;
969
970 for (int i=0; i<(int)read; ++i)
971 {
972 t = buffer[i];
973 buffer[i] ^= decryptByte(keys[2]);
974 updateKeys(keys, t);
975 }
976}
977
978//! \internal Detects the best compression level for a given file extension.
979Zip::CompressionLevel ZipPrivate::detectCompressionByMime(const QString& ext)
980{
981 // files really hard to compress
982 if ((ext == "png") ||
983 (ext == "jpg") ||
984 (ext == "jpeg") ||
985 (ext == "mp3") ||
986 (ext == "ogg") ||
987 (ext == "ogm") ||
988 (ext == "avi") ||
989 (ext == "mov") ||
990 (ext == "rm") ||
991 (ext == "ra") ||
992 (ext == "zip") ||
993 (ext == "rar") ||
994 (ext == "bz2") ||
995 (ext == "gz") ||
996 (ext == "7z") ||
997 (ext == "z") ||
998 (ext == "jar")
999 ) return Zip::Store;
1000
1001 // files slow and hard to compress
1002 if ((ext == "exe") ||
1003 (ext == "bin") ||
1004 (ext == "rpm") ||
1005 (ext == "deb")
1006 ) return Zip::Deflate2;
1007
1008 return Zip::Deflate9;
1009}
1010
1011/*!
1012 Closes the current archive and writes out pending data.
1013*/
1014Zip::ErrorCode ZipPrivate::closeArchive()
1015{
1016 // Close current archive by writing out central directory
1017 // and free up resources
1018
1019 if (device == 0)
1020 return Zip::Ok;
1021
1022 if (headers == 0)
1023 return Zip::Ok;
1024
1025 const ZipEntryP* h;
1026
1027 unsigned int sz;
1028 quint32 szCentralDir = 0;
1029 quint32 offCentralDir = device->pos();
1030
1031 for (QMap<QString,ZipEntryP*>::ConstIterator itr = headers->constBegin(); itr != headers->constEnd(); ++itr)
1032 {
1033 h = itr.value();
1034
1035 // signature
1036 buffer1[0] = 'P';
1037 buffer1[1] = 'K';
1038 buffer1[2] = 0x01;
1039 buffer1[3] = 0x02;
1040
1041 // version made by (currently only MS-DOS/FAT - no symlinks or other stuff supported)
1042 buffer1[ZIP_CD_OFF_MADEBY] = buffer1[ZIP_CD_OFF_MADEBY + 1] = 0;
1043
1044 // version needed to extract
1045 buffer1[ZIP_CD_OFF_VERSION] = ZIP_VERSION;
1046 buffer1[ZIP_CD_OFF_VERSION + 1] = 0;
1047
1048 // general purpose flag
1049 buffer1[ZIP_CD_OFF_GPFLAG] = h->gpFlag[0];
1050 buffer1[ZIP_CD_OFF_GPFLAG + 1] = h->gpFlag[1];
1051
1052 // compression method
1053 buffer1[ZIP_CD_OFF_CMET] = h->compMethod & 0xFF;
1054 buffer1[ZIP_CD_OFF_CMET + 1] = (h->compMethod >> 8) & 0xFF;
1055
1056 // last mod file time
1057 buffer1[ZIP_CD_OFF_MODT] = h->modTime[0];
1058 buffer1[ZIP_CD_OFF_MODT + 1] = h->modTime[1];
1059
1060 // last mod file date
1061 buffer1[ZIP_CD_OFF_MODD] = h->modDate[0];
1062 buffer1[ZIP_CD_OFF_MODD + 1] = h->modDate[1];
1063
1064 // crc (4bytes) [16,17,18,19]
1065 setULong(h->crc, buffer1, ZIP_CD_OFF_CRC);
1066
1067 // compressed size (4bytes: [20,21,22,23])
1068 setULong(h->szComp, buffer1, ZIP_CD_OFF_CSIZE);
1069
1070 // uncompressed size [24,25,26,27]
1071 setULong(h->szUncomp, buffer1, ZIP_CD_OFF_USIZE);
1072
1073 // filename
1074 QByteArray fileNameBytes = itr.key().toAscii();
1075 sz = fileNameBytes.size();
1076 buffer1[ZIP_CD_OFF_NAMELEN] = sz & 0xFF;
1077 buffer1[ZIP_CD_OFF_NAMELEN + 1] = (sz >> 8) & 0xFF;
1078
1079 // extra field length
1080 buffer1[ZIP_CD_OFF_XLEN] = buffer1[ZIP_CD_OFF_XLEN + 1] = 0;
1081
1082 // file comment length
1083 buffer1[ZIP_CD_OFF_COMMLEN] = buffer1[ZIP_CD_OFF_COMMLEN + 1] = 0;
1084
1085 // disk number start
1086 buffer1[ZIP_CD_OFF_DISKSTART] = buffer1[ZIP_CD_OFF_DISKSTART + 1] = 0;
1087
1088 // internal file attributes
1089 buffer1[ZIP_CD_OFF_IATTR] = buffer1[ZIP_CD_OFF_IATTR + 1] = 0;
1090
1091 // external file attributes
1092 buffer1[ZIP_CD_OFF_EATTR] =
1093 buffer1[ZIP_CD_OFF_EATTR + 1] =
1094 buffer1[ZIP_CD_OFF_EATTR + 2] =
1095 buffer1[ZIP_CD_OFF_EATTR + 3] = 0;
1096
1097 // relative offset of local header [42->45]
1098 setULong(h->lhOffset, buffer1, ZIP_CD_OFF_LHOFF);
1099
1100 if (device->write(buffer1, ZIP_CD_SIZE) != ZIP_CD_SIZE)
1101 {
1102 //! \todo See if we can detect QFile objects using the Qt Meta Object System
1103 /*
1104 if (!device->remove())
1105 qDebug() << tr("Unable to delete corrupted archive: %1").arg(device->fileName());
1106 */
1107 return Zip::WriteFailed;
1108 }
1109
1110 // Write out filename
1111 if ((unsigned int)device->write(fileNameBytes) != sz)
1112 {
1113 //! \todo SAME AS ABOVE: See if we can detect QFile objects using the Qt Meta Object System
1114 /*
1115 if (!device->remove())
1116 qDebug() << tr("Unable to delete corrupted archive: %1").arg(device->fileName());
1117 */
1118 return Zip::WriteFailed;
1119 }
1120
1121 szCentralDir += (ZIP_CD_SIZE + sz);
1122
1123 } // central dir headers loop
1124
1125
1126 // Write end of central directory
1127
1128 // signature
1129 buffer1[0] = 'P';
1130 buffer1[1] = 'K';
1131 buffer1[2] = 0x05;
1132 buffer1[3] = 0x06;
1133
1134 // number of this disk
1135 buffer1[ZIP_EOCD_OFF_DISKNUM] = buffer1[ZIP_EOCD_OFF_DISKNUM + 1] = 0;
1136
1137 // number of disk with central directory
1138 buffer1[ZIP_EOCD_OFF_CDDISKNUM] = buffer1[ZIP_EOCD_OFF_CDDISKNUM + 1] = 0;
1139
1140 // number of entries in this disk
1141 sz = headers->count();
1142 buffer1[ZIP_EOCD_OFF_ENTRIES] = sz & 0xFF;
1143 buffer1[ZIP_EOCD_OFF_ENTRIES + 1] = (sz >> 8) & 0xFF;
1144
1145 // total number of entries
1146 buffer1[ZIP_EOCD_OFF_CDENTRIES] = buffer1[ZIP_EOCD_OFF_ENTRIES];
1147 buffer1[ZIP_EOCD_OFF_CDENTRIES + 1] = buffer1[ZIP_EOCD_OFF_ENTRIES + 1];
1148
1149 // size of central directory [12->15]
1150 setULong(szCentralDir, buffer1, ZIP_EOCD_OFF_CDSIZE);
1151
1152 // central dir offset [16->19]
1153 setULong(offCentralDir, buffer1, ZIP_EOCD_OFF_CDOFF);
1154
1155 // ZIP file comment length
1156 QByteArray commentBytes = comment.toAscii();
1157 quint16 commentLength = commentBytes.size();
1158
1159 if (commentLength == 0)
1160 {
1161 buffer1[ZIP_EOCD_OFF_COMMLEN] = buffer1[ZIP_EOCD_OFF_COMMLEN + 1] = 0;
1162 }
1163 else
1164 {
1165 buffer1[ZIP_EOCD_OFF_COMMLEN] = commentLength & 0xFF;
1166 buffer1[ZIP_EOCD_OFF_COMMLEN + 1] = (commentLength >> 8) & 0xFF;
1167 }
1168
1169 if (device->write(buffer1, ZIP_EOCD_SIZE) != ZIP_EOCD_SIZE)
1170 {
1171 //! \todo SAME AS ABOVE: See if we can detect QFile objects using the Qt Meta Object System
1172 /*
1173 if (!device->remove())
1174 qDebug() << tr("Unable to delete corrupted archive: %1").arg(device->fileName());
1175 */
1176 return Zip::WriteFailed;
1177 }
1178
1179 if (commentLength != 0)
1180 {
1181 if ((unsigned int)device->write(commentBytes) != commentLength)
1182 {
1183 //! \todo SAME AS ABOVE: See if we can detect QFile objects using the Qt Meta Object System
1184 /*
1185 if (!device->remove())
1186 qDebug() << tr("Unable to delete corrupted archive: %1").arg(device->fileName());
1187 */
1188 return Zip::WriteFailed;
1189 }
1190 }
1191
1192 return Zip::Ok;
1193}
1194
1195//! \internal
1196void ZipPrivate::reset()
1197{
1198 comment.clear();
1199
1200 if (headers != 0)
1201 {
1202 qDeleteAll(*headers);
1203 delete headers;
1204 headers = 0;
1205 }
1206
1207 delete device; device = 0;
1208}
1209
1210//! \internal Returns the path of the parent directory
1211QString ZipPrivate::extractRoot(const QString& p)
1212{
1213 QDir d(QDir::cleanPath(p));
1214 if (!d.exists())
1215 return QString();
1216
1217 if (!d.cdUp())
1218 return QString();
1219
1220 return d.absolutePath();
1221}
diff --git a/rbutil/rbutilqt/zip/zip.h b/rbutil/rbutilqt/zip/zip.h
deleted file mode 100644
index dfe5deb064..0000000000
--- a/rbutil/rbutilqt/zip/zip.h
+++ /dev/null
@@ -1,115 +0,0 @@
1/****************************************************************************
2** Filename: zip.h
3** Last updated [dd/mm/yyyy]: 01/02/2007
4**
5** pkzip 2.0 file compression.
6**
7** Some of the code has been inspired by other open source projects,
8** (mainly Info-Zip and Gilles Vollant's minizip).
9** Compression and decompression actually uses the zlib library.
10**
11** Copyright (C) 2007-2008 Angius Fabrizio. All rights reserved.
12**
13** This file is part of the OSDaB project (http://osdab.sourceforge.net/).
14**
15** This file may be distributed and/or modified under the terms of the
16** GNU General Public License version 2 as published by the Free Software
17** Foundation and appearing in the file LICENSE.GPL included in the
18** packaging of this file.
19**
20** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
21** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22**
23** See the file LICENSE.GPL that came with this software distribution or
24** visit http://www.gnu.org/copyleft/gpl.html for GPL licensing information.
25**
26**********************************************************************/
27
28#ifndef OSDAB_ZIP__H
29#define OSDAB_ZIP__H
30
31#include <QtGlobal>
32#include <QMap>
33
34#include <zlib/zlib.h>
35
36class ZipPrivate;
37
38class QIODevice;
39class QFile;
40class QDir;
41class QStringList;
42class QString;
43
44
45class Zip
46{
47public:
48 enum ErrorCode
49 {
50 Ok,
51 ZlibInit,
52 ZlibError,
53 FileExists,
54 OpenFailed,
55 NoOpenArchive,
56 FileNotFound,
57 ReadFailed,
58 WriteFailed,
59 SeekFailed
60 };
61
62 enum CompressionLevel
63 {
64 Store,
65 Deflate1 = 1, Deflate2, Deflate3, Deflate4,
66 Deflate5, Deflate6, Deflate7, Deflate8, Deflate9,
67 AutoCPU, AutoMIME, AutoFull
68 };
69
70 enum CompressionOption
71 {
72 //! Does not preserve absolute paths in the zip file when adding a file/directory (default)
73 RelativePaths = 0x0001,
74 //! Preserve absolute paths
75 AbsolutePaths = 0x0002,
76 //! Do not store paths. All the files are put in the (evtl. user defined) root of the zip file
77 IgnorePaths = 0x0004
78 };
79 Q_DECLARE_FLAGS(CompressionOptions, CompressionOption)
80
81 Zip();
82 virtual ~Zip();
83
84 bool isOpen() const;
85
86 void setPassword(const QString& pwd);
87 void clearPassword();
88 QString password() const;
89
90 ErrorCode createArchive(const QString& file, bool overwrite = true);
91 ErrorCode createArchive(QIODevice* device);
92
93 QString archiveComment() const;
94 void setArchiveComment(const QString& comment);
95
96 ErrorCode addDirectoryContents(const QString& path, CompressionLevel level = AutoFull);
97 ErrorCode addDirectoryContents(const QString& path, const QString& root, CompressionLevel level = AutoFull);
98
99 ErrorCode addDirectory(const QString& path, CompressionOptions options = RelativePaths, CompressionLevel level = AutoFull);
100 ErrorCode addDirectory(const QString& path, const QString& root, CompressionLevel level = AutoFull);
101 ErrorCode addDirectory(const QString& path, const QString& root, CompressionOptions options = RelativePaths, CompressionLevel level = AutoFull);
102
103 ErrorCode closeArchive();
104
105 QString formatError(ErrorCode c) const;
106
107 virtual void progress() {}
108
109private:
110 ZipPrivate* d;
111};
112
113Q_DECLARE_OPERATORS_FOR_FLAGS(Zip::CompressionOptions)
114
115#endif // OSDAB_ZIP__H
diff --git a/rbutil/rbutilqt/zip/zip_p.h b/rbutil/rbutilqt/zip/zip_p.h
deleted file mode 100644
index 271cc1859f..0000000000
--- a/rbutil/rbutilqt/zip/zip_p.h
+++ /dev/null
@@ -1,93 +0,0 @@
1/****************************************************************************
2** Filename: zip_p.h
3** Last updated [dd/mm/yyyy]: 28/01/2007
4**
5** pkzip 2.0 file compression.
6**
7** Some of the code has been inspired by other open source projects,
8** (mainly Info-Zip and Gilles Vollant's minizip).
9** Compression and decompression actually uses the zlib library.
10**
11** Copyright (C) 2007-2008 Angius Fabrizio. All rights reserved.
12**
13** This file is part of the OSDaB project (http://osdab.sourceforge.net/).
14**
15** This file may be distributed and/or modified under the terms of the
16** GNU General Public License version 2 as published by the Free Software
17** Foundation and appearing in the file LICENSE.GPL included in the
18** packaging of this file.
19**
20** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
21** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22**
23** See the file LICENSE.GPL that came with this software distribution or
24** visit http://www.gnu.org/copyleft/gpl.html for GPL licensing information.
25**
26**********************************************************************/
27
28//
29// W A R N I N G
30// -------------
31//
32// This file is not part of the Zip/UnZip API. It exists purely as an
33// implementation detail. This header file may change from version to
34// version without notice, or even be removed.
35//
36// We mean it.
37//
38
39#ifndef OSDAB_ZIP_P__H
40#define OSDAB_ZIP_P__H
41
42#include "zip.h"
43#include "zipentry_p.h"
44
45#include <QtGlobal>
46#include <QFileInfo>
47
48/*!
49 zLib authors suggest using larger buffers (128K or 256K) for (de)compression (especially for inflate())
50 we use a 256K buffer here - if you want to use this code on a pre-iceage mainframe please change it ;)
51*/
52#define ZIP_READ_BUFFER (256*1024)
53
54class ZipPrivate
55{
56public:
57 ZipPrivate();
58 virtual ~ZipPrivate();
59
60 QMap<QString,ZipEntryP*>* headers;
61
62 QIODevice* device;
63
64 char buffer1[ZIP_READ_BUFFER];
65 char buffer2[ZIP_READ_BUFFER];
66
67 unsigned char* uBuffer;
68
69 const quint32* crcTable;
70
71 QString comment;
72 QString password;
73
74 Zip::ErrorCode createArchive(QIODevice* device);
75 Zip::ErrorCode closeArchive();
76 void reset();
77
78 bool zLibInit();
79
80 Zip::ErrorCode createEntry(const QFileInfo& file, const QString& root, Zip::CompressionLevel level);
81 Zip::CompressionLevel detectCompressionByMime(const QString& ext);
82
83 inline void encryptBytes(quint32* keys, char* buffer, qint64 read);
84
85 inline void setULong(quint32 v, char* buffer, unsigned int offset);
86 inline void updateKeys(quint32* keys, int c) const;
87 inline void initKeys(quint32* keys) const;
88 inline int decryptByte(quint32 key2) const;
89
90 inline QString extractRoot(const QString& p);
91};
92
93#endif // OSDAB_ZIP_P__H
diff --git a/rbutil/rbutilqt/zip/zipentry_p.h b/rbutil/rbutilqt/zip/zipentry_p.h
deleted file mode 100644
index c88253ee8c..0000000000
--- a/rbutil/rbutilqt/zip/zipentry_p.h
+++ /dev/null
@@ -1,78 +0,0 @@
1/****************************************************************************
2** Filename: ZipEntryP.h
3** Last updated [dd/mm/yyyy]: 28/01/2007
4**
5** Wrapper for a ZIP local header.
6**
7** Some of the code has been inspired by other open source projects,
8** (mainly Info-Zip and Gilles Vollant's minizip).
9** Compression and decompression actually uses the zlib library.
10**
11** Copyright (C) 2007-2008 Angius Fabrizio. All rights reserved.
12**
13** This file is part of the OSDaB project (http://osdab.sourceforge.net/).
14**
15** This file may be distributed and/or modified under the terms of the
16** GNU General Public License version 2 as published by the Free Software
17** Foundation and appearing in the file LICENSE.GPL included in the
18** packaging of this file.
19**
20** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
21** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22**
23** See the file LICENSE.GPL that came with this software distribution or
24** visit http://www.gnu.org/copyleft/gpl.html for GPL licensing information.
25**
26**********************************************************************/
27
28//
29// W A R N I N G
30// -------------
31//
32// This file is not part of the Zip/UnZip API. It exists purely as an
33// implementation detail. This header file may change from version to
34// version without notice, or even be removed.
35//
36// We mean it.
37//
38
39#ifndef OSDAB_ZIPENTRY_P__H
40#define OSDAB_ZIPENTRY_P__H
41
42#include <QtGlobal>
43#include <QString>
44
45class ZipEntryP
46{
47public:
48 ZipEntryP()
49 {
50 lhOffset = 0;
51 dataOffset = 0;
52 gpFlag[0] = gpFlag[1] = 0;
53 compMethod = 0;
54 modTime[0] = modTime[1] = 0;
55 modDate[0] = modDate[1] = 0;
56 crc = 0;
57 szComp = szUncomp = 0;
58 lhEntryChecked = false;
59 }
60
61 quint32 lhOffset; // Offset of the local header record for this entry
62 quint32 dataOffset; // Offset of the file data for this entry
63 unsigned char gpFlag[2]; // General purpose flag
64 quint16 compMethod; // Compression method
65 unsigned char modTime[2]; // Last modified time
66 unsigned char modDate[2]; // Last modified date
67 quint32 crc; // CRC32
68 quint32 szComp; // Compressed file size
69 quint32 szUncomp; // Uncompressed file size
70 QString comment; // File comment
71
72 bool lhEntryChecked; // Is true if the local header record for this entry has been parsed
73
74 inline bool isEncrypted() const { return gpFlag[0] & 0x01; }
75 inline bool hasDataDescriptor() const { return gpFlag[0] & 0x08; }
76};
77
78#endif // OSDAB_ZIPENTRY_P__H