37bool QgsZipUtils::unzip(
const QString &zipFilename,
const QString &dir, QStringList &files,
bool checkConsistency )
41 if ( !QFileInfo::exists( zipFilename ) )
46 else if ( zipFilename.isEmpty() )
51 else if ( !QDir( dir ).exists( dir ) )
56 else if ( !QFileInfo( dir ).isDir() )
61 else if ( !QFileInfo( dir ).isWritable() )
68 const QByteArray fileNamePtr = zipFilename.toUtf8();
69 struct zip *z = zip_open( fileNamePtr.constData(), checkConsistency ? ZIP_CHECKCONS : 0, &rc );
71 if ( rc == ZIP_ER_OK && z )
73 const int count = zip_get_num_entries( z, ZIP_FL_UNCHANGED );
78 for (
int i = 0; i < count; i++ )
80 zip_stat_index( z, i, 0, &stat );
81 const size_t len = stat.size;
83 struct zip_file *file = zip_fopen_index( z, i, 0 );
84 const std::unique_ptr< char[] > buf(
new char[len] );
85 if ( zip_fread( file, buf.get(), len ) != -1 )
87 const QString fileName( stat.name );
88 const QFileInfo newFile( QDir( dir ), fileName );
91 if ( !newFile.absoluteDir().exists() )
93 if ( !QDir( dir ).mkpath( newFile.absolutePath() ) )
97 QFile outFile( newFile.absoluteFilePath() );
98 if ( !outFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
104 outFile.write( buf.get(), len );
107 files.append( newFile.absoluteFilePath() );
128 QgsMessageLog::logMessage( QObject::tr(
"Error opening zip archive: '%1' (Error code: %2)" ).arg( z ? zip_strerror( z ) : zipFilename ).arg( rc ) );
137 if ( zipFilename.isEmpty() )
144 const QByteArray zipFileNamePtr = zipFilename.toUtf8();
145 struct zip *z = zip_open( zipFileNamePtr.constData(), ZIP_CREATE, &rc );
147 if ( rc == ZIP_ER_OK && z )
149 for (
const auto &file :
files )
151 const QFileInfo fileInfo( file );
152 if ( !fileInfo.exists() )
159 const QByteArray fileNamePtr = file.toUtf8();
160 zip_source *src = zip_source_file( z, fileNamePtr.constData(), 0, 0 );
163 const QByteArray fileInfoPtr = fileInfo.fileName().toUtf8();
164#if LIBZIP_VERSION_MAJOR < 1
165 rc = ( int ) zip_add( z, fileInfoPtr.constData(), src );
167 rc = ( int ) zip_file_add( z, fileInfoPtr.constData(), src, 0 );
202 unsigned char *bytesInPtr =
reinterpret_cast<unsigned char *
>(
const_cast<char *
>( bytesIn ) );
203 uint bytesInLeft =
static_cast<uint
>( size );
205 const uint CHUNK = 16384;
206 unsigned char out[CHUNK];
207 const int DEC_MAGIC_NUM_FOR_GZIP = 16;
211 strm.zalloc = Z_NULL;
213 strm.opaque = Z_NULL;
215 strm.next_in = Z_NULL;
217 int ret = inflateInit2( &strm, MAX_WBITS + DEC_MAGIC_NUM_FOR_GZIP );
221 while ( ret != Z_STREAM_END )
224 const uint bytesToProcess = std::min( CHUNK, bytesInLeft );
225 strm.next_in = bytesInPtr;
226 strm.avail_in = bytesToProcess;
227 bytesInPtr += bytesToProcess;
228 bytesInLeft -= bytesToProcess;
230 if ( bytesToProcess == 0 )
236 strm.avail_out = CHUNK;
238 ret = inflate( &strm, Z_NO_FLUSH );
239 Q_ASSERT( ret != Z_STREAM_ERROR );
240 if ( ret == Z_NEED_DICT || ret == Z_DATA_ERROR || ret == Z_MEM_ERROR )
245 const unsigned have = CHUNK - strm.avail_out;
246 bytesOut.append( QByteArray::fromRawData(
reinterpret_cast<const char *
>( out ),
static_cast<int>( have ) ) );
248 while ( strm.avail_out == 0 );
252 return ret == Z_STREAM_END;
257 unsigned char *bytesInPtr =
reinterpret_cast<unsigned char *
>(
const_cast<char *
>( bytesIn.constData() ) );
258 const uint bytesInLeft =
static_cast<uint
>( bytesIn.count() );
260 const uint CHUNK = 16384;
261 unsigned char out[CHUNK];
262 const int DEC_MAGIC_NUM_FOR_GZIP = 16;
266 strm.zalloc = Z_NULL;
268 strm.opaque = Z_NULL;
270 int ret = deflateInit2( &strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, MAX_WBITS + DEC_MAGIC_NUM_FOR_GZIP, 8, Z_DEFAULT_STRATEGY );
274 strm.avail_in = bytesInLeft;
275 strm.next_in = bytesInPtr;
281 strm.avail_out = CHUNK;
283 ret = deflate( &strm, Z_FINISH );
284 Q_ASSERT( ret != Z_STREAM_ERROR );
286 const unsigned have = CHUNK - strm.avail_out;
287 bytesOut.append( QByteArray::fromRawData(
reinterpret_cast<const char *
>( out ),
static_cast<int>( have ) ) );
289 while ( strm.avail_out == 0 );
290 Q_ASSERT( ret == Z_STREAM_END );
299 if (
zip.isEmpty() && !QFileInfo::exists(
zip ) )
301 return QStringList();
306 const QByteArray fileNamePtr =
zip.toUtf8();
307 struct zip *z = zip_open( fileNamePtr.constData(), 0, &rc );
309 if ( rc == ZIP_ER_OK && z )
311 const int count = zip_get_num_entries( z, ZIP_FL_UNCHANGED );
314 struct zip_stat stat;
316 for (
int i = 0; i < count; i++ )
318 zip_stat_index( z, i, 0, &stat );
319 files << QString( stat.name );
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
CORE_EXPORT bool unzip(const QString &zip, const QString &dir, QStringList &files, bool checkConsistency=true)
Unzip a zip file in an output directory.