Skip to content

Commit

Permalink
Merge pull request #9595 from rldhont/backport-9525-9526-forwardport-…
Browse files Browse the repository at this point in the history
…9418-on-release-3_6

Backport 9525 9526 forwardport 9418 on release 3 6 [Server]
  • Loading branch information
rldhont committed Mar 22, 2019
2 parents fc258ab + 88fa485 commit 2acbbc3
Show file tree
Hide file tree
Showing 12 changed files with 127 additions and 28 deletions.
22 changes: 15 additions & 7 deletions src/server/services/wms/qgswmsgetprint.cpp
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -35,28 +35,36 @@ namespace QgsWms
QgsWmsParameters wmsParameters( QUrlQuery( request.url() ) ); QgsWmsParameters wmsParameters( QUrlQuery( request.url() ) );
QgsRenderer renderer( serverIface, project, wmsParameters ); QgsRenderer renderer( serverIface, project, wmsParameters );


QString format = params.value( "FORMAT" ); QString format = params.value( QStringLiteral( "FORMAT" ) );
QString contentType; QString contentType;


// GetPrint supports svg/png/pdf // GetPrint supports svg/png/pdf
if ( format.compare( QLatin1String( "image/png" ), Qt::CaseInsensitive ) == 0 || if ( format.compare( QLatin1String( "image/png" ), Qt::CaseInsensitive ) == 0 ||
format.compare( QLatin1String( "png" ), Qt::CaseInsensitive ) == 0 ) format.compare( QLatin1String( "png" ), Qt::CaseInsensitive ) == 0 )
{ {
format = "png"; format = QStringLiteral( "png" );
contentType = "image/png"; contentType = QStringLiteral( "image/png" );
}
else if ( format.compare( QLatin1String( "image/jpg" ), Qt::CaseInsensitive ) == 0 ||
format.compare( QLatin1String( "image/jpeg" ), Qt::CaseInsensitive ) == 0 ||
format.compare( QLatin1String( "jpg" ), Qt::CaseInsensitive ) == 0 ||
format.compare( QLatin1String( "jpeg" ), Qt::CaseInsensitive ) == 0 )
{
format = QStringLiteral( "jpg" );
contentType = QStringLiteral( "image/jpeg" );
} }
else if ( format.compare( QLatin1String( "image/svg" ), Qt::CaseInsensitive ) == 0 || else if ( format.compare( QLatin1String( "image/svg" ), Qt::CaseInsensitive ) == 0 ||
format.compare( QLatin1String( "image/svg+xml" ), Qt::CaseInsensitive ) == 0 || format.compare( QLatin1String( "image/svg+xml" ), Qt::CaseInsensitive ) == 0 ||
format.compare( QLatin1String( "svg" ), Qt::CaseInsensitive ) == 0 ) format.compare( QLatin1String( "svg" ), Qt::CaseInsensitive ) == 0 )
{ {
format = "svg"; format = QStringLiteral( "svg" );
contentType = "image/svg+xml"; contentType = QStringLiteral( "image/svg+xml" );
} }
else if ( format.compare( QLatin1String( "application/pdf" ), Qt::CaseInsensitive ) == 0 || else if ( format.compare( QLatin1String( "application/pdf" ), Qt::CaseInsensitive ) == 0 ||
format.compare( QLatin1String( "pdf" ), Qt::CaseInsensitive ) == 0 ) format.compare( QLatin1String( "pdf" ), Qt::CaseInsensitive ) == 0 )
{ {
format = "pdf"; format = QStringLiteral( "pdf" );
contentType = "application/pdf"; contentType = QStringLiteral( "application/pdf" );
} }
else else
{ {
Expand Down
16 changes: 14 additions & 2 deletions src/server/services/wms/qgswmsrenderer.cpp
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -1085,8 +1085,16 @@ namespace QgsWms
QgsMapSettings mapSettings; QgsMapSettings mapSettings;
std::unique_ptr<QImage> outputImage( createImage( imageWidth, imageHeight ) ); std::unique_ptr<QImage> outputImage( createImage( imageWidth, imageHeight ) );


// The CRS parameter is considered as mandatory in configureMapSettings
// but in the case of filter parameter, CRS parameter has not to be mandatory
bool mandatoryCrsParam = true;
if ( filtersDefined && !ijDefined && !xyDefined && mWmsParameters.crs().isEmpty() )
{
mandatoryCrsParam = false;
}

// configure map settings (background, DPI, ...) // configure map settings (background, DPI, ...)
configureMapSettings( outputImage.get(), mapSettings ); configureMapSettings( outputImage.get(), mapSettings, mandatoryCrsParam );


QgsMessageLog::logMessage( "mapSettings.destinationCrs(): " + mapSettings.destinationCrs().authid() ); QgsMessageLog::logMessage( "mapSettings.destinationCrs(): " + mapSettings.destinationCrs().authid() );
QgsMessageLog::logMessage( "mapSettings.extent(): " + mapSettings.extent().toString() ); QgsMessageLog::logMessage( "mapSettings.extent(): " + mapSettings.extent().toString() );
Expand Down Expand Up @@ -1223,7 +1231,7 @@ namespace QgsWms
return image.release(); return image.release();
} }


void QgsRenderer::configureMapSettings( const QPaintDevice *paintDevice, QgsMapSettings &mapSettings ) const void QgsRenderer::configureMapSettings( const QPaintDevice *paintDevice, QgsMapSettings &mapSettings, bool mandatoryCrsParam ) const
{ {
if ( !paintDevice ) if ( !paintDevice )
{ {
Expand All @@ -1246,6 +1254,10 @@ namespace QgsWms
crs = QString( "EPSG:4326" ); crs = QString( "EPSG:4326" );
mapExtent.invert(); mapExtent.invert();
} }
else if ( crs.isEmpty() && !mandatoryCrsParam )
{
crs = QString( "EPSG:4326" );
}


QgsCoordinateReferenceSystem outputCRS; QgsCoordinateReferenceSystem outputCRS;


Expand Down
3 changes: 2 additions & 1 deletion src/server/services/wms/qgswmsrenderer.h
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -188,9 +188,10 @@ namespace QgsWms
* Configures map settings according to WMS parameters. * Configures map settings according to WMS parameters.
* \param paintDevice The device that is used for painting (for dpi) * \param paintDevice The device that is used for painting (for dpi)
* \param mapSettings Map settings to use for rendering * \param mapSettings Map settings to use for rendering
* \param mandatoryCrsParam does the CRS parameter has to be considered mandatory
* may throw an exception * may throw an exception
*/ */
void configureMapSettings( const QPaintDevice *paintDevice, QgsMapSettings &mapSettings ) const; void configureMapSettings( const QPaintDevice *paintDevice, QgsMapSettings &mapSettings, bool mandatoryCrsParam = true ) const;


QDomDocument featureInfoDocument( QList<QgsMapLayer *> &layers, const QgsMapSettings &mapSettings, QDomDocument featureInfoDocument( QList<QgsMapLayer *> &layers, const QgsMapSettings &mapSettings,
const QImage *outputImage, const QString &version ) const; const QImage *outputImage, const QString &version ) const;
Expand Down
46 changes: 30 additions & 16 deletions tests/src/python/test_qgsserver.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -176,12 +176,20 @@ def _result(self, data):


return data[1], headers return data[1], headers


def _img_diff(self, image, control_image, max_diff, max_size_diff=QSize()): def _img_diff(self, image, control_image, max_diff, max_size_diff=QSize(), outputJpg=False):
temp_image = os.path.join(tempfile.gettempdir(), "%s_result.png" % control_image)
extFile = 'png'
if outputJpg:
extFile = 'jpg'

temp_image = os.path.join(tempfile.gettempdir(), "%s_result.%s" % (control_image, extFile))


with open(temp_image, "wb") as f: with open(temp_image, "wb") as f:
f.write(image) f.write(image)


if outputJpg:
return (True, "QgsRenderChecker can't be used for JPG images")

control = QgsRenderChecker() control = QgsRenderChecker()
control.setControlPathPrefix("qgis_server") control.setControlPathPrefix("qgis_server")
control.setControlName(control_image) control.setControlName(control_image)
Expand All @@ -190,35 +198,41 @@ def _img_diff(self, image, control_image, max_diff, max_size_diff=QSize()):
control.setSizeTolerance(max_size_diff.width(), max_size_diff.height()) control.setSizeTolerance(max_size_diff.width(), max_size_diff.height())
return control.compareImages(control_image, max_diff), control.report() return control.compareImages(control_image, max_diff), control.report()


def _img_diff_error(self, response, headers, image, max_diff=100, max_size_diff=QSize(), unittest_data_path='control_images'): def _img_diff_error(self, response, headers, image, max_diff=100, max_size_diff=QSize(), unittest_data_path='control_images', outputJpg=False):

extFile = 'png'
contentType = 'image/png'
if outputJpg:
extFile = 'jpg'
contentType = 'image/jpeg'


reference_path = unitTestDataPath(unittest_data_path) + '/qgis_server/' + image + '/' + image + '.png' reference_path = unitTestDataPath(unittest_data_path) + '/qgis_server/' + image + '/' + image + '.' + extFile
self.store_reference(reference_path, response) self.store_reference(reference_path, response)


self.assertEqual( self.assertEqual(
headers.get("Content-Type"), "image/png", headers.get("Content-Type"), contentType,
"Content type is wrong: %s\n%s" % (headers.get("Content-Type"), response)) "Content type is wrong: %s instead of %s\n%s" % (headers.get("Content-Type"), contentType, response))


test, report = self._img_diff(response, image, max_diff, max_size_diff) test, report = self._img_diff(response, image, max_diff, max_size_diff, outputJpg)


with open(os.path.join(tempfile.gettempdir(), image + "_result.png"), "rb") as rendered_file: with open(os.path.join(tempfile.gettempdir(), image + "_result." + extFile), "rb") as rendered_file:
encoded_rendered_file = base64.b64encode(rendered_file.read()) encoded_rendered_file = base64.b64encode(rendered_file.read())
if not os.environ.get('ENCODED_OUTPUT'): if not os.environ.get('ENCODED_OUTPUT'):
message = "Image is wrong\: rendered file %s/%s_result.png" % (tempfile.gettempdir(), image) message = "Image is wrong\: rendered file %s/%s_result.%s" % (tempfile.gettempdir(), image, extFile)
else: else:
message = "Image is wrong\n%s\nImage:\necho '%s' | base64 -d >%s/%s_result.png" % ( message = "Image is wrong\n%s\nImage:\necho '%s' | base64 -d >%s/%s_result.%s" % (
report, encoded_rendered_file.strip().decode('utf8'), tempfile.gettempdir(), image report, encoded_rendered_file.strip().decode('utf8'), tempfile.gettempdir(), image, extFile
) )


# If the failure is in image sizes the diff file will not exists. # If the failure is in image sizes the diff file will not exists.
if os.path.exists(os.path.join(tempfile.gettempdir(), image + "_result_diff.png")): if os.path.exists(os.path.join(tempfile.gettempdir(), image + "_result_diff." + extFile)):
with open(os.path.join(tempfile.gettempdir(), image + "_result_diff.png"), "rb") as diff_file: with open(os.path.join(tempfile.gettempdir(), image + "_result_diff." + extFile), "rb") as diff_file:
if not os.environ.get('ENCODED_OUTPUT'): if not os.environ.get('ENCODED_OUTPUT'):
message = "Image is wrong\: diff file %s/%s_result_diff.png" % (tempfile.gettempdir(), image) message = "Image is wrong\: diff file %s/%s_result_diff.%s" % (tempfile.gettempdir(), image, extFile)
else: else:
encoded_diff_file = base64.b64encode(diff_file.read()) encoded_diff_file = base64.b64encode(diff_file.read())
message += "\nDiff:\necho '%s' | base64 -d > %s/%s_result_diff.png" % ( message += "\nDiff:\necho '%s' | base64 -d > %s/%s_result_diff.%s" % (
encoded_diff_file.strip().decode('utf8'), tempfile.gettempdir(), image encoded_diff_file.strip().decode('utf8'), tempfile.gettempdir(), image, extFile
) )


self.assertTrue(test, message) self.assertTrue(test, message)
Expand Down
9 changes: 7 additions & 2 deletions tests/src/python/test_qgsserver_accesscontrol.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -202,8 +202,13 @@ def _post_restricted(self, data, query_string=None):
self._server.putenv("QGIS_PROJECT_FILE", '') self._server.putenv("QGIS_PROJECT_FILE", '')
return result return result


def _img_diff(self, image, control_image, max_diff, max_size_diff=QSize()): def _img_diff(self, image, control_image, max_diff, max_size_diff=QSize(), outputJpg=False):
temp_image = os.path.join(tempfile.gettempdir(), "%s_result.png" % control_image)
extFile = 'png'
if outputJpg:
extFile = 'jpg'

temp_image = os.path.join(tempfile.gettempdir(), "%s_result.%s" % (control_image, extFile))


with open(temp_image, "wb") as f: with open(temp_image, "wb") as f:
f.write(image) f.write(image)
Expand Down
7 changes: 7 additions & 0 deletions tests/src/python/test_qgsserver_wfs.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -374,6 +374,13 @@ def test_getfeature_post(self):
def test_getFeatureBBOX(self): def test_getFeatureBBOX(self):
"""Test with (1.1.0) and without (1.0.0) CRS""" """Test with (1.1.0) and without (1.0.0) CRS"""


# Tests without CRS
self.wfs_request_compare(
"GetFeature", '1.0.0', "TYPENAME=testlayer&RESULTTYPE=hits&BBOX=8.20347,44.901471,8.2035354,44.901493", 'wfs_getFeature_1_0_0_bbox_1_feature')
self.wfs_request_compare(
"GetFeature", '1.0.0', "TYPENAME=testlayer&RESULTTYPE=hits&BBOX=8.203127,44.9012765,8.204138,44.901632", 'wfs_getFeature_1_0_0_bbox_3_feature')

# Tests with CRS
self.wfs_request_compare( self.wfs_request_compare(
"GetFeature", '1.0.0', "SRSNAME=EPSG:4326&TYPENAME=testlayer&RESULTTYPE=hits&BBOX=8.20347,44.901471,8.2035354,44.901493,EPSG:4326", 'wfs_getFeature_1_0_0_epsgbbox_1_feature') "GetFeature", '1.0.0', "SRSNAME=EPSG:4326&TYPENAME=testlayer&RESULTTYPE=hits&BBOX=8.20347,44.901471,8.2035354,44.901493,EPSG:4326", 'wfs_getFeature_1_0_0_epsgbbox_1_feature')
self.wfs_request_compare( self.wfs_request_compare(
Expand Down
10 changes: 10 additions & 0 deletions tests/src/python/test_qgsserver_wms_getfeatureinfo.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -347,6 +347,16 @@ def testGetFeatureInfoFilter(self):
urllib.parse.quote(':"NAME" = \'two\''), urllib.parse.quote(':"NAME" = \'two\''),
'wms_getfeatureinfo_filter_no_width') 'wms_getfeatureinfo_filter_no_width')


# Test a filter without CRS parameter
self.wms_request_compare('GetFeatureInfo',
'&layers=testlayer%20%C3%A8%C3%A9&' +
'INFO_FORMAT=text%2Fxml&' +
'width=600&height=400&' +
'query_layers=testlayer%20%C3%A8%C3%A9&' +
'FEATURE_COUNT=10&FILTER=testlayer%20%C3%A8%C3%A9' +
urllib.parse.quote(':"NAME" = \'two\''),
'wms_getfeatureinfo_filter_no_crs')

def testGetFeatureInfoTolerance(self): def testGetFeatureInfoTolerance(self):
self.wms_request_compare('GetFeatureInfo', self.wms_request_compare('GetFeatureInfo',
'&layers=layer3&styles=&' + '&layers=layer3&styles=&' +
Expand Down
16 changes: 16 additions & 0 deletions tests/src/python/test_qgsserver_wms_getprint.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -91,6 +91,22 @@ def test_wms_getprint_basic(self):
r, h = self._result(self._execute_request(qs)) r, h = self._result(self._execute_request(qs))
self._img_diff_error(r, h, "WMS_GetPrint_Basic") self._img_diff_error(r, h, "WMS_GetPrint_Basic")


# Output JPEG
qs = "?" + "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(self.projectPath),
"SERVICE": "WMS",
"VERSION": "1.1.1",
"REQUEST": "GetPrint",
"TEMPLATE": "layoutA4",
"FORMAT": "jpeg",
"map0:EXTENT": "-33626185.498,-13032965.185,33978427.737,16020257.031",
"LAYERS": "Country,Hello",
"CRS": "EPSG:3857"
}.items())])

r, h = self._result(self._execute_request(qs))
self._img_diff_error(r, h, "WMS_GetPrint_Basic", outputJpg=True)

def test_wms_getprint_style(self): def test_wms_getprint_style(self):
# default style # default style
qs = "?" + "&".join(["%s=%s" % i for i in list({ qs = "?" + "&".join(["%s=%s" % i for i in list({
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,6 @@
Content-Type: text/xml; subtype=gml/2.1.2; charset=utf-8

<wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs" xmlns:ogc="http://www.opengis.net/ogc" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:qgs="http://www.qgis.org/gml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd http://www.qgis.org/gml ?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test_project_wfs.qgs&amp;SRSNAME=EPSG:4326&amp;RESULTTYPE=hits&amp;SERVICE=WFS&amp;VERSION=1.0.0&amp;REQUEST=DescribeFeatureType&amp;TYPENAME=testlayer&amp;OUTPUTFORMAT=XMLSCHEMA"
timeStamp="2019-01-23T12:09:05"
numberOfFeatures="1">
</wfs:FeatureCollection>
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,6 @@
Content-Type: text/xml; subtype=gml/2.1.2; charset=utf-8

<wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs" xmlns:ogc="http://www.opengis.net/ogc" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:qgs="http://www.qgis.org/gml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd http://www.qgis.org/gml ?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test_project_wfs.qgs&amp;SRSNAME=EPSG:4326&amp;RESULTTYPE=hits&amp;SERVICE=WFS&amp;VERSION=1.0.0&amp;REQUEST=DescribeFeatureType&amp;TYPENAME=testlayer&amp;OUTPUTFORMAT=XMLSCHEMA"
timeStamp="2019-01-23T12:09:05"
numberOfFeatures="3">
</wfs:FeatureCollection>
14 changes: 14 additions & 0 deletions tests/testdata/qgis_server/wms_getfeatureinfo_filter_no_crs.txt
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,14 @@
Content-Length: 577
Content-Type: text/xml; charset=utf-8

<GetFeatureInfoResponse>
<BoundingBox maxy="44.90143568" maxx="8.20354699" miny="44.90143568" CRS="EPSG:4326" minx="8.20354699"/>
<Layer name="testlayer èé">
<Feature id="1">
<Attribute value="2" name="id"/>
<Attribute value="two" name="name"/>
<Attribute value="two àò" name="utf8nameè"/>
<BoundingBox maxy="44.9014" maxx="8.2035" miny="44.9014" CRS="EPSG:4326" minx="8.2035"/>
</Feature>
</Layer>
</GetFeatureInfoResponse>

0 comments on commit 2acbbc3

Please sign in to comment.