diff --git a/src/core/qgsdatasourceuri.cpp b/src/core/qgsdatasourceuri.cpp index 689690e40035..40442fe2f7b0 100644 --- a/src/core/qgsdatasourceuri.cpp +++ b/src/core/qgsdatasourceuri.cpp @@ -681,17 +681,17 @@ QByteArray QgsDataSourceUri::encodedUri() const QUrlQuery url; for ( auto it = mParams.constBegin(); it != mParams.constEnd(); ++it ) { - url.addQueryItem( it.key(), it.value() ); + url.addQueryItem( it.key(), QUrl::toPercentEncoding( it.value() ) ); } if ( !mUsername.isEmpty() ) - url.addQueryItem( QStringLiteral( "username" ), mUsername ); + url.addQueryItem( QStringLiteral( "username" ), QUrl::toPercentEncoding( mUsername ) ); if ( !mPassword.isEmpty() ) - url.addQueryItem( QStringLiteral( "password" ), mPassword ); + url.addQueryItem( QStringLiteral( "password" ), QUrl::toPercentEncoding( mPassword ) ); if ( !mAuthConfigId.isEmpty() ) - url.addQueryItem( QStringLiteral( "authcfg" ), mAuthConfigId ); + url.addQueryItem( QStringLiteral( "authcfg" ), QUrl::toPercentEncoding( mAuthConfigId ) ); mHttpHeaders.updateUrlQuery( url ); @@ -711,7 +711,7 @@ void QgsDataSourceUri::setEncodedUri( const QByteArray &uri ) mHttpHeaders.setFromUrlQuery( query ); - const auto constQueryItems = query.queryItems(); + const auto constQueryItems = query.queryItems( QUrl::ComponentFormattingOption::FullyDecoded ); for ( const QPair &item : constQueryItems ) { if ( !item.first.startsWith( QgsHttpHeaders::PARAM_PREFIX ) && item.first != QgsHttpHeaders::KEY_REFERER ) @@ -908,7 +908,7 @@ QString QgsDataSourceUri::param( const QString &key ) const else if ( key == QLatin1String( "authcfg" ) && !mAuthConfigId.isEmpty() ) return mAuthConfigId; - return mParams.value( key ); + return mParams.value( key ).toUtf8(); } QStringList QgsDataSourceUri::params( const QString &key ) const diff --git a/src/core/vectortile/qgsvectortileprovidermetadata.cpp b/src/core/vectortile/qgsvectortileprovidermetadata.cpp index f7a8b5f1fd9c..f0b9b5c3bbc2 100644 --- a/src/core/vectortile/qgsvectortileprovidermetadata.cpp +++ b/src/core/vectortile/qgsvectortileprovidermetadata.cpp @@ -147,7 +147,7 @@ QString QgsVectorTileProviderMetadata::absoluteToRelativeUri( const QString &uri // relative path will become "file:./x.txt" const QString relSrcUrl = context.pathResolver().writePath( sourceUrl.toLocalFile() ); dsUri.removeParam( QStringLiteral( "url" ) ); // needed because setParam() would insert second "url" key - dsUri.setParam( QStringLiteral( "url" ), QUrl::fromLocalFile( relSrcUrl ).toString() ); + dsUri.setParam( QStringLiteral( "url" ), QUrl::fromLocalFile( relSrcUrl ).toString( QUrl::DecodeReserved ) ); return dsUri.encodedUri(); } } diff --git a/src/core/vectortile/qgsxyzvectortiledataprovider.cpp b/src/core/vectortile/qgsxyzvectortiledataprovider.cpp index be607514666d..08c45dbe3c55 100644 --- a/src/core/vectortile/qgsxyzvectortiledataprovider.cpp +++ b/src/core/vectortile/qgsxyzvectortiledataprovider.cpp @@ -316,7 +316,7 @@ QString QgsXyzVectorTileDataProviderMetadata::absoluteToRelativeUri( const QStri // relative path will become "file:./x.txt" const QString relSrcUrl = context.pathResolver().writePath( sourceUrl.toLocalFile() ); dsUri.removeParam( QStringLiteral( "url" ) ); // needed because setParam() would insert second "url" key - dsUri.setParam( QStringLiteral( "url" ), QUrl::fromLocalFile( relSrcUrl ).toString() ); + dsUri.setParam( QStringLiteral( "url" ), QUrl::fromLocalFile( relSrcUrl ).toString( QUrl::DecodeReserved ) ); return dsUri.encodedUri(); } @@ -335,7 +335,7 @@ QString QgsXyzVectorTileDataProviderMetadata::relativeToAbsoluteUri( const QStri { const QString absSrcUrl = context.pathResolver().readPath( sourceUrl.toLocalFile() ); dsUri.removeParam( QStringLiteral( "url" ) ); // needed because setParam() would insert second "url" key - dsUri.setParam( QStringLiteral( "url" ), QUrl::fromLocalFile( absSrcUrl ).toString() ); + dsUri.setParam( QStringLiteral( "url" ), QUrl::fromLocalFile( absSrcUrl ).toString( QUrl::DecodeReserved ) ); return dsUri.encodedUri(); } diff --git a/src/providers/wms/qgswmsprovider.cpp b/src/providers/wms/qgswmsprovider.cpp index bff0e2cb9319..89162eab5d6b 100644 --- a/src/providers/wms/qgswmsprovider.cpp +++ b/src/providers/wms/qgswmsprovider.cpp @@ -276,7 +276,10 @@ QgsWmsProvider::QgsWmsProvider( QString const &uri, const ProviderOptions &optio QString QgsWmsProvider::prepareUri( QString uri ) { // some services provide a percent/url encoded (legend) uri string, always decode here - uri = QUrl::fromPercentEncoding( uri.toUtf8() ); + if ( uri.startsWith( "https%3A%2F%2F" ) || uri.startsWith( "http%3A%2F%2F" ) ) + { + uri = QUrl::fromPercentEncoding( uri.toUtf8() ); + } if ( isUrlForWMTS( uri ) ) { diff --git a/tests/src/app/testqgsidentify.cpp b/tests/src/app/testqgsidentify.cpp index 856d5077c15c..401e58747d8c 100644 --- a/tests/src/app/testqgsidentify.cpp +++ b/tests/src/app/testqgsidentify.cpp @@ -932,7 +932,9 @@ void TestQgsIdentify::identifyVectorTile() const QString vtPath = QStringLiteral( TEST_DATA_DIR ) + QStringLiteral( "/vector_tile/{z}-{x}-{y}.pbf" ); QgsDataSourceUri dsUri; dsUri.setParam( QStringLiteral( "type" ), QStringLiteral( "xyz" ) ); - dsUri.setParam( QStringLiteral( "url" ), QUrl::fromLocalFile( vtPath ).toString() ); + // The values need to be passed to QgsDataSourceUri::setParam() in the same format they are expected to be retrieved. + // QUrl::fromPercentEncoding() is needed here because QUrl::fromLocalFile(vtPath).toString() returns the curly braces in an URL-encoded format. + dsUri.setParam( QStringLiteral( "url" ), QUrl::fromPercentEncoding( QUrl::fromLocalFile( vtPath ).toString().toUtf8() ) ); QgsVectorTileLayer *tempLayer = new QgsVectorTileLayer( dsUri.encodedUri(), QStringLiteral( "testlayer" ) ); QVERIFY( tempLayer->isValid() ); diff --git a/tests/src/core/testqgsdatasourceuri.cpp b/tests/src/core/testqgsdatasourceuri.cpp index 409b059b4889..76327eaa6fee 100644 --- a/tests/src/core/testqgsdatasourceuri.cpp +++ b/tests/src/core/testqgsdatasourceuri.cpp @@ -564,7 +564,7 @@ void TestQgsDataSourceUri::checkAuthParams() // issue GH #53654 QgsDataSourceUri uri5; uri5.setEncodedUri( QStringLiteral( "zmax=14&zmin=0&styleUrl=http://localhost:8000/&f=application%2Fvnd.geoserver.mbstyle%2Bjson" ) ); - QCOMPARE( uri5.param( QStringLiteral( "f" ) ), QStringLiteral( "application%2Fvnd.geoserver.mbstyle%2Bjson" ) ); + QCOMPARE( uri5.param( QStringLiteral( "f" ) ), QStringLiteral( "application/vnd.geoserver.mbstyle+json" ) ); uri5.setEncodedUri( QStringLiteral( "zmax=14&zmin=0&styleUrl=http://localhost:8000/&f=application/vnd.geoserver.mbstyle+json" ) ); QCOMPARE( uri5.param( QStringLiteral( "f" ) ), QStringLiteral( "application/vnd.geoserver.mbstyle+json" ) ); diff --git a/tests/src/core/testqgsgdalcloudconnection.cpp b/tests/src/core/testqgsgdalcloudconnection.cpp index e43c4757ee7f..0e69eb210ab5 100644 --- a/tests/src/core/testqgsgdalcloudconnection.cpp +++ b/tests/src/core/testqgsgdalcloudconnection.cpp @@ -59,7 +59,7 @@ void TestQgsGdalCloudConnection::encodeDecode() data.rootPath = QStringLiteral( "some/path" ); data.credentialOptions = QVariantMap { { "pw", QStringLiteral( "xxxx" ) }, { "key", QStringLiteral( "yyy" ) } }; - QCOMPARE( QgsGdalCloudProviderConnection::encodedUri( data ), QStringLiteral( "container=my_container&credentialOptions=key%3Dyyy%7Cpw%3Dxxxx&handler=vsis3&rootPath=some/path" ) ); + QCOMPARE( QgsGdalCloudProviderConnection::encodedUri( data ), QStringLiteral( "container=my_container&credentialOptions=key%3Dyyy%7Cpw%3Dxxxx&handler=vsis3&rootPath=some%2Fpath" ) ); const QgsGdalCloudProviderConnection::Data data2 = QgsGdalCloudProviderConnection::decodedUri( QStringLiteral( "container=my_container&credentialOptions=key%3Dyyy%7Cpw%3Dxxxx&handler=vsis3&rootPath=some/path" ) ); QCOMPARE( data2.vsiHandler, QStringLiteral( "vsis3" ) ); @@ -94,7 +94,7 @@ void TestQgsGdalCloudConnection::testConnections() // retrieve stored connection conn = QgsGdalCloudProviderConnection( QStringLiteral( "my connection" ) ); - QCOMPARE( conn.uri(), QStringLiteral( "container=my_container&credentialOptions=key%3Dyyy%7Cpw%3Dxxxx&handler=vsis3&rootPath=some/path" ) ); + QCOMPARE( conn.uri(), QStringLiteral( "container=my_container&credentialOptions=key%3Dyyy%7Cpw%3Dxxxx&handler=vsis3&rootPath=some%2Fpath" ) ); // add a second connection QgsGdalCloudProviderConnection::Data data2; diff --git a/tests/src/core/testqgshttpheaders.cpp b/tests/src/core/testqgshttpheaders.cpp index 9c2df3cc20ec..58ad7638fd1b 100644 --- a/tests/src/core/testqgshttpheaders.cpp +++ b/tests/src/core/testqgshttpheaders.cpp @@ -159,7 +159,7 @@ void TestQgsHttpheaders::createQgsOwsConnection() QgsDataSourceUri uri3( uri2.uri() ); QCOMPARE( uri3.httpHeader( QgsHttpHeaders::KEY_REFERER ), "http://test.com" ); QCOMPARE( uri3.httpHeader( "other_http_header" ), "value" ); - QCOMPARE( uri3.encodedUri(), "https://www.ogc.org/?p1=v1&referer=http://test.com&http-header:other_http_header=value&http-header:referer=http://test.com" ); + QCOMPARE( uri3.encodedUri(), "https://www.ogc.org/?p1=v1&referer=http%3A%2F%2Ftest.com&http-header:other_http_header=value&http-header:referer=http://test.com" ); } diff --git a/tests/src/core/testqgssensorthingsconnection.cpp b/tests/src/core/testqgssensorthingsconnection.cpp index b6e68ffce933..ddfef807bc5c 100644 --- a/tests/src/core/testqgssensorthingsconnection.cpp +++ b/tests/src/core/testqgssensorthingsconnection.cpp @@ -60,7 +60,7 @@ void TestQgsSensorThingsConnection::encodeDecode() data.password = QStringLiteral( "my_pw" ); data.httpHeaders.insert( QStringLiteral( "my_header" ), QStringLiteral( "value" ) ); - QCOMPARE( QgsSensorThingsProviderConnection::encodedUri( data ), QStringLiteral( "url=http://testurl&username=my_user&password=my_pw&authcfg=my_auth&http-header:my_header=value" ) ); + QCOMPARE( QgsSensorThingsProviderConnection::encodedUri( data ), QStringLiteral( "url=http%3A%2F%2Ftesturl&username=my_user&password=my_pw&authcfg=my_auth&http-header:my_header=value" ) ); QCOMPARE( QgsSensorThingsProviderConnection::encodedLayerUri( data ), QStringLiteral( "user='my_user' password='my_pw' authcfg=my_auth url='http://testurl' http-header:my_header='value'" ) ); const QgsSensorThingsProviderConnection::Data data2 = QgsSensorThingsProviderConnection::decodedUri( QStringLiteral( "url=http://testurl&username=my_user&password=my_pw&authcfg=my_auth&http-header:my_header=value" ) ); @@ -93,7 +93,7 @@ void TestQgsSensorThingsConnection::testConnections() // retrieve stored connection conn = QgsSensorThingsProviderConnection( QStringLiteral( "my connection" ) ); - QCOMPARE( conn.uri(), QStringLiteral( "url=http://testurl&username=my_user&password=my_pw&authcfg=my_auth&http-header:my_header=value" ) ); + QCOMPARE( conn.uri(), QStringLiteral( "url=http%3A%2F%2Ftesturl&username=my_user&password=my_pw&authcfg=my_auth&http-header:my_header=value" ) ); // add a second connection QgsSensorThingsProviderConnection::Data data2; @@ -104,7 +104,7 @@ void TestQgsSensorThingsConnection::testConnections() data2.httpHeaders.insert( QStringLiteral( "my_header" ), QStringLiteral( "value2" ) ); // construct connection using encoded uri QgsSensorThingsProviderConnection conn2( QgsSensorThingsProviderConnection::encodedUri( data2 ), {} ); - QCOMPARE( conn2.uri(), QStringLiteral( "url=http://testurl2&username=my_user2&password=my_pw2&authcfg=my_auth2&http-header:my_header=value2" ) ); + QCOMPARE( conn2.uri(), QStringLiteral( "url=http%3A%2F%2Ftesturl2&username=my_user2&password=my_pw2&authcfg=my_auth2&http-header:my_header=value2" ) ); conn2.store( QStringLiteral( "second connection" ) ); // retrieve stored connections diff --git a/tests/src/core/testqgstiledsceneconnection.cpp b/tests/src/core/testqgstiledsceneconnection.cpp index 1f5d4263c67e..c579080d4da2 100644 --- a/tests/src/core/testqgstiledsceneconnection.cpp +++ b/tests/src/core/testqgstiledsceneconnection.cpp @@ -61,8 +61,8 @@ void TestQgsTiledSceneConnection::encodeDecode() data.password = QStringLiteral( "my_pw" ); data.httpHeaders.insert( QStringLiteral( "my_header" ), QStringLiteral( "value" ) ); - QCOMPARE( QgsTiledSceneProviderConnection::encodedUri( data ), QStringLiteral( "url=http://testurl&username=my_user&password=my_pw&authcfg=my_auth&http-header:my_header=value" ) ); - QCOMPARE( QgsTiledSceneProviderConnection::encodedLayerUri( data ), QStringLiteral( "url=http://testurl&username=my_user&password=my_pw&authcfg=my_auth&http-header:my_header=value" ) ); + QCOMPARE( QgsTiledSceneProviderConnection::encodedUri( data ), QStringLiteral( "url=http%3A%2F%2Ftesturl&username=my_user&password=my_pw&authcfg=my_auth&http-header:my_header=value" ) ); + QCOMPARE( QgsTiledSceneProviderConnection::encodedLayerUri( data ), QStringLiteral( "url=http%3A%2F%2Ftesturl&username=my_user&password=my_pw&authcfg=my_auth&http-header:my_header=value" ) ); const QgsTiledSceneProviderConnection::Data data2 = QgsTiledSceneProviderConnection::decodedUri( QStringLiteral( "url=http://testurl&username=my_user&password=my_pw&authcfg=my_auth&http-header:my_header=value" ) ); QCOMPARE( data2.url, QStringLiteral( "http://testurl" ) ); @@ -97,8 +97,10 @@ void TestQgsTiledSceneConnection::testConnections() // retrieve stored connection conn = QgsTiledSceneProviderConnection( QStringLiteral( "my connection" ) ); - QCOMPARE( conn.uri(), QStringLiteral( "url=http://testurl&username=my_user&password=my_pw&authcfg=my_auth&http-header:my_header=value" ) ); - QCOMPARE( qgis::down_cast( &conn )->providerKey(), QStringLiteral( "test_provider" ) ); + + QCOMPARE( conn.uri(), QStringLiteral( "url=http%3A%2F%2Ftesturl&username=my_user&password=my_pw&authcfg=my_auth&http-header:my_header=value" ) ); + QCOMPARE( qgis::down_cast< QgsTiledSceneProviderConnection * >( &conn )->providerKey(), QStringLiteral( "test_provider" ) ); + // add a second connection QgsTiledSceneProviderConnection::Data data2; @@ -110,8 +112,10 @@ void TestQgsTiledSceneConnection::testConnections() data2.httpHeaders.insert( QStringLiteral( "my_header" ), QStringLiteral( "value2" ) ); // construct connection using encoded uri QgsTiledSceneProviderConnection conn2( QgsTiledSceneProviderConnection::encodedUri( data2 ), QStringLiteral( "test_provider2" ), {} ); - QCOMPARE( conn2.uri(), QStringLiteral( "url=http://testurl2&username=my_user2&password=my_pw2&authcfg=my_auth2&http-header:my_header=value2" ) ); - QCOMPARE( qgis::down_cast( &conn2 )->providerKey(), QStringLiteral( "test_provider2" ) ); + + QCOMPARE( conn2.uri(), QStringLiteral( "url=http%3A%2F%2Ftesturl2&username=my_user2&password=my_pw2&authcfg=my_auth2&http-header:my_header=value2" ) ); + QCOMPARE( qgis::down_cast< QgsTiledSceneProviderConnection * >( &conn2 )->providerKey(), QStringLiteral( "test_provider2" ) ); + conn2.store( QStringLiteral( "second connection" ) ); // retrieve stored connections diff --git a/tests/src/core/testqgsvectortileconnection.cpp b/tests/src/core/testqgsvectortileconnection.cpp index e539eb0be697..d73454fa4289 100644 --- a/tests/src/core/testqgsvectortileconnection.cpp +++ b/tests/src/core/testqgsvectortileconnection.cpp @@ -62,13 +62,13 @@ void TestQgsVectorTileConnection::test_encodedUri() conn.zMin = 0; conn.zMax = 18; QString uri = QgsVectorTileProviderConnection::encodedUri( conn ); - QCOMPARE( uri, QStringLiteral( "type=xyz&url=https://api.maptiler.com/tiles/v3/%7Bz%7D/%7Bx%7D/%7By%7D.pbf?key%3Dabcdef12345&zmax=18&zmin=0" ) ); + QCOMPARE( uri, QStringLiteral( "type=xyz&url=https%3A%2F%2Fapi.maptiler.com%2Ftiles%2Fv3%2F%7Bz%7D%2F%7Bx%7D%2F%7By%7D.pbf%3Fkey%3Dabcdef12345&zmax=18&zmin=0" ) ); conn.url = QStringLiteral( "file:///home/user/tiles.mbtiles" ); conn.zMin = 0; conn.zMax = 18; uri = QgsVectorTileProviderConnection::encodedUri( conn ); - QCOMPARE( uri, QStringLiteral( "type=mbtiles&url=file:///home/user/tiles.mbtiles&zmax=18&zmin=0" ) ); + QCOMPARE( uri, QStringLiteral( "type=mbtiles&url=file%3A%2F%2F%2Fhome%2Fuser%2Ftiles.mbtiles&zmax=18&zmin=0" ) ); } diff --git a/tests/src/core/testqgsvectortilelayer.cpp b/tests/src/core/testqgsvectortilelayer.cpp index 4a5f82f0b0db..f7e41cf28f58 100644 --- a/tests/src/core/testqgsvectortilelayer.cpp +++ b/tests/src/core/testqgsvectortilelayer.cpp @@ -256,11 +256,13 @@ void TestQgsVectorTileLayer::testMbtilesProviderMetadata() QCOMPARE( vectorTileMetadata->validLayerTypesForUri( QStringLiteral( "type=mbtiles&url=%1/vector_tile/mbtiles_vt.mbtiles" ).arg( TEST_DATA_DIR ) ), { Qgis::LayerType::VectorTile } ); // query sublayers + QString localMbtilesPath = QStringLiteral( "%1%2" ).arg( QUrl::toPercentEncoding( TEST_DATA_DIR ), QUrl::toPercentEncoding( QStringLiteral( "/vector_tile/mbtiles_vt.mbtiles" ) ) ); QList sublayers = vectorTileMetadata->querySublayers( QStringLiteral( "%1/vector_tile/mbtiles_vt.mbtiles" ).arg( TEST_DATA_DIR ) ); + QCOMPARE( sublayers.size(), 1 ); QCOMPARE( sublayers.at( 0 ).providerKey(), QStringLiteral( "mbtilesvectortiles" ) ); QCOMPARE( sublayers.at( 0 ).name(), QStringLiteral( "mbtiles_vt" ) ); - QCOMPARE( sublayers.at( 0 ).uri(), QStringLiteral( "type=mbtiles&url=%1/vector_tile/mbtiles_vt.mbtiles" ).arg( TEST_DATA_DIR ) ); + QCOMPARE( sublayers.at( 0 ).uri(), QStringLiteral( "type=mbtiles&url=%1" ).arg( localMbtilesPath ) ); QCOMPARE( sublayers.at( 0 ).type(), Qgis::LayerType::VectorTile ); QVERIFY( !sublayers.at( 0 ).skippedContainerScan() ); QVERIFY( !QgsProviderUtils::sublayerDetailsAreIncomplete( sublayers ) ); @@ -269,7 +271,7 @@ void TestQgsVectorTileLayer::testMbtilesProviderMetadata() QCOMPARE( sublayers.size(), 1 ); QCOMPARE( sublayers.at( 0 ).providerKey(), QStringLiteral( "mbtilesvectortiles" ) ); QCOMPARE( sublayers.at( 0 ).name(), QStringLiteral( "mbtiles_vt" ) ); - QCOMPARE( sublayers.at( 0 ).uri(), QStringLiteral( "type=mbtiles&url=%1/vector_tile/mbtiles_vt.mbtiles" ).arg( TEST_DATA_DIR ) ); + QCOMPARE( sublayers.at( 0 ).uri(), QStringLiteral( "type=mbtiles&url=%1" ).arg( localMbtilesPath ) ); QCOMPARE( sublayers.at( 0 ).type(), Qgis::LayerType::VectorTile ); QVERIFY( !sublayers.at( 0 ).skippedContainerScan() ); @@ -278,7 +280,7 @@ void TestQgsVectorTileLayer::testMbtilesProviderMetadata() QCOMPARE( sublayers.size(), 1 ); QCOMPARE( sublayers.at( 0 ).providerKey(), QStringLiteral( "mbtilesvectortiles" ) ); QCOMPARE( sublayers.at( 0 ).name(), QStringLiteral( "mbtiles_vt" ) ); - QCOMPARE( sublayers.at( 0 ).uri(), QStringLiteral( "type=mbtiles&url=%1/vector_tile/mbtiles_vt.mbtiles" ).arg( TEST_DATA_DIR ) ); + QCOMPARE( sublayers.at( 0 ).uri(), QStringLiteral( "type=mbtiles&url=%1" ).arg( localMbtilesPath ) ); QCOMPARE( sublayers.at( 0 ).type(), Qgis::LayerType::VectorTile ); QVERIFY( sublayers.at( 0 ).skippedContainerScan() ); QVERIFY( QgsProviderUtils::sublayerDetailsAreIncomplete( sublayers ) ); @@ -287,17 +289,19 @@ void TestQgsVectorTileLayer::testMbtilesProviderMetadata() QCOMPARE( sublayers.size(), 1 ); QCOMPARE( sublayers.at( 0 ).providerKey(), QStringLiteral( "mbtilesvectortiles" ) ); QCOMPARE( sublayers.at( 0 ).name(), QStringLiteral( "mbtiles_vt" ) ); - QCOMPARE( sublayers.at( 0 ).uri(), QStringLiteral( "type=mbtiles&url=%1/vector_tile/mbtiles_vt.mbtiles" ).arg( TEST_DATA_DIR ) ); + QCOMPARE( sublayers.at( 0 ).uri(), QStringLiteral( "type=mbtiles&url=%1" ).arg( localMbtilesPath ) ); QCOMPARE( sublayers.at( 0 ).type(), Qgis::LayerType::VectorTile ); QVERIFY( sublayers.at( 0 ).skippedContainerScan() ); // fast scan mode means that any mbtile file will be reported, including those with only raster tiles // (we are skipping a potentially expensive db open and format check) + QString localIsleOfManPath = QStringLiteral( "%1%2" ).arg( QUrl::toPercentEncoding( TEST_DATA_DIR ), QUrl::toPercentEncoding( QStringLiteral( "/isle_of_man.mbtiles" ) ) ); + sublayers = vectorTileMetadata->querySublayers( QStringLiteral( "%1/isle_of_man.mbtiles" ).arg( TEST_DATA_DIR ), Qgis::SublayerQueryFlag::FastScan ); QCOMPARE( sublayers.size(), 1 ); QCOMPARE( sublayers.at( 0 ).providerKey(), QStringLiteral( "mbtilesvectortiles" ) ); QCOMPARE( sublayers.at( 0 ).name(), QStringLiteral( "isle_of_man" ) ); - QCOMPARE( sublayers.at( 0 ).uri(), QStringLiteral( "type=mbtiles&url=%1/isle_of_man.mbtiles" ).arg( TEST_DATA_DIR ) ); + QCOMPARE( sublayers.at( 0 ).uri(), QStringLiteral( "type=mbtiles&url=%1" ).arg( localIsleOfManPath ) ); QCOMPARE( sublayers.at( 0 ).type(), Qgis::LayerType::VectorTile ); QVERIFY( sublayers.at( 0 ).skippedContainerScan() ); @@ -328,8 +332,9 @@ void TestQgsVectorTileLayer::test_relativePathsMbTiles() QgsReadWriteContext contextRel; contextRel.setPathResolver( QgsPathResolver( QStringLiteral( TEST_DATA_DIR ) + QStringLiteral( "/project.qgs" ) ) ); const QgsReadWriteContext contextAbs; + QString localMbtilesPath = QStringLiteral( "%1%2" ).arg( QUrl::toPercentEncoding( TEST_DATA_DIR ), QUrl::toPercentEncoding( QStringLiteral( "/vector_tile/mbtiles_vt.mbtiles" ) ) ); - const QString srcMbtiles = QStringLiteral( "type=mbtiles&url=%1/vector_tile/mbtiles_vt.mbtiles" ).arg( TEST_DATA_DIR ); + const QString srcMbtiles = QStringLiteral( "type=mbtiles&url=%1" ).arg( localMbtilesPath ); std::unique_ptr layer = std::make_unique( srcMbtiles ); QVERIFY( layer->isValid() ); @@ -337,7 +342,7 @@ void TestQgsVectorTileLayer::test_relativePathsMbTiles() // encode source: converting absolute paths to relative const QString srcMbtilesRel = layer->encodedSource( srcMbtiles, contextRel ); - QCOMPARE( srcMbtilesRel, QStringLiteral( "type=mbtiles&url=./vector_tile/mbtiles_vt.mbtiles" ) ); + QCOMPARE( srcMbtilesRel, QStringLiteral( "type=mbtiles&url=.%2Fvector_tile%2Fmbtiles_vt.mbtiles" ) ); // encode source: keeping absolute paths QCOMPARE( layer->encodedSource( srcMbtiles, contextAbs ), srcMbtiles ); @@ -377,7 +382,7 @@ void TestQgsVectorTileLayer::test_relativePathsXyz() contextRel.setPathResolver( QgsPathResolver( "/home/qgis/project.qgs" ) ); const QgsReadWriteContext contextAbs; - const QString srcXyzLocal = "type=xyz&url=file:///home/qgis/%7Bz%7D/%7Bx%7D/%7By%7D.pbf"; + const QString srcXyzLocal = "type=xyz&url=file%3A%2F%2F%2Fhome%2Fqgis%2F%7Bz%7D%2F%7Bx%7D%2F%7By%7D.pbf"; const QString srcXyzRemote = "type=xyz&url=http://www.example.com/%7Bz%7D/%7Bx%7D/%7By%7D.pbf"; std::unique_ptr layer = std::make_unique( srcXyzLocal ); @@ -385,7 +390,7 @@ void TestQgsVectorTileLayer::test_relativePathsXyz() // encode source: converting absolute paths to relative const QString srcXyzLocalRel = layer->encodedSource( srcXyzLocal, contextRel ); - QCOMPARE( srcXyzLocalRel, QStringLiteral( "type=xyz&url=file:./%7Bz%7D/%7Bx%7D/%7By%7D.pbf" ) ); + QCOMPARE( srcXyzLocalRel, QStringLiteral( "type=xyz&url=file%3A.%2F%7Bz%7D%2F%7Bx%7D%2F%7By%7D.pbf" ) ); QCOMPARE( layer->encodedSource( srcXyzRemote, contextRel ), srcXyzRemote ); // encode source: keeping absolute paths @@ -421,7 +426,8 @@ void TestQgsVectorTileLayer::test_absoluteRelativeUriXyz() QString absoluteUri = dsAbs.encodedUri(); QString relativeUri = dsRel.encodedUri(); - QCOMPARE( vectorTileMetadata->absoluteToRelativeUri( absoluteUri, context ), relativeUri ); + QString absToRelUri = vectorTileMetadata->absoluteToRelativeUri( absoluteUri, context ); + QCOMPARE( absToRelUri, relativeUri ); QCOMPARE( vectorTileMetadata->relativeToAbsoluteUri( relativeUri, context ), absoluteUri ); } @@ -443,22 +449,26 @@ void TestQgsVectorTileLayer::testVtpkProviderMetadata() QVERIFY( vectorTileMetadata->querySublayers( QStringLiteral( "type=vtpk&url=%1/points.shp" ).arg( TEST_DATA_DIR ) ).isEmpty() ); // vtpk uris + QString localVtpkPath = QStringLiteral( "%1%2" ).arg( QUrl::toPercentEncoding( TEST_DATA_DIR ), QUrl::toPercentEncoding( QStringLiteral( "/testvtpk.vtpk" ) ) ); + QCOMPARE( vectorTileMetadata->priorityForUri( QStringLiteral( TEST_DATA_DIR ) + QStringLiteral( "/testvtpk.vtpk" ) ), 100 ); QCOMPARE( vectorTileMetadata->validLayerTypesForUri( QStringLiteral( TEST_DATA_DIR ) + QStringLiteral( "/testvtpk.vtpk" ) ), { Qgis::LayerType::VectorTile } ); QList sublayers = vectorTileMetadata->querySublayers( QStringLiteral( TEST_DATA_DIR ) + QStringLiteral( "/testvtpk.vtpk" ) ); QCOMPARE( sublayers.size(), 1 ); QCOMPARE( sublayers.at( 0 ).providerKey(), QStringLiteral( "vtpkvectortiles" ) ); QCOMPARE( sublayers.at( 0 ).name(), QStringLiteral( "testvtpk" ) ); - QCOMPARE( sublayers.at( 0 ).uri(), QStringLiteral( "type=vtpk&url=%1/testvtpk.vtpk" ).arg( TEST_DATA_DIR ) ); + QCOMPARE( sublayers.at( 0 ).uri(), QStringLiteral( "type=vtpk&url=%1" ).arg( localVtpkPath ) ); QCOMPARE( sublayers.at( 0 ).type(), Qgis::LayerType::VectorTile ); + QCOMPARE( vectorTileMetadata->priorityForUri( QStringLiteral( "type=vtpk&url=%1/testvtpk.vtpk" ).arg( TEST_DATA_DIR ) ), 100 ); QCOMPARE( vectorTileMetadata->validLayerTypesForUri( QStringLiteral( "type=vtpk&url=%1/testvtpk.vtpk" ).arg( TEST_DATA_DIR ) ), { Qgis::LayerType::VectorTile } ); sublayers = vectorTileMetadata->querySublayers( QStringLiteral( "type=vtpk&url=%1/testvtpk.vtpk" ).arg( TEST_DATA_DIR ) ); + QCOMPARE( sublayers.size(), 1 ); QCOMPARE( sublayers.at( 0 ).providerKey(), QStringLiteral( "vtpkvectortiles" ) ); QCOMPARE( sublayers.at( 0 ).name(), QStringLiteral( "testvtpk" ) ); - QCOMPARE( sublayers.at( 0 ).uri(), QStringLiteral( "type=vtpk&url=%1/testvtpk.vtpk" ).arg( TEST_DATA_DIR ) ); + QCOMPARE( sublayers.at( 0 ).uri(), QStringLiteral( "type=vtpk&url=%1" ).arg( localVtpkPath ) ); QCOMPARE( sublayers.at( 0 ).type(), Qgis::LayerType::VectorTile ); // test that vtpk provider is the preferred provider for vtpk files @@ -485,7 +495,9 @@ void TestQgsVectorTileLayer::test_relativePathsVtpk() contextRel.setPathResolver( QgsPathResolver( QStringLiteral( TEST_DATA_DIR ) + QStringLiteral( "/project.qgs" ) ) ); const QgsReadWriteContext contextAbs; - const QString srcVtpk = QStringLiteral( "type=vtpk&url=%1/testvtpk.vtpk" ).arg( TEST_DATA_DIR ); + QString localVtpkPath = QStringLiteral( "%1%2" ).arg( QUrl::toPercentEncoding( TEST_DATA_DIR ), QUrl::toPercentEncoding( QStringLiteral( "/testvtpk.vtpk" ) ) ); + + const QString srcVtpk = QStringLiteral( "type=vtpk&url=%1" ).arg( localVtpkPath ); std::unique_ptr layer = std::make_unique( srcVtpk ); QVERIFY( layer->isValid() ); @@ -493,7 +505,7 @@ void TestQgsVectorTileLayer::test_relativePathsVtpk() // encode source: converting absolute paths to relative const QString srcVtpkRel = layer->encodedSource( srcVtpk, contextRel ); - QCOMPARE( srcVtpkRel, QStringLiteral( "type=vtpk&url=./testvtpk.vtpk" ) ); + QCOMPARE( srcVtpkRel, QStringLiteral( "type=vtpk&url=.%2Ftestvtpk.vtpk" ) ); // encode source: keeping absolute paths QCOMPARE( layer->encodedSource( srcVtpk, contextAbs ), srcVtpk ); diff --git a/tests/src/providers/testqgswmsprovider.cpp b/tests/src/providers/testqgswmsprovider.cpp index 48ac8fa4df27..3171fbf00302 100644 --- a/tests/src/providers/testqgswmsprovider.cpp +++ b/tests/src/providers/testqgswmsprovider.cpp @@ -475,8 +475,8 @@ void TestQgsWmsProvider::absoluteRelativeUri() QgsProviderMetadata *wmsMetadata = QgsProviderRegistry::instance()->providerMetadata( "wms" ); QVERIFY( wmsMetadata ); - QString absoluteUri = "type=mbtiles&url=file://" + QStringLiteral( TEST_DATA_DIR ) + "/isle_of_man.mbtiles"; - QString relativeUri = "type=mbtiles&url=file:./isle_of_man.mbtiles"; + QString absoluteUri = "type=mbtiles&url=" + QString( QUrl::toPercentEncoding( "file://" + QStringLiteral( TEST_DATA_DIR ) + "/isle_of_man.mbtiles" ) ); + QString relativeUri = "type=mbtiles&url=file%3A.%2Fisle_of_man.mbtiles"; QCOMPARE( wmsMetadata->absoluteToRelativeUri( absoluteUri, context ), relativeUri ); QCOMPARE( wmsMetadata->relativeToAbsoluteUri( relativeUri, context ), absoluteUri ); } diff --git a/tests/src/python/test_qgsvectortile.py b/tests/src/python/test_qgsvectortile.py index a4866d1229b1..73b46c352193 100644 --- a/tests/src/python/test_qgsvectortile.py +++ b/tests/src/python/test_qgsvectortile.py @@ -105,7 +105,7 @@ def testEncodeDecodeUri(self): parts["path"] = "/my/new/file.mbtiles" uri = md.encodeUri(parts) - self.assertEqual(uri, "type=mbtiles&url=/my/new/file.mbtiles") + self.assertEqual(uri, "type=mbtiles&url=%2Fmy%2Fnew%2Ffile.mbtiles") uri = ( "type=xyz&url=https://fake.server/%7Bx%7D/%7By%7D/%7Bz%7D.png&zmin=0&zmax=2" @@ -125,7 +125,7 @@ def testEncodeDecodeUri(self): uri = md.encodeUri(parts) self.assertEqual( uri, - "type=xyz&url=https://fake.new.server/%7Bx%7D/%7By%7D/%7Bz%7D.png&zmax=2&zmin=0", + "type=xyz&url=https%3A%2F%2Ffake.new.server%2F%7Bx%7D%2F%7By%7D%2F%7Bz%7D.png&zmax=2&zmin=0", ) uri = "type=xyz&serviceType=arcgis&url=https://fake.server/%7Bx%7D/%7By%7D/%7Bz%7D.png&zmax=2&http-header:referer=https://qgis.org/&styleUrl=https://qgis.org/" @@ -147,7 +147,7 @@ def testEncodeDecodeUri(self): uri = md.encodeUri(parts) self.assertEqual( uri, - "serviceType=arcgis&styleUrl=https://qgis.org/&type=xyz&url=https://fake.new.server/%7Bx%7D/%7By%7D/%7Bz%7D.png&zmax=2&http-header:referer=https://qgis.org/", + "serviceType=arcgis&styleUrl=https%3A%2F%2Fqgis.org%2F&type=xyz&url=https%3A%2F%2Ffake.new.server%2F%7Bx%7D%2F%7By%7D%2F%7Bz%7D.png&zmax=2&http-header:referer=https://qgis.org/", ) def testZoomRange(self): diff --git a/tests/src/server/wms/test_qgsserver_wms_parameters.cpp b/tests/src/server/wms/test_qgsserver_wms_parameters.cpp index 792325c642b1..5aa2ab3bd9f9 100644 --- a/tests/src/server/wms/test_qgsserver_wms_parameters.cpp +++ b/tests/src/server/wms/test_qgsserver_wms_parameters.cpp @@ -64,14 +64,14 @@ void TestQgsServerWmsParameters::external_layers() QgsWms::QgsWmsParametersLayer layer_params = layers_params[0]; QCOMPARE( layer_params.mNickname, QString( "external_layer_1" ) ); - QCOMPARE( layer_params.mExternalUri, QString( "layers=layer_1_name&url=http://url_1" ) ); + QCOMPARE( layer_params.mExternalUri, QString( "layers=layer_1_name&url=http%3A%2F%2Furl_1" ) ); layer_params = layers_params[1]; QCOMPARE( layer_params.mNickname, QString( "layer" ) ); layer_params = layers_params[2]; QCOMPARE( layer_params.mNickname, QString( "external_layer_2" ) ); - QCOMPARE( layer_params.mExternalUri, QString( "layers=layer_2_name&opacities=100&url=http://url_2" ) ); + QCOMPARE( layer_params.mExternalUri, QString( "layers=layer_2_name&opacities=100&url=http%3A%2F%2Furl_2" ) ); //test if opacities are also applied to external layers QCOMPARE( layers_params[0].mOpacity, 255 ); @@ -94,7 +94,7 @@ void TestQgsServerWmsParameters::external_layers() QgsWms::QgsWmsParametersLayer layer_params2 = layers_params2[0]; QCOMPARE( layer_params2.mNickname, QString( "external_layer_1" ) ); - QCOMPARE( layer_params2.mExternalUri, QString( "layers=layer_1_name&url=http://url_1" ) ); + QCOMPARE( layer_params2.mExternalUri, QString( "layers=layer_1_name&url=http%3A%2F%2Furl_1" ) ); } void TestQgsServerWmsParameters::percent_encoding()