This is an automated email from the git hooks/post-receive script. sebastic pushed a commit to branch experimental in repository qgis.
commit 859d1f99ed6e44bd657dfa569b9400bce4e0bb6d Author: Bas Couwenberg <[email protected]> Date: Fri Dec 16 13:57:41 2016 +0100 Imported Upstream version 2.14.10+dfsg --- CMakeLists.txt | 2 +- ChangeLog | 157 +++++++++++++++++++++ debian/changelog | 10 +- .../plugins/processing/algs/taudem/TauDEMUtils.py | 13 ++ .../plugins/processing/modeler/ModelerAlgorithm.py | 5 +- python/plugins/processing/tools/dataobjects.py | 3 +- src/app/qgscustomization.cpp | 2 +- .../symbology-ng/qgspointdisplacementrenderer.cpp | 7 + .../symbology-ng/qgspointdisplacementrenderer.h | 4 + src/gui/qgsfiledownloader.cpp | 14 +- src/gui/qgsfiledownloader.h | 2 - .../checks/qgsgeometrygapcheck.cpp | 4 +- .../geometry_checker/utils/qgsfeaturepool.cpp | 9 +- .../virtual/qgsvirtuallayersqlitemodule.cpp | 10 +- src/server/qgsconfigparserutils.cpp | 12 +- src/server/qgsserverprojectparser.cpp | 2 +- src/server/qgswmsserver.cpp | 130 +++++++++++++++-- src/server/qgswmsserver.h | 6 +- tests/src/gui/testqgsfiledownloader.cpp | 12 +- tests/src/python/test_qgsfiledownloader.py | 14 +- tests/src/python/test_qgsserver.py | 130 +++++++++++++++++ tests/src/python/test_qgsserver_accesscontrol.py | 32 ++--- .../WMS_GetLegendGraphic_BBox.png | Bin 0 -> 839 bytes .../WMS_GetLegendGraphic_BBox2.png | Bin 0 -> 601 bytes .../WMS_GetLegendGraphic_Basic.png | Bin 0 -> 601 bytes .../WMS_GetLegendGraphic_BoxSpace.png | Bin 0 -> 3938 bytes .../WMS_GetLegendGraphic_IconLabelSpace.png | Bin 0 -> 783 bytes .../WMS_GetLegendGraphic_SymbolSize.png | Bin 0 -> 1248 bytes .../WMS_GetLegendGraphic_SymbolSpace.png | Bin 0 -> 968 bytes tests/testdata/qgis_server/getcapabilities.txt | 4 +- .../qgis_server/getcapabilities_inspire.txt | 4 +- tests/testdata/qgis_server/getprojectsettings.txt | 4 +- tests/testdata/qgis_server/wfs_getcapabilities.txt | 2 +- 33 files changed, 520 insertions(+), 74 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d6db4b1..4398ee7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ SET(CPACK_PACKAGE_VERSION_MAJOR "2") SET(CPACK_PACKAGE_VERSION_MINOR "14") -SET(CPACK_PACKAGE_VERSION_PATCH "9") +SET(CPACK_PACKAGE_VERSION_PATCH "10") SET(COMPLETE_VERSION ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}) SET(RELEASE_NAME "Essen") IF (POLICY CMP0048) # in CMake 3.0.0+ diff --git a/ChangeLog b/ChangeLog index e5b78ef..3a7cd94 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,160 @@ +Alexander Bruy <[email protected]> 2016-12-15 + + [processing] quote file paths in TauDEM provider + +Alessandro Pasotti <[email protected]> 2016-12-14 + + [BACKPORT][BUGFIX] Fixed a crash on bad network protocol + + ( from f48f90ead ) + +rldhont <[email protected]> 2016-12-13 + + Fix WMS 1.3. compliance: distort image if width/height ratio of bbox is different to WIDTH/HEIGHT of requested image + + Not decrease but increase image + +Merge: 02d70fa a1a4ad9 +rldhont <[email protected]> 2016-12-13 + + Merge pull request #3862 from rldhont/release-2_14-wms-130-compliance + + Backport 214 wms 130 compliance + +Blottiere Paul <[email protected]> 2016-12-09 + + fix getLegendGraphics when BBox parameter is used + +rldhont <[email protected]> 2016-12-12 + + Adapt WFS capabilties in server test for WMS 1.3.0 compliance + +Marco Hugentobler <[email protected]> 2016-12-01 + + Fix access control tests such that bbox width/height ration matches image width/height + +Marco Hugentobler <[email protected]> 2016-12-01 + + Adapt expected capabilities / project settings response in server test for WMS 1.3.0 compliance + +rldhont <[email protected]> 2016-12-12 + + Fix typo + +Marco Hugentobler <[email protected]> 2016-12-09 + + Backward support for parameters 'MTVER' and 'capabilities' from WMS 1.0.0 is required for WMS 1.1.1 + +Marco Hugentobler <[email protected]> 2016-12-01 + + Indentation + +Marco Hugentobler <[email protected]> 2016-12-01 + + WMS server: parse bounding box only if the BBOX parameter is really there + +Marco Hugentobler <[email protected]> 2016-11-29 + + WMS 1.3 compliance: Each OnlineResource URL intended for HTTP Get requests in the capabilities document is a URL prefix + +Marco Hugentobler <[email protected]> 2016-11-29 + + Exception format is XML, not capabilities format + +Marco Hugentobler <[email protected]> 2016-11-29 + + WMS 1.3. compliance: distort image if width/height ratio of bbox is different to WIDTH/HEIGHT of requested image + +Marco Hugentobler <[email protected]> 2016-11-29 + + WMS 1.3.0 compliance: If a layer bounding box is there, it is not allowed to be empty (also if a layer has only one point) + +Marco Hugentobler <[email protected]> 2016-11-29 + + WMS 1.3.0 compliance: throw exception if bbox is empty + +Marco Hugentobler <[email protected]> 2016-11-29 + + Fix typo + +Marco Hugentobler <[email protected]> 2016-11-29 + + WMS 1.3.0 compliance: exception format must be advertized as 'XML', not 'text/xml' + +Marco Hugentobler <[email protected]> 2016-11-29 + + WMS 1.3.0 compliance: CRS:84 needs to be supported + +Marco Hugentobler <[email protected]> 2016-11-29 + + WMS 1.3.0 compliance: support BGCOLOR parameter + +Marco Hugentobler <[email protected]> 2016-11-29 + + WMS 1.3.0 compliance: throw exception if feature info point is not within the WIDTH/HEIGHT parameters + +Marco Hugentobler <[email protected]> 2016-11-29 + + WMS 1.3.0 compliance: use the reserved word 'None' if no fees + +nirvn <[email protected]> 2016-12-08 + + Revert "[style dock] emit widgetChanged() when raster palette labels updated" + + This reverts commit f92928d4da7ece907b94713e8706e550e6ab4c5e. + +nirvn <[email protected]> 2016-12-08 + + [style dock] emit widgetChanged() when raster palette labels updated + +Sandro Mani <[email protected]> 2016-12-06 + + [Geometry Checker] Don't add geometry-less features to feature-pool + +Hugo Mercier <[email protected]> 2016-12-05 + + [virtual layer] Fix xFilter for null value comparisons + +Merge: b3742fe 8dc7799 +volaya <[email protected]> 2016-12-02 + + Merge pull request #3826 from alexbruy/processing-models + + fix loading of models containing user-defined scripts + +Alexander Bruy <[email protected]> 2016-12-02 + + fix loading of models containing user-defined scripts + +Sandro Mani <[email protected]> 2016-12-01 + + [Geometry checker] Fix possible use of deleted geometry + +rldhont <[email protected]> 2016-11-30 + + Update QgsPointDisplacementRenderer::legendKeysForFeature note + +rldhont <[email protected]> 2016-11-30 + + [BUGFIX] Filter Legend By Map Content doesn't maintain point displacement legend + + Fixed #11572 + Manually cherry-picked 4d71cf968c4608359514637ceabcf4f3dcfb09ce + +borys <[email protected]> 2016-11-29 + + [bugfix] Fix broken docks customization. Fixes #8055 + +volaya <[email protected]> 2016-11-27 + + [processing] fixed file extension when exporting layer + + fixes #15898 + +Juergen E. Fischer <[email protected]> 2016-11-25 + + Release of 2.14.9 + Matthias Kuhn <[email protected]> 2016-10-17 Don't rely on RTTI to convert symbol layer to sip objects diff --git a/debian/changelog b/debian/changelog index e11ca65..d17c0b5 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,8 +1,14 @@ -qgis (2.14.9) UNRELEASED; urgency=medium +qgis (2.14.10) UNRELEASED; urgency=medium + + * Release of 2.14.10 + + -- Jürgen E. Fischer <[email protected]> Fri, 16 Dec 2016 13:00:16 +0100 + +qgis (2.14.9) unstable; urgency=medium * Release of 2.14.9 - -- Jürgen E. Fischer <[email protected]> Fri, 25 Nov 2016 14:11:24 +0100 + -- Jürgen E. Fischer <[email protected]> Fri, 16 Dec 2016 13:00:16 +0100 qgis (2.14.8) unstable; urgency=medium diff --git a/python/plugins/processing/algs/taudem/TauDEMUtils.py b/python/plugins/processing/algs/taudem/TauDEMUtils.py index 48150ce..6c57657 100644 --- a/python/plugins/processing/algs/taudem/TauDEMUtils.py +++ b/python/plugins/processing/algs/taudem/TauDEMUtils.py @@ -102,6 +102,7 @@ class TauDEMUtils: def executeTauDEM(command, progress): loglines = [] loglines.append(TauDEMUtils.tr('TauDEM execution console output')) + command = TauDEMUtils.escapeAndJoin(command) fused_command = ''.join(['"%s" ' % c for c in command]) progress.setInfo(TauDEMUtils.tr('TauDEM command:')) progress.setCommand(fused_command.replace('" "', ' ').strip('"')) @@ -119,6 +120,18 @@ class TauDEMUtils: ProcessingLog.addToLog(ProcessingLog.LOG_INFO, loglines) @staticmethod + def escapeAndJoin(strList): + joined = '' + for s in strList: + if s[0] != '-' and ' ' in s: + escaped = '"' + s.replace('\\', '\\\\').replace('"', '\\"') \ + + '"' + else: + escaped = s + joined += escaped + ' ' + return joined.strip() + + @staticmethod def tr(string, context=''): if context == '': context = 'TauDEMUtils' diff --git a/python/plugins/processing/modeler/ModelerAlgorithm.py b/python/plugins/processing/modeler/ModelerAlgorithm.py index 0872485..91b0f7d 100644 --- a/python/plugins/processing/modeler/ModelerAlgorithm.py +++ b/python/plugins/processing/modeler/ModelerAlgorithm.py @@ -566,7 +566,10 @@ class ModelerAlgorithm(GeoAlgorithm): def fromdict(d): try: fullClassName = d["class"] - tokens = fullClassName.split(".") + if isinstance(fullClassName, basestring): + tokens = fullClassName.split(".") + else: + tokens = fullClassName.__class__.__name__.split(".") className = tokens[-1] moduleName = ".".join(tokens[:-1]) values = d["values"] diff --git a/python/plugins/processing/tools/dataobjects.py b/python/plugins/processing/tools/dataobjects.py index a23ed78..7e014ce 100644 --- a/python/plugins/processing/tools/dataobjects.py +++ b/python/plugins/processing/tools/dataobjects.py @@ -308,7 +308,8 @@ def exportVectorLayer(layer, supported=None): unicode(layer.source()).decode('ascii') except UnicodeEncodeError: isASCII = False - if not os.path.splitext(layer.source())[1].lower() in supported or not isASCII: + ext = os.path.splitext(layer.source())[-1].lower()[1:] + if ext not in supported or not isASCII: writer = QgsVectorFileWriter( output, systemEncoding, layer.pendingFields(), provider.geometryType(), diff --git a/src/app/qgscustomization.cpp b/src/app/qgscustomization.cpp index 0f9c5c7..a30a214 100644 --- a/src/app/qgscustomization.cpp +++ b/src/app/qgscustomization.cpp @@ -576,7 +576,7 @@ void QgsCustomization::createTreeItemToolbars() void QgsCustomization::createTreeItemDocks() { QStringList data; - data << "Panels"; + data << "Docks"; QTreeWidgetItem *topItem = new QTreeWidgetItem( data ); diff --git a/src/core/symbology-ng/qgspointdisplacementrenderer.cpp b/src/core/symbology-ng/qgspointdisplacementrenderer.cpp index 15c79af..a2bedf9 100644 --- a/src/core/symbology-ng/qgspointdisplacementrenderer.cpp +++ b/src/core/symbology-ng/qgspointdisplacementrenderer.cpp @@ -329,6 +329,13 @@ QgsSymbolV2List QgsPointDisplacementRenderer::originalSymbolsForFeature( QgsFeat return mRenderer->originalSymbolsForFeature( feat, context ); } +QSet< QString > QgsPointDisplacementRenderer::legendKeysForFeature( QgsFeature& feat, QgsRenderContext& context ) +{ + if ( !mRenderer ) + return QSet< QString >() << QString(); + return mRenderer->legendKeysForFeature( feat, context ); +} + bool QgsPointDisplacementRenderer::willRenderFeature( QgsFeature& feat, QgsRenderContext& context ) { if ( !mRenderer ) diff --git a/src/core/symbology-ng/qgspointdisplacementrenderer.h b/src/core/symbology-ng/qgspointdisplacementrenderer.h index 10dd03e..848e968 100644 --- a/src/core/symbology-ng/qgspointdisplacementrenderer.h +++ b/src/core/symbology-ng/qgspointdisplacementrenderer.h @@ -77,6 +77,10 @@ class CORE_EXPORT QgsPointDisplacementRenderer: public QgsFeatureRendererV2 @note available in python as originalSymbolsForFeature2 */ virtual QgsSymbolV2List originalSymbolsForFeature( QgsFeature& feat, QgsRenderContext& context ) override; + /** Returns which legend keys match the feature + * @note added in QGIS 2.14.10 + */ + virtual QSet< QString > legendKeysForFeature( QgsFeature& feature, QgsRenderContext& context ) override; /** Proxy that will call this method on the embedded renderer. @note available in python as willRenderFeature2 */ diff --git a/src/gui/qgsfiledownloader.cpp b/src/gui/qgsfiledownloader.cpp index 36cde63..83520d2 100644 --- a/src/gui/qgsfiledownloader.cpp +++ b/src/gui/qgsfiledownloader.cpp @@ -60,7 +60,6 @@ void QgsFileDownloader::startDownload() mReply = nam->get( request ); connect( mReply, SIGNAL( readyRead() ), this, SLOT( onReadyRead() ) ); - connect( mReply, SIGNAL( error( QNetworkReply::NetworkError ) ), this, SLOT( onNetworkError( QNetworkReply::NetworkError ) ) ); connect( mReply, SIGNAL( finished() ), this, SLOT( onFinished() ) ); connect( mReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( onDownloadProgress( qint64, qint64 ) ) ); connect( nam, SIGNAL( requestTimedOut( QNetworkReply* ) ), this, SLOT( onRequestTimedOut() ) ); @@ -161,7 +160,7 @@ void QgsFileDownloader::onFinished() if ( mReply->error() ) { mFile.remove(); - error( tr( "Download failed: %1." ).arg( mReply->errorString() ) ); + error( tr( "Download failed: %1" ).arg( mReply->errorString() ) ); } else if ( !redirectionTarget.isNull() ) { @@ -174,18 +173,15 @@ void QgsFileDownloader::onFinished() startDownload(); return; } - // All done - emit downloadCompleted(); + else + { + emit downloadCompleted(); + } } emit downloadExited(); this->deleteLater(); } -void QgsFileDownloader::onNetworkError( QNetworkReply::NetworkError err ) -{ - Q_ASSERT( mReply ); - error( QString( "Network error %1: %2" ).arg( err ).arg( mReply->errorString() ) ); -} void QgsFileDownloader::onDownloadProgress( qint64 bytesReceived, qint64 bytesTotal ) { diff --git a/src/gui/qgsfiledownloader.h b/src/gui/qgsfiledownloader.h index 62e6d29..c9276f7 100644 --- a/src/gui/qgsfiledownloader.h +++ b/src/gui/qgsfiledownloader.h @@ -75,8 +75,6 @@ class GUI_EXPORT QgsFileDownloader : public QObject void onReadyRead(); /** Called when the network reply has finished */ void onFinished(); - /** Called on Network Error */ - void onNetworkError( QNetworkReply::NetworkError err ); /** Called on data ready to be processed */ void onDownloadProgress( qint64 bytesReceived, qint64 bytesTotal ); /** Called when a network request times out */ diff --git a/src/plugins/geometry_checker/checks/qgsgeometrygapcheck.cpp b/src/plugins/geometry_checker/checks/qgsgeometrygapcheck.cpp index 85c3564..c86c2da 100644 --- a/src/plugins/geometry_checker/checks/qgsgeometrygapcheck.cpp +++ b/src/plugins/geometry_checker/checks/qgsgeometrygapcheck.cpp @@ -79,7 +79,7 @@ void QgsGeometryGapCheck::collectErrors( QList<QgsGeometryCheckError*>& errors, // For each gap polygon which does not lie on the boundary, get neighboring polygons and add error for ( int iPart = 0, nParts = diffGeom->partCount(); iPart < nParts; ++iPart ) { - QgsAbstractGeometryV2* geom = QgsGeomUtils::getGeomPart( diffGeom, iPart ); + QgsAbstractGeometryV2* geom = QgsGeomUtils::getGeomPart( diffGeom, iPart )->clone(); // Skip the gap between features and boundingbox if ( geom->boundingBox() == envelope->boundingBox() ) { @@ -118,7 +118,7 @@ void QgsGeometryGapCheck::collectErrors( QList<QgsGeometryCheckError*>& errors, } // Add error - errors.append( new QgsGeometryGapCheckError( this, geom->clone(), neighboringIds, geom->area(), gapAreaBBox ) ); + errors.append( new QgsGeometryGapCheckError( this, geom, neighboringIds, geom->area(), gapAreaBBox ) ); } delete unionGeom; diff --git a/src/plugins/geometry_checker/utils/qgsfeaturepool.cpp b/src/plugins/geometry_checker/utils/qgsfeaturepool.cpp index 86e1d7d..c8f49cd 100644 --- a/src/plugins/geometry_checker/utils/qgsfeaturepool.cpp +++ b/src/plugins/geometry_checker/utils/qgsfeaturepool.cpp @@ -44,7 +44,14 @@ QgsFeaturePool::QgsFeaturePool( QgsVectorLayer *layer, bool selectedOnly ) QgsFeatureIterator it = layer->getFeatures( req ); while ( it.nextFeature( feature ) ) { - mIndex.insertFeature( feature ); + if ( feature.geometry() ) + { + mIndex.insertFeature( feature ); + } + else + { + mFeatureIds.remove( feature.id() ); + } } } diff --git a/src/providers/virtual/qgsvirtuallayersqlitemodule.cpp b/src/providers/virtual/qgsvirtuallayersqlitemodule.cpp index 478a2ad..7d17fd9 100644 --- a/src/providers/virtual/qgsvirtuallayersqlitemodule.cpp +++ b/src/providers/virtual/qgsvirtuallayersqlitemodule.cpp @@ -616,13 +616,13 @@ int vtableFilter( sqlite3_vtab_cursor * cursor, int idxNum, const char *idxStr, expr += "'" + str.replace( "'", "''" ) + "'"; break; } + case SQLITE_NULL: + case SQLITE_BLOB: // comparison to blob ignored default: - expr = ""; - } - if ( !expr.isEmpty() ) - { - request.setFilterExpression( expr ); + expr += " is null"; + break; } + request.setFilterExpression( expr ); } VTableCursor *c = reinterpret_cast<VTableCursor*>( cursor ); c->filter( request ); diff --git a/src/server/qgsconfigparserutils.cpp b/src/server/qgsconfigparserutils.cpp index b73d5b7..f89c41e 100644 --- a/src/server/qgsconfigparserutils.cpp +++ b/src/server/qgsconfigparserutils.cpp @@ -65,6 +65,9 @@ void QgsConfigParserUtils::appendCRSElementsToLayer( QDomElement& layerElement, appendCRSElementToLayer( layerElement, CRSPrecedingElement, crs, doc ); } } + + //Support for CRS:84 is mandatory (equals EPSG:4326 with reversed axis) + appendCRSElementToLayer( layerElement, CRSPrecedingElement, QString( "CRS:84" ), doc ); } void QgsConfigParserUtils::appendCRSElementToLayer( QDomElement& layerElement, const QDomElement& precedingElement, @@ -77,7 +80,7 @@ void QgsConfigParserUtils::appendCRSElementToLayer( QDomElement& layerElement, c layerElement.insertAfter( crsElement, precedingElement ); } -void QgsConfigParserUtils::appendLayerBoundingBoxes( QDomElement& layerElem, QDomDocument& doc, const QgsRectangle& layerExtent, +void QgsConfigParserUtils::appendLayerBoundingBoxes( QDomElement& layerElem, QDomDocument& doc, const QgsRectangle& lExtent, const QgsCoordinateReferenceSystem& layerCRS, const QStringList &crsList, const QStringList& constrainedCrsList ) { if ( layerElem.isNull() ) @@ -85,6 +88,13 @@ void QgsConfigParserUtils::appendLayerBoundingBoxes( QDomElement& layerElem, QDo return; } + QgsRectangle layerExtent = lExtent; + if ( qgsDoubleNear( layerExtent.xMinimum(), layerExtent.xMaximum() ) || qgsDoubleNear( layerExtent.yMinimum(), layerExtent.yMaximum() ) ) + { + //layer bbox cannot be empty + layerExtent.grow( 0.000001 ); + } + const QgsCoordinateReferenceSystem& wgs84 = QgsCRSCache::instance()->crsByAuthId( GEO_EPSG_CRS_AUTHID ); QString version = doc.documentElement().attribute( "version" ); diff --git a/src/server/qgsserverprojectparser.cpp b/src/server/qgsserverprojectparser.cpp index 860bec2..a2d7729 100644 --- a/src/server/qgsserverprojectparser.cpp +++ b/src/server/qgsserverprojectparser.cpp @@ -595,7 +595,7 @@ void QgsServerProjectParser::serviceCapabilities( QDomElement& parentElement, QD //Fees QDomElement feesElem = propertiesElement.firstChildElement( "WMSFees" ); QDomElement wmsFeesElem = doc.createElement( "Fees" ); - QDomText wmsFeesText = doc.createTextNode( "conditions unknown" ); // default value if access conditions are unknown + QDomText wmsFeesText = doc.createTextNode( "None" ); // default value if access conditions are unknown if ( !feesElem.isNull() && !feesElem.text().isEmpty() ) { wmsFeesText = doc.createTextNode( feesElem.text() ); diff --git a/src/server/qgswmsserver.cpp b/src/server/qgswmsserver.cpp index ffa24f5..807384e 100644 --- a/src/server/qgswmsserver.cpp +++ b/src/server/qgswmsserver.cpp @@ -147,13 +147,30 @@ void QgsWMSServer::executeRequest() } //version - QString version = mParameters.value( "VERSION", "1.3.0" ); + QString version = "1.3.0"; + if ( mParameters.contains( "VERSION" ) ) + { + version = mParameters.value( "VERSION" ); + } + else if ( mParameters.contains( "WMTVER" ) ) //WMTVER needs to be supported by WMS 1.1.1 for backwards compatibility with WMS 1.0.0 + { + version = mParameters.value( "WMTVER" ); + } + bool getProjectSettings = ( request.compare( "GetProjectSettings", Qt::CaseInsensitive ) == 0 ); if ( getProjectSettings ) { version = "1.3.0"; //getProjectSettings extends WMS 1.3.0 capabilities } + if ( version == "1.1.1" ) + { + if ( request.compare( "capabilities", Qt::CaseInsensitive ) == 0 ) + { + request = QString( "GetCapabilities" ); + } + } + //GetCapabilities if ( request.compare( "GetCapabilities", Qt::CaseInsensitive ) == 0 || getProjectSettings ) { @@ -423,6 +440,12 @@ QDomDocument QgsWMSServer::getCapabilities( QString version, bool fullProjectInf hrefString = serviceUrl(); } + //href needs to be a prefix + if ( !hrefString.endsWith( "?" ) && !hrefString.endsWith( "&" ) ) + { + hrefString.append( hrefString.contains( "?" ) ? "&" : "?" ); + } + if ( version == "1.1.1" ) { doc = QDomDocument( "WMT_MS_Capabilities SYSTEM 'http://schemas.opengis.net/wms/1.1.1/WMS_MS_Capabilities.dtd'" ); //WMS 1.1.1 needs DOCTYPE "SYSTEM http://schemas.opengis.net/wms/1.1.1/WMS_MS_Capabilities.dtd" @@ -556,7 +579,7 @@ QDomDocument QgsWMSServer::getCapabilities( QString version, bool fullProjectInf //Exception element is mandatory elem = doc.createElement( "Exception" ); - appendFormats( doc, elem, QStringList() << ( version == "1.1.1" ? "application/vnd.ogc.se_xml" : "text/xml" ) ); + appendFormats( doc, elem, QStringList() << ( version == "1.1.1" ? "application/vnd.ogc.se_xml" : "XML" ) ); capabilityElement.appendChild( elem ); //UserDefinedSymbolization element @@ -690,6 +713,10 @@ static QgsRectangle _parseBBOX( const QString &bboxStr, bool &ok ) } ok = true; + if ( d[2] <= d[0] || d[3] <= d[1] ) + { + throw QgsMapServiceException( "InvalidParameterValue", "BBOX is empty" ); + } return QgsRectangle( d[0], d[1], d[2], d[3] ); } @@ -822,8 +849,6 @@ QImage* QgsWMSServer::getLegendGraphics() } QgsLayerTreeModel legendModel( &rootGroup ); - QList<QgsLayerTreeNode*> rootChildren = rootGroup.children(); - if ( scaleDenominator > 0 ) legendModel.setLegendFilterByScale( scaleDenominator ); @@ -863,7 +888,7 @@ QImage* QgsWMSServer::getLegendGraphics() } // find out DPI - QImage* tmpImage = createImage( 1, 1 ); + QImage* tmpImage = createImage( 1, 1, false ); if ( !tmpImage ) return nullptr; qreal dpmm = tmpImage->dotsPerMeterX() / 1000.0; @@ -893,7 +918,7 @@ QImage* QgsWMSServer::getLegendGraphics() if ( !rule.isEmpty() ) { //create second image with the right dimensions - QImage* paintImage = createImage( ruleSymbolWidth, ruleSymbolHeight ); + QImage* paintImage = createImage( ruleSymbolWidth, ruleSymbolHeight, false ); //go through the items a second time for painting QPainter p( paintImage ); @@ -915,6 +940,7 @@ QImage* QgsWMSServer::getLegendGraphics() return paintImage; } + QList<QgsLayerTreeNode*> rootChildren = rootGroup.children(); Q_FOREACH ( QgsLayerTreeNode* node, rootChildren ) { if ( QgsLayerTree::isLayer( node ) ) @@ -954,7 +980,7 @@ QImage* QgsWMSServer::getLegendGraphics() QSizeF minSize = legendRenderer.minimumSize(); QSize s( minSize.width() * dpmm, minSize.height() * dpmm ); - QImage* paintImage = createImage( s.width(), s.height() ); + QImage* paintImage = createImage( s.width(), s.height(), false ); QPainter p( paintImage ); p.setRenderHint( QPainter::Antialiasing, true ); @@ -1449,6 +1475,17 @@ QImage* QgsWMSServer::getMap( HitTest* hitTest ) // theImage->save( QDir::tempPath() + QDir::separator() + "lastrender.png" ); //#endif + thePainter.end(); + + //test if width / height ratio of image is the same as the ratio of WIDTH / HEIGHT parameters. If not, the image has to be scaled (required by WMS spec) + int widthParam = mParameters.value( "WIDTH", "0" ).toInt(); + int heightParam = mParameters.value( "HEIGHT", "0" ).toInt(); + if ( widthParam != theImage->width() || heightParam != theImage->height() ) + { + //scale image + *theImage = theImage->scaled( widthParam, heightParam, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ); + } + return theImage; } @@ -1570,7 +1607,6 @@ int QgsWMSServer::getFeatureInfo( QDomDocument& result, const QString& version ) QgsRectangle mapExtent = mMapRenderer->extent(); double scaleDenominator = scaleCalc.calculate( mapExtent, outputImage->width() ); mConfigParser->setScaleDenominator( scaleDenominator ); - delete outputImage; //no longer needed for feature info //read FEATURE_COUNT int featureCount = 1; @@ -1610,6 +1646,16 @@ int QgsWMSServer::getFeatureInfo( QDomDocument& result, const QString& version ) j = -1; } + //In case the output image is distorted (WIDTH/HEIGHT ratio not equal to BBOX width/height), I and J need to be adapted as well + int widthParam = mParameters.value( "WIDTH", "-1" ).toInt(); + int heightParam = mParameters.value( "HEIGHT", "-1" ).toInt(); + if (( i != -1 && j != -1 && widthParam != -1 && heightParam != -1 ) && ( widthParam != outputImage->width() || heightParam != outputImage->height() ) ) + { + i *= ( outputImage->width() / ( double )widthParam ); + j *= ( outputImage->height() / ( double )heightParam ); + } + delete outputImage; //no longer needed for feature info + //Normally, I/J or X/Y are mandatory parameters. //However, in order to make attribute only queries via the FILTER parameter, it is allowed to skip them if the FILTER parameter is there @@ -1926,7 +1972,7 @@ QImage* QgsWMSServer::initializeRendering( QStringList& layersList, QStringList& return theImage; } -QImage* QgsWMSServer::createImage( int width, int height ) const +QImage* QgsWMSServer::createImage( int width, int height, bool useBbox ) const { bool conversionSuccess; @@ -1946,6 +1992,32 @@ QImage* QgsWMSServer::createImage( int width, int height ) const } } + //Adapt width / height if the aspect ratio does not correspond with the BBOX. + //Required by WMS spec. 1.3. + if ( useBbox ) + { + bool bboxOk; + QgsRectangle mapExtent = _parseBBOX( mParameters.value( "BBOX" ), bboxOk ); + if ( bboxOk ) + { + double mapWidthHeightRatio = mapExtent.width() / mapExtent.height(); + double imageWidthHeightRatio = ( double )width / ( double )height; + if ( !qgsDoubleNear( mapWidthHeightRatio, imageWidthHeightRatio, 0.0001 ) ) + { + if ( mapWidthHeightRatio >= imageWidthHeightRatio ) + { + //increase image height + height = width * mapWidthHeightRatio; + } + else + { + //increase image width + width = height / mapWidthHeightRatio; + } + } + } + } + if ( width < 0 || height < 0 ) { return nullptr; @@ -1962,6 +2034,19 @@ QImage* QgsWMSServer::createImage( int width, int height ) const //transparent parameter bool transparent = mParameters.value( "TRANSPARENT" ).compare( "true", Qt::CaseInsensitive ) == 0; + //background color + QString bgColorString = mParameters.value( "BGCOLOR" ); + if ( bgColorString.startsWith( "0x", Qt::CaseInsensitive ) ) + { + bgColorString.replace( 0, 2, "#" ); + } + QColor backgroundColor; + backgroundColor.setNamedColor( bgColorString ); + if ( !backgroundColor.isValid() ) + { + backgroundColor = QColor( Qt::white ); + } + //use alpha channel only if necessary because it slows down performance if ( transparent && !jpeg ) { @@ -1971,7 +2056,7 @@ QImage* QgsWMSServer::createImage( int width, int height ) const else { theImage = new QImage( width, height, QImage::Format_RGB32 ); - theImage->fill( qRgb( 255, 255, 255 ) ); + theImage->fill( backgroundColor ); } if ( !theImage ) @@ -2007,17 +2092,32 @@ int QgsWMSServer::configureMapRender( const QPaintDevice* paintDevice ) const mMapRenderer->setOutputSize( QSize( paintDevice->width(), paintDevice->height() ), paintDevice->logicalDpiX() ); //map extent - bool bboxOk; - QgsRectangle mapExtent = _parseBBOX( mParameters.value( "BBOX", "0,0,0,0" ), bboxOk ); + bool bboxOk = true; + QgsRectangle mapExtent; + if ( mParameters.contains( "BBOX" ) ) + { + mapExtent = _parseBBOX( mParameters.value( "BBOX", "0,0,0,0" ), bboxOk ); + } + if ( !bboxOk ) { //throw a service exception throw QgsMapServiceException( "InvalidParameterValue", "Invalid BBOX parameter" ); } + if ( mParameters.contains( "BBOX" ) && mapExtent.isEmpty() ) + { + throw QgsMapServiceException( "InvalidParameterValue", "BBOX is empty" ); + } + QGis::UnitType mapUnits = QGis::Degrees; QString crs = mParameters.value( "CRS", mParameters.value( "SRS" ) ); + if ( crs.compare( "CRS:84", Qt::CaseInsensitive ) == 0 ) + { + crs = QString( "EPSG:4326" ); + mapExtent.invert(); + } QgsCoordinateReferenceSystem outputCRS; @@ -2154,6 +2254,12 @@ bool QgsWMSServer::infoPointToMapCoordinates( int i, int j, QgsPoint* infoPoint, return false; } + //check if i, j are in the pixel range of the image + if ( i < 0 || i > mapRenderer->width() || j < 0 || j > mapRenderer->height() ) + { + throw QgsMapServiceException( "InvalidPoint", "I/J parameters not within the pixel range" ); + } + double xRes = mapRenderer->extent().width() / mapRenderer->width(); double yRes = mapRenderer->extent().height() / mapRenderer->height(); infoPoint->setX( mapRenderer->extent().xMinimum() + i * xRes + xRes / 2.0 ); diff --git a/src/server/qgswmsserver.h b/src/server/qgswmsserver.h index 26f2c37..edc580b 100644 --- a/src/server/qgswmsserver.h +++ b/src/server/qgswmsserver.h @@ -133,9 +133,11 @@ class QgsWMSServer: public QgsOWSServer /** Creates a QImage from the HEIGHT and WIDTH parameters @param width image width (or -1 if width should be taken from WIDTH wms parameter) @param height image height (or -1 if height should be taken from HEIGHT wms parameter) + @param useBbox flag to indicate if the BBOX has to be used to adapt aspect ratio @return 0 in case of error*/ - QImage* createImage( int width = -1, int height = -1 ) const; - /** Configures mMapRenderer to the parameters + QImage* createImage( int width = -1, int height = -1, bool useBbox = true ) const; + + /** Configures mapSettings to the parameters HEIGHT, WIDTH, BBOX, CRS. @param paintDevice the device that is used for painting (for dpi) @return 0 in case of success*/ diff --git a/tests/src/gui/testqgsfiledownloader.cpp b/tests/src/gui/testqgsfiledownloader.cpp index fa9a7dc..9ab5bd0 100644 --- a/tests/src/gui/testqgsfiledownloader.cpp +++ b/tests/src/gui/testqgsfiledownloader.cpp @@ -172,7 +172,7 @@ void TestQgsFileDownloader::testInValidDownload() QVERIFY( mError ); QVERIFY( !mCanceled ); QVERIFY( mTempFile->size() == 0 ); - QCOMPARE( mErrorMessage, QString( "Network error 3: Host www.doesnotexistofthatimsure.qgis not found" ) ); + QCOMPARE( mErrorMessage, QString( "Download failed: Host www.doesnotexistofthatimsure.qgis not found" ) ); } void TestQgsFileDownloader::testCanceledDownload() @@ -205,7 +205,7 @@ void TestQgsFileDownloader::testInvalidUrl() QVERIFY( !mCompleted ); QVERIFY( mError ); QVERIFY( !mCanceled ); - QCOMPARE( mErrorMessage, QString( "Network error 301: Protocol \"xyz\" is unknown" ) ); + QCOMPARE( mErrorMessage, QString( "Download failed: Protocol \"xyz\" is unknown" ) ); } void TestQgsFileDownloader::testBlankUrl() @@ -216,7 +216,7 @@ void TestQgsFileDownloader::testBlankUrl() QVERIFY( !mCompleted ); QVERIFY( mError ); QVERIFY( !mCanceled ); - QCOMPARE( mErrorMessage, QString( "Network error 301: Protocol \"\" is unknown" ) ); + QCOMPARE( mErrorMessage, QString( "Download failed: Protocol \"\" is unknown" ) ); } #ifndef QT_NO_OPENSSL @@ -225,9 +225,9 @@ void TestQgsFileDownloader::testSslError_data() QTest::addColumn<QString>( "url" ); QTest::addColumn<QString>( "result" ); - QTest::newRow( "expired" ) << "https://expired.badssl.com/" << "Network error 6: SSL handshake failed;SSL Errors: ;The certificate has expired"; - QTest::newRow( "self-signed" ) << "https://self-signed.badssl.com/" << "Network error 6: SSL handshake failed;SSL Errors: ;The certificate is self-signed, and untrusted"; - QTest::newRow( "untrusted-root" ) << "https://untrusted-root.badssl.com/" << "Network error 6: SSL handshake failed;No certificates could be verified;SSL Errors: ;The issuer certificate of a locally looked up certificate could not be found;The root CA certificate is not trusted for this purpose"; + QTest::newRow( "expired" ) << "https://expired.badssl.com/" << "SSL Errors: ;The certificate has expired"; + QTest::newRow( "self-signed" ) << "https://self-signed.badssl.com/" << "SSL Errors: ;The certificate is self-signed, and untrusted"; + QTest::newRow( "untrusted-root" ) << "https://untrusted-root.badssl.com/" << "No certificates could be verified;SSL Errors: ;The issuer certificate of a locally looked up certificate could not be found;The root CA certificate is not trusted for this purpose"; } void TestQgsFileDownloader::testSslError() diff --git a/tests/src/python/test_qgsfiledownloader.py b/tests/src/python/test_qgsfiledownloader.py index 776ad49..0fe3b09 100644 --- a/tests/src/python/test_qgsfiledownloader.py +++ b/tests/src/python/test_qgsfiledownloader.py @@ -78,7 +78,7 @@ class TestQgsFileDownloader(unittest.TestCase): self.assertTrue(self.progress_was_called) self.assertFalse(self.canceled_was_called) self.assertTrue(self.error_was_called) - self.assertEqual(self.error_args[1], [u'Network error 3: Host www.doesnotexistofthatimsure.qgis not found']) + self.assertEqual(self.error_args[1], [u'Download failed: Host www.doesnotexistofthatimsure.qgis not found']) self.assertFalse(os.path.isfile(destination)) def test_dowloadCanceled(self): @@ -99,7 +99,7 @@ class TestQgsFileDownloader(unittest.TestCase): self.assertFalse(self.canceled_was_called) self.assertTrue(self.error_was_called) self.assertFalse(os.path.isfile(destination)) - self.assertEqual(self.error_args[1], [u"Network error 301: Protocol \"xyz\" is unknown"]) + self.assertEqual(self.error_args[1], [u"Download failed: Protocol \"xyz\" is unknown"]) def test_InvalidFile(self): self._make_download('https://github.com/qgis/QGIS/archive/master.zip', "") @@ -117,7 +117,7 @@ class TestQgsFileDownloader(unittest.TestCase): self.assertFalse(self.canceled_was_called) self.assertTrue(self.error_was_called) self.assertFalse(os.path.isfile(destination)) - self.assertEqual(self.error_args[1], [u"Network error 301: Protocol \"\" is unknown"]) + self.assertEqual(self.error_args[1], [u"Download failed: Protocol \"\" is unknown"]) def ssl_compare(self, name, url, error): destination = tempfile.mktemp() @@ -130,12 +130,12 @@ class TestQgsFileDownloader(unittest.TestCase): self.assertFalse(os.path.isfile(destination), msg) result = sorted(self.error_args[1]) result = ';'.join(result) - self.assertEqual(result, error, msg + "expected:\n%s\nactual:\n%s\n" % (result, error)) + self.assertEqual(result, error, msg + "expected:\n%s\nactual:\n%s\n" % (error, result)) def test_sslExpired(self): - self.ssl_compare("expired", "https://expired.badssl.com/", "Network error 6: SSL handshake failed;SSL Errors: ;The certificate has expired") - self.ssl_compare("self-signed", "https://self-signed.badssl.com/", "Network error 6: SSL handshake failed;SSL Errors: ;The certificate is self-signed, and untrusted") - self.ssl_compare("untrusted-root", "https://untrusted-root.badssl.com/", "Network error 6: SSL handshake failed;No certificates could be verified;SSL Errors: ;The issuer certificate of a locally looked up certificate could not be found;The root CA certificate is not trusted for this purpose") + self.ssl_compare("expired", "https://expired.badssl.com/", "SSL Errors: ;The certificate has expired") + self.ssl_compare("self-signed", "https://self-signed.badssl.com/", "SSL Errors: ;The certificate is self-signed, and untrusted") + self.ssl_compare("untrusted-root", "https://untrusted-root.badssl.com/", "No certificates could be verified;SSL Errors: ;The issuer certificate of a locally looked up certificate could not be found;The root CA certificate is not trusted for this purpose") def _set_slot(self, *args, **kwargs): #print('_set_slot(%s) called' % args[0]) diff --git a/tests/src/python/test_qgsserver.py b/tests/src/python/test_qgsserver.py index 99a3ec4..f5e58a9 100644 --- a/tests/src/python/test_qgsserver.py +++ b/tests/src/python/test_qgsserver.py @@ -35,6 +35,10 @@ class TestQgsServer(unittest.TestCase): def setUp(self): """Create the server instance""" self.testdata_path = unitTestDataPath('qgis_server') + '/' + + d = unitTestDataPath('qgis_server_accesscontrol') + '/' + self.projectPath = os.path.join(d, "project.qgs") + # Clean env just to be sure env_vars = ['QUERY_STRING', 'QGIS_PROJECT_FILE'] for ev in env_vars: @@ -407,6 +411,132 @@ class TestQgsServer(unittest.TestCase): r, h = self._result(self.server.handleRequest(qs)) self._img_diff_error(r, h, "WMS_GetLegendGraphic_test_layertitle_false", 250, QSize(10, 10)) + def test_wms_GetLegendGraphic_Basic(self): + qs = "&".join(["%s=%s" % i for i in list({ + "MAP": urllib.quote(self.projectPath), + "SERVICE": "WMS", + "VERSION": "1.1.1", + "REQUEST": "GetLegendGraphic", + "LAYER": "Country,Hello", + "LAYERTITLE": "FALSE", + "FORMAT": "image/png", + "HEIGHT": "500", + "WIDTH": "500", + "CRS": "EPSG:3857" + }.items())]) + + r, h = self._result(self.server.handleRequest(qs)) + self._img_diff_error(r, h, "WMS_GetLegendGraphic_Basic") + + def test_wms_GetLegendGraphic_BoxSpace(self): + qs = "&".join(["%s=%s" % i for i in list({ + "MAP": urllib.quote(self.projectPath), + "SERVICE": "WMS", + "VERSION": "1.1.1", + "REQUEST": "GetLegendGraphic", + "LAYER": "Country,Hello", + "LAYERTITLE": "FALSE", + "BOXSPACE": "100", + "FORMAT": "image/png", + "HEIGHT": "500", + "WIDTH": "500", + "CRS": "EPSG:3857" + }.items())]) + + r, h = self._result(self.server.handleRequest(qs)) + self._img_diff_error(r, h, "WMS_GetLegendGraphic_BoxSpace") + + def test_wms_GetLegendGraphic_SymbolSpace(self): + qs = "&".join(["%s=%s" % i for i in list({ + "MAP": urllib.quote(self.projectPath), + "SERVICE": "WMS", + "VERSION": "1.1.1", + "REQUEST": "GetLegendGraphic", + "LAYER": "Country,Hello", + "LAYERTITLE": "FALSE", + "SYMBOLSPACE": "100", + "FORMAT": "image/png", + "HEIGHT": "500", + "WIDTH": "500", + "CRS": "EPSG:3857" + }.items())]) + + r, h = self._result(self.server.handleRequest(qs)) + self._img_diff_error(r, h, "WMS_GetLegendGraphic_SymbolSpace") + + def test_wms_GetLegendGraphic_IconLabelSpace(self): + qs = "&".join(["%s=%s" % i for i in list({ + "MAP": urllib.quote(self.projectPath), + "SERVICE": "WMS", + "VERSION": "1.1.1", + "REQUEST": "GetLegendGraphic", + "LAYER": "Country,Hello", + "LAYERTITLE": "FALSE", + "ICONLABELSPACE": "100", + "FORMAT": "image/png", + "HEIGHT": "500", + "WIDTH": "500", + "CRS": "EPSG:3857" + }.items())]) + + r, h = self._result(self.server.handleRequest(qs)) + self._img_diff_error(r, h, "WMS_GetLegendGraphic_IconLabelSpace") + + def test_wms_GetLegendGraphic_SymbolSize(self): + qs = "&".join(["%s=%s" % i for i in list({ + "MAP": urllib.quote(self.projectPath), + "SERVICE": "WMS", + "VERSION": "1.1.1", + "REQUEST": "GetLegendGraphic", + "LAYER": "Country,Hello", + "LAYERTITLE": "FALSE", + "SYMBOLWIDTH": "50", + "SYMBOLHEIGHT": "30", + "FORMAT": "image/png", + "HEIGHT": "500", + "WIDTH": "500", + "CRS": "EPSG:3857" + }.items())]) + + r, h = self._result(self.server.handleRequest(qs)) + self._img_diff_error(r, h, "WMS_GetLegendGraphic_SymbolSize") + + def test_wms_GetLegendGraphic_BBox(self): + qs = "&".join(["%s=%s" % i for i in list({ + "MAP": urllib.quote(self.projectPath), + "SERVICE": "WMS", + "VERSION": "1.1.1", + "REQUEST": "GetLegendGraphic", + "LAYER": "Country,Hello,db_point", + "LAYERTITLE": "FALSE", + "FORMAT": "image/png", + "HEIGHT": "500", + "WIDTH": "500", + "BBOX": "-151.7,-38.9,51.0,78.0", + "CRS": "EPSG:4326" + }.items())]) + + r, h = self._result(self.server.handleRequest(qs)) + self._img_diff_error(r, h, "WMS_GetLegendGraphic_BBox") + + def test_wms_GetLegendGraphic_BBox2(self): + qs = "&".join(["%s=%s" % i for i in list({ + "MAP": urllib.quote(self.projectPath), + "SERVICE": "WMS", + "VERSION": "1.1.1", + "REQUEST": "GetLegendGraphic", + "LAYER": "Country,Hello,db_point", + "LAYERTITLE": "FALSE", + "FORMAT": "image/png", + "HEIGHT": "500", + "WIDTH": "500", + "BBOX": "-76.08,-6.4,-19.38,38.04", + "SRS": "EPSG:4326" + }.items())]) + + r, h = self._result(self.server.handleRequest(qs)) + self._img_diff_error(r, h, "WMS_GetLegendGraphic_BBox2") + def _result(self, data): headers = {} for line in data[0].decode('UTF-8').split("\n"): diff --git a/tests/src/python/test_qgsserver_accesscontrol.py b/tests/src/python/test_qgsserver_accesscontrol.py index 02c7c66..2d58d77 100644 --- a/tests/src/python/test_qgsserver_accesscontrol.py +++ b/tests/src/python/test_qgsserver_accesscontrol.py @@ -294,7 +294,7 @@ class TestQgsServerAccessControl(unittest.TestCase): "LAYERS": "Country,Hello", "STYLES": "", "FORMAT": "image/png", - "BBOX": "-16817707,-4710778,5696513,14587125", + "BBOX": "-16817707,-6318936.5,5696513,16195283.5", "HEIGHT": "500", "WIDTH": "500", "SRS": "EPSG:3857" @@ -311,7 +311,7 @@ class TestQgsServerAccessControl(unittest.TestCase): "LAYERS": "Hello", "STYLES": "", "FORMAT": "image/png", - "BBOX": "-16817707,-4710778,5696513,14587125", + "BBOX": "-16817707,-6318936.5,5696513,16195283.5", "HEIGHT": "500", "WIDTH": "500", "SRS": "EPSG:3857" @@ -327,7 +327,7 @@ class TestQgsServerAccessControl(unittest.TestCase): "LAYERS": "Country", "STYLES": "", "FORMAT": "image/png", - "BBOX": "-16817707,-4710778,5696513,14587125", + "BBOX": "-16817707,-6318936.5,5696513,16195283.5", "HEIGHT": "500", "WIDTH": "500", "SRS": "EPSG:3857" @@ -351,7 +351,7 @@ class TestQgsServerAccessControl(unittest.TestCase): "QUERY_LAYERS": "Hello", "STYLES": "", "FORMAT": "image/png", - "BBOX": "-16817707,-4710778,5696513,14587125", + "BBOX": "-16817707,-6318936.5,5696513,16195283.5", "HEIGHT": "500", "WIDTH": "500", "SRS": "EPSG:3857", @@ -390,7 +390,7 @@ class TestQgsServerAccessControl(unittest.TestCase): "QUERY_LAYERS": "Hello", "STYLES": "", "FORMAT": "image/png", - "BBOX": "-16817707,-4710778,5696513,14587125", + "BBOX": "-16817707,-6318936.5,5696513,16195283.5", "HEIGHT": "500", "WIDTH": "500", "SRS": "EPSG:3857", @@ -420,7 +420,7 @@ class TestQgsServerAccessControl(unittest.TestCase): "QUERY_LAYERS": "Country", "STYLES": "", "FORMAT": "image/png", - "BBOX": "-16817707,-4710778,5696513,14587125", + "BBOX": "-16817707,-6318936.5,5696513,16195283.5", "HEIGHT": "500", "WIDTH": "500", "SRS": "EPSG:3857", @@ -842,7 +842,7 @@ class TestQgsServerAccessControl(unittest.TestCase): "LAYERS": "Country,Hello_SubsetString", "STYLES": "", "FORMAT": "image/png", - "BBOX": "-16817707,-4710778,5696513,14587125", + "BBOX": "-16817707,-6318936.5,5696513,16195283.5", "HEIGHT": "500", "WIDTH": "500", "SRS": "EPSG:3857" @@ -859,7 +859,7 @@ class TestQgsServerAccessControl(unittest.TestCase): "LAYERS": "Hello_SubsetString", "STYLES": "", "FORMAT": "image/png", - "BBOX": "-16817707,-4710778,5696513,14587125", + "BBOX": "-16817707,-6318936.5,5696513,16195283.5", "HEIGHT": "500", "WIDTH": "500", "SRS": "EPSG:3857" @@ -882,7 +882,7 @@ class TestQgsServerAccessControl(unittest.TestCase): "FILTER": "Hello_Filter_SubsetString:\"pkuid\" IN ( 7 , 8 )", "STYLES": "", "FORMAT": "image/png", - "BBOX": "-16817707,-4710778,5696513,14587125", + "BBOX": "-16817707,-6318936.5,5696513,16195283.5", "HEIGHT": "500", "WIDTH": "500", "SRS": "EPSG:3857" @@ -900,7 +900,7 @@ class TestQgsServerAccessControl(unittest.TestCase): "FILTER": "Hello_Filter_SubsetString:\"pkuid\" IN ( 7 , 8 )", "STYLES": "", "FORMAT": "image/png", - "BBOX": "-16817707,-4710778,5696513,14587125", + "BBOX": "-16817707,-6318936.5,5696513,16195283.5", "HEIGHT": "500", "WIDTH": "500", "SRS": "EPSG:3857" @@ -919,7 +919,7 @@ class TestQgsServerAccessControl(unittest.TestCase): "LAYERS": "Hello_Project_SubsetString", "STYLES": "", "FORMAT": "image/png", - "BBOX": "-16817707,-4710778,5696513,14587125", + "BBOX": "-16817707,-6318936.5,5696513,16195283.5", "HEIGHT": "500", "WIDTH": "500", "SRS": "EPSG:3857" @@ -936,7 +936,7 @@ class TestQgsServerAccessControl(unittest.TestCase): "LAYERS": "Hello_Project_SubsetString", "STYLES": "", "FORMAT": "image/png", - "BBOX": "-16817707,-4710778,5696513,14587125", + "BBOX": "-16817707,-6318936.5,5696513,16195283.5", "HEIGHT": "500", "WIDTH": "500", "SRS": "EPSG:3857" @@ -954,7 +954,7 @@ class TestQgsServerAccessControl(unittest.TestCase): "QUERY_LAYERS": "Hello_SubsetString", "STYLES": "", "FORMAT": "image/png", - "BBOX": "-16817707,-4710778,5696513,14587125", + "BBOX": "-16817707,-6318936.5,5696513,16195283.5", "HEIGHT": "500", "WIDTH": "500", "SRS": "EPSG:3857", @@ -990,7 +990,7 @@ class TestQgsServerAccessControl(unittest.TestCase): "QUERY_LAYERS": "Hello_SubsetString", "STYLES": "", "FORMAT": "image/png", - "BBOX": "-16817707,-4710778,5696513,14587125", + "BBOX": "-16817707,-6318936.5,5696513,16195283.5", "HEIGHT": "500", "WIDTH": "500", "SRS": "EPSG:3857", @@ -1026,7 +1026,7 @@ class TestQgsServerAccessControl(unittest.TestCase): "QUERY_LAYERS": "Hello_Project_SubsetString", "STYLES": "", "FORMAT": "image/png", - "BBOX": "-16817707,-4710778,5696513,14587125", + "BBOX": "-16817707,-6318936.5,5696513,16195283.5", "HEIGHT": "500", "WIDTH": "500", "SRS": "EPSG:3857", @@ -1135,7 +1135,7 @@ class TestQgsServerAccessControl(unittest.TestCase): "FILTER": "Hello_Filter_SubsetString:\"pkuid\" IN ( 7 , 8 )", "STYLES": "", "FORMAT": "image/png", - "BBOX": "-16817707,-4710778,5696513,14587125", + "BBOX": "-16817707,-6318936.5,5696513,16195283.5", "HEIGHT": "500", "WIDTH": "500", "SRS": "EPSG:3857", diff --git a/tests/testdata/control_images/qgis_server/WMS_GetLegendGraphic_BBox/WMS_GetLegendGraphic_BBox.png b/tests/testdata/control_images/qgis_server/WMS_GetLegendGraphic_BBox/WMS_GetLegendGraphic_BBox.png new file mode 100644 index 0000000..8b720ab Binary files /dev/null and b/tests/testdata/control_images/qgis_server/WMS_GetLegendGraphic_BBox/WMS_GetLegendGraphic_BBox.png differ diff --git a/tests/testdata/control_images/qgis_server/WMS_GetLegendGraphic_BBox2/WMS_GetLegendGraphic_BBox2.png b/tests/testdata/control_images/qgis_server/WMS_GetLegendGraphic_BBox2/WMS_GetLegendGraphic_BBox2.png new file mode 100644 index 0000000..131d528 Binary files /dev/null and b/tests/testdata/control_images/qgis_server/WMS_GetLegendGraphic_BBox2/WMS_GetLegendGraphic_BBox2.png differ diff --git a/tests/testdata/control_images/qgis_server/WMS_GetLegendGraphic_Basic/WMS_GetLegendGraphic_Basic.png b/tests/testdata/control_images/qgis_server/WMS_GetLegendGraphic_Basic/WMS_GetLegendGraphic_Basic.png new file mode 100644 index 0000000..131d528 Binary files /dev/null and b/tests/testdata/control_images/qgis_server/WMS_GetLegendGraphic_Basic/WMS_GetLegendGraphic_Basic.png differ diff --git a/tests/testdata/control_images/qgis_server/WMS_GetLegendGraphic_BoxSpace/WMS_GetLegendGraphic_BoxSpace.png b/tests/testdata/control_images/qgis_server/WMS_GetLegendGraphic_BoxSpace/WMS_GetLegendGraphic_BoxSpace.png new file mode 100644 index 0000000..0c8e440 Binary files /dev/null and b/tests/testdata/control_images/qgis_server/WMS_GetLegendGraphic_BoxSpace/WMS_GetLegendGraphic_BoxSpace.png differ diff --git a/tests/testdata/control_images/qgis_server/WMS_GetLegendGraphic_IconLabelSpace/WMS_GetLegendGraphic_IconLabelSpace.png b/tests/testdata/control_images/qgis_server/WMS_GetLegendGraphic_IconLabelSpace/WMS_GetLegendGraphic_IconLabelSpace.png new file mode 100644 index 0000000..b300268 Binary files /dev/null and b/tests/testdata/control_images/qgis_server/WMS_GetLegendGraphic_IconLabelSpace/WMS_GetLegendGraphic_IconLabelSpace.png differ diff --git a/tests/testdata/control_images/qgis_server/WMS_GetLegendGraphic_SymbolSize/WMS_GetLegendGraphic_SymbolSize.png b/tests/testdata/control_images/qgis_server/WMS_GetLegendGraphic_SymbolSize/WMS_GetLegendGraphic_SymbolSize.png new file mode 100644 index 0000000..7a49f43 Binary files /dev/null and b/tests/testdata/control_images/qgis_server/WMS_GetLegendGraphic_SymbolSize/WMS_GetLegendGraphic_SymbolSize.png differ diff --git a/tests/testdata/control_images/qgis_server/WMS_GetLegendGraphic_SymbolSpace/WMS_GetLegendGraphic_SymbolSpace.png b/tests/testdata/control_images/qgis_server/WMS_GetLegendGraphic_SymbolSpace/WMS_GetLegendGraphic_SymbolSpace.png new file mode 100644 index 0000000..dcab569 Binary files /dev/null and b/tests/testdata/control_images/qgis_server/WMS_GetLegendGraphic_SymbolSpace/WMS_GetLegendGraphic_SymbolSpace.png differ diff --git a/tests/testdata/qgis_server/getcapabilities.txt b/tests/testdata/qgis_server/getcapabilities.txt index ea62c81..ac29926 100644 --- a/tests/testdata/qgis_server/getcapabilities.txt +++ b/tests/testdata/qgis_server/getcapabilities.txt @@ -97,11 +97,12 @@ Content-Type: text/xml; charset=utf-8 </qgs:GetStyles> </Request> <Exception> - <Format>text/xml</Format> + <Format>XML</Format> </Exception> <Layer queryable="1"> <Name>QGIS Test Project</Name> <Title>QGIS Test Project</Title> + <CRS>CRS:84</CRS> <CRS>EPSG:4326</CRS> <CRS>EPSG:3857</CRS> <EX_GeographicBoundingBox> @@ -116,6 +117,7 @@ Content-Type: text/xml; charset=utf-8 <Name>testlayer èé</Name> <Title>A test vector layer</Title> <Abstract>A test vector layer with unicode òà</Abstract> + <CRS>CRS:84</CRS> <CRS>EPSG:4326</CRS> <CRS>EPSG:3857</CRS> <EX_GeographicBoundingBox> diff --git a/tests/testdata/qgis_server/getcapabilities_inspire.txt b/tests/testdata/qgis_server/getcapabilities_inspire.txt index da2f31d..d71d302 100644 --- a/tests/testdata/qgis_server/getcapabilities_inspire.txt +++ b/tests/testdata/qgis_server/getcapabilities_inspire.txt @@ -97,7 +97,7 @@ Content-Type: text/xml; charset=utf-8 </qgs:GetStyles> </Request> <Exception> - <Format>text/xml</Format> + <Format>XML</Format> </Exception> <sld:UserDefinedSymbolization RemoteWFS="0" RemoteWCS="0" InlineFeature="0" UserStyle="1" SupportSLD="1" UserLayer="0"/> <inspire_vs:ExtendedCapabilities> @@ -123,6 +123,7 @@ Content-Type: text/xml; charset=utf-8 <Layer queryable="1"> <Name>QGIS Test Project</Name> <Title>QGIS Test Project</Title> + <CRS>CRS:84</CRS> <CRS>EPSG:4326</CRS> <CRS>EPSG:3857</CRS> <EX_GeographicBoundingBox> @@ -137,6 +138,7 @@ Content-Type: text/xml; charset=utf-8 <Name>testlayer èé</Name> <Title>A test vector layer</Title> <Abstract>A test vector layer with unicode òà</Abstract> + <CRS>CRS:84</CRS> <CRS>EPSG:4326</CRS> <CRS>EPSG:3857</CRS> <EX_GeographicBoundingBox> diff --git a/tests/testdata/qgis_server/getprojectsettings.txt b/tests/testdata/qgis_server/getprojectsettings.txt index 7d25c2e..62b1fe6 100644 --- a/tests/testdata/qgis_server/getprojectsettings.txt +++ b/tests/testdata/qgis_server/getprojectsettings.txt @@ -109,7 +109,7 @@ Content-Type: text/xml; charset=utf-8 </GetPrint> </Request> <Exception> - <Format>text/xml</Format> + <Format>XML</Format> </Exception> <sld:UserDefinedSymbolization RemoteWFS="0" RemoteWCS="0" InlineFeature="0" UserStyle="1" SupportSLD="1" UserLayer="0"/> <WFSLayers> @@ -118,6 +118,7 @@ Content-Type: text/xml; charset=utf-8 <Layer queryable="1"> <Name>QGIS Test Project</Name> <Title>QGIS Test Project</Title> + <CRS>CRS:84</CRS> <CRS>EPSG:4326</CRS> <CRS>EPSG:3857</CRS> <EX_GeographicBoundingBox> @@ -133,6 +134,7 @@ Content-Type: text/xml; charset=utf-8 <Name>testlayer èé</Name> <Title>A test vector layer</Title> <Abstract>A test vector layer with unicode òà</Abstract> + <CRS>CRS:84</CRS> <CRS>EPSG:4326</CRS> <CRS>EPSG:3857</CRS> <EX_GeographicBoundingBox> diff --git a/tests/testdata/qgis_server/wfs_getcapabilities.txt b/tests/testdata/qgis_server/wfs_getcapabilities.txt index 2a7714c..420df60 100644 --- a/tests/testdata/qgis_server/wfs_getcapabilities.txt +++ b/tests/testdata/qgis_server/wfs_getcapabilities.txt @@ -7,7 +7,7 @@ Content-Type: text/xml; charset=utf-8 <Title>QGIS TestProject</Title> <Abstract>Some UTF8 text èòù</Abstract> <OnlineResource></OnlineResource> - <Fees>conditions unknown</Fees> + <Fees>None</Fees> <AccessConstraints>None</AccessConstraints> </Service> <Capability> -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/qgis.git _______________________________________________ Pkg-grass-devel mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-grass-devel

