From 313020a60b0f2c5140933614cc5faa673232e7b4 Mon Sep 17 00:00:00 2001 From: "r.abdullaev" Date: Thu, 25 Jul 2024 02:24:58 +0300 Subject: [PATCH] Fix vsiSuffix extraction for GDAL provider 1. Extract VSI suffixes only with slashes which prevents mishandling of domains like foo.ziplock.localdomain. The .zip TLD is still affected and requires major refactoring. 2. Do not extract suffixes from *.gz files as they aren't archives. (cherry picked from commit 24712fcd88a72b63aba15873cd1ebf2e2194fb1c) --- .../providers/gdal/qgsgdalproviderbase.cpp | 2 +- tests/src/core/testqgsgdalprovider.cpp | 43 +++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/core/providers/gdal/qgsgdalproviderbase.cpp b/src/core/providers/gdal/qgsgdalproviderbase.cpp index 1a219a9f54b4..21711955eca6 100644 --- a/src/core/providers/gdal/qgsgdalproviderbase.cpp +++ b/src/core/providers/gdal/qgsgdalproviderbase.cpp @@ -406,7 +406,7 @@ QVariantMap QgsGdalProviderBase::decodeGdalUri( const QString &uri ) { path = path.mid( vsiPrefix.count() ); - const thread_local QRegularExpression vsiRegex( QStringLiteral( "(?:\\.zip|\\.tar|\\.gz|\\.tar\\.gz|\\.tgz)([^|]+)" ) ); + const thread_local QRegularExpression vsiRegex( QStringLiteral( "(?:\\.zip|\\.tar|\\.tar\\.gz|\\.tgz)([\\\\/][^|]+)" ) ); const QRegularExpressionMatch match = vsiRegex.match( path ); if ( match.hasMatch() ) { diff --git a/tests/src/core/testqgsgdalprovider.cpp b/tests/src/core/testqgsgdalprovider.cpp index a064e36275c2..315437136210 100644 --- a/tests/src/core/testqgsgdalprovider.cpp +++ b/tests/src/core/testqgsgdalprovider.cpp @@ -140,6 +140,49 @@ void TestQgsGdalProvider::decodeUri() components = QgsProviderRegistry::instance()->decodeUri( QStringLiteral( "gdal" ), uri ); QCOMPARE( components.value( QStringLiteral( "path" ) ).toString(), QString( "/vsicurl/https://www.qgis.org/dataset.tif" ) ); QCOMPARE( components.value( QStringLiteral( "authcfg" ) ).toString(), QString( "1234567" ) ); + + //test .[extension] in domain-part of http[s] + uri = QStringLiteral( "/vsicurl/https://www.qgis.zip.org/dataset.tif" ); + components = QgsProviderRegistry::instance()->decodeUri( QStringLiteral( "gdal" ), uri ); + QCOMPARE( components.value( QStringLiteral( "path" ) ).toString(), QString( "https://www.qgis.zip.org/dataset.tif" ) ); + QCOMPARE( components.value( QStringLiteral( "vsiSuffix" ) ).toString(), QString( "" ) ); + QCOMPARE( components.value( QStringLiteral( "vsiPrefix" ) ).toString(), QString( "/vsicurl/" ) ); + + //test .zip archive with non-latin symbol in the path + uri = QStringLiteral( "/vsizip/α.zip/img.tif" ); + components = QgsProviderRegistry::instance()->decodeUri( QStringLiteral( "gdal" ), uri ); + QCOMPARE( components.value( QStringLiteral( "path" ) ).toString(), QString( "α.zip" ) ); + QCOMPARE( components.value( QStringLiteral( "vsiPrefix" ) ).toString(), QString( "/vsizip/" ) ); + QCOMPARE( components.value( QStringLiteral( "vsiSuffix" ) ).toString(), QString( "/img.tif" ) ); + + // test .tar archive in local path + uri = QStringLiteral( "/vsitar/path/arc.tar/img.tif" ); + components = QgsProviderRegistry::instance()->decodeUri( QStringLiteral( "gdal" ), uri ); + QCOMPARE( components.value( QStringLiteral( "path" ) ).toString(), QString( "path/arc.tar" ) ); + QCOMPARE( components.value( QStringLiteral( "vsiPrefix" ) ).toString(), QString( "/vsitar/" ) ); + QCOMPARE( components.value( QStringLiteral( "vsiSuffix" ) ).toString(), QString( "/img.tif" ) ); + + // test windows path + uri = QStringLiteral( "/vsizip/C:\\arc.zip/img.tif" ); + components = QgsProviderRegistry::instance()->decodeUri( QStringLiteral( "gdal" ), uri ); + QCOMPARE( components.value( QStringLiteral( "path" ) ).toString(), QString( "C:\\arc.zip" ) ); + QCOMPARE( components.value( QStringLiteral( "vsiPrefix" ) ).toString(), QString( "/vsizip/" ) ); + QCOMPARE( components.value( QStringLiteral( "vsiSuffix" ) ).toString(), QString( "/img.tif" ) ); + + // test backslash after .[extension] in the path + uri = QStringLiteral( "/vsizip/C:\\arc.zip\\img.tif" ); + components = QgsProviderRegistry::instance()->decodeUri( QStringLiteral( "gdal" ), uri ); + QCOMPARE( components.value( QStringLiteral( "path" ) ).toString(), QString( "C:\\arc.zip" ) ); + QCOMPARE( components.value( QStringLiteral( "vsiPrefix" ) ).toString(), QString( "/vsizip/" ) ); + QCOMPARE( components.value( QStringLiteral( "vsiSuffix" ) ).toString(), QString( "\\img.tif" ) ); + + // TODO: [zip] in TLD domain - this test will fail. + // Due to recent updates of web-standards allowing .zip in domain - it has to be protected from the zip-extension check + //uri = QStringLiteral( "/vsizip/vsicurl/https://tld.zip/img.tif" ); + //components = QgsProviderRegistry::instance()->decodeUri( QStringLiteral( "gdal" ), uri ); + //QCOMPARE( components.value( QStringLiteral( "path" ) ).toString(), QString( "/vsizip/vsicurl/https://tld.zip/img.tif" ) ); + //QCOMPARE( components.value( QStringLiteral( "vsiPrefix" ) ).toString(), QString( "" ) ); + //QCOMPARE( components.value( QStringLiteral( "vsiSuffix" ) ).toString(), QString( "" ) ); } void TestQgsGdalProvider::encodeUri()