From 7d7462c33334a501167813d720fb2589d3c579ec Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Tue, 22 Jan 2019 11:16:32 +1000 Subject: [PATCH] Fix loss of project when saving to QGZ format and path contains non-ascii chars Fixes #19567 --- src/core/qgsziputils.cpp | 22 +++++----- tests/src/core/testqgsziputils.cpp | 38 +++++++++++++++++- ...3\250\303\252\303\246\303\275\303\254.zip" | Bin 0 -> 162 bytes .../zip/a\303\246\303\275\303\254.txt" | 0 4 files changed, 49 insertions(+), 11 deletions(-) create mode 100644 "tests/testdata/zip/Chars \303\250\303\252\303\246\303\275\303\254.zip" create mode 100644 "tests/testdata/zip/a\303\246\303\275\303\254.txt" diff --git a/src/core/qgsziputils.cpp b/src/core/qgsziputils.cpp index 10338088b0c0..0272371cea7e 100644 --- a/src/core/qgsziputils.cpp +++ b/src/core/qgsziputils.cpp @@ -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 ) { @@ -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() ); @@ -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 ) { @@ -161,17 +163,19 @@ 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; @@ -179,7 +183,7 @@ bool QgsZipUtils::zip( const QString &zipFilename, const QStringList &files ) } 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; @@ -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; } diff --git a/tests/src/core/testqgsziputils.cpp b/tests/src/core/testqgsziputils.cpp index bb7074de8930..11fad10d1e74 100644 --- a/tests/src/core/testqgsziputils.cpp +++ b/tests/src/core/testqgsziputils.cpp @@ -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 ); @@ -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 @@ -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 diff --git "a/tests/testdata/zip/Chars \303\250\303\252\303\246\303\275\303\254.zip" "b/tests/testdata/zip/Chars \303\250\303\252\303\246\303\275\303\254.zip" new file mode 100644 index 0000000000000000000000000000000000000000..345b0f13978ed1c090cadf255b0b254c0a57f95c GIT binary patch literal 162 zcmWIWW@h1HVBlb2FbgyDV?Y9YK=$DkhgTh5c6jgMHF_l#B>~=yO!f@8RI5PsDnMye ny<7|saYhCS29E=qem&lJg%O<&@MdKLX=Vh%1R$*g;xGUJ*2yMr literal 0 HcmV?d00001 diff --git "a/tests/testdata/zip/a\303\246\303\275\303\254.txt" "b/tests/testdata/zip/a\303\246\303\275\303\254.txt" new file mode 100644 index 000000000000..e69de29bb2d1