Skip to content
Browse files

Merge branch 'master' of https://github.com/iptton/Rythem

Conflicts:
	Rythem.pro
  • Loading branch information...
2 parents b6d4c9f + 88a1557 commit 87421e4d0c69c739cd6c0f3c6434750f3b995571 @iptton iptton committed Apr 13, 2012
View
32 Rythem.pro
@@ -26,7 +26,17 @@ SOURCES += main.cpp\
proxy/rywinhttp.cpp \
proxy/ryproxyserver.cpp \
proxy/rypipedata.cpp \
- proxy/ryconnection.cpp
+ proxy/ryconnection.cpp \
+ ryconnectiontableview.cpp \
+ quazip/zip.c \
+ quazip/unzip.c \
+ quazip/quazipnewinfo.cpp \
+ quazip/quazipfile.cpp \
+ quazip/quazip.cpp \
+ quazip/quacrc32.cpp \
+ quazip/quaadler32.cpp \
+ quazip/qioapi.cpp \
+ quazip/JlCompress.cpp
mac:SOURCES -= qiwinhttp.cpp
@@ -44,7 +54,22 @@ HEADERS += mainwindow.h \
proxy/rywinhttp.h \
proxy/ryproxyserver.h \
proxy/rypipedata.h \
- proxy/ryconnection.h
+ proxy/ryconnection.h \
+ ryconnectiontableview.h \
+ quazip/zip.h \
+ quazip/unzip.h \
+ quazip/quazipnewinfo.h \
+ quazip/quazipfileinfo.h \
+ quazip/quazipfile.h \
+ quazip/quazip.h \
+ quazip/quazip_global.h \
+ quazip/quacrc32.h \
+ quazip/quachecksum32.h \
+ quazip/quaadler32.h \
+ quazip/JlCompress.h \
+ quazip/ioapi.h \
+ quazip/crypt.h \
+ rymimedata.h
win32:HEADERS += zlib/zutil.h \
zlib/zlib.h \
zlib/zconf.h \
@@ -92,8 +117,7 @@ OTHER_FILES += \
static/icloud_64.png \
RythemTimes/lib/parseuri.js \
RythemTimes/lib/jo2.js \
- RythemTimes/lib/jo2.dom.js \
- logo.rc
+ RythemTimes/lib/jo2.dom.js
CONFIG(release){
#DEFINES += DEBUGTOFILE
#message("debug")
View
16 composer.cpp
@@ -1,6 +1,9 @@
#include "composer.h"
#include "ui_composer.h"
#include <QNetworkProxy>
+
+#include "rymimedata.h"
+
Composer::Composer(QWidget *parent) :
QWidget(parent),
ui(new Ui::Composer){
@@ -177,6 +180,7 @@ void Composer::setupProxy(QString host,qint16 port){
}
void Composer::dragEnterEvent(QDragEnterEvent *event){
+
qDebug()<<"drag enter";
if (event->mimeData()->hasText()) {
if (event->source() == this) {
@@ -188,12 +192,18 @@ void Composer::dragEnterEvent(QDragEnterEvent *event){
} else {
event->ignore();
}
+
}
void Composer::dropEvent(QDropEvent *event){
- qDebug()<<event->source();
- if (event->mimeData()->hasText()) {
- const QMimeData *mime = event->mimeData();
+ qDebug()<<"drop";
+ const RyMimeData* mime = dynamic_cast<const RyMimeData*>(event->mimeData());
+
+ if (mime) {
+ RyPipeData_ptr d = mime->pipeData();
+ this->ui->server->setText(d->host);
+ this->ui->port->setText(QString::number(d->port));
+ this->ui->request->setPlainText(QString(d->requestHeaderRawData()).append("\r\n\r\n").append(d->requestBodyRawData()));
qDebug()<<"drop text="<<mime->text();
event->acceptProposedAction();
} else {
View
14 composer.ui
@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
- <width>624</width>
+ <width>727</width>
<height>385</height>
</rect>
</property>
@@ -22,6 +22,9 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
+ <property name="acceptDrops">
+ <bool>false</bool>
+ </property>
<property name="text">
<string>w.l.qq.com</string>
</property>
@@ -50,6 +53,9 @@
<height>16777215</height>
</size>
</property>
+ <property name="acceptDrops">
+ <bool>false</bool>
+ </property>
<property name="text">
<string>80</string>
</property>
@@ -101,6 +107,9 @@
</item>
<item row="1" column="0" colspan="6">
<widget class="QPlainTextEdit" name="request">
+ <property name="acceptDrops">
+ <bool>false</bool>
+ </property>
<property name="toolTip">
<string>request</string>
</property>
@@ -126,6 +135,9 @@ Range: bytes=48-6116217
</item>
<item row="2" column="0" colspan="6">
<widget class="QPlainTextEdit" name="response">
+ <property name="acceptDrops">
+ <bool>false</bool>
+ </property>
<property name="toolTip">
<string>response</string>
</property>
View
3 httpfiles.qrc
@@ -23,5 +23,8 @@
<file>static/icloud_64.png</file>
<file>logo.png</file>
<file>family.png</file>
+ <file>915.png</file>
+ <file>201111291315331602.png</file>
+ <file>201111291315335930.png</file>
</qresource>
</RCC>
View
1 logo.rc
@@ -0,0 +1 @@
+IDI_ICON1 ICON DISCARDABLE "lol.ico"
View
BIN lol.ico
Binary file not shown.
View
6 main.cpp
@@ -51,7 +51,7 @@ int main(int argc, char *argv[])
{
QApplication a(argc, argv);
a.setQuitOnLastWindowClosed(false);
- a.setWindowIcon(QIcon(":/static/logo.png"));
+ //a.setWindowIcon(QIcon(":/static/rythem.icns"));
appPath = qApp->applicationDirPath();
@@ -79,8 +79,8 @@ int main(int argc, char *argv[])
server->connect(server,SIGNAL(pipeError(RyPipeData_ptr)),&w,SLOT(onPipeUpdate(RyPipeData_ptr)));
server->listen(QHostAddress("127.0.0.1"),8889);
- w.showMaximized();
-
+ //w.showMaximized();
+ w.show();
return a.exec();
}
View
89 mainwindow.cpp
@@ -37,6 +37,8 @@
#include <QMovie>
#include <QPixmap>
+#include <quazip/quazip.h>
+#include <quazip/quazipfile.h>
QByteArray gzipDecompress(QByteArray data){
@@ -219,15 +221,65 @@ MainWindow::~MainWindow()
}
void MainWindow::createMenus(){
fileMenu = menuBar()->addMenu(tr("&File"));
- captureAct = new QAction(tr("&Capture"),this);
- captureAct->setCheckable(true);
- fileMenu->addAction(captureAct);
- QAction *a = fileMenu->addAction(tr("&rules"));
- connect(a,SIGNAL(triggered()),SLOT(showSettingsDialog()));
- connect(captureAct,SIGNAL(triggered()),SLOT(toggleCapture()));
+ QAction *importSessions = fileMenu->addAction(tr("&import session..."));
+ connect(importSessions,SIGNAL(triggered()),SLOT(importSessions()));
}
-void MainWindow::showSettingsDialog(){
+void MainWindow::importSessions(){
+ QFileDialog dialog;
+ QString fileName = dialog.getOpenFileName(this,tr("select file to open"),"","Archiev Files(*.saz *.zip)");
+ QuaZip zip(fileName);
+ if(!zip.open(QuaZip::mdUnzip)){
+ qDebug()<<"cannot open "<<fileName;
+ return;
+ }
+ QuaZipFileInfo info;
+ QuaZipFile file(&zip);
+
+ RyPipeData_ptr pipeData;
+
+ QString name;
+ for (bool more = zip.goToFirstFile(); more; more = zip.goToNextFile()) {
+
+ if (!zip.getCurrentFileInfo(&info)) {
+ qWarning("testRead(): getCurrentFileInfo(): %d\n", zip.getZipError());
+ return;
+ }
+
+ if (!file.open(QIODevice::ReadOnly)) {
+ qWarning("testRead(): file.open(): %d", file.getZipError());
+ return;
+ }
+
+ name = file.getActualFileName();
+ QByteArray ba = file.readAll();
+ if(name.endsWith("_c.txt")){
+ //pipeData.clear();
+ pipeData = RyPipeData_ptr(new RyPipeData(0,0));
+ pipeData->isImported = true;
+ pipeData->parseRequest(&ba);
+ onNewPipe(pipeData);
+ }else if(name.endsWith("_s.txt")){
+ pipeData->parseResponse(&ba);
+ onPipeUpdate(pipeData);
+ pipeData.clear();
+ }
+
+ if (file.getZipError() != UNZ_OK) {
+ qWarning("testRead(): file.getFileName(): %d", file.getZipError());
+ return ;
+ }
+
+ file.close();
+
+ if (file.getZipError() != UNZ_OK) {
+ qWarning("testRead(): file.close(): %d", file.getZipError());
+ return ;
+ }
+
+ }
+
+ zip.close();
}
@@ -345,27 +397,6 @@ void MainWindow::onWaterfallActionTriggered(){
}
-void MainWindow::mousePressEvent(QMouseEvent *event){
- qDebug()<<"mouseenter";
- QTableView *table = static_cast<QTableView*>(childAt(event->pos()));
- if (!table || table!=ui->tableView){
- return;
- }
- qDebug()<<"is table";
- QPoint hotSpot = event->pos() - table->pos();
- QMimeData *mimeData = new QMimeData;
- mimeData->setText("child->text()");
- QDrag *drag = new QDrag(this);
- drag->setMimeData(mimeData);
- //drag->setPixmap(pixmap);
- drag->setHotSpot(hotSpot);
- drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction);
-}
-
-void MainWindow::dragEnterEvent(QDragEnterEvent *){
-
-}
-
void MainWindow::toggleProxy(){
if(isUsingCapture){
isUsingCapture = false;
@@ -428,7 +459,7 @@ void MainWindow::toggleProxy(){
}
void MainWindow::toggleCapture(){
- captureAct->setChecked(!isUsingCapture);
+ //captureAct->setChecked(!isUsingCapture);
#ifdef Q_WS_WIN32
RyWinHttp::init();
toggleProxy();
View
5 mainwindow.h
@@ -46,7 +46,7 @@ class MainWindow : public QMainWindow
private slots:
void toggleCapture();
- void showSettingsDialog();
+ void importSessions();
public:
explicit MainWindow(QWidget *parent=0);
~MainWindow();
@@ -70,9 +70,6 @@ public slots:
}ProxyInfo;
RyTableModel pipeTableModel;
-protected:
- void mousePressEvent(QMouseEvent *);
- void dragEnterEvent(QDragEnterEvent *);
private:
Ui::MainWindow *ui;
View
25 mainwindow.ui
@@ -13,21 +13,23 @@
<property name="windowTitle">
<string>Rythem</string>
</property>
- <property name="windowIcon">
- <iconset>
- <normaloff>logo.png</normaloff>logo.png</iconset>
- </property>
<widget class="QWidget" name="centralWidget">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
- <widget class="QTableView" name="tableView"/>
+ <widget class="RyConnectionTableView" name="tableView"/>
<widget class="QTabWidget" name="tollTabs">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Ignored" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
<property name="currentIndex">
- <number>0</number>
+ <number>2</number>
</property>
<widget class="QWidget" name="inspectorTab">
<attribute name="title">
@@ -88,8 +90,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>557</width>
- <height>195</height>
+ <width>98</width>
+ <height>40</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
@@ -153,7 +155,7 @@
<x>0</x>
<y>0</y>
<width>818</width>
- <height>23</height>
+ <height>22</height>
</rect>
</property>
</widget>
@@ -241,6 +243,11 @@
<header>composer.h</header>
<container>1</container>
</customwidget>
+ <customwidget>
+ <class>RyConnectionTableView</class>
+ <extends>QTableView</extends>
+ <header>ryconnectiontableview.h</header>
+ </customwidget>
</customwidgets>
<resources>
<include location="httpfiles.qrc"/>
View
2 proxy/rypipedata.cpp
@@ -10,6 +10,8 @@ RyPipeData::RyPipeData(int _socketHandle,quint64 connectionId,QObject *parent):
socketConnectionId = connectionId;
_isContentLenthUnLimit =false;
_isResponseChunked = false;
+ isMatchingRule = false;
+ isImported = false;
}
bool RyPipeData::operator <(RyPipeData &pipeData){
View
1 proxy/rypipedata.h
@@ -116,6 +116,7 @@ class RyPipeData : public QObject
QString getResponseHeader(const QString& name)const;
bool isMatchingRule;
+ bool isImported;
int ruleType;
QByteArray requestHeaderRawData()const{
View
490 quazip/JlCompress.cpp
@@ -0,0 +1,490 @@
+#include "JlCompress.h"
+#include <QDebug>
+
+static bool copyData(QIODevice &inFile, QIODevice &outFile)
+{
+ while (!inFile.atEnd()) {
+ char buf[4096];
+ qint64 readLen = inFile.read(buf, 4096);
+ if (readLen <= 0)
+ return false;
+ if (outFile.write(buf, readLen) != readLen)
+ return false;
+ }
+ return true;
+}
+
+/**OK
+ * Comprime il file fileName, nell'oggetto zip, con il nome fileDest.
+ *
+ * La funzione fallisce se:
+ * * zip==NULL;
+ * * l'oggetto zip e stato aperto in una modalita non compatibile con l'aggiunta di file;
+ * * non e possibile aprire il file d'origine;
+ * * non e possibile creare il file all'interno dell'oggetto zip;
+ * * si e rilevato un errore nella copia dei dati;
+ * * non e stato possibile chiudere il file all'interno dell'oggetto zip;
+ */
+bool JlCompress::compressFile(QuaZip* zip, QString fileName, QString fileDest) {
+ // zip: oggetto dove aggiungere il file
+ // fileName: nome del file reale
+ // fileDest: nome del file all'interno del file compresso
+
+ // Controllo l'apertura dello zip
+ if (!zip) return false;
+ if (zip->getMode()!=QuaZip::mdCreate &&
+ zip->getMode()!=QuaZip::mdAppend &&
+ zip->getMode()!=QuaZip::mdAdd) return false;
+
+ // Apro il file originale
+ QFile inFile;
+ inFile.setFileName(fileName);
+ if(!inFile.open(QIODevice::ReadOnly)) return false;
+
+ // Apro il file risulato
+ QuaZipFile outFile(zip);
+ if(!outFile.open(QIODevice::WriteOnly, QuaZipNewInfo(fileDest, inFile.fileName()))) return false;
+
+ // Copio i dati
+ if (!copyData(inFile, outFile) || outFile.getZipError()!=UNZ_OK) {
+ return false;
+ }
+
+ // Chiudo i file
+ outFile.close();
+ if (outFile.getZipError()!=UNZ_OK) return false;
+ inFile.close();
+
+ return true;
+}
+
+/**OK
+ * Comprime la cartella dir nel file fileCompressed, se recursive e true allora
+ * comprime anche le sotto cartelle. I nomi dei file preceduti dal path creato
+ * togliendo il pat della cartella origDir al path della cartella dir.
+ * Se la funzione fallisce restituisce false e cancella il file che si e tentato
+ * di creare.
+ *
+ * La funzione fallisce se:
+ * * zip==NULL;
+ * * l'oggetto zip e stato aperto in una modalita non compatibile con l'aggiunta di file;
+ * * la cartella dir non esiste;
+ * * la compressione di una sotto cartella fallisce (1);
+ * * la compressione di un file fallisce;
+ * (1) La funzione si richiama in maniera ricorsiva per comprimere le sotto cartelle
+ * dunque gli errori di compressione di una sotto cartella sono gli stessi di questa
+ * funzione.
+ */
+bool JlCompress::compressSubDir(QuaZip* zip, QString dir, QString origDir, bool recursive) {
+ // zip: oggetto dove aggiungere il file
+ // dir: cartella reale corrente
+ // origDir: cartella reale originale
+ // (path(dir)-path(origDir)) = path interno all'oggetto zip
+
+ // Controllo l'apertura dello zip
+ if (!zip) return false;
+ if (zip->getMode()!=QuaZip::mdCreate &&
+ zip->getMode()!=QuaZip::mdAppend &&
+ zip->getMode()!=QuaZip::mdAdd) return false;
+
+ // Controllo la cartella
+ QDir directory(dir);
+ if (!directory.exists()) return false;
+
+ // Se comprimo anche le sotto cartelle
+ if (recursive) {
+ // Per ogni sotto cartella
+ QFileInfoList files = directory.entryInfoList(QDir::AllDirs|QDir::NoDotAndDotDot);
+ Q_FOREACH (QFileInfo file, files) {
+ // Comprimo la sotto cartella
+ if(!compressSubDir(zip,file.absoluteFilePath(),origDir,recursive)) return false;
+ }
+ }
+
+ // Per ogni file nella cartella
+ QFileInfoList files = directory.entryInfoList(QDir::Files);
+ QDir origDirectory(origDir);
+ Q_FOREACH (QFileInfo file, files) {
+ // Se non e un file o e il file compresso che sto creando
+ if(!file.isFile()||file.absoluteFilePath()==zip->getZipName()) continue;
+
+ // Creo il nome relativo da usare all'interno del file compresso
+ QString filename = origDirectory.relativeFilePath(file.absoluteFilePath());
+
+ // Comprimo il file
+ if (!compressFile(zip,file.absoluteFilePath(),filename)) return false;
+ }
+
+ return true;
+}
+
+/**OK
+ * Estrae il file fileName, contenuto nell'oggetto zip, con il nome fileDest.
+ * Se la funzione fallisce restituisce false e cancella il file che si e tentato di estrarre.
+ *
+ * La funzione fallisce se:
+ * * zip==NULL;
+ * * l'oggetto zip e stato aperto in una modalita non compatibile con l'estrazione di file;
+ * * non e possibile aprire il file all'interno dell'oggetto zip;
+ * * non e possibile creare il file estratto;
+ * * si e rilevato un errore nella copia dei dati (1);
+ * * non e stato possibile chiudere il file all'interno dell'oggetto zip (1);
+ *
+ * (1): prima di uscire dalla funzione cancella il file estratto.
+ */
+bool JlCompress::extractFile(QuaZip* zip, QString fileName, QString fileDest) {
+ // zip: oggetto dove aggiungere il file
+ // filename: nome del file reale
+ // fileincompress: nome del file all'interno del file compresso
+
+ // Controllo l'apertura dello zip
+ if (!zip) return false;
+ if (zip->getMode()!=QuaZip::mdUnzip) return false;
+
+ // Apro il file compresso
+ zip->setCurrentFile(fileName);
+ QuaZipFile inFile(zip);
+ if(!inFile.open(QIODevice::ReadOnly) || inFile.getZipError()!=UNZ_OK) return false;
+
+ // Controllo esistenza cartella file risultato
+ QDir curDir;
+ if (!curDir.mkpath(QFileInfo(fileDest).absolutePath())) {
+ return false;
+ }
+
+ if (QFileInfo(fileDest).isDir())
+ return true;
+
+ // Apro il file risultato
+ QFile outFile;
+ outFile.setFileName(fileDest);
+ if(!outFile.open(QIODevice::WriteOnly)) return false;
+
+ // Copio i dati
+ if (!copyData(inFile, outFile) || inFile.getZipError()!=UNZ_OK) {
+ outFile.close();
+ removeFile(QStringList(fileDest));
+ return false;
+ }
+ outFile.close();
+
+ // Chiudo i file
+ inFile.close();
+ if (inFile.getZipError()!=UNZ_OK) {
+ removeFile(QStringList(fileDest));
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Rimuove i file il cui nome e specificato all'interno di listFile.
+ * Restituisce true se tutti i file sono stati cancellati correttamente, attenzione
+ * perche puo restituire false anche se alcuni file non esistevano e si e tentato
+ * di cancellarli.
+ */
+bool JlCompress::removeFile(QStringList listFile) {
+ bool ret = true;
+ // Per ogni file
+ for (int i=0; i<listFile.count(); i++) {
+ // Lo elimino
+ ret = ret && QFile::remove(listFile.at(i));
+ }
+ return ret;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+/**OK
+ * Comprime il file fileName nel file fileCompressed.
+ * Se la funzione fallisce restituisce false e cancella il file che si e tentato
+ * di creare.
+ *
+ * La funzione fallisce se:
+ * * non si riesce ad aprire l'oggetto zip;
+ * * la compressione del file fallisce;
+ * * non si riesce a chiudere l'oggetto zip;
+ */
+bool JlCompress::compressFile(QString fileCompressed, QString file) {
+ // Creo lo zip
+ QuaZip* zip = new QuaZip(QFileInfo(fileCompressed).absoluteFilePath());
+ QDir().mkpath(QFileInfo(fileCompressed).absolutePath());
+ if(!zip->open(QuaZip::mdCreate)) {
+ delete zip;
+ QFile::remove(fileCompressed);
+ return false;
+ }
+
+ // Aggiungo il file
+ if (!compressFile(zip,file,QFileInfo(file).fileName())) {
+ delete zip;
+ QFile::remove(fileCompressed);
+ return false;
+ }
+
+ // Chiudo il file zip
+ zip->close();
+ if(zip->getZipError()!=0) {
+ delete zip;
+ QFile::remove(fileCompressed);
+ return false;
+ }
+ delete zip;
+
+ return true;
+}
+
+/**OK
+ * Comprime i file specificati in files nel file fileCompressed.
+ * Se la funzione fallisce restituisce false e cancella il file che si e tentato
+ * di creare.
+ *
+ * La funzione fallisce se:
+ * * non si riesce ad aprire l'oggetto zip;
+ * * la compressione di un file fallisce;
+ * * non si riesce a chiudere l'oggetto zip;
+ */
+bool JlCompress::compressFiles(QString fileCompressed, QStringList files) {
+ // Creo lo zip
+ QuaZip* zip = new QuaZip(QFileInfo(fileCompressed).absoluteFilePath());
+ QDir().mkpath(QFileInfo(fileCompressed).absolutePath());
+ if(!zip->open(QuaZip::mdCreate)) {
+ delete zip;
+ QFile::remove(fileCompressed);
+ return false;
+ }
+
+ // Comprimo i file
+ QFileInfo info;
+ Q_FOREACH (QString file, files) {
+ info.setFile(file);
+ if (!info.exists() || !compressFile(zip,file,info.fileName())) {
+ delete zip;
+ QFile::remove(fileCompressed);
+ return false;
+ }
+ }
+
+ // Chiudo il file zip
+ zip->close();
+ if(zip->getZipError()!=0) {
+ delete zip;
+ QFile::remove(fileCompressed);
+ return false;
+ }
+ delete zip;
+
+ return true;
+}
+
+/**OK
+ * Comprime la cartella dir nel file fileCompressed, se recursive e true allora
+ * comprime anche le sotto cartelle.
+ * Se la funzione fallisce restituisce false e cancella il file che si e tentato
+ * di creare.
+ *
+ * La funzione fallisce se:
+ * * non si riesce ad aprire l'oggetto zip;
+ * * la compressione di un file fallisce;
+ * * non si riesce a chiudere l'oggetto zip;
+ */
+bool JlCompress::compressDir(QString fileCompressed, QString dir, bool recursive) {
+ // Creo lo zip
+ QuaZip* zip = new QuaZip(QFileInfo(fileCompressed).absoluteFilePath());
+ QDir().mkpath(QFileInfo(fileCompressed).absolutePath());
+ if(!zip->open(QuaZip::mdCreate)) {
+ delete zip;
+ QFile::remove(fileCompressed);
+ return false;
+ }
+
+ // Aggiungo i file e le sotto cartelle
+ if (!compressSubDir(zip,dir,dir,recursive)) {
+ delete zip;
+ QFile::remove(fileCompressed);
+ return false;
+ }
+
+ // Chiudo il file zip
+ zip->close();
+ if(zip->getZipError()!=0) {
+ delete zip;
+ QFile::remove(fileCompressed);
+ return false;
+ }
+ delete zip;
+
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+/**OK
+ * Estrae il file fileName, contenuto nel file fileCompressed, con il nome fileDest.
+ * Se fileDest = "" allora il file viene estratto con lo stesso nome con cui e
+ * stato compresso.
+ * Se la funzione fallisce cancella il file che si e tentato di estrarre.
+ * Restituisce il nome assoluto del file estratto.
+ *
+ * La funzione fallisce se:
+ * * non si riesce ad aprire l'oggetto zip;
+ * * l'estrazione del file fallisce;
+ * * non si riesce a chiudere l'oggetto zip;
+ */
+QString JlCompress::extractFile(QString fileCompressed, QString fileName, QString fileDest) {
+ // Apro lo zip
+ QuaZip* zip = new QuaZip(QFileInfo(fileCompressed).absoluteFilePath());
+ if(!zip->open(QuaZip::mdUnzip)) {
+ delete zip;
+ return QString();
+ }
+
+ // Estraggo il file
+ if (fileDest.isEmpty()) fileDest = fileName;
+ if (!extractFile(zip,fileName,fileDest)) {
+ delete zip;
+ return QString();
+ }
+
+ // Chiudo il file zip
+ zip->close();
+ if(zip->getZipError()!=0) {
+ removeFile(QStringList(fileDest));
+ return QString();
+ }
+ delete zip;
+
+ return QFileInfo(fileDest).absoluteFilePath();
+}
+
+/**OK
+ * Estrae i file specificati in files, contenuti nel file fileCompressed, nella
+ * cartella dir. La struttura a cartelle del file compresso viene rispettata.
+ * Se dir = "" allora il file viene estratto nella cartella corrente.
+ * Se la funzione fallisce cancella i file che si e tentato di estrarre.
+ * Restituisce i nomi assoluti dei file estratti.
+ *
+ * La funzione fallisce se:
+ * * non si riesce ad aprire l'oggetto zip;
+ * * l'estrazione di un file fallisce;
+ * * non si riesce a chiudere l'oggetto zip;
+ */
+QStringList JlCompress::extractFiles(QString fileCompressed, QStringList files, QString dir) {
+ // Creo lo zip
+ QuaZip* zip = new QuaZip(QFileInfo(fileCompressed).absoluteFilePath());
+ if(!zip->open(QuaZip::mdUnzip)) {
+ delete zip;
+ return QStringList();
+ }
+
+ // Estraggo i file
+ QStringList extracted;
+ for (int i=0; i<files.count(); i++) {
+ QString absPath = QDir(dir).absoluteFilePath(files.at(i));
+ if (!extractFile(zip, files.at(i), absPath)) {
+ delete zip;
+ removeFile(extracted);
+ return QStringList();
+ }
+ extracted.append(absPath);
+ }
+
+ // Chiudo il file zip
+ zip->close();
+ if(zip->getZipError()!=0) {
+ delete zip;
+ removeFile(extracted);
+ return QStringList();
+ }
+ delete zip;
+
+ return extracted;
+}
+
+/**OK
+ * Estrae il file fileCompressed nella cartella dir.
+ * Se dir = "" allora il file viene estratto nella cartella corrente.
+ * Se la funzione fallisce cancella i file che si e tentato di estrarre.
+ * Restituisce i nomi assoluti dei file estratti.
+ *
+ * La funzione fallisce se:
+ * * non si riesce ad aprire l'oggetto zip;
+ * * la compressione di un file fallisce;
+ * * non si riesce a chiudere l'oggetto zip;
+ */
+QStringList JlCompress::extractDir(QString fileCompressed, QString dir) {
+ // Apro lo zip
+ QuaZip* zip = new QuaZip(QFileInfo(fileCompressed).absoluteFilePath());
+ if(!zip->open(QuaZip::mdUnzip)) {
+ delete zip;
+ return QStringList();
+ }
+
+ // Estraggo i file
+ QStringList lst = getFileList(fileCompressed);
+
+ QDir directory(dir);
+ QStringList extracted;
+ for (int i=0; i<lst.count(); i++) {
+ QString absFilePath = directory.absoluteFilePath(lst.at(i));
+ if (!extractFile(zip, lst.at(i), absFilePath)) {
+ delete zip;
+ removeFile(extracted);
+ return QStringList();
+ }
+ extracted.append(absFilePath);
+ }
+
+ // Chiudo il file zip
+ zip->close();
+ if(zip->getZipError()!=0) {
+ delete zip;
+ removeFile(extracted);
+ return QStringList();
+ }
+ delete zip;
+
+ return extracted;
+}
+
+/**OK
+ * Restituisce la lista dei file resenti nel file compresso fileCompressed.
+ * Se la funzione fallisce, restituisce un elenco vuoto.
+ *
+ * La funzione fallisce se:
+ * * non si riesce ad aprire l'oggetto zip;
+ * * la richiesta di informazioni di un file fallisce;
+ * * non si riesce a chiudere l'oggetto zip;
+ */
+QStringList JlCompress::getFileList(QString fileCompressed) {
+ // Apro lo zip
+ QuaZip* zip = new QuaZip(QFileInfo(fileCompressed).absoluteFilePath());
+ if(!zip->open(QuaZip::mdUnzip)) {
+ delete zip;
+ return QStringList();
+ }
+
+ // Estraggo i nomi dei file
+ QStringList lst;
+ QuaZipFileInfo info;
+ for(bool more=zip->goToFirstFile(); more; more=zip->goToNextFile()) {
+ if(!zip->getCurrentFileInfo(&info)) {
+ delete zip;
+ return QStringList();
+ }
+ lst << info.name;
+ //info.name.toLocal8Bit().constData()
+ }
+
+ // Chiudo il file zip
+ zip->close();
+ if(zip->getZipError()!=0) {
+ delete zip;
+ return QStringList();
+ }
+ delete zip;
+
+ return lst;
+}
+
View
114 quazip/JlCompress.h
@@ -0,0 +1,114 @@
+#ifndef JLCOMPRESSFOLDER_H_
+#define JLCOMPRESSFOLDER_H_
+
+#include "quazip.h"
+#include "quazipfile.h"
+#include "quazipfileinfo.h"
+#include <QString>
+#include <QDir>
+#include <QFileInfo>
+#include <QFile>
+
+/// Utility class for typical operations.
+/**
+ This class contains a number of useful static functions to perform
+ simple operations, such as mass ZIP packing or extraction.
+ */
+class QUAZIP_EXPORT JlCompress {
+private:
+ /// Compress a single file.
+ /**
+ \param zip Opened zip to compress the file to.
+ \param fileName The full path to the source file.
+ \param fileDest The full name of the file inside the archive.
+ \return true if success, false otherwise.
+ */
+ static bool compressFile(QuaZip* zip, QString fileName, QString fileDest);
+ /// Compress a subdirectory.
+ /**
+ \param parentZip Opened zip containing the parent directory.
+ \param dir The full path to the directory to pack.
+ \param parentDir The full path to the directory corresponding to
+ the root of the ZIP.
+ \param recursive Whether to pack sub-directories as well or only
+ files.
+ \return true if success, false otherwise.
+ */
+ static bool compressSubDir(QuaZip* parentZip, QString dir, QString parentDir, bool recursive = true);
+ /// Extract a single file.
+ /**
+ \param zip The opened zip archive to extract from.
+ \param fileName The full name of the file to extract.
+ \param fileDest The full path to the destination file.
+ \return true if success, false otherwise.
+ */
+ static bool extractFile(QuaZip* zip, QString fileName, QString fileDest);
+ /// Remove some files.
+ /**
+ \param listFile The list of files to remove.
+ \return true if success, false otherwise.
+ */
+ static bool removeFile(QStringList listFile);
+
+public:
+ /// Compress a single file.
+ /**
+ \param fileCompressed The name of the archive.
+ \param file The file to compress.
+ \return true if success, false otherwise.
+ */
+ static bool compressFile(QString fileCompressed, QString file);
+ /// Compress a list of files.
+ /**
+ \param fileCompressed The name of the archive.
+ \param files The file list to compress.
+ \return true if success, false otherwise.
+ */
+ static bool compressFiles(QString fileCompressed, QStringList files);
+ /// Compress a whole directory.
+ /**
+ \param fileCompressed The name of the archive.
+ \param dir The directory to compress.
+ \param recursive Whether to pack the subdirectories as well, or
+ just regular files.
+ \return true if success, false otherwise.
+ */
+ static bool compressDir(QString fileCompressed, QString dir = QString(), bool recursive = true);
+
+public:
+ /// Extract a single file.
+ /**
+ \param fileCompressed The name of the archive.
+ \param fileName The file to extract.
+ \param fileDest The destination file, assumed to be identical to
+ \a file if left empty.
+ \return The list of the full paths of the files extracted, empty on failure.
+ */
+ static QString extractFile(QString fileCompressed, QString fileName, QString fileDest = QString());
+ /// Extract a list of files.
+ /**
+ \param fileCompressed The name of the archive.
+ \param files The file list to extract.
+ \param dir The directory to put the files to, the current
+ directory if left empty.
+ \return The list of the full paths of the files extracted, empty on failure.
+ */
+ static QStringList extractFiles(QString fileCompressed, QStringList files, QString dir = QString());
+ /// Extract a whole archive.
+ /**
+ \param fileCompressed The name of the archive.
+ \param dir The directory to extract to, the current directory if
+ left empty.
+ \return The list of the full paths of the files extracted, empty on failure.
+ */
+ static QStringList extractDir(QString fileCompressed, QString dir = QString());
+ /// Get the file list.
+ /**
+ \return The list of the files in the archive, or, more precisely, the
+ list of the entries, including both files and directories if they
+ are present separately.
+ */
+ static QStringList getFileList(QString fileCompressed);
+};
+
+#endif /* JLCOMPRESSFOLDER_H_ */
View
135 quazip/crypt.h
@@ -0,0 +1,135 @@
+/* crypt.h -- base code for crypt/uncrypt ZIPfile
+
+
+ Version 1.01e, February 12th, 2005
+
+ Copyright (C) 1998-2005 Gilles Vollant
+
+ This code is a modified version of crypting code in Infozip distribution
+
+ The encryption/decryption parts of this source code (as opposed to the
+ non-echoing password parts) were originally written in Europe. The
+ whole source package can be freely distributed, including from the USA.
+ (Prior to January 2000, re-export from the US was a violation of US law.)
+
+ This encryption code is a direct transcription of the algorithm from
+ Roger Schlafly, described by Phil Katz in the file appnote.txt. This
+ file (appnote.txt) is distributed with the PKZIP program (even in the
+ version without encryption capabilities).
+
+ If you don't need crypting in your application, just define symbols
+ NOCRYPT and NOUNCRYPT.
+
+ This code support the "Traditional PKWARE Encryption".
+
+ The new AES encryption added on Zip format by Winzip (see the page
+ http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong
+ Encryption is not supported.
+*/
+
+#include "quazip_global.h"
+
+#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8))
+
+/***********************************************************************
+ * Return the next byte in the pseudo-random sequence
+ */
+static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab UNUSED)
+{
+ //(void) pcrc_32_tab; /* avoid "unused parameter" warning */
+ unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an
+ * unpredictable manner on 16-bit systems; not a problem
+ * with any known compiler so far, though */
+
+ temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2;
+ return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
+}
+
+/***********************************************************************
+ * Update the encryption keys with the next byte of plain text
+ */
+static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c)
+{
+ (*(pkeys+0)) = CRC32((*(pkeys+0)), c);
+ (*(pkeys+1)) += (*(pkeys+0)) & 0xff;
+ (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1;
+ {
+ register int keyshift = (int)((*(pkeys+1)) >> 24);
+ (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift);
+ }
+ return c;
+}
+
+
+/***********************************************************************
+ * Initialize the encryption keys and the random header according to
+ * the given password.
+ */
+static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab)
+{
+ *(pkeys+0) = 305419896L;
+ *(pkeys+1) = 591751049L;
+ *(pkeys+2) = 878082192L;
+ while (*passwd != '\0') {
+ update_keys(pkeys,pcrc_32_tab,(int)*passwd);
+ passwd++;
+ }
+}
+
+#define zdecode(pkeys,pcrc_32_tab,c) \
+ (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab)))
+
+#define zencode(pkeys,pcrc_32_tab,c,t) \
+ (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c))
+
+#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED
+
+#define RAND_HEAD_LEN 12
+ /* "last resort" source for second part of crypt seed pattern */
+# ifndef ZCR_SEED2
+# define ZCR_SEED2 3141592654UL /* use PI as default pattern */
+# endif
+
+static int crypthead(passwd, buf, bufSize, pkeys, pcrc_32_tab, crcForCrypting)
+ const char *passwd; /* password string */
+ unsigned char *buf; /* where to write header */
+ int bufSize;
+ unsigned long* pkeys;
+ const unsigned long* pcrc_32_tab;
+ unsigned long crcForCrypting;
+{
+ int n; /* index in random header */
+ int t; /* temporary */
+ int c; /* random byte */
+ unsigned char header[RAND_HEAD_LEN-2]; /* random header */
+ static unsigned calls = 0; /* ensure different random header each time */
+
+ if (bufSize<RAND_HEAD_LEN)
+ return 0;
+
+ /* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the
+ * output of rand() to get less predictability, since rand() is
+ * often poorly implemented.
+ */
+ if (++calls == 1)
+ {
+ srand((unsigned)(time(NULL) ^ ZCR_SEED2));
+ }
+ init_keys(passwd, pkeys, pcrc_32_tab);
+ for (n = 0; n < RAND_HEAD_LEN-2; n++)
+ {
+ c = (rand() >> 7) & 0xff;
+ header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t);
+ }
+ /* Encrypt random header (last two bytes is high word of crc) */
+ init_keys(passwd, pkeys, pcrc_32_tab);
+ for (n = 0; n < RAND_HEAD_LEN-2; n++)
+ {
+ buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t);
+ }
+ buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t);
+ buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t);
+ return n;
+}
+
+#endif
View
77 quazip/ioapi.h
@@ -0,0 +1,77 @@
+/* ioapi.h -- IO base function header for compress/uncompress .zip
+ files using zlib + zip or unzip API
+
+ Version 1.01e, February 12th, 2005
+
+ Copyright (C) 1998-2005 Gilles Vollant
+
+ Modified by Sergey A. Tachenov to integrate with Qt.
+*/
+
+#ifndef _ZLIBIOAPI_H
+#define _ZLIBIOAPI_H
+
+
+#define ZLIB_FILEFUNC_SEEK_CUR (1)
+#define ZLIB_FILEFUNC_SEEK_END (2)
+#define ZLIB_FILEFUNC_SEEK_SET (0)
+
+#define ZLIB_FILEFUNC_MODE_READ (1)
+#define ZLIB_FILEFUNC_MODE_WRITE (2)
+#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3)
+
+#define ZLIB_FILEFUNC_MODE_EXISTING (4)
+#define ZLIB_FILEFUNC_MODE_CREATE (8)
+
+
+#ifndef ZCALLBACK
+
+#if (defined(WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK)
+#define ZCALLBACK CALLBACK
+#else
+#define ZCALLBACK
+#endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, voidpf file, int mode));
+typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size));
+typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size));
+typedef uLong (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream));
+typedef int (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin));
+typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream));
+typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream));
+
+typedef struct zlib_filefunc_def_s
+{
+ open_file_func zopen_file;
+ read_file_func zread_file;
+ write_file_func zwrite_file;
+ tell_file_func ztell_file;
+ seek_file_func zseek_file;
+ close_file_func zclose_file;
+ testerror_file_func zerror_file;
+ voidpf opaque;
+} zlib_filefunc_def;
+
+
+
+void fill_qiodevice_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));
+
+#define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size))
+#define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size))
+#define ZTELL(filefunc,filestream) ((*((filefunc).ztell_file))((filefunc).opaque,filestream))
+#define ZSEEK(filefunc,filestream,pos,mode) ((*((filefunc).zseek_file))((filefunc).opaque,filestream,pos,mode))
+#define ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream))
+#define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream))
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
View
145 quazip/qioapi.cpp
@@ -0,0 +1,145 @@
+/* ioapi.c -- IO base function header for compress/uncompress .zip
+ files using zlib + zip or unzip API
+
+ Version 1.01e, February 12th, 2005
+
+ Copyright (C) 1998-2005 Gilles Vollant
+
+ Modified by Sergey A. Tachenov to integrate with Qt.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "zlib/zlib.h"
+#include "ioapi.h"
+#include "quazip_global.h"
+#include <QIODevice>
+
+
+/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
+
+#ifndef SEEK_CUR
+#define SEEK_CUR 1
+#endif
+
+#ifndef SEEK_END
+#define SEEK_END 2
+#endif
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#endif
+
+voidpf ZCALLBACK qiodevice_open_file_func (
+ voidpf opaque UNUSED,
+ voidpf file,
+ int mode)
+{
+ QIODevice *iodevice = reinterpret_cast<QIODevice*>(file);
+ if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
+ iodevice->open(QIODevice::ReadOnly);
+ else
+ if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
+ iodevice->open(QIODevice::ReadWrite);
+ else
+ if (mode & ZLIB_FILEFUNC_MODE_CREATE)
+ iodevice->open(QIODevice::WriteOnly);
+
+ if (iodevice->isOpen()) {
+ if (iodevice->isSequential()) {
+ iodevice->close();
+ return NULL;
+ } else {
+ return iodevice;
+ }
+ } else
+ return NULL;
+}
+
+
+uLong ZCALLBACK qiodevice_read_file_func (
+ voidpf opaque UNUSED,
+ voidpf stream,
+ void* buf,
+ uLong size)
+{
+ uLong ret;
+ ret = (uLong)((QIODevice*)stream)->read((char*)buf,size);
+ return ret;
+}
+
+
+uLong ZCALLBACK qiodevice_write_file_func (
+ voidpf opaque UNUSED,
+ voidpf stream,
+ const void* buf,
+ uLong size)
+{
+ uLong ret;
+ ret = (uLong)((QIODevice*)stream)->write((char*)buf,size);
+ return ret;
+}
+
+uLong ZCALLBACK qiodevice_tell_file_func (
+ voidpf opaque UNUSED,
+ voidpf stream)
+{
+ uLong ret;
+ ret = ((QIODevice*)stream)->pos();
+ return ret;
+}
+
+int ZCALLBACK qiodevice_seek_file_func (
+ voidpf opaque UNUSED,
+ voidpf stream,
+ uLong offset,
+ int origin)
+{
+ uLong qiodevice_seek_result=0;
+ int ret;
+ switch (origin)
+ {
+ case ZLIB_FILEFUNC_SEEK_CUR :
+ qiodevice_seek_result = ((QIODevice*)stream)->pos() + offset;
+ break;
+ case ZLIB_FILEFUNC_SEEK_END :
+ qiodevice_seek_result = ((QIODevice*)stream)->size() - offset;
+ break;
+ case ZLIB_FILEFUNC_SEEK_SET :
+ qiodevice_seek_result = offset;
+ break;
+ default: return -1;
+ }
+ ret = !((QIODevice*)stream)->seek(qiodevice_seek_result);
+ return ret;
+}
+
+int ZCALLBACK qiodevice_close_file_func (
+ voidpf opaque UNUSED,
+ voidpf stream)
+{
+ ((QIODevice*)stream)->close();
+ return 0;
+}
+
+int ZCALLBACK qiodevice_error_file_func (
+ voidpf opaque UNUSED,
+ voidpf stream)
+{
+ return !((QIODevice*)stream)->errorString().isEmpty();
+}
+
+void fill_qiodevice_filefunc (
+ zlib_filefunc_def* pzlib_filefunc_def)
+{
+ pzlib_filefunc_def->zopen_file = qiodevice_open_file_func;
+ pzlib_filefunc_def->zread_file = qiodevice_read_file_func;
+ pzlib_filefunc_def->zwrite_file = qiodevice_write_file_func;
+ pzlib_filefunc_def->ztell_file = qiodevice_tell_file_func;
+ pzlib_filefunc_def->zseek_file = qiodevice_seek_file_func;
+ pzlib_filefunc_def->zclose_file = qiodevice_close_file_func;
+ pzlib_filefunc_def->zerror_file = qiodevice_error_file_func;
+ pzlib_filefunc_def->opaque = NULL;
+}
View
28 quazip/quaadler32.cpp
@@ -0,0 +1,28 @@
+#include "quaadler32.h"
+
+#include "zlib/zlib.h"
+
+QuaAdler32::QuaAdler32()
+{
+ reset();
+}
+
+quint32 QuaAdler32::calculate(const QByteArray &data)
+{
+ return adler32( adler32(0L, Z_NULL, 0), (const Bytef*)data.data(), data.size() );
+}
+
+void QuaAdler32::reset()
+{
+ checksum = adler32(0L, Z_NULL, 0);
+}
+
+void QuaAdler32::update(const QByteArray &buf)
+{
+ checksum = adler32( checksum, (const Bytef*)buf.data(), buf.size() );
+}
+
+quint32 QuaAdler32::value()
+{
+ return checksum;
+}
View
29 quazip/quaadler32.h
@@ -0,0 +1,29 @@
+#ifndef QUAADLER32_H
+#define QUAADLER32_H
+
+#include <QByteArray>
+
+#include "quachecksum32.h"
+
+/// Adler32 checksum
+/** \class QuaAdler32 quaadler32.h <quazip/quaadler32.h>
+ * This class wrappers the adler32 function with the QuaChecksum32 interface.
+ * See QuaChecksum32 for more info.
+ */
+class QUAZIP_EXPORT QuaAdler32 : public QuaChecksum32
+{
+
+public:
+ QuaAdler32();
+
+ quint32 calculate(const QByteArray &data);
+
+ void reset();
+ void update(const QByteArray &buf);
+ quint32 value();
+
+private:
+ quint32 checksum;
+};
+
+#endif //QUAADLER32_H
View
54 quazip/quachecksum32.h
@@ -0,0 +1,54 @@
+#ifndef QUACHECKSUM32_H
+#define QUACHECKSUM32_H
+
+#include <QByteArray>
+#include "quazip_global.h"
+
+/// Checksum interface.
+/** \class QuaChecksum32 quachecksum32.h <quazip/quachecksum32.h>
+ * This is an interface for 32 bit checksums.
+ * Classes implementing this interface can calcunate a certin
+ * checksum in a single step:
+ * \code
+ * QChecksum32 *crc32 = new QuaCrc32();
+ * rasoult = crc32->calculate(data);
+ * \endcode
+ * or by streaming the data:
+ * \code
+ * QChecksum32 *crc32 = new QuaCrc32();
+ * while(!fileA.atEnd())
+ * crc32->update(fileA.read(bufSize));
+ * resoultA = crc32->value();
+ * crc32->reset();
+ * while(!fileB.atEnd())
+ * crc32->update(fileB.read(bufSize));
+ * resoultB = crc32->value();
+ * \endcode
+ */
+class QUAZIP_EXPORT QuaChecksum32
+{
+
+public:
+ ///Calculates the checksum for data.
+ /** \a data source data
+ * \return data checksum
+ *
+ * This function has no efect on the value returned by value().
+ */
+ virtual quint32 calculate(const QByteArray &data) = 0;
+
+ ///Resets the calculation on a checksun for a stream.
+ virtual void reset() = 0;
+
+ ///Updates the calculated checksum for the stream
+ /** \a buf next portion of data from the stream
+ */
+ virtual void update(const QByteArray &buf) = 0;
+
+ ///Value of the checksum calculated for the stream passed throw update().
+ /** \return checksum
+ */
+ virtual quint32 value() = 0;
+};
+
+#endif //QUACHECKSUM32_H
View
28 quazip/quacrc32.cpp
@@ -0,0 +1,28 @@
+#include "quacrc32.h"
+
+#include "zlib/zlib.h"
+
+QuaCrc32::QuaCrc32()
+{
+ reset();
+}
+
+quint32 QuaCrc32::calculate(const QByteArray &data)
+{
+ return crc32( crc32(0L, Z_NULL, 0), (const Bytef*)data.data(), data.size() );
+}
+
+void QuaCrc32::reset()
+{
+ checksum = crc32(0L, Z_NULL, 0);
+}
+
+void QuaCrc32::update(const QByteArray &buf)
+{
+ checksum = crc32( checksum, (const Bytef*)buf.data(), buf.size() );
+}
+
+quint32 QuaCrc32::value()
+{
+ return checksum;
+}
View
26 quazip/quacrc32.h
@@ -0,0 +1,26 @@
+#ifndef QUACRC32_H
+#define QUACRC32_H
+
+#include "quachecksum32.h"
+
+///CRC32 checksum
+/** \class QuaCrc32 quacrc32.h <quazip/quacrc32.h>
+* This class wrappers the crc32 function with the QuaChecksum32 interface.
+* See QuaChecksum32 for more info.
+*/
+class QUAZIP_EXPORT QuaCrc32 : public QuaChecksum32 {
+
+public:
+ QuaCrc32();
+
+ quint32 calculate(const QByteArray &data);
+
+ void reset();
+ void update(const QByteArray &buf);
+ quint32 value();
+
+private:
+ quint32 checksum;
+};
+
+#endif //QUACRC32_H
View
546 quazip/quazip.cpp
@@ -0,0 +1,546 @@
+/*
+Copyright (C) 2005-2011 Sergey A. Tachenov
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software Foundation,
+Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+See COPYING file for the full LGPL text.
+
+Original ZIP package is copyrighted by Gilles Vollant, see
+quazip/(un)zip.h files for details, basically it's zlib license.
+ **/
+
+#include <QFile>
+#include <QFlags>
+
+#include "quazip.h"
+
+/// All the internal stuff for the QuaZip class.
+/**
+ \internal
+
+ This class keeps all the private stuff for the QuaZip class so it can
+ be changed without breaking binary compatibility, according to the
+ Pimpl idiom.
+ */
+class QuaZipPrivate {
+ friend class QuaZip;
+ private:
+ /// The pointer to the corresponding QuaZip instance.
+ QuaZip *q;
+ /// The codec for file names.
+ QTextCodec *fileNameCodec;
+ /// The codec for comments.
+ QTextCodec *commentCodec;
+ /// The archive file name.
+ QString zipName;
+ /// The device to access the archive.
+ QIODevice *ioDevice;
+ /// The global comment.
+ QString comment;
+ /// The open mode.
+ QuaZip::Mode mode;
+ union {
+ /// The internal handle for UNZIP modes.
+ unzFile unzFile_f;
+ /// The internal handle for ZIP modes.
+ zipFile zipFile_f;
+ };
+ /// Whether a current file is set.
+ bool hasCurrentFile_f;
+ /// The last error.
+ int zipError;
+ /// Whether \ref QuaZip::setDataDescriptorWritingEnabled() "the data descriptor writing mode" is enabled.
+ bool dataDescriptorWritingEnabled;
+ /// The constructor for the corresponding QuaZip constructor.
+ inline QuaZipPrivate(QuaZip *q):
+ q(q),
+ fileNameCodec(QTextCodec::codecForLocale()),
+ commentCodec(QTextCodec::codecForLocale()),
+ ioDevice(NULL),
+ mode(QuaZip::mdNotOpen),
+ hasCurrentFile_f(false),
+ zipError(UNZ_OK),
+ dataDescriptorWritingEnabled(true) {}
+ /// The constructor for the corresponding QuaZip constructor.
+ inline QuaZipPrivate(QuaZip *q, const QString &zipName):
+ q(q),
+ fileNameCodec(QTextCodec::codecForLocale()),
+ commentCodec(QTextCodec::codecForLocale()),
+ zipName(zipName),
+ ioDevice(NULL),
+ mode(QuaZip::mdNotOpen),
+ hasCurrentFile_f(false),
+ zipError(UNZ_OK),
+ dataDescriptorWritingEnabled(true) {}
+ /// The constructor for the corresponding QuaZip constructor.
+ inline QuaZipPrivate(QuaZip *q, QIODevice *ioDevice):
+ q(q),
+ fileNameCodec(QTextCodec::codecForLocale()),
+ commentCodec(QTextCodec::codecForLocale()),
+ ioDevice(ioDevice),
+ mode(QuaZip::mdNotOpen),
+ hasCurrentFile_f(false),
+ zipError(UNZ_OK),
+ dataDescriptorWritingEnabled(true) {}
+ /// Returns either a list of file names or a list of QuaZipFileInfo.
+ template<typename TFileInfo>
+ bool getFileInfoList(QList<TFileInfo> *result) const;
+};
+
+QuaZip::QuaZip():
+ p(new QuaZipPrivate(this))
+{
+}
+
+QuaZip::QuaZip(const QString& zipName):
+ p(new QuaZipPrivate(this, zipName))
+{
+}
+
+QuaZip::QuaZip(QIODevice *ioDevice):
+ p(new QuaZipPrivate(this, ioDevice))
+{
+}
+
+QuaZip::~QuaZip()
+{
+ if(isOpen())
+ close();
+ delete p;
+}
+
+bool QuaZip::open(Mode mode, zlib_filefunc_def* ioApi)
+{
+ p->zipError=UNZ_OK;
+ if(isOpen()) {
+ qWarning("QuaZip::open(): ZIP already opened");
+ return false;
+ }
+ QIODevice *ioDevice = p->ioDevice;
+ if (ioDevice == NULL) {
+ if (p->zipName.isEmpty()) {
+ qWarning("QuaZip::open(): set either ZIP file name or IO device first");
+ return false;
+ } else {
+ ioDevice = new QFile(p->zipName);
+ }
+ }
+ switch(mode) {
+ case mdUnzip:
+ p->unzFile_f=unzOpen2(ioDevice, ioApi);
+ if(p->unzFile_f!=NULL) {
+ p->mode=mode;
+ p->ioDevice = ioDevice;
+ return true;
+ } else {
+ p->zipError=UNZ_OPENERROR;
+ if (!p->zipName.isEmpty())
+ delete ioDevice;
+ return false;
+ }
+ case mdCreate:
+ case mdAppend:
+ case mdAdd:
+ p->zipFile_f=zipOpen2(ioDevice,
+ mode==mdCreate?APPEND_STATUS_CREATE:
+ mode==mdAppend?APPEND_STATUS_CREATEAFTER:
+ APPEND_STATUS_ADDINZIP,
+ NULL,
+ ioApi);
+ if(p->zipFile_f!=NULL) {
+ p->mode=mode;
+ p->ioDevice = ioDevice;
+ return true;
+ } else {
+ p->zipError=UNZ_OPENERROR;
+ if (!p->zipName.isEmpty())
+ delete ioDevice;
+ return false;
+ }
+ default:
+ qWarning("QuaZip::open(): unknown mode: %d", (int)mode);
+ if (!p->zipName.isEmpty())
+ delete ioDevice;
+ return false;
+ break;
+ }
+}
+
+void QuaZip::close()
+{
+ p->zipError=UNZ_OK;
+ switch(p->mode) {
+ case mdNotOpen:
+ qWarning("QuaZip::close(): ZIP is not open");
+ return;
+ case mdUnzip:
+ p->zipError=unzClose(p->unzFile_f);
+ break;
+ case mdCreate:
+ case mdAppend:
+ case mdAdd:
+ p->zipError=zipClose(p->zipFile_f, p->commentCodec->fromUnicode(p->comment).constData());
+ break;
+ default:
+ qWarning("QuaZip::close(): unknown mode: %d", (int)p->mode);
+ return;
+ }
+ // opened by name, need to delete the internal IO device
+ if (!p->zipName.isEmpty()) {
+ delete p->ioDevice;
+ p->ioDevice = NULL;
+ }
+ if(p->zipError==UNZ_OK)
+ p->mode=mdNotOpen;
+}
+
+void QuaZip::setZipName(const QString& zipName)
+{
+ if(isOpen()) {
+ qWarning("QuaZip::setZipName(): ZIP is already open!");
+ return;
+ }
+ p->zipName=zipName;
+ p->ioDevice = NULL;
+}
+
+void QuaZip::setIoDevice(QIODevice *ioDevice)
+{
+ if(isOpen()) {
+ qWarning("QuaZip::setIoDevice(): ZIP is already open!");
+ return;
+ }
+ p->ioDevice = ioDevice;
+ p->zipName = QString();
+}
+
+int QuaZip::getEntriesCount()const
+{
+ QuaZip *fakeThis=(QuaZip*)this; // non-const
+ fakeThis->p->zipError=UNZ_OK;
+ if(p->mode!=mdUnzip) {
+ qWarning("QuaZip::getEntriesCount(): ZIP is not open in mdUnzip mode");
+ return -1;
+ }
+ unz_global_info globalInfo;
+ if((fakeThis->p->zipError=unzGetGlobalInfo(p->unzFile_f, &globalInfo))!=UNZ_OK)
+ return p->zipError;
+ return (int)globalInfo.number_entry;
+}
+
+QString QuaZip::getComment()const
+{
+ QuaZip *fakeThis=(QuaZip*)this; // non-const
+ fakeThis->p->zipError=UNZ_OK;
+ if(p->mode!=mdUnzip) {
+ qWarning("QuaZip::getComment(): ZIP is not open in mdUnzip mode");
+ return QString();
+ }
+ unz_global_info globalInfo;
+ QByteArray comment;
+ if((fakeThis->p->zipError=unzGetGlobalInfo(p->unzFile_f, &globalInfo))!=UNZ_OK)
+ return QString();
+ comment.resize(globalInfo.size_comment);
+ if((fakeThis->p->zipError=unzGetGlobalComment(p->unzFile_f, comment.data(), comment.size())) < 0)
+ return QString();
+ fakeThis->p->zipError = UNZ_OK;
+ return p->commentCodec->toUnicode(comment);
+}
+
+bool QuaZip::setCurrentFile(const QString& fileName, CaseSensitivity cs)
+{
+ p->zipError=UNZ_OK;
+ if(p->mode!=mdUnzip) {
+ qWarning("QuaZip::setCurrentFile(): ZIP is not open in mdUnzip mode");
+ return false;
+ }
+ if(fileName.isEmpty()) {
+ p->hasCurrentFile_f=false;
+ return true;
+ }
+ // Unicode-aware reimplementation of the unzLocateFile function
+ if(p->unzFile_f==NULL) {
+ p->zipError=UNZ_PARAMERROR;
+ return false;
+ }
+ if(fileName.length()>MAX_FILE_NAME_LENGTH) {
+ p->zipError=UNZ_PARAMERROR;
+ return false;
+ }
+ bool sens;
+ if(cs==csDefault) {
+#ifdef Q_WS_WIN
+ sens=false;
+#else
+ sens=true;
+#endif
+ } else sens=cs==csSensitive;
+ QString lower, current;
+ if(!sens) lower=fileName.toLower();
+ p->hasCurrentFile_f=false;
+ for(bool more=goToFirstFile(); more; more=goToNextFile()) {
+ current=getCurrentFileName();
+ if(current.isEmpty()) return false;
+ if(sens) {
+ if(current==fileName) break;
+ } else {
+ if(current.toLower()==lower) break;
+ }
+ }
+ return p->hasCurrentFile_f;
+}
+
+bool QuaZip::goToFirstFile()
+{
+ p->zipError=UNZ_OK;
+ if(p->mode!=mdUnzip) {
+ qWarning("QuaZip::goToFirstFile(): ZIP is not open in mdUnzip mode");
+ return false;
+ }
+ p->zipError=unzGoToFirstFile(p->unzFile_f);
+ p->hasCurrentFile_f=p->zipError==UNZ_OK;
+ return p->hasCurrentFile_f;
+}
+
+bool QuaZip::goToNextFile()
+{
+ p->zipError=UNZ_OK;
+ if(p->mode!=mdUnzip) {
+ qWarning("QuaZip::goToFirstFile(): ZIP is not open in mdUnzip mode");
+ return false;
+ }
+ p->zipError=unzGoToNextFile(p->unzFile_f);
+ p->hasCurrentFile_f=p->zipError==UNZ_OK;
+ if(p->zipError==UNZ_END_OF_LIST_OF_FILE)
+ p->zipError=UNZ_OK;
+ return p->hasCurrentFile_f;
+}
+
+bool QuaZip::getCurrentFileInfo(QuaZipFileInfo *info)const
+{
+ QuaZip *fakeThis=(QuaZip*)this; // non-const
+ fakeThis->p->zipError=UNZ_OK;
+ if(p->mode!=mdUnzip) {
+ qWarning("QuaZip::getCurrentFileInfo(): ZIP is not open in mdUnzip mode");
+ return false;
+ }
+ unz_file_info info_z;
+ QByteArray fileName;
+ QByteArray extra;
+ QByteArray comment;
+ if(info==NULL) return false;
+ if(!isOpen()||!hasCurrentFile()) return false;
+ if((fakeThis->p->zipError=unzGetCurrentFileInfo(p->unzFile_f, &info_z, NULL, 0, NULL, 0, NULL, 0))!=UNZ_OK)
+ return false;
+ fileName.resize(info_z.size_filename);
+ extra.resize(info_z.size_file_extra);
+ comment.resize(info_z.size_file_comment);
+ if((fakeThis->p->zipError=unzGetCurrentFileInfo(p->unzFile_f, NULL,
+ fileName.data(), fileName.size(),
+ extra.data(), extra.size(),
+ comment.data(), comment.size()))!=UNZ_OK)
+ return false;
+ info->versionCreated=info_z.version;
+ info->versionNeeded=info_z.version_needed;
+ info->flags=info_z.flag;
+ info->method=info_z.compression_method;
+ info->crc=info_z.crc;
+ info->compressedSize=info_z.compressed_size;
+ info->uncompressedSize=info_z.uncompressed_size;
+ info->diskNumberStart=info_z.disk_num_start;
+ info->internalAttr=info_z.internal_fa;
+ info->externalAttr=info_z.external_fa;
+ info->name=p->fileNameCodec->toUnicode(fileName);
+ info->comment=p->commentCodec->toUnicode(comment);
+ info->extra=extra;
+ info->dateTime=QDateTime(
+ QDate(info_z.tmu_date.tm_year, info_z.tmu_date.tm_mon+1, info_z.tmu_date.tm_mday),
+ QTime(info_z.tmu_date.tm_hour, info_z.tmu_date.tm_min, info_z.tmu_date.tm_sec));
+ return true;
+}
+
+QString QuaZip::getCurrentFileName()const
+{
+ QuaZip *fakeThis=(QuaZip*)this; // non-const
+ fakeThis->p->zipError=UNZ_OK;
+ if(p->mode!=mdUnzip) {
+ qWarning("QuaZip::getCurrentFileName(): ZIP is not open in mdUnzip mode");
+ return QString();
+ }
+ if(!isOpen()||!hasCurrentFile()) return QString();
+ QByteArray fileName(MAX_FILE_NAME_LENGTH, 0);
+ if((fakeThis->p->zipError=unzGetCurrentFileInfo(p->unzFile_f, NULL, fileName.data(), fileName.size(),
+ NULL, 0, NULL, 0))!=UNZ_OK)
+ return QString();
+ return p->fileNameCodec->toUnicode(fileName.constData());
+}
+
+void QuaZip::setFileNameCodec(QTextCodec *fileNameCodec)
+{
+ p->fileNameCodec=fileNameCodec;
+}
+
+void QuaZip::setFileNameCodec(const char *fileNameCodecName)
+{
+ p->fileNameCodec=QTextCodec::codecForName(fileNameCodecName);
+}
+
+QTextCodec *QuaZip::getFileNameCodec()const
+{
+ return p->fileNameCodec;
+}
+
+void QuaZip::setCommentCodec(QTextCodec *commentCodec)
+{
+ p->commentCodec=commentCodec;
+}
+
+void QuaZip::setCommentCodec(const char *commentCodecName)
+{
+ p->commentCodec=QTextCodec::codecForName(commentCodecName);
+}
+
+QTextCodec *QuaZip::getCommentCodec()const
+{
+ return p->commentCodec;
+}
+
+QString QuaZip::getZipName() const
+{
+ return p->zipName;
+}
+
+QIODevice *QuaZip::getIoDevice() const
+{
+ if (!p->zipName.isEmpty()) // opened by name, using an internal QIODevice
+ return NULL;
+ return p->ioDevice;
+}
+
+QuaZip::Mode QuaZip::getMode()const
+{
+ return p->mode;
+}
+
+bool QuaZip::isOpen()const
+{
+ return p->mode!=mdNotOpen;
+}
+
+int QuaZip::getZipError() const
+{
+ return p->zipError;
+}
+
+void QuaZip::setComment(const QString& comment)
+{
+ p->comment=comment;
+}
+
+bool QuaZip::hasCurrentFile()const
+{
+ return p->hasCurrentFile_f;
+}
+
+unzFile QuaZip::getUnzFile()
+{
+ return p->unzFile_f;
+}
+
+zipFile QuaZip::getZipFile()
+{
+ return p->zipFile_f;
+}
+
+void QuaZip::setDataDescriptorWritingEnabled(bool enabled)
+{
+ p->dataDescriptorWritingEnabled = enabled;
+}
+
+bool QuaZip::isDataDescriptorWritingEnabled() const
+{
+ return p->dataDescriptorWritingEnabled;
+}
+
+template<typename TFileInfo>
+static TFileInfo getFileInfo(QuaZip *zip, bool *ok);
+
+template<>
+QuaZipFileInfo getFileInfo(QuaZip *zip, bool *ok)
+{
+ QuaZipFileInfo info;
+ *ok = zip->getCurrentFileInfo(&info);
+ return info;
+}
+
+template<>
+QString getFileInfo(QuaZip *zip, bool *ok)
+{
+ QString name = zip->getCurrentFileName();
+ *ok = !name.isEmpty();
+ return name;
+}
+
+template<typename TFileInfo>
+bool QuaZipPrivate::getFileInfoList(QList<TFileInfo> *result) const
+{
+ QuaZipPrivate *fakeThis=const_cast<QuaZipPrivate*>(this);
+ fakeThis->zipError=UNZ_OK;
+ if (mode!=QuaZip::mdUnzip) {
+ qWarning("QuaZip::getFileNameList/getFileInfoList(): "
+ "ZIP is not open in mdUnzip mode");
+ return false;
+ }
+ QString currentFile;
+ if (q->hasCurrentFile()) {
+ currentFile = q->getCurrentFileName();
+ }
+ if (q->goToFirstFile()) {
+ do {
+ bool ok;
+ result->append(getFileInfo<TFileInfo>(q, &ok));
+ if (!ok)
+ return false;
+ } while (q->goToNextFile());
+ }
+ if (zipError != UNZ_OK)
+ return false;
+ if (currentFile.isEmpty()) {
+ if (!q->setCurrentFile(currentFile))
+ return false;
+ } else {
+ if (!q->goToFirstFile())
+ return false;
+ }
+ return true;
+}
+
+QStringList QuaZip::getFileNameList() const
+{
+ QStringList list;
+ if (p->getFileInfoList(&list))
+ return list;
+ else
+ return QStringList();
+}
+
+QList<QuaZipFileInfo> QuaZip::getFileInfoList() const
+{
+ QList<QuaZipFileInfo> list;
+ if (p->getFileInfoList(&list))
+ return list;
+ else
+ return QList<QuaZipFileInfo>();
+}
View
406 quazip/quazip.h
@@ -0,0 +1,406 @@
+#ifndef QUA_ZIP_H
+#define QUA_ZIP_H
+
+/*
+Copyright (C) 2005-2011 Sergey A. Tachenov
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software Foundation,
+Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+See COPYING file for the full LGPL text.
+
+Original ZIP package is copyrighted by Gilles Vollant, see
+quazip/(un)zip.h files for details, basically it's zlib license.
+ **/
+
+#include <QString>
+#include <QStringList>
+#include <QTextCodec>
+
+#include "zip.h"
+#include "unzip.h"
+
+#include "quazip_global.h"
+#include "quazipfileinfo.h"
+
+// just in case it will be defined in the later versions of the ZIP/UNZIP
+#ifndef UNZ_OPENERROR
+// define additional error code
+#define UNZ_OPENERROR -1000
+#endif
+
+class QuaZipPrivate;
+
+/// ZIP archive.
+/** \class QuaZip quazip.h <quazip/quazip.h>
+ * This class implements basic interface to the ZIP archive. It can be
+ * used to read table contents of the ZIP archive and retreiving
+ * information about the files inside it.
+ *
+ * You can also use this class to open files inside archive by passing
+ * pointer to the instance of this class to the constructor of the
+ * QuaZipFile class. But see QuaZipFile::QuaZipFile(QuaZip*, QObject*)
+ * for the possible pitfalls.
+ *
+ * This class is indended to provide interface to the ZIP subpackage of
+ * the ZIP/UNZIP package as well as to the UNZIP subpackage. But
+ * currently it supports only UNZIP.
+ *
+ * The use of this class is simple - just create instance using
+ * constructor, then set ZIP archive file name using setFile() function
+ * (if you did not passed the name to the constructor), then open() and
+ * then use different functions to work with it! Well, if you are
+ * paranoid, you may also wish to call close before destructing the
+ * instance, to check for errors on close.
+ *
+ * You may also use getUnzFile() and getZipFile() functions to get the
+ * ZIP archive handle and use it with ZIP/UNZIP package API directly.
+ *
+ * This class supports localized file names inside ZIP archive, but you
+ * have to set up proper codec with setCodec() function. By default,
+ * locale codec will be used, which is probably ok for UNIX systems, but
+ * will almost certainly fail with ZIP archives created in Windows. This
+ * is because Windows ZIP programs have strange habit of using DOS
+ * encoding for file names in ZIP archives. For example, ZIP archive
+ * with cyrillic names created in Windows will have file names in \c
+ * IBM866 encoding instead of \c WINDOWS-1251. I think that calling one
+ * function is not much trouble, but for true platform independency it
+ * would be nice to have some mechanism for file name encoding auto
+ * detection using locale information. Does anyone know a good way to do
+ * it?
+ **/
+class QUAZIP_EXPORT QuaZip {
+ friend class QuaZipPrivate;
+ public:
+ /// Useful constants.
+ enum Constants {
+ MAX_FILE_NAME_LENGTH=256 /**< Maximum file name length. Taken from
+ \c UNZ_MAXFILENAMEINZIP constant in
+ unzip.c. */
+ };
+ /// Open mode of the ZIP file.
+ enum Mode {
+ mdNotOpen, ///< ZIP file is not open. This is the initial mode.
+ mdUnzip, ///< ZIP file is open for reading files inside it.
+ mdCreate, ///< ZIP file was created with open() call.
+ mdAppend, /**< ZIP file was opened in append mode. This refers to
+ * \c APPEND_STATUS_CREATEAFTER mode in ZIP/UNZIP package
+ * and means that zip is appended to some existing file
+ * what is useful when that file contains
+ * self-extractor code. This is obviously \em not what
+ * you whant to use to add files to the existing ZIP
+ * archive.
+ **/
+ mdAdd ///< ZIP file was opened for adding files in the archive.
+ };
+ /// Case sensitivity for the file names.
+ /** This is what you specify when accessing files in the archive.
+ * Works perfectly fine with any characters thanks to Qt's great
+ * unicode support. This is different from ZIP/UNZIP API, where
+ * only US-ASCII characters was supported.
+ **/
+ enum CaseSensitivity {
+ csDefault=0, ///< Default for platform. Case sensitive for UNIX, not for Windows.
+ csSensitive=1, ///< Case sensitive.
+ csInsensitive=2 ///< Case insensitive.
+ };
+ private:
+ QuaZipPrivate *p;
+ // not (and will not be) implemented
+ QuaZip(const QuaZip& that);
+ // not (and will not be) implemented
+ QuaZip& operator=(const QuaZip& that);
+ public:
+ /// Constructs QuaZip object.
+ /** Call setName() before opening constructed object. */
+ QuaZip();
+ /// Constructs QuaZip object associated with ZIP file \a zipName.
+ QuaZip(const QString& zipName);
+ /// Constructs QuaZip object associated with ZIP file represented by \a ioDevice.
+ /** The IO device must be seekable, otherwise an error will occur when opening. */
+ QuaZip(QIODevice *ioDevice);
+ /// Destroys QuaZip object.
+ /** Calls close() if necessary. */
+ ~QuaZip();
+ /// Opens ZIP file.
+ /**
+ * Argument \a mode specifies open mode of the ZIP archive. See Mode
+ * for details. Note that there is zipOpen2() function in the
+ * ZIP/UNZIP API which accepts \a globalcomment argument, but it
+ * does not use it anywhere, so this open() function does not have this
+ * argument. See setComment() if you need to set global comment.
+ *
+ * If the ZIP file is accessed via explicitly set QIODevice, then
+ * this device is opened in the necessary mode. If the device was
+ * already opened by some other means, then the behaviour is defined by
+ * the device implementation, but generally it is not a very good
+ * idea. For example, QFile will at least issue a warning.
+ *
+ * \return \c true if successful, \c false otherwise.
+ *
+ * \note ZIP/UNZIP API open calls do not return error code - they
+ * just return \c NULL indicating an error. But to make things
+ * easier, quazip.h header defines additional error code \c
+ * UNZ_ERROROPEN and getZipError() will return it if the open call
+ * of the ZIP/UNZIP API returns \c NULL.
+ *
+ * Argument \a ioApi specifies IO function set for ZIP/UNZIP
+ * package to use. See unzip.h, zip.h and ioapi.h for details. Note
+ * that IO API for QuaZip is different from the original package.
+ * The file path argument was changed to be of type \c voidpf, and
+ * QuaZip passes a QIODevice pointer there. This QIODevice is either
+ * set explicitly via setIoDevice() or the QuaZip(QIODevice*)
+ * constructor, or it is created internally when opening the archive
+ * by its file name. The default API (qioapi.cpp) just delegates
+ * everything to the QIODevice API. Not only this allows to use a
+ * QIODevice instead of file name, but also has a nice side effect
+ * of raising the file size limit from 2G to 4G.
+ *
+ * In short: just forget about the \a ioApi argument and you'll be
+ * fine.
+ **/
+ bool open(Mode mode, zlib_filefunc_def *ioApi =NULL);
+ /// Closes ZIP file.
+ /** Call getZipError() to determine if the close was successful. The
+ * underlying QIODevice is also closed, regardless of whether it was
+ * set explicitly or not. */
+ void close();
+ /// Sets the codec used to encode/decode file names inside archive.
+ /** This is necessary to access files in the ZIP archive created
+ * under Windows with non-latin characters in file names. For
+ * example, file names with cyrillic letters will be in \c IBM866
+ * encoding.
+ **/
+ void setFileNameCodec(QTextCodec *fileNameCodec);
+ /// Sets the codec used to encode/decode file names inside archive.
+ /** \overload
+ * Equivalent to calling setFileNameCodec(QTextCodec::codecForName(codecName));
+ **/
+ void setFileNameCodec(const char *fileNameCodecName);
+ /// Returns the codec used to encode/decode comments inside archive.
+ QTextCodec* getFileNameCodec() const;
+ /// Sets the codec used to encode/decode comments inside archive.
+ /** This codec defaults to locale codec, which is probably ok.
+ **/
+ void setCommentCodec(QTextCodec *commentCodec);
+ /// Sets the codec used to encode/decode comments inside archive.
+ /** \overload
+ * Equivalent to calling setCommentCodec(QTextCodec::codecForName(codecName));
+ **/
+ void setCommentCodec(const char *commentCodecName);
+ /// Returns the codec used to encode/decode comments inside archive.
+ QTextCodec* getCommentCodec() const;
+ /// Returns the name of the ZIP file.
+ /** Returns null string if no ZIP file name has been set, for
+ * example when the QuaZip instance is set up to use a QIODevice
+ * instead.
+ * \sa setZipName(), setIoDevice(), getIoDevice()
+ **/
+ QString getZipName() const;
+ /// Sets the name of the ZIP file.
+ /** Does nothing if the ZIP file is open.
+ *
+ * Does not reset error code returned by getZipError().
+ * \sa setIoDevice(), getIoDevice(), getZipName()
+ **/
+ void setZipName(const QString& zipName);
+ /// Returns the device representing this ZIP file.
+ /** Returns null string if no device has been set explicitly, for
+ * example when opening a ZIP file by name.
+ * \sa setIoDevice(), getZipName(), setZipName()
+ **/
+ QIODevice *getIoDevice() const;
+ /// Sets the device representing the ZIP file.
+ /** Does nothing if the ZIP file is open.
+ *
+ * Does not reset error code returned by getZipError().
+ * \sa getIoDevice(), getZipName(), setZipName()
+ **/
+ void setIoDevice(QIODevice *ioDevice);
+ /// Returns the mode in which ZIP file was opened.
+ Mode getMode() const;
+ /// Returns \c true if ZIP file is open, \c false otherwise.
+ bool isOpen() const;
+ /// Returns the error code of the last operation.
+ /** Returns \c UNZ_OK if the last operation was successful.
+ *
+ * Error code resets to \c UNZ_OK every time you call any function
+ * that accesses something inside ZIP archive, even if it is \c
+ * const (like getEntriesCount()). open() and close() calls reset
+ * error code too. See documentation for the specific functions for
+ * details on error detection.
+ **/
+ int getZipError() const;
+ /// Returns number of the entries in the ZIP central directory