mirror of
https://github.com/qgis/QGIS.git
synced 2025-07-03 00:03:10 -04:00
Compare commits
20 Commits
83143a5c31
...
0b8e960237
Author | SHA1 | Date | |
---|---|---|---|
|
0b8e960237 | ||
|
739c6ec98e | ||
|
2b40e3a7a4 | ||
|
a3b523d368 | ||
|
4de79c55ba | ||
|
3d392af31d | ||
|
fa7f98a666 | ||
|
fd7c2bfec4 | ||
|
ade7904a42 | ||
|
6ee3e72827 | ||
|
f43bad1baa | ||
|
74549aad26 | ||
|
eac401c009 | ||
|
1f0166d35e | ||
|
ada589bb1d | ||
|
b1c8ef3265 | ||
|
f4cf09d4b0 | ||
|
9db58e3726 | ||
|
551aa20f20 | ||
|
a156c43f7b |
@ -979,7 +979,31 @@ if (WITH_CORE)
|
||||
else()
|
||||
# UNIX
|
||||
set (DEFAULT_BIN_SUBDIR bin)
|
||||
set (DEFAULT_CGIBIN_SUBDIR bin)
|
||||
|
||||
# From https://www.cyberciti.biz/faq/how-do-i-find-the-url-for-my-cgi-bin/
|
||||
execute_process(COMMAND lsb_release -a OUTPUT_VARIABLE LSB_RELEASE_A)
|
||||
if(EXISTS "/etc/fedora-release")
|
||||
# in /var/www/cgi-bin
|
||||
set (DEFAULT_CGIBIN_SUBDIR www/cgi-bin)
|
||||
|
||||
elseif (${CMAKE_HOST_SYSTEM_NAME} MATCHES "FreeBSD")
|
||||
# in /usr/local/www/cgi-bin/
|
||||
set (DEFAULT_CGIBIN_SUBDIR www/cgi-bin)
|
||||
|
||||
elseif (${CMAKE_HOST_SYSTEM_NAME} MATCHES "BSD")
|
||||
# in /usr/local/libexec/cgi-bin/
|
||||
set (DEFAULT_CGIBIN_SUBDIR libexec/cgi-bin)
|
||||
|
||||
elseif ("${LSB_RELEASE_A}" MATCHES "Ubuntu" OR "${LSB_RELEASE_A}" MATCHES "Debian" OR "${LSB_RELEASE_A}" MATCHES "Mint")
|
||||
# in /usr/lib/cgi-bin/
|
||||
set (DEFAULT_CGIBIN_SUBDIR lib/cgi-bin)
|
||||
|
||||
else()
|
||||
# others: Red Hat/CentOS/Rocky/Alma Linux
|
||||
# in /var/www/cgi-bin/
|
||||
set (DEFAULT_CGIBIN_SUBDIR www/cgi-bin)
|
||||
endif()
|
||||
|
||||
set (DEFAULT_LIB_SUBDIR lib${LIB_SUFFIX})
|
||||
set (DEFAULT_DATA_SUBDIR share/qgis)
|
||||
set (DEFAULT_LIBEXEC_SUBDIR lib${LIB_SUFFIX}/qgis)
|
||||
|
@ -659,7 +659,10 @@ class Repositories(QObject):
|
||||
.strip()
|
||||
)
|
||||
if not qgisMaximumVersion:
|
||||
qgisMaximumVersion = qgisMinimumVersion[0] + ".99"
|
||||
if qgisMinimumVersion[0] == "3" and supports_qt6:
|
||||
qgisMaximumVersion = "4.99"
|
||||
else:
|
||||
qgisMaximumVersion = qgisMinimumVersion[0] + ".99"
|
||||
# if compatible, add the plugin to the list
|
||||
if not pluginNodes.item(i).firstChildElement(
|
||||
"disabled"
|
||||
@ -845,7 +848,10 @@ class Plugins(QObject):
|
||||
qgisMinimumVersion = "0"
|
||||
qgisMaximumVersion = pluginMetadata("qgisMaximumVersion").strip()
|
||||
if not qgisMaximumVersion:
|
||||
qgisMaximumVersion = qgisMinimumVersion[0] + ".99"
|
||||
if qgisMinimumVersion[0] == "3" and supports_qt6:
|
||||
qgisMaximumVersion = "4.99"
|
||||
else:
|
||||
qgisMaximumVersion = qgisMinimumVersion[0] + ".99"
|
||||
# if compatible, add the plugin to the list
|
||||
if not isCompatible(
|
||||
pyQgisVersion(), qgisMinimumVersion, qgisMaximumVersion
|
||||
|
@ -727,19 +727,25 @@ bool QgsPluginRegistry::checkPythonPlugin( const QString &packageName )
|
||||
bool QgsPluginRegistry::isPythonPluginCompatible( const QString &packageName ) const
|
||||
{
|
||||
#ifdef WITH_BINDINGS
|
||||
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
|
||||
bool supportsQgis4 = true;
|
||||
const QString supportsQt6 = mPythonUtils->getPluginMetadata( packageName, QStringLiteral( "supportsQt6" ) ).trimmed();
|
||||
if ( supportsQt6.compare( QLatin1String( "YES" ), Qt::CaseInsensitive ) != 0 && supportsQt6.compare( QLatin1String( "TRUE" ), Qt::CaseInsensitive ) != 0 )
|
||||
{
|
||||
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
|
||||
if ( !getenv( "QGIS_DISABLE_SUPPORTS_QT6_CHECK" ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
supportsQgis4 = false;
|
||||
}
|
||||
const QString minVersion = mPythonUtils->getPluginMetadata( packageName, QStringLiteral( "qgisMinimumVersion" ) );
|
||||
// try to read qgisMaximumVersion. Note checkQgisVersion can cope with "__error__" value.
|
||||
const QString maxVersion = mPythonUtils->getPluginMetadata( packageName, QStringLiteral( "qgisMaximumVersion" ) );
|
||||
QString maxVersion = mPythonUtils->getPluginMetadata( packageName, QStringLiteral( "qgisMaximumVersion" ) );
|
||||
if ( maxVersion == QLatin1String( "__error__" ) && minVersion.startsWith( QLatin1String( "3." ) ) && supportsQgis4 )
|
||||
{
|
||||
maxVersion = QLatin1String( "4.99.0" );
|
||||
}
|
||||
return minVersion != QLatin1String( "__error__" ) && checkQgisVersion( minVersion, maxVersion );
|
||||
#else
|
||||
Q_UNUSED( packageName )
|
||||
|
@ -1532,6 +1532,7 @@ void QgsLineString::visitPointsByRegularDistance( const double distance, const s
|
||||
double pZ = std::numeric_limits<double>::quiet_NaN();
|
||||
double pM = std::numeric_limits<double>::quiet_NaN();
|
||||
double nextPointDistance = distance;
|
||||
const double eps = 4 * nextPointDistance * std::numeric_limits<double>::epsilon ();
|
||||
for ( int i = 1; i < totalPoints; ++i )
|
||||
{
|
||||
double thisX = *x++;
|
||||
@ -1540,7 +1541,7 @@ void QgsLineString::visitPointsByRegularDistance( const double distance, const s
|
||||
double thisM = m ? *m++ : 0.0;
|
||||
|
||||
const double segmentLength = QgsGeometryUtilsBase::distance2D( thisX, thisY, prevX, prevY );
|
||||
while ( nextPointDistance < distanceTraversed + segmentLength || qgsDoubleNear( nextPointDistance, distanceTraversed + segmentLength ) )
|
||||
while ( nextPointDistance < distanceTraversed + segmentLength || qgsDoubleNear( nextPointDistance, distanceTraversed + segmentLength, eps ) )
|
||||
{
|
||||
// point falls on this segment - truncate to segment length if qgsDoubleNear test was actually > segment length
|
||||
const double distanceToPoint = std::min( nextPointDistance - distanceTraversed, segmentLength );
|
||||
|
@ -73,7 +73,7 @@ bool QgsHttpHeaders::updateUrlQuery( QUrlQuery &uri ) const
|
||||
{
|
||||
for ( auto ite = mHeaders.constBegin(); ite != mHeaders.constEnd(); ++ite )
|
||||
{
|
||||
uri.addQueryItem( QgsHttpHeaders::PARAM_PREFIX + ite.key().toUtf8(), ite.value().toString().toUtf8() );
|
||||
uri.addQueryItem( QgsHttpHeaders::PARAM_PREFIX + ite.key().toUtf8(), QUrl::toPercentEncoding( ite.value().toString() ) );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -116,21 +116,6 @@ QStringList makeKeyTokens_( const QString &scope, const QString &key )
|
||||
// be sure to include the canonical root node
|
||||
keyTokens.push_front( QStringLiteral( "properties" ) );
|
||||
|
||||
//check validy of keys since an invalid xml name will will be dropped upon saving the xml file. If not valid, we print a message to the console.
|
||||
for ( int i = 0; i < keyTokens.size(); ++i )
|
||||
{
|
||||
const QString keyToken = keyTokens.at( i );
|
||||
|
||||
//invalid chars in XML are found at http://www.w3.org/TR/REC-xml/#NT-NameChar
|
||||
//note : it seems \x10000-\xEFFFF is valid, but it when added to the regexp, a lot of unwanted characters remain
|
||||
const thread_local QRegularExpression sInvalidRegexp = QRegularExpression( QStringLiteral( "([^:A-Z_a-z\\x{C0}-\\x{D6}\\x{D8}-\\x{F6}\\x{F8}-\\x{2FF}\\x{370}-\\x{37D}\\x{37F}-\\x{1FFF}\\x{200C}-\\x{200D}\\x{2070}-\\x{218F}\\x{2C00}-\\x{2FEF}\\x{3001}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFFD}\\-\\.0-9\\x{B7}\\x{0300}-\\x{036F}\\x{203F}-\\x{2040}]|^[^:A-Z_a-z\\x{C0}-\\x{D6}\\x{D8}-\\x{F6}\\x{F8}-\\x{2FF}\\x{370}-\\x{37D}\\x{37F}-\\x{1FFF}\\x{200C}-\\x{200D}\\x{2070}-\\x{218F}\\x{2C00}-\\x{2FEF}\\x{3001}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFFD}])" ) );
|
||||
if ( keyToken.contains( sInvalidRegexp ) )
|
||||
{
|
||||
const QString errorString = QObject::tr( "Entry token invalid : '%1'. The token will not be saved to file." ).arg( keyToken );
|
||||
QgsMessageLog::logMessage( errorString, QString(), Qgis::MessageLevel::Critical );
|
||||
}
|
||||
}
|
||||
|
||||
return keyTokens;
|
||||
}
|
||||
|
||||
@ -1322,20 +1307,20 @@ void dump_( const QgsProjectPropertyKey &topQgsPropertyKey )
|
||||
* scope. "layers" is a list containing three string values.
|
||||
*
|
||||
* \code{.xml}
|
||||
* <properties>
|
||||
* <fsplugin>
|
||||
* <foo type="int" >42</foo>
|
||||
* <baz type="int" >1</baz>
|
||||
* <layers type="QStringList" >
|
||||
* <properties name="properties">
|
||||
* <properties name="fsplugin">
|
||||
* <properties name="foo" type="int" >42</properties>
|
||||
* <properties name="baz" type="int" >1</properties>
|
||||
* <properties name="layers" type="QStringList">
|
||||
* <value>railroad</value>
|
||||
* <value>airport</value>
|
||||
* </layers>
|
||||
* <xyqzzy type="int" >1</xyqzzy>
|
||||
* <bar type="double" >123.456</bar>
|
||||
* <feature_types type="QStringList" >
|
||||
* </properties>
|
||||
* <properties name="xyqzzy" type="int" >1</properties>
|
||||
* <properties name="bar" type="double" >123.456</properties>
|
||||
* <properties name="feature_types" type="QStringList">
|
||||
* <value>type</value>
|
||||
* </feature_types>
|
||||
* </fsplugin>
|
||||
* </properties>
|
||||
* </properties>
|
||||
* </properties>
|
||||
* \endcode
|
||||
*
|
||||
@ -3992,10 +3977,25 @@ bool QgsProject::createEmbeddedLayer( const QString &layerId, const QString &pro
|
||||
const QDomElement propertiesElem = sProjectDocument.documentElement().firstChildElement( QStringLiteral( "properties" ) );
|
||||
if ( !propertiesElem.isNull() )
|
||||
{
|
||||
const QDomElement absElem = propertiesElem.firstChildElement( QStringLiteral( "Paths" ) ).firstChildElement( QStringLiteral( "Absolute" ) );
|
||||
if ( !absElem.isNull() )
|
||||
QDomElement e = propertiesElem.firstChildElement( QStringLiteral( "Paths" ) );
|
||||
if ( e.isNull() )
|
||||
{
|
||||
useAbsolutePaths = absElem.text().compare( QLatin1String( "true" ), Qt::CaseInsensitive ) == 0;
|
||||
e = propertiesElem.firstChildElement( QStringLiteral( "properties" ) );
|
||||
while ( !e.isNull() && e.attribute( QStringLiteral( "name" ) ) != QStringLiteral( "Paths" ) )
|
||||
e = e.nextSiblingElement( QStringLiteral( "properties" ) );
|
||||
|
||||
e = e.firstChildElement( QStringLiteral( "properties" ) );
|
||||
while ( !e.isNull() && e.attribute( QStringLiteral( "name" ) ) != QStringLiteral( "Absolute" ) )
|
||||
e = e.nextSiblingElement( QStringLiteral( "properties" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
e = e.firstChildElement( QStringLiteral( "Absolute" ) );
|
||||
}
|
||||
|
||||
if ( !e.isNull() )
|
||||
{
|
||||
useAbsolutePaths = e.text().compare( QLatin1String( "true" ), Qt::CaseInsensitive ) == 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -233,15 +233,15 @@ bool QgsProjectPropertyValue::readXml( const QDomNode &keyNode )
|
||||
|
||||
// keyElement is created by parent QgsProjectPropertyKey
|
||||
bool QgsProjectPropertyValue::writeXml( QString const &nodeName,
|
||||
QDomElement &keyElement,
|
||||
QDomDocument &document )
|
||||
QDomElement &keyElement,
|
||||
QDomDocument &document )
|
||||
{
|
||||
QDomElement valueElement = document.createElement( nodeName );
|
||||
QDomElement valueElement = document.createElement( QStringLiteral( "properties" ) );
|
||||
|
||||
// remember the type so that we can rebuild it when the project is read in
|
||||
valueElement.setAttribute( QStringLiteral( "name" ), nodeName );
|
||||
valueElement.setAttribute( QStringLiteral( "type" ), mValue.typeName() );
|
||||
|
||||
|
||||
// we handle string lists differently from other types in that we
|
||||
// create a sequence of repeated elements to cover all the string list
|
||||
// members; each value will be in a <value></value> tag.
|
||||
@ -362,33 +362,41 @@ bool QgsProjectPropertyKey::readXml( const QDomNode &keyNode )
|
||||
|
||||
while ( i < subkeys.count() )
|
||||
{
|
||||
const QDomNode subkey = subkeys.item( i );
|
||||
QString name;
|
||||
|
||||
if ( subkey.nodeName() == QStringLiteral( "properties" ) &&
|
||||
subkey.hasAttributes() && // if we have attributes
|
||||
subkey.isElement() && // and we're an element
|
||||
subkey.toElement().hasAttribute( QStringLiteral( "name" ) ) ) // and we have a "name" attribute
|
||||
name = subkey.toElement().attribute( QStringLiteral( "name" ) );
|
||||
else
|
||||
name = subkey.nodeName();
|
||||
|
||||
// if the current node is an element that has a "type" attribute,
|
||||
// then we know it's a leaf node; i.e., a subkey _value_, and not
|
||||
// a subkey
|
||||
if ( subkeys.item( i ).hasAttributes() && // if we have attributes
|
||||
subkeys.item( i ).isElement() && // and we're an element
|
||||
subkeys.item( i ).toElement().hasAttribute( QStringLiteral( "type" ) ) ) // and we have a "type" attribute
|
||||
if ( subkey.hasAttributes() && // if we have attributes
|
||||
subkey.isElement() && // and we're an element
|
||||
subkey.toElement().hasAttribute( QStringLiteral( "type" ) ) ) // and we have a "type" attribute
|
||||
{
|
||||
// then we're a key value
|
||||
delete mProperties.take( subkeys.item( i ).nodeName() );
|
||||
mProperties.insert( subkeys.item( i ).nodeName(), new QgsProjectPropertyValue );
|
||||
//
|
||||
delete mProperties.take( name );
|
||||
mProperties.insert( name, new QgsProjectPropertyValue );
|
||||
|
||||
QDomNode subkey = subkeys.item( i );
|
||||
|
||||
if ( !mProperties[subkeys.item( i ).nodeName()]->readXml( subkey ) )
|
||||
if ( !mProperties[name]->readXml( subkey ) )
|
||||
{
|
||||
QgsDebugError( QStringLiteral( "unable to parse key value %1" ).arg( subkeys.item( i ).nodeName() ) );
|
||||
QgsDebugError( QStringLiteral( "unable to parse key value %1" ).arg( name ) );
|
||||
}
|
||||
}
|
||||
else // otherwise it's a subkey, so just recurse on down the remaining keys
|
||||
{
|
||||
addKey( subkeys.item( i ).nodeName() );
|
||||
addKey( name );
|
||||
|
||||
QDomNode subkey = subkeys.item( i );
|
||||
|
||||
if ( !mProperties[subkeys.item( i ).nodeName()]->readXml( subkey ) )
|
||||
if ( !mProperties[name]->readXml( subkey ) )
|
||||
{
|
||||
QgsDebugError( QStringLiteral( "unable to parse subkey %1" ).arg( subkeys.item( i ).nodeName() ) );
|
||||
QgsDebugError( QStringLiteral( "unable to parse subkey %1" ).arg( name ) );
|
||||
}
|
||||
}
|
||||
|
||||
@ -408,7 +416,8 @@ bool QgsProjectPropertyKey::writeXml( QString const &nodeName, QDomElement &elem
|
||||
// If it's an _empty_ node (i.e., one with no properties) we need to emit
|
||||
// an empty place holder; else create new Dom elements as necessary.
|
||||
|
||||
QDomElement keyElement = document.createElement( nodeName ); // Dom element for this property key
|
||||
QDomElement keyElement = document.createElement( "properties" ); // Dom element for this property key
|
||||
keyElement.toElement().setAttribute( QStringLiteral( "name" ), nodeName );
|
||||
|
||||
if ( ! mProperties.isEmpty() )
|
||||
{
|
||||
|
@ -33,8 +33,7 @@ QgsProjectStorage *QgsProjectStorageRegistry::projectStorageFromUri( const QStri
|
||||
for ( auto it = mBackends.constBegin(); it != mBackends.constEnd(); ++it )
|
||||
{
|
||||
QgsProjectStorage *storage = it.value();
|
||||
const QString scheme = storage->type() + ':';
|
||||
if ( uri.startsWith( scheme ) )
|
||||
if ( uri.startsWith( storage->type() + ':' ) || uri.startsWith( storage->type() + "%3A" ) )
|
||||
return storage;
|
||||
}
|
||||
|
||||
|
@ -701,17 +701,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 );
|
||||
|
||||
@ -731,7 +731,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<QString, QString> &item : constQueryItems )
|
||||
{
|
||||
if ( !item.first.startsWith( QgsHttpHeaders::PARAM_PREFIX ) && item.first != QgsHttpHeaders::KEY_REFERER )
|
||||
@ -928,7 +928,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
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -933,7 +933,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() );
|
||||
|
||||
|
@ -38,6 +38,7 @@ class TestQgsDataSourceUri : public QObject
|
||||
void checkParameterKeys();
|
||||
void checkRemovePassword();
|
||||
void checkUnicodeUri();
|
||||
void checkUriInUri();
|
||||
};
|
||||
|
||||
void TestQgsDataSourceUri::checkparser_data()
|
||||
@ -775,7 +776,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" ) );
|
||||
@ -822,6 +823,83 @@ void TestQgsDataSourceUri::checkUnicodeUri()
|
||||
QCOMPARE( uri.param( QStringLiteral( "url" ) ), QStringLiteral( "file:///directory/テスト.mbtiles" ) );
|
||||
}
|
||||
|
||||
void TestQgsDataSourceUri::checkUriInUri()
|
||||
{
|
||||
QString dataUri = QStringLiteral( "dpiMode=7&url=%1&SERVICE=WMS&REQUEST=GetCapabilities&username=username&password=qgis%C3%A8%C3%A9" );
|
||||
|
||||
// If the 'url' field references a QGIS server then the 'MAP' parameter can contain an url to the project file.
|
||||
// When the project is saved in a postgresql db, the connection url will also contains '&' and '='.
|
||||
{
|
||||
QgsDataSourceUri uri;
|
||||
// here the project url is encoded but the whole serverUrl is not encoded.
|
||||
// The OGC server will receive a call with this url: http://localhost:8000/ows/?MAP=postgresql://?service=qgis_test&dbname&schema=project&project=luxembourg&SERVICE=WMS&REQUEST=GetCapabilities
|
||||
// from the OGC server POV the 'schema' and 'project' keys will be parsed as main query parameters for 'http://localhost:8000/ows/?'
|
||||
// and not associated to the project file uri.
|
||||
QString project = "postgresql://?service=qgis_test&dbname&schema=project&project=luxembourg";
|
||||
QString projectEnc = QUrl::toPercentEncoding( project );
|
||||
QString serverUrl = QString( "http://localhost:8000/ows/?MAP=%1" );
|
||||
uri.setEncodedUri( dataUri.arg( serverUrl.arg( projectEnc ) ) );
|
||||
QCOMPARE( uri.param( QStringLiteral( "username" ) ), QStringLiteral( "username" ) );
|
||||
QCOMPARE( uri.username(), QStringLiteral( "username" ) );
|
||||
QCOMPARE( uri.param( QStringLiteral( "password" ) ), QStringLiteral( "qgisèé" ) );
|
||||
QCOMPARE( uri.password(), QStringLiteral( "qgisèé" ) );
|
||||
QCOMPARE( uri.param( QStringLiteral( "SERVICE" ) ), QStringLiteral( "WMS" ) );
|
||||
QCOMPARE( uri.param( QStringLiteral( "REQUEST" ) ), QStringLiteral( "GetCapabilities" ) );
|
||||
// not enough encoded at the beginning ==> bad encoding at the end
|
||||
QCOMPARE( uri.param( QStringLiteral( "url" ) ), serverUrl.arg( project ) );
|
||||
|
||||
QgsDataSourceUri uri2;
|
||||
// here the project url is encoded and the whole serverUrl is also encoded.
|
||||
// The OGC server will receive a call with this url: http://localhost:8000/ows/?MAP=postgresql%3A%2F%2F%3Fservice%3Dqgis_test%26dbname%26schema%3Dproject%26project%3Dluxembourg&SERVICE=WMS&REQUEST=GetCapabilities
|
||||
// and will be able to decode all parameters
|
||||
QString serverUrlEnc = QUrl::toPercentEncoding( serverUrl.arg( projectEnc ) );
|
||||
uri2.setEncodedUri( dataUri.arg( serverUrlEnc ) );
|
||||
QCOMPARE( uri2.param( QStringLiteral( "username" ) ), QStringLiteral( "username" ) );
|
||||
QCOMPARE( uri2.username(), QStringLiteral( "username" ) );
|
||||
QCOMPARE( uri2.param( QStringLiteral( "password" ) ), QStringLiteral( "qgisèé" ) );
|
||||
QCOMPARE( uri2.password(), QStringLiteral( "qgisèé" ) );
|
||||
QCOMPARE( uri2.param( QStringLiteral( "SERVICE" ) ), QStringLiteral( "WMS" ) );
|
||||
QCOMPARE( uri2.param( QStringLiteral( "REQUEST" ) ), QStringLiteral( "GetCapabilities" ) );
|
||||
QCOMPARE( uri2.param( QStringLiteral( "url" ) ), serverUrl.arg( projectEnc ) );
|
||||
}
|
||||
|
||||
// same as above but with extra param at the end of the
|
||||
{
|
||||
QgsDataSourceUri uri;
|
||||
// here the project url is encoded but the whole serverUrl is not encoded.
|
||||
// The OGC server will receive a call with this url: https://titiler.xyz/cog/tiles/WebMercatorQuad/16/34060/23336@1x?url=https://data.geo.admin.ch/ch.swisstopo.swissalti3d/swissalti3d_2019_2573-1085/swissalti3d_2019_2573-1085_0.5_2056_5728.tif&bidx=1&rescale=1600%2C2100&colormap_name=gist_earth
|
||||
// from the OGC server POV the 'rescale' and 'colormap_name' keys could be parsed as sub query parameters for 'https://data.geo.admin.ch/'
|
||||
QString project = "https://data.geo.admin.ch/ch.swisstopo.swissalti3d/swissalti3d_2019_2573-1085/swissalti3d_2019_2573-1085_0.5_2056_5728.tif";
|
||||
QString projectEnc = QUrl::toPercentEncoding( project );
|
||||
QString extraParam = "&bidx=1&rescale=1600%2C2100&colormap_name=gist_earth";
|
||||
QString serverUrl = QString( "https://titiler.xyz/cog/tiles/WebMercatorQuad/16/34060/23336@1x?url=%1" );
|
||||
|
||||
uri.setEncodedUri( dataUri.arg( serverUrl.arg( projectEnc ) + extraParam ) );
|
||||
QCOMPARE( uri.param( QStringLiteral( "username" ) ), QStringLiteral( "username" ) );
|
||||
QCOMPARE( uri.username(), QStringLiteral( "username" ) );
|
||||
QCOMPARE( uri.param( QStringLiteral( "password" ) ), QStringLiteral( "qgisèé" ) );
|
||||
QCOMPARE( uri.password(), QStringLiteral( "qgisèé" ) );
|
||||
QCOMPARE( uri.param( QStringLiteral( "SERVICE" ) ), QStringLiteral( "WMS" ) );
|
||||
QCOMPARE( uri.param( QStringLiteral( "REQUEST" ) ), QStringLiteral( "GetCapabilities" ) );
|
||||
// not enough encoded at the beginning ==> bad encoding at the end
|
||||
QCOMPARE( uri.param( QStringLiteral( "url" ) ), serverUrl.arg( project ) );
|
||||
|
||||
QgsDataSourceUri uri2;
|
||||
// here the project url is encoded and the whole serverUrl is also encoded.
|
||||
// The OGC server will receive a call with this url: https://titiler.xyz/cog/tiles/WebMercatorQuad/16/34060/23336@1x?url=https%3A%2F%2Fdata.geo.admin.ch%2Fch.swisstopo.swissalti3d%2Fswissalti3d_2019_2573-1085%2Fswissalti3d_2019_2573-1085_0.5_2056_5728.tif&bidx=1&rescale=1600%2C2100&colormap_name=gist_earth
|
||||
// and will be able to decode all parameters
|
||||
QString serverUrlEnc = QUrl::toPercentEncoding( serverUrl.arg( projectEnc ) + extraParam );
|
||||
uri2.setEncodedUri( dataUri.arg( serverUrlEnc ) );
|
||||
QCOMPARE( uri2.param( QStringLiteral( "username" ) ), QStringLiteral( "username" ) );
|
||||
QCOMPARE( uri2.username(), QStringLiteral( "username" ) );
|
||||
QCOMPARE( uri2.param( QStringLiteral( "password" ) ), QStringLiteral( "qgisèé" ) );
|
||||
QCOMPARE( uri2.password(), QStringLiteral( "qgisèé" ) );
|
||||
QCOMPARE( uri2.param( QStringLiteral( "SERVICE" ) ), QStringLiteral( "WMS" ) );
|
||||
QCOMPARE( uri2.param( QStringLiteral( "REQUEST" ) ), QStringLiteral( "GetCapabilities" ) );
|
||||
QCOMPARE( uri2.param( QStringLiteral( "url" ) ), serverUrl.arg( projectEnc ) + extraParam );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QGSTEST_MAIN( TestQgsDataSourceUri )
|
||||
#include "testqgsdatasourceuri.moc"
|
||||
|
@ -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;
|
||||
|
@ -187,11 +187,14 @@ void TestQgsHttpheaders::createQgsOwsConnection()
|
||||
|
||||
QgsOwsConnection ows( "service", "name" );
|
||||
QCOMPARE( ows.connectionInfo(), ",authcfg=,referer=http://test.com" );
|
||||
QCOMPARE( ows.uri().encodedUri(), "url&http-header:other_http_header=value&http-header:referer=http://test.com" );
|
||||
if ( ows.uri().encodedUri().startsWith( "url=" ) )
|
||||
QCOMPARE( ows.uri().encodedUri(), "url=&http-header:other_http_header=value&http-header:referer=http%3A%2F%2Ftest.com" );
|
||||
else
|
||||
QCOMPARE( ows.uri().encodedUri(), "url&http-header:other_http_header=value&http-header:referer=http%3A%2F%2Ftest.com" );
|
||||
|
||||
QgsDataSourceUri uri( QString( "https://www.ogc.org/?p1=v1" ) );
|
||||
QgsDataSourceUri uri2 = ows.addWmsWcsConnectionSettings( uri, "service", "name" );
|
||||
QCOMPARE( uri2.encodedUri(), "https://www.ogc.org/?p1=v1&http-header:other_http_header=value&http-header:referer=http://test.com" );
|
||||
QCOMPARE( uri2.encodedUri(), "https://www.ogc.org/?p1=v1&http-header:other_http_header=value&http-header:referer=http%3A%2F%2Ftest.com" );
|
||||
|
||||
// check space separated string
|
||||
QCOMPARE( uri2.uri(), " https://www.ogc.org/?p1='v1' http-header:other_http_header='value' http-header:referer='http://test.com' referer='http://test.com'" );
|
||||
@ -199,7 +202,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%3A%2F%2Ftest.com" );
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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,7 +97,7 @@ 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( 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
|
||||
@ -110,7 +110,7 @@ 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( 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" ) );
|
||||
|
||||
|
@ -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" ) );
|
||||
}
|
||||
|
||||
|
||||
|
@ -260,11 +260,12 @@ 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<QgsProviderSublayerDetails> 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 ) );
|
||||
@ -273,7 +274,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() );
|
||||
|
||||
@ -282,7 +283,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 ) );
|
||||
@ -291,17 +292,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() );
|
||||
|
||||
@ -332,8 +335,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 );
|
||||
|
||||
auto layer = std::make_unique<QgsVectorTileLayer>( srcMbtiles );
|
||||
QVERIFY( layer->isValid() );
|
||||
@ -341,7 +345,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 );
|
||||
@ -392,7 +396,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";
|
||||
|
||||
auto layer = std::make_unique<QgsVectorTileLayer>( srcXyzLocal );
|
||||
@ -400,7 +404,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
|
||||
@ -436,7 +440,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 );
|
||||
}
|
||||
|
||||
@ -458,22 +463,24 @@ 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<QgsProviderSublayerDetails> 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( vectorTileMetadata->priorityForUri( QStringLiteral( "type=vtpk&url=%1" ).arg( localVtpkPath ) ), 100 );
|
||||
QCOMPARE( vectorTileMetadata->validLayerTypesForUri( QStringLiteral( "type=vtpk&url=%1" ).arg( localVtpkPath ) ), {Qgis::LayerType::VectorTile} );
|
||||
sublayers = vectorTileMetadata->querySublayers( QStringLiteral( "type=vtpk&url=%1" ).arg( localVtpkPath ) );
|
||||
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
|
||||
@ -500,7 +507,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 );
|
||||
|
||||
auto layer = std::make_unique<QgsVectorTileLayer>( srcVtpk );
|
||||
QVERIFY( layer->isValid() );
|
||||
@ -508,7 +517,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 );
|
||||
|
@ -469,8 +469,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 );
|
||||
}
|
||||
|
@ -65,84 +65,6 @@ class TestQgsProject(QgisTestCase):
|
||||
QgisTestCase.__init__(self, methodName)
|
||||
self.messageCaught = False
|
||||
|
||||
def test_makeKeyTokens_(self):
|
||||
# see http://www.w3.org/TR/REC-xml/#d0e804 for a list of valid characters
|
||||
|
||||
invalidTokens = []
|
||||
validTokens = []
|
||||
|
||||
# all test tokens will be generated by prepending or inserting characters to this token
|
||||
validBase = "valid"
|
||||
|
||||
# some invalid characters, not allowed anywhere in a token
|
||||
# note that '/' must not be added here because it is taken as a separator by makeKeyTokens_()
|
||||
invalidChars = "+*,;<>|!$%()=?#\x01"
|
||||
|
||||
# generate the characters that are allowed at the start of a token (and at every other position)
|
||||
validStartChars = ":_"
|
||||
charRanges = [
|
||||
(ord("a"), ord("z")),
|
||||
(ord("A"), ord("Z")),
|
||||
(0x00F8, 0x02FF),
|
||||
(0x0370, 0x037D),
|
||||
(0x037F, 0x1FFF),
|
||||
(0x200C, 0x200D),
|
||||
(0x2070, 0x218F),
|
||||
(0x2C00, 0x2FEF),
|
||||
(0x3001, 0xD7FF),
|
||||
(0xF900, 0xFDCF),
|
||||
(0xFDF0, 0xFFFD),
|
||||
# (0x10000, 0xEFFFF), while actually valid, these are not yet accepted by makeKeyTokens_()
|
||||
]
|
||||
for r in charRanges:
|
||||
for c in range(r[0], r[1]):
|
||||
validStartChars += chr(c)
|
||||
|
||||
# generate the characters that are only allowed inside a token, not at the start
|
||||
validInlineChars = "-.\xB7"
|
||||
charRanges = [
|
||||
(ord("0"), ord("9")),
|
||||
(0x0300, 0x036F),
|
||||
(0x203F, 0x2040),
|
||||
]
|
||||
for r in charRanges:
|
||||
for c in range(r[0], r[1]):
|
||||
validInlineChars += chr(c)
|
||||
|
||||
# test forbidden start characters
|
||||
for c in invalidChars + validInlineChars:
|
||||
invalidTokens.append(c + validBase)
|
||||
|
||||
# test forbidden inline characters
|
||||
for c in invalidChars:
|
||||
invalidTokens.append(validBase[:4] + c + validBase[4:])
|
||||
|
||||
# test each allowed start character
|
||||
for c in validStartChars:
|
||||
validTokens.append(c + validBase)
|
||||
|
||||
# test each allowed inline character
|
||||
for c in validInlineChars:
|
||||
validTokens.append(validBase[:4] + c + validBase[4:])
|
||||
|
||||
logger = QgsApplication.messageLog()
|
||||
logger.messageReceived.connect(self.catchMessage)
|
||||
prj = QgsProject.instance()
|
||||
|
||||
for token in validTokens:
|
||||
self.messageCaught = False
|
||||
prj.readEntry("test", token)
|
||||
myMessage = f"valid token '{token}' not accepted"
|
||||
assert not self.messageCaught, myMessage
|
||||
|
||||
for token in invalidTokens:
|
||||
self.messageCaught = False
|
||||
prj.readEntry("test", token)
|
||||
myMessage = f"invalid token '{token}' accepted"
|
||||
assert self.messageCaught, myMessage
|
||||
|
||||
logger.messageReceived.disconnect(self.catchMessage)
|
||||
|
||||
def catchMessage(self):
|
||||
self.messageCaught = True
|
||||
|
||||
|
@ -105,7 +105,7 @@ class TestVectorTile(QgisTestCase):
|
||||
|
||||
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 @@ class TestVectorTile(QgisTestCase):
|
||||
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 @@ class TestVectorTile(QgisTestCase):
|
||||
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%3A%2F%2Fqgis.org%2F",
|
||||
)
|
||||
|
||||
def testZoomRange(self):
|
||||
|
@ -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()
|
||||
|
Loading…
x
Reference in New Issue
Block a user