Skip to content

Commit

Permalink
Add utilities functions for zip support
Browse files Browse the repository at this point in the history
  • Loading branch information
pblottiere committed Jul 31, 2017
1 parent 5eba29e commit 7c85b20
Show file tree
Hide file tree
Showing 5 changed files with 281 additions and 0 deletions.
1 change: 1 addition & 0 deletions python/core/core_auto.sip
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@
%Include qgsvirtuallayerdefinitionutils.sip
%Include qgsmapthemecollection.sip
%Include qgsxmlutils.sip
%Include qgsziputils.sip
%Include qgsvector.sip
%Include auth/qgsauthcertutils.sip
%Include auth/qgsauthconfig.sip
Expand Down
48 changes: 48 additions & 0 deletions python/core/qgsziputils.sip
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgsziputils.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/



%ModuleHeaderCode
#include "qgsziputils.h"
%End

namespace QgsZipUtils
{

bool unzip( const QString &zip, const QString &dir, QStringList &files /Out/ );
%Docstring
Unzip a zip file in an output directory. An error is returned if the zip
filename does not exist, the output directory does not exist or is
not writable.
\param zip The zip filename
\param dir The output directory
\param files The absolute path of unzipped files
.. versionadded:: 3.0
:rtype: bool
%End

bool zip( const QString &zip, const QStringList &files );
%Docstring
Zip the list of files in the zip file. If the zip file yet exists or is
empty, an error is returned. If an input file does not exist, an error is
also returned.
\param zip The zip filename
\param files The absolute path filles to embed within the zip
.. versionadded:: 3.0
:rtype: bool
%End
};

/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgsziputils.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
3 changes: 3 additions & 0 deletions src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ SET(QGIS_CORE_SRCS
qgsxmlutils.cpp
qgssettings.cpp
qgsstacktrace.cpp
qgsziputils.cpp

composer/qgsaddremoveitemcommand.cpp
composer/qgsaddremovemultiframecommand.cpp
Expand Down Expand Up @@ -892,6 +893,7 @@ SET(QGIS_CORE_HDRS
qgsvirtuallayerdefinitionutils.h
qgsmapthemecollection.h
qgsxmlutils.h
qgsziputils.h
qgsvector.h
qgslocalec.h

Expand Down Expand Up @@ -1218,6 +1220,7 @@ TARGET_LINK_LIBRARIES(qgis_core
${EXPAT_LIBRARY}
${SQLITE3_LIBRARY}
${SPATIALITE_LIBRARY}
${LIBZIP_LIBRARY}
)

IF (Qt5Positioning_FOUND)
Expand Down
177 changes: 177 additions & 0 deletions src/core/qgsziputils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
/***************************************************************************
qgsziputils.cpp
---------------------
begin : Jul 2017
copyright : (C) 2017 by Paul Blottiere
email : paul.blottiere@oslandia.com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include <fstream>

#include <QFileInfo>
#include <QDir>

#include "zip.h"

#include "qgsmessagelog.h"
#include "qgsziputils.h"

#include <iostream>

bool QgsZipUtils::unzip( const QString &zipFilename, const QString &dir, QStringList &files )
{
files.clear();

if ( !QFileInfo::exists( zipFilename ) )
{
QString err = QObject::tr( "Error zip file does not exist: '%1'" ).arg( zipFilename );
QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
return false;
}
else if ( zipFilename.isEmpty() )
{
QString err = QObject::tr( "Error zip filename is empty" );
QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
return false;
}
else if ( !QDir( dir ).exists( dir ) )
{
QString err = QObject::tr( "Error output dir does not exist: '%1'" ).arg( dir );
QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
return false;
}
else if ( !QFileInfo( dir ).isDir() )
{
QString err = QObject::tr( "Error output dir is not a directory: '%1'" ).arg( dir );
QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
return false;
}
else if ( !QFileInfo( dir ).isWritable() )
{
QString err = QObject::tr( "Error output dir is not writable: '%1'" ).arg( dir );
QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
return false;
}

int rc = 0;
struct zip *z = zip_open( zipFilename.toStdString().c_str(), ZIP_CHECKCONS, &rc );

if ( rc == ZIP_ER_OK && z != NULL )
{
int count = zip_get_num_files( z );
if ( count != -1 )
{
struct zip_stat stat;

for ( int i = 0; i < count; i++ )
{
zip_stat_index( z, i, 0, &stat );
size_t len = stat.size;

struct zip_file *file = zip_fopen_index( z, i, 0 );
char *buf = new char[len];
if ( zip_fread( file, buf, len ) != -1 )
{
QFileInfo newFile( QDir( dir ), QString( stat.name ) );
std::ofstream( newFile.absoluteFilePath().toStdString() ).write( buf, len );
zip_fclose( file );
files.append( newFile.absoluteFilePath() );
}
else
{
zip_fclose( file );
QString err = QObject::tr( "Error reading file: '%1'" ).arg( zip_strerror( z ) );
QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
return false;
}
}
}
else
{
zip_close( z );
QString err = QObject::tr( "Error getting files: '%1'" ).arg( zip_strerror( z ) );
QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
return false;
}

zip_close( z );
}
else
{
QString err = QObject::tr( "Error opening zip archive: '%1'" ).arg( zip_strerror( z ) );
QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
return false;
}

return true;
}

bool QgsZipUtils::zip( const QString &zipFilename, const QStringList &files )
{
if ( QFileInfo::exists( zipFilename ) )
{
QString err = QObject::tr( "Error zip file yet exist: '%1'" ).arg( zipFilename );
QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
return false;
}
else if ( zipFilename.isEmpty() )
{
QString err = QObject::tr( "Error zip filename is empty" );
QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
return false;
}

int rc = 0;
struct zip *z = zip_open( zipFilename.toStdString().c_str(), ZIP_CREATE, &rc );

if ( rc == ZIP_ER_OK && z != NULL )
{
Q_FOREACH ( QString file, files )
{
QFileInfo fileInfo( file );
if ( !fileInfo.exists() )
{
QString err = QObject::tr( "Error input file does not exist: '%1'" ).arg( file );
QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
return false;
zip_close( z );
}

zip_source *src = zip_source_file( z, file.toStdString().c_str(), 0, 0 );
if ( src != NULL )
{
if ( zip_file_add( z, fileInfo.fileName().toStdString().c_str(), src, 0 ) == -1 )
{
QString err = QObject::tr( "Error adding file: '%1'" ).arg( zip_strerror( z ) );
QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
zip_close( z );
return false;
}
}
else
{
QString err = QObject::tr( "Error creating data source: '%1'" ).arg( zip_strerror( z ) );
QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
zip_close( z );
return false;
}
}

zip_close( z );
}
else
{
QString err = QObject::tr( "Error creating zip archive: '%1'" ).arg( zip_strerror( z ) );
QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
return false;
}

return true;
}
52 changes: 52 additions & 0 deletions src/core/qgsziputils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/***************************************************************************
qgsziputils.h
---------------------
begin : Jul 2017
copyright : (C) 2017 by Paul Blottiere
email : paul.blottiere@oslandia.com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#ifndef QGSZIPUTILS_H
#define QGSZIPUTILS_H

#include "qgis_core.h"
#include "qgis.h"
#include <QStringList>

#ifdef SIP_RUN
% ModuleHeaderCode
#include "qgsziputils.h"
% End
#endif

namespace QgsZipUtils
{

/** Unzip a zip file in an output directory. An error is returned if the zip
* filename does not exist, the output directory does not exist or is
* not writable.
* \param zip The zip filename
* \param dir The output directory
* \param files The absolute path of unzipped files
* \since QGIS 3.0
*/
CORE_EXPORT bool unzip( const QString &zip, const QString &dir, QStringList &files SIP_OUT );

/** Zip the list of files in the zip file. If the zip file yet exists or is
* empty, an error is returned. If an input file does not exist, an error is
* also returned.
* \param zip The zip filename
* \param files The absolute path filles to embed within the zip
* \since QGIS 3.0
*/
CORE_EXPORT bool zip( const QString &zip, const QStringList &files );
};

#endif //QGSZIPUTILS_H

0 comments on commit 7c85b20

Please sign in to comment.