QGIS API Documentation  3.2.0-Bonn (bc43194)
qgsziputils.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsziputils.cpp
3  ---------------------
4  begin : Jul 2017
5  copyright : (C) 2017 by Paul Blottiere
6  email : [email protected]
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::isZipFile( const QString &filename )
29 {
30  return QFileInfo( filename ).suffix().compare( QLatin1String( "qgz" ), Qt::CaseInsensitive ) == 0;
31 }
32 
33 bool QgsZipUtils::unzip( const QString &zipFilename, const QString &dir, QStringList &files )
34 {
35  files.clear();
36 
37  if ( !QFileInfo::exists( zipFilename ) )
38  {
39  QString err = QObject::tr( "Error zip file does not exist: '%1'" ).arg( zipFilename );
40  QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
41  return false;
42  }
43  else if ( zipFilename.isEmpty() )
44  {
45  QString err = QObject::tr( "Error zip filename is empty" );
46  QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
47  return false;
48  }
49  else if ( !QDir( dir ).exists( dir ) )
50  {
51  QString err = QObject::tr( "Error output dir does not exist: '%1'" ).arg( dir );
52  QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
53  return false;
54  }
55  else if ( !QFileInfo( dir ).isDir() )
56  {
57  QString err = QObject::tr( "Error output dir is not a directory: '%1'" ).arg( dir );
58  QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
59  return false;
60  }
61  else if ( !QFileInfo( dir ).isWritable() )
62  {
63  QString err = QObject::tr( "Error output dir is not writable: '%1'" ).arg( dir );
64  QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
65  return false;
66  }
67 
68  int rc = 0;
69  struct zip *z = zip_open( zipFilename.toStdString().c_str(), ZIP_CHECKCONS, &rc );
70 
71  if ( rc == ZIP_ER_OK && z )
72  {
73  int count = zip_get_num_files( z );
74  if ( count != -1 )
75  {
76  struct zip_stat stat;
77 
78  for ( int i = 0; i < count; i++ )
79  {
80  zip_stat_index( z, i, 0, &stat );
81  size_t len = stat.size;
82 
83  struct zip_file *file = zip_fopen_index( z, i, 0 );
84  char *buf = new char[len];
85  if ( zip_fread( file, buf, len ) != -1 )
86  {
87  QFileInfo newFile( QDir( dir ), QString( stat.name ) );
88  std::ofstream( newFile.absoluteFilePath().toStdString() ).write( buf, len );
89  zip_fclose( file );
90  files.append( newFile.absoluteFilePath() );
91  }
92  else
93  {
94  zip_fclose( file );
95  QString err = QObject::tr( "Error reading file: '%1'" ).arg( zip_strerror( z ) );
96  QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
97  return false;
98  }
99  }
100  }
101  else
102  {
103  zip_close( z );
104  QString err = QObject::tr( "Error getting files: '%1'" ).arg( zip_strerror( z ) );
105  QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
106  return false;
107  }
108 
109  zip_close( z );
110  }
111  else
112  {
113  QString err = QObject::tr( "Error opening zip archive: '%1'" ).arg( zip_strerror( z ) );
114  QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
115  return false;
116  }
117 
118  return true;
119 }
120 
121 bool QgsZipUtils::zip( const QString &zipFilename, const QStringList &files )
122 {
123  if ( zipFilename.isEmpty() )
124  {
125  QString err = QObject::tr( "Error zip filename is empty" );
126  QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
127  return false;
128  }
129 
130  int rc = 0;
131  struct zip *z = zip_open( zipFilename.toStdString().c_str(), ZIP_CREATE, &rc );
132 
133  if ( rc == ZIP_ER_OK && z )
134  {
135  for ( const auto &file : files )
136  {
137  QFileInfo fileInfo( file );
138  if ( !fileInfo.exists() )
139  {
140  QString err = QObject::tr( "Error input file does not exist: '%1'" ).arg( file );
141  QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
142  zip_close( z );
143  return false;
144  }
145 
146  zip_source *src = zip_source_file( z, file.toStdString().c_str(), 0, 0 );
147  if ( src )
148  {
149 #if LIBZIP_VERSION_MAJOR < 1
150  int rc = ( int ) zip_add( z, fileInfo.fileName().toStdString().c_str(), src );
151 #else
152  int rc = ( int ) zip_file_add( z, fileInfo.fileName().toStdString().c_str(), src, 0 );
153 #endif
154  if ( rc == -1 )
155  {
156  QString err = QObject::tr( "Error adding file: '%1'" ).arg( zip_strerror( z ) );
157  QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
158  zip_close( z );
159  return false;
160  }
161  }
162  else
163  {
164  QString err = QObject::tr( "Error creating data source: '%1'" ).arg( zip_strerror( z ) );
165  QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
166  zip_close( z );
167  return false;
168  }
169  }
170 
171  zip_close( z );
172  }
173  else
174  {
175  QString err = QObject::tr( "Error creating zip archive: '%1'" ).arg( zip_strerror( z ) );
176  QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
177  return false;
178  }
179 
180  return true;
181 }
CORE_EXPORT bool unzip(const QString &zip, const QString &dir, QStringList &files)
Unzip a zip file in an output directory.
Definition: qgsziputils.cpp:33
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
CORE_EXPORT bool isZipFile(const QString &filename)
Returns true if the file name is a zipped file ( i.e with a &#39;.qgz&#39; extension, false otherwise...
Definition: qgsziputils.cpp:28
CORE_EXPORT bool zip(const QString &zip, const QStringList &files)
Zip the list of files in the zip file.