Skip to content

Commit 7c85b20

Browse files
committedJul 31, 2017
Add utilities functions for zip support
1 parent 5eba29e commit 7c85b20

File tree

5 files changed

+281
-0
lines changed

5 files changed

+281
-0
lines changed
 

‎python/core/core_auto.sip

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@
127127
%Include qgsvirtuallayerdefinitionutils.sip
128128
%Include qgsmapthemecollection.sip
129129
%Include qgsxmlutils.sip
130+
%Include qgsziputils.sip
130131
%Include qgsvector.sip
131132
%Include auth/qgsauthcertutils.sip
132133
%Include auth/qgsauthconfig.sip

‎python/core/qgsziputils.sip

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/************************************************************************
2+
* This file has been generated automatically from *
3+
* *
4+
* src/core/qgsziputils.h *
5+
* *
6+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
7+
************************************************************************/
8+
9+
10+
11+
%ModuleHeaderCode
12+
#include "qgsziputils.h"
13+
%End
14+
15+
namespace QgsZipUtils
16+
{
17+
18+
bool unzip( const QString &zip, const QString &dir, QStringList &files /Out/ );
19+
%Docstring
20+
Unzip a zip file in an output directory. An error is returned if the zip
21+
filename does not exist, the output directory does not exist or is
22+
not writable.
23+
\param zip The zip filename
24+
\param dir The output directory
25+
\param files The absolute path of unzipped files
26+
.. versionadded:: 3.0
27+
:rtype: bool
28+
%End
29+
30+
bool zip( const QString &zip, const QStringList &files );
31+
%Docstring
32+
Zip the list of files in the zip file. If the zip file yet exists or is
33+
empty, an error is returned. If an input file does not exist, an error is
34+
also returned.
35+
\param zip The zip filename
36+
\param files The absolute path filles to embed within the zip
37+
.. versionadded:: 3.0
38+
:rtype: bool
39+
%End
40+
};
41+
42+
/************************************************************************
43+
* This file has been generated automatically from *
44+
* *
45+
* src/core/qgsziputils.h *
46+
* *
47+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
48+
************************************************************************/

‎src/core/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@ SET(QGIS_CORE_SRCS
305305
qgsxmlutils.cpp
306306
qgssettings.cpp
307307
qgsstacktrace.cpp
308+
qgsziputils.cpp
308309

309310
composer/qgsaddremoveitemcommand.cpp
310311
composer/qgsaddremovemultiframecommand.cpp
@@ -892,6 +893,7 @@ SET(QGIS_CORE_HDRS
892893
qgsvirtuallayerdefinitionutils.h
893894
qgsmapthemecollection.h
894895
qgsxmlutils.h
896+
qgsziputils.h
895897
qgsvector.h
896898
qgslocalec.h
897899

@@ -1218,6 +1220,7 @@ TARGET_LINK_LIBRARIES(qgis_core
12181220
${EXPAT_LIBRARY}
12191221
${SQLITE3_LIBRARY}
12201222
${SPATIALITE_LIBRARY}
1223+
${LIBZIP_LIBRARY}
12211224
)
12221225

12231226
IF (Qt5Positioning_FOUND)

‎src/core/qgsziputils.cpp

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
/***************************************************************************
2+
qgsziputils.cpp
3+
---------------------
4+
begin : Jul 2017
5+
copyright : (C) 2017 by Paul Blottiere
6+
email : paul.blottiere@oslandia.com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
#include <fstream>
17+
18+
#include <QFileInfo>
19+
#include <QDir>
20+
21+
#include "zip.h"
22+
23+
#include "qgsmessagelog.h"
24+
#include "qgsziputils.h"
25+
26+
#include <iostream>
27+
28+
bool QgsZipUtils::unzip( const QString &zipFilename, const QString &dir, QStringList &files )
29+
{
30+
files.clear();
31+
32+
if ( !QFileInfo::exists( zipFilename ) )
33+
{
34+
QString err = QObject::tr( "Error zip file does not exist: '%1'" ).arg( zipFilename );
35+
QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
36+
return false;
37+
}
38+
else if ( zipFilename.isEmpty() )
39+
{
40+
QString err = QObject::tr( "Error zip filename is empty" );
41+
QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
42+
return false;
43+
}
44+
else if ( !QDir( dir ).exists( dir ) )
45+
{
46+
QString err = QObject::tr( "Error output dir does not exist: '%1'" ).arg( dir );
47+
QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
48+
return false;
49+
}
50+
else if ( !QFileInfo( dir ).isDir() )
51+
{
52+
QString err = QObject::tr( "Error output dir is not a directory: '%1'" ).arg( dir );
53+
QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
54+
return false;
55+
}
56+
else if ( !QFileInfo( dir ).isWritable() )
57+
{
58+
QString err = QObject::tr( "Error output dir is not writable: '%1'" ).arg( dir );
59+
QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
60+
return false;
61+
}
62+
63+
int rc = 0;
64+
struct zip *z = zip_open( zipFilename.toStdString().c_str(), ZIP_CHECKCONS, &rc );
65+
66+
if ( rc == ZIP_ER_OK && z != NULL )
67+
{
68+
int count = zip_get_num_files( z );
69+
if ( count != -1 )
70+
{
71+
struct zip_stat stat;
72+
73+
for ( int i = 0; i < count; i++ )
74+
{
75+
zip_stat_index( z, i, 0, &stat );
76+
size_t len = stat.size;
77+
78+
struct zip_file *file = zip_fopen_index( z, i, 0 );
79+
char *buf = new char[len];
80+
if ( zip_fread( file, buf, len ) != -1 )
81+
{
82+
QFileInfo newFile( QDir( dir ), QString( stat.name ) );
83+
std::ofstream( newFile.absoluteFilePath().toStdString() ).write( buf, len );
84+
zip_fclose( file );
85+
files.append( newFile.absoluteFilePath() );
86+
}
87+
else
88+
{
89+
zip_fclose( file );
90+
QString err = QObject::tr( "Error reading file: '%1'" ).arg( zip_strerror( z ) );
91+
QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
92+
return false;
93+
}
94+
}
95+
}
96+
else
97+
{
98+
zip_close( z );
99+
QString err = QObject::tr( "Error getting files: '%1'" ).arg( zip_strerror( z ) );
100+
QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
101+
return false;
102+
}
103+
104+
zip_close( z );
105+
}
106+
else
107+
{
108+
QString err = QObject::tr( "Error opening zip archive: '%1'" ).arg( zip_strerror( z ) );
109+
QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
110+
return false;
111+
}
112+
113+
return true;
114+
}
115+
116+
bool QgsZipUtils::zip( const QString &zipFilename, const QStringList &files )
117+
{
118+
if ( QFileInfo::exists( zipFilename ) )
119+
{
120+
QString err = QObject::tr( "Error zip file yet exist: '%1'" ).arg( zipFilename );
121+
QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
122+
return false;
123+
}
124+
else if ( zipFilename.isEmpty() )
125+
{
126+
QString err = QObject::tr( "Error zip filename is empty" );
127+
QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
128+
return false;
129+
}
130+
131+
int rc = 0;
132+
struct zip *z = zip_open( zipFilename.toStdString().c_str(), ZIP_CREATE, &rc );
133+
134+
if ( rc == ZIP_ER_OK && z != NULL )
135+
{
136+
Q_FOREACH ( QString file, files )
137+
{
138+
QFileInfo fileInfo( file );
139+
if ( !fileInfo.exists() )
140+
{
141+
QString err = QObject::tr( "Error input file does not exist: '%1'" ).arg( file );
142+
QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
143+
return false;
144+
zip_close( z );
145+
}
146+
147+
zip_source *src = zip_source_file( z, file.toStdString().c_str(), 0, 0 );
148+
if ( src != NULL )
149+
{
150+
if ( zip_file_add( z, fileInfo.fileName().toStdString().c_str(), src, 0 ) == -1 )
151+
{
152+
QString err = QObject::tr( "Error adding file: '%1'" ).arg( zip_strerror( z ) );
153+
QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
154+
zip_close( z );
155+
return false;
156+
}
157+
}
158+
else
159+
{
160+
QString err = QObject::tr( "Error creating data source: '%1'" ).arg( zip_strerror( z ) );
161+
QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
162+
zip_close( z );
163+
return false;
164+
}
165+
}
166+
167+
zip_close( z );
168+
}
169+
else
170+
{
171+
QString err = QObject::tr( "Error creating zip archive: '%1'" ).arg( zip_strerror( z ) );
172+
QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
173+
return false;
174+
}
175+
176+
return true;
177+
}

‎src/core/qgsziputils.h

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/***************************************************************************
2+
qgsziputils.h
3+
---------------------
4+
begin : Jul 2017
5+
copyright : (C) 2017 by Paul Blottiere
6+
email : paul.blottiere@oslandia.com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
#ifndef QGSZIPUTILS_H
17+
#define QGSZIPUTILS_H
18+
19+
#include "qgis_core.h"
20+
#include "qgis.h"
21+
#include <QStringList>
22+
23+
#ifdef SIP_RUN
24+
% ModuleHeaderCode
25+
#include "qgsziputils.h"
26+
% End
27+
#endif
28+
29+
namespace QgsZipUtils
30+
{
31+
32+
/** Unzip a zip file in an output directory. An error is returned if the zip
33+
* filename does not exist, the output directory does not exist or is
34+
* not writable.
35+
* \param zip The zip filename
36+
* \param dir The output directory
37+
* \param files The absolute path of unzipped files
38+
* \since QGIS 3.0
39+
*/
40+
CORE_EXPORT bool unzip( const QString &zip, const QString &dir, QStringList &files SIP_OUT );
41+
42+
/** Zip the list of files in the zip file. If the zip file yet exists or is
43+
* empty, an error is returned. If an input file does not exist, an error is
44+
* also returned.
45+
* \param zip The zip filename
46+
* \param files The absolute path filles to embed within the zip
47+
* \since QGIS 3.0
48+
*/
49+
CORE_EXPORT bool zip( const QString &zip, const QStringList &files );
50+
};
51+
52+
#endif //QGSZIPUTILS_H

0 commit comments

Comments
 (0)
Please sign in to comment.