QGIS API Documentation 3.43.0-Master (32433f7016e)
qgsarchive.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsarchive.cpp
3 ----------------
4
5 begin : July 07, 2017
6 copyright : (C) 2017 by Paul Blottiere
7 email : paul.blottiere@oslandia.com
8 ***************************************************************************/
9
10/***************************************************************************
11 * *
12 * This program is free software; you can redistribute it and/or modify *
13 * it under the terms of the GNU General Public License as published by *
14 * the Free Software Foundation; either version 2 of the License, or *
15 * (at your option) any later version. *
16 * *
17 ***************************************************************************/
18
19#include "qgsarchive.h"
20#include "qgsziputils.h"
21#include "qgsmessagelog.h"
22#include "qgsauxiliarystorage.h"
23
24
25#ifdef Q_OS_WIN
26#include <windows.h>
27#endif
28
29#include <QStandardPaths>
30#include <QUuid>
31
33 : mDir( new QTemporaryDir() )
34{
35}
36
38 : mFiles( other.mFiles )
39 , mDir( new QTemporaryDir() )
40{
41}
42
44{
45 if ( this != &other )
46 {
47 mFiles = other.mFiles;
48 mDir.reset( new QTemporaryDir() );
49 }
50
51 return *this;
52}
53
54QString QgsArchive::dir() const
55{
56 return mDir->path();
57}
58
60{
61 mDir.reset( new QTemporaryDir() );
62 mFiles.clear();
63}
64
65bool QgsArchive::zip( const QString &filename )
66{
67 QTemporaryFile tmpFilePath( QDir::temp().absoluteFilePath( QStringLiteral( "qgis-project-XXXXXX.zip" ) ) );
68 tmpFilePath.open();
69 tmpFilePath.close();
70 const QString tempPath = tmpFilePath.fileName();
71
72 // zip content
73 if ( ! QgsZipUtils::zip( tempPath, mFiles, true ) )
74 {
75 const QString err = QObject::tr( "Unable to zip content" );
76 QgsMessageLog::logMessage( err, QStringLiteral( "QgsArchive" ) );
77 return false;
78 }
79
80 QString target {filename};
81
82 // remove existing zip file
83 if ( QFile::exists( target ) )
84 {
85 // If symlink -> we want to write to its target instead
86 const QFileInfo targetFileInfo( target );
87 target = targetFileInfo.canonicalFilePath();
88 // If target still exists, remove (might not exist if was a dangling symlink)
89 if ( QFile::exists( target ) )
90 QFile::remove( target );
91 }
92
93#ifdef Q_OS_WIN
94 // Clear temporary flag (see GH #32118)
95 DWORD dwAttrs;
96#ifdef UNICODE
97 dwAttrs = GetFileAttributes( qUtf16Printable( tempPath ) );
98 SetFileAttributes( qUtf16Printable( tempPath ), dwAttrs & ~ FILE_ATTRIBUTE_TEMPORARY );
99#else
100 dwAttrs = GetFileAttributes( tempPath.toLocal8Bit( ).data( ) );
101 SetFileAttributes( tempPath.toLocal8Bit( ).data( ), dwAttrs & ~ FILE_ATTRIBUTE_TEMPORARY );
102#endif
103
104#endif // Q_OS_WIN
105
106 // save zip archive
107 if ( !QFile::rename( tempPath, target ) )
108 {
109 const QString err = QObject::tr( "Unable to save zip file '%1'" ).arg( target );
110 QgsMessageLog::logMessage( err, QStringLiteral( "QgsArchive" ) );
111 return false;
112 }
113
114 return true;
115}
116
117bool QgsArchive::unzip( const QString &filename )
118{
119 clear();
120 return QgsZipUtils::unzip( filename, mDir->path(), mFiles );
121}
122
123void QgsArchive::addFile( const QString &file )
124{
125 mFiles.append( file );
126}
127
128bool QgsArchive::removeFile( const QString &file )
129{
130 bool rc = false;
131
132 if ( !file.isEmpty() && mFiles.contains( file ) && QFile::exists( file ) )
133 rc = QFile::remove( file );
134
135 mFiles.removeOne( file );
136
137 return rc;
138}
139
140QStringList QgsArchive::files() const
141{
142 return mFiles;
143}
144
146{
147 return QFileInfo::exists( mDir->path() );
148}
149
151{
152 const auto constFiles = files();
153 for ( const QString &file : constFiles )
154 {
155 const QFileInfo fileInfo( file );
156 if ( fileInfo.suffix().compare( QLatin1String( "qgs" ), Qt::CaseInsensitive ) == 0 )
157 return file;
158 }
159
160 return QString();
161}
162
163bool QgsProjectArchive::unzip( const QString &filename )
164{
165 if ( QgsArchive::unzip( filename ) )
166 return ! projectFile().isEmpty();
167 else
168 return false;
169}
170
175
177{
178 const QString extension = QgsAuxiliaryStorage::extension();
179
180 const QStringList fileList = files();
181 for ( const QString &file : fileList )
182 {
183 const QFileInfo fileInfo( file );
184 if ( fileInfo.suffix().compare( extension, Qt::CaseInsensitive ) == 0 )
185 return file;
186 }
187
188 return QString();
189}
Manages zip/unzip operations for an archive.
Definition qgsarchive.h:35
QgsArchive & operator=(const QgsArchive &other)
virtual bool unzip(const QString &zipFilename)
Clear the current content of this archive and unzip.
bool zip(const QString &zipFilename)
Zip the content of this archive.
void clear()
Clear the current content of this archive and create a new temporary directory.
bool exists() const
Returns true if the archive exists on the filesystem, false otherwise.
void addFile(const QString &filename)
Add a new file to this archive.
bool removeFile(const QString &filename)
Remove a file from this archive and from the filesystem.
QString dir() const
Returns the current temporary directory.
QStringList files() const
Returns the list of files within this archive.
static QString extension()
Returns the extension used for auxiliary databases.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE())
Adds a message to the log instance (and creates it if necessary).
QString projectFile() const
Returns the current .qgs project file or an empty string if there's none.
QString auxiliaryStorageFile() const
Returns the current .qgd auxiliary storage file or an empty string if there's none.
bool clearProjectFile()
Remove the current .qgs project file from the temporary directory.
bool unzip(const QString &zipFilename) override
Clear the current content of this archive and unzip.
static bool zip(const QString &zip, const QStringList &files, bool overwrite=false)
Zip the list of files in the zip file.
static bool unzip(const QString &zip, const QString &dir, QStringList &files, bool checkConsistency=true)
Unzip a zip file in an output directory.