Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix loss of project when saving to QGZ format and path contains non-a…
…scii chars

Fixes #19567
  • Loading branch information
nyalldawson committed Jan 22, 2019
1 parent d3924ad commit 7d7462c
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 11 deletions.
22 changes: 13 additions & 9 deletions src/core/qgsziputils.cpp
Expand Up @@ -67,7 +67,8 @@ bool QgsZipUtils::unzip( const QString &zipFilename, const QString &dir, QString
}

int rc = 0;
struct zip *z = zip_open( zipFilename.toStdString().c_str(), ZIP_CHECKCONS, &rc );
const QByteArray fileNamePtr = zipFilename.toUtf8();
struct zip *z = zip_open( fileNamePtr.constData(), ZIP_CHECKCONS, &rc );

if ( rc == ZIP_ER_OK && z )
{
Expand All @@ -92,7 +93,7 @@ bool QgsZipUtils::unzip( const QString &zipFilename, const QString &dir, QString
if ( !newFile.absoluteDir().exists() )
{
if ( !QDir( dir ).mkpath( newFile.absolutePath() ) )
QgsMessageLog::logMessage( QString( "Failed to create a subdirectory %1/%2" ).arg( dir ).arg( fileName ) );
QgsMessageLog::logMessage( QStringLiteral( "Failed to create a subdirectory %1/%2" ).arg( dir ).arg( fileName ) );
}

QFile outFile( newFile.absoluteFilePath() );
Expand Down Expand Up @@ -146,7 +147,8 @@ bool QgsZipUtils::zip( const QString &zipFilename, const QStringList &files )
}

int rc = 0;
struct zip *z = zip_open( zipFilename.toStdString().c_str(), ZIP_CREATE, &rc );
const QByteArray fileNamePtr = zipFilename.toUtf8();
struct zip *z = zip_open( fileNamePtr.constData(), ZIP_CREATE, &rc );

if ( rc == ZIP_ER_OK && z )
{
Expand All @@ -161,25 +163,27 @@ bool QgsZipUtils::zip( const QString &zipFilename, const QStringList &files )
return false;
}

zip_source *src = zip_source_file( z, file.toStdString().c_str(), 0, 0 );
const QByteArray fileNamePtr = file.toUtf8();
zip_source *src = zip_source_file( z, fileNamePtr.constData(), 0, 0 );
if ( src )
{
const QByteArray fileInfoPtr = fileInfo.fileName().toUtf8();
#if LIBZIP_VERSION_MAJOR < 1
int rc = ( int ) zip_add( z, fileInfo.fileName().toStdString().c_str(), src );
int rc = ( int ) zip_add( z, fileInfoPtr.constData(), src );
#else
int rc = ( int ) zip_file_add( z, fileInfo.fileName().toStdString().c_str(), src, 0 );
int rc = ( int ) zip_file_add( z, fileInfoPtr.constData(), src, 0 );
#endif
if ( rc == -1 )
{
QString err = QObject::tr( "Error adding file: '%1'" ).arg( zip_strerror( z ) );
QString err = QObject::tr( "Error adding file '%1': %2" ).arg( file, 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 ) );
QString err = QObject::tr( "Error creating data source '%1': %2" ).arg( file, zip_strerror( z ) );
QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
zip_close( z );
return false;
Expand All @@ -190,7 +194,7 @@ bool QgsZipUtils::zip( const QString &zipFilename, const QStringList &files )
}
else
{
QString err = QObject::tr( "Error creating zip archive: '%1'" ).arg( zip_strerror( z ) );
QString err = QObject::tr( "Error creating zip archive '%1': %2" ).arg( zipFilename, zip_strerror( z ) );
QgsMessageLog::logMessage( err, QStringLiteral( "QgsZipUtils" ) );
return false;
}
Expand Down
38 changes: 36 additions & 2 deletions tests/src/core/testqgsziputils.cpp
Expand Up @@ -33,6 +33,8 @@ class TestQgsZipUtils: public QObject

void unzipWithSubdirs();
void unzipWithSubdirs2();
void specialChars();
void testZip();

private:
void genericTest( QString zipName, int expectedEntries, bool includeFolders, const QStringList &testFileNames );
Expand Down Expand Up @@ -83,6 +85,38 @@ void TestQgsZipUtils::unzipWithSubdirs2()
genericTest( QString( "diff_structured" ), 3, false, QStringList() << "/subfolder/3.txt" );
}

void TestQgsZipUtils::specialChars()
{
genericTest( "Chars èêæýì", 1, false, QStringList() << "/èêæýì.txt" );
}

void TestQgsZipUtils::testZip()
{
QString txtFile = QString( TEST_DATA_DIR ) + "/zip/aæýì.txt";

QString zipDirPath = QDir::tempPath() + "/test_special_chars æì";
QStringList files;

// Create a root folder otherwise nothing is unzipped
QDir dir( zipDirPath );
if ( dir.exists( zipDirPath ) )
{
dir.remove( zipDirPath );
QFile::remove( zipDirPath + "/special_zip æì.zip" );
QFile::remove( zipDirPath + "/aæýì.txt" );
}
else
{
dir.mkdir( zipDirPath );
}

QVERIFY( QgsZipUtils::zip( zipDirPath + "/special_zip æì.zip", QStringList() << txtFile ) );
QVERIFY( QgsZipUtils::unzip( zipDirPath + "/special_zip æì.zip", zipDirPath, files ) );
QCOMPARE( files.count(), 1 );
QCOMPARE( files.at( 0 ), zipDirPath + "/aæýì.txt" );
QVERIFY( QFile::exists( zipDirPath + "/aæýì.txt" ) );
}

/**
* \brief TestQgsZipUtils::genericTest
* \param zipName File to unzip
Expand All @@ -92,11 +126,11 @@ void TestQgsZipUtils::unzipWithSubdirs2()
*/
void TestQgsZipUtils::genericTest( QString zipName, int expectedEntries, bool includeFolders, const QStringList &testFileNames )
{
QFile zipFile( QString( TEST_DATA_DIR ) + QString( "/zip/%1.zip" ).arg( zipName ) );
QFile zipFile( QString( TEST_DATA_DIR ) + QStringLiteral( "/zip/%1.zip" ).arg( zipName ) );
QVERIFY( zipFile.exists() );

QFileInfo fileInfo( zipFile );
QString unzipDirPath = QDir::tempPath() + zipName;
QString unzipDirPath = QDir::tempPath() + '/' + zipName;
QStringList files;

// Create a root folder otherwise nothing is unzipped
Expand Down
Binary file added tests/testdata/zip/Chars èêæýì.zip
Binary file not shown.
Empty file added tests/testdata/zip/aæýì.txt
Empty file.

0 comments on commit 7d7462c

Please sign in to comment.