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 authored 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 Diff line number Diff line change
Expand Up @@ -35,28 +35,36 @@ namespace QgsWms
QgsWmsParameters wmsParameters( QUrlQuery( request.url() ) );
QgsRenderer renderer( serverIface, project, wmsParameters );

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

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

QgsMessageLog::logMessage( "mapSettings.destinationCrs(): " + mapSettings.destinationCrs().authid() );
QgsMessageLog::logMessage( "mapSettings.extent(): " + mapSettings.extent().toString() );
Expand Down Expand Up @@ -1223,7 +1231,7 @@ namespace QgsWms
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 )
{
Expand All @@ -1246,6 +1254,10 @@ namespace QgsWms
crs = QString( "EPSG:4326" );
mapExtent.invert();
}
else if ( crs.isEmpty() && !mandatoryCrsParam )
{
crs = QString( "EPSG:4326" );
}

QgsCoordinateReferenceSystem outputCRS;

Expand Down
3 changes: 2 additions & 1 deletion src/server/services/wms/qgswmsrenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,9 +188,10 @@ namespace QgsWms
* Configures map settings according to WMS parameters.
* \param paintDevice The device that is used for painting (for dpi)
* \param mapSettings Map settings to use for rendering
* \param mandatoryCrsParam does the CRS parameter has to be considered mandatory
* 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,
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 Diff line number Diff line change
Expand Up @@ -176,12 +176,20 @@ def _result(self, data):

return data[1], headers

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

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:
f.write(image)

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

control = QgsRenderChecker()
control.setControlPathPrefix("qgis_server")
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())
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.assertEqual(
headers.get("Content-Type"), "image/png",
"Content type is wrong: %s\n%s" % (headers.get("Content-Type"), response))
headers.get("Content-Type"), contentType,
"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())
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:
message = "Image is wrong\n%s\nImage:\necho '%s' | base64 -d >%s/%s_result.png" % (
report, encoded_rendered_file.strip().decode('utf8'), tempfile.gettempdir(), image
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, extFile
)

# 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")):
with open(os.path.join(tempfile.gettempdir(), image + "_result_diff.png"), "rb") as diff_file:
if os.path.exists(os.path.join(tempfile.gettempdir(), image + "_result_diff." + extFile)):
with open(os.path.join(tempfile.gettempdir(), image + "_result_diff." + extFile), "rb") as diff_file:
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:
encoded_diff_file = base64.b64encode(diff_file.read())
message += "\nDiff:\necho '%s' | base64 -d > %s/%s_result_diff.png" % (
encoded_diff_file.strip().decode('utf8'), tempfile.gettempdir(), image
message += "\nDiff:\necho '%s' | base64 -d > %s/%s_result_diff.%s" % (
encoded_diff_file.strip().decode('utf8'), tempfile.gettempdir(), image, extFile
)

self.assertTrue(test, message)
Expand Down
9 changes: 7 additions & 2 deletions tests/src/python/test_qgsserver_accesscontrol.py
Original file line number 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", '')
return result

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

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:
f.write(image)
Expand Down
7 changes: 7 additions & 0 deletions tests/src/python/test_qgsserver_wfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,13 @@ def test_getfeature_post(self):
def test_getFeatureBBOX(self):
"""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(
"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(
Expand Down
10 changes: 10 additions & 0 deletions tests/src/python/test_qgsserver_wms_getfeatureinfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,16 @@ def testGetFeatureInfoFilter(self):
urllib.parse.quote(':"NAME" = \'two\''),
'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):
self.wms_request_compare('GetFeatureInfo',
'&layers=layer3&styles=&' +
Expand Down
16 changes: 16 additions & 0 deletions tests/src/python/test_qgsserver_wms_getprint.py
Original file line number 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))
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):
# default style
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 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 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 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.