What is the bug or the crash?
QGIS improperly encodes/decodes data source URLs, including URL parameter values, causing the original values to be altered and leading to data loss. Additionally, QgsDataSourceUri does not fully URL-encode the values when assembling the data source string leading to potential data loss.
When constructing a QgsDataSourceUri, parameter values are not fully URL-encoded. In this case only the =is encoded to %26. This can result in incorrect URL parameters being sent in the requests. For example:
-
Original URL added as WMS source:
https://127.0.0.1/%26%3F%26%3F/?non_standard_param=%26%3F%26%3F%26%3F
-
Resulting QgsDataSourceUri string:
dpiMode=7&featureCount=10&tilePixelRatio=0&url=https://127.0.0.1/%26%3F%26%3F/?non_standard_param%3D%26%3F%26%3F%26%3F
-
Actual GetCapabilities Request Sent:
https://127.0.0.1/&?&?/?non_standard_param=&?&?&?SERVICE=WMS&REQUEST=GetCapabilities
Expected behaviour
-
Original URL added as WMS source:
https://127.0.0.1/%26%3F%26%3F/?non_standard_param=%26%3F%26%3F%26%3F
-
Resulting QgsDataSourceUri string (values are fully URL-encoded:
dpiMode=7&featureCount=10&tilePixelRatio=0&url=https%3A%2F%2F127.0.0.1%2F%2526%253F%2526%253F%2F%3Fnon_standard_param%3D%2526%253F%2526%253F%2526%253F
-
Actual GetCapabilities Request Sent:
https://127.0.0.1/%26%3F%26%3F/?non_standard_param=%26%3F%26%3F%26%3F&SERVICE=WMS&REQUEST=GetCapabilities
Steps to reproduce the issue
- open QGIS and the request debug console
- add a WMS data source with the URL
https://127.0.0.1/%26%3F%26%3F/?non_standard_param=%26%3F%26%3F%26%3F
- in qgsnewhttpconnection.cpp (363) QUrl decodes some of the URL-encoded characters resulting in
https://127.0.0.1/%26?%26?/
QUrl url( txtUrl->text().trimmed() );
- in qgsnewhttpconnection.cpp (381) the QUrl query is set to
non_standard_param=%26%3F%26%3F%26%3F
url.setQuery( query );
- in qgsowsconnection.cpp (87) the QgsDataSourceUri param "url" is set to the original url
https://127.0.0.1/%26%3F%26%3F/?non_standard_param=%26%3F%26%3F%26%3F resulting in the param value
mUri.setParam( QStringLiteral( "url" ), url );
- right click the new WMS data source and click refresh
- in qgswmsdataitems.cpp (61) the QgsDataSourceUri is parsed. mUri has the value
dpiMode=7&featureCount=10&tilePixelRatio=0&url=https://127.0.0.1/%26%3F%26%3F/?non_standard_param%3D%26%3F%26%3F%26%3F. The key-value separator "=" has been URL-encoded to %3D the other character left untouched making it impossible to retain the original URL. The "url" param of uri becomes https://127.0.0.1/&%3F&%3F/?non_standard_param=&%3F&%3F&%3F resulting in an empty value for non_standard_param.
uri.setEncodedUri( mUri );
- in qgswmsprovider.cpp (280) the whole thing is URL-decoded resulting in
https://127.0.0.1/&?&?/?non_standard_param=&?&?&?
// some services provide a percent/url encoded (legend) uri string, always decode here
uri = QUrl::fromPercentEncoding( uri.toUtf8() );
- the GetCapabilities request is made to
https://127.0.0.1/&?&?/?non_standard_param=&?&?&?SERVICE=WMS&REQUEST=GetCapabilities
- qgswmscapabilities.cpp (2559)
QNetworkRequest request( url );
Versions
QGIS 3.38.3 (probably all previous versions since QgsDataSourceUri was added and used for non database providers)
Master
Supported QGIS version
New profile
Additional context
Related Issues:
What is the bug or the crash?
QGIS improperly encodes/decodes data source URLs, including URL parameter values, causing the original values to be altered and leading to data loss. Additionally, QgsDataSourceUri does not fully URL-encode the values when assembling the data source string leading to potential data loss.
When constructing a
QgsDataSourceUri, parameter values are not fully URL-encoded. In this case only the=is encoded to%26. This can result in incorrect URL parameters being sent in the requests. For example:Original URL added as WMS source:
https://127.0.0.1/%26%3F%26%3F/?non_standard_param=%26%3F%26%3F%26%3FResulting QgsDataSourceUri string:
dpiMode=7&featureCount=10&tilePixelRatio=0&url=https://127.0.0.1/%26%3F%26%3F/?non_standard_param%3D%26%3F%26%3F%26%3FActual GetCapabilities Request Sent:
https://127.0.0.1/&?&?/?non_standard_param=&?&?&?SERVICE=WMS&REQUEST=GetCapabilitiesExpected behaviour
Original URL added as WMS source:
https://127.0.0.1/%26%3F%26%3F/?non_standard_param=%26%3F%26%3F%26%3FResulting QgsDataSourceUri string (values are fully URL-encoded:
dpiMode=7&featureCount=10&tilePixelRatio=0&url=https%3A%2F%2F127.0.0.1%2F%2526%253F%2526%253F%2F%3Fnon_standard_param%3D%2526%253F%2526%253F%2526%253FActual GetCapabilities Request Sent:
https://127.0.0.1/%26%3F%26%3F/?non_standard_param=%26%3F%26%3F%26%3F&SERVICE=WMS&REQUEST=GetCapabilitiesSteps to reproduce the issue
https://127.0.0.1/%26%3F%26%3F/?non_standard_param=%26%3F%26%3F%26%3Fhttps://127.0.0.1/%26?%26?/QUrl url( txtUrl->text().trimmed() );non_standard_param=%26%3F%26%3F%26%3Furl.setQuery( query );https://127.0.0.1/%26%3F%26%3F/?non_standard_param=%26%3F%26%3F%26%3Fresulting in the param valuemUri.setParam( QStringLiteral( "url" ), url );dpiMode=7&featureCount=10&tilePixelRatio=0&url=https://127.0.0.1/%26%3F%26%3F/?non_standard_param%3D%26%3F%26%3F%26%3F. The key-value separator "=" has been URL-encoded to %3D the other character left untouched making it impossible to retain the original URL. The "url" param of uri becomeshttps://127.0.0.1/&%3F&%3F/?non_standard_param=&%3F&%3F&%3Fresulting in an empty value fornon_standard_param.uri.setEncodedUri( mUri );https://127.0.0.1/&?&?/?non_standard_param=&?&?&?https://127.0.0.1/&?&?/?non_standard_param=&?&?&?SERVICE=WMS&REQUEST=GetCapabilitiesQNetworkRequest request( url );Versions
QGIS 3.38.3 (probably all previous versions since QgsDataSourceUri was added and used for non database providers)
Master
Supported QGIS version
New profile
Additional context
Related Issues: