[qgis] 03/08: Imported Upstream version 2.14.10+dfsg

Bas Couwenberg sebastic at debian.org
Fri Dec 16 15:08:02 UTC 2016


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 <sebastic at xs4all.nl>
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 <alexander.bruy at gmail.com>	2016-12-15
+
+    [processing] quote file paths in TauDEM provider
+
+Alessandro Pasotti <apasotti at boundlessgeo.com>	2016-12-14
+
+    [BACKPORT][BUGFIX] Fixed a crash on bad network protocol
+
+     ( from f48f90ead )
+
+rldhont <rldhont at gmail.com>	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 <rldhont at gmail.com>	2016-12-13
+
+    Merge pull request #3862 from rldhont/release-2_14-wms-130-compliance
+
+    Backport 214 wms 130 compliance
+
+Blottiere Paul <blottiere.paul at gmail.com>	2016-12-09
+
+    fix getLegendGraphics when BBox parameter is used
+
+rldhont <rldhont at gmail.com>	2016-12-12
+
+    Adapt WFS capabilties in server test for WMS 1.3.0 compliance
+
+Marco Hugentobler <marco.hugentobler at sourcepole.ch>	2016-12-01
+
+    Fix access control tests such that bbox width/height ration matches image width/height
+
+Marco Hugentobler <marco.hugentobler at sourcepole.ch>	2016-12-01
+
+    Adapt expected capabilities / project settings response in server test for WMS 1.3.0 compliance
+
+rldhont <rldhont at gmail.com>	2016-12-12
+
+    Fix typo
+
+Marco Hugentobler <marco.hugentobler at sourcepole.ch>	2016-12-09
+
+    Backward support for parameters 'MTVER' and 'capabilities' from WMS 1.0.0 is required for WMS 1.1.1
+
+Marco Hugentobler <marco.hugentobler at sourcepole.ch>	2016-12-01
+
+    Indentation
+
+Marco Hugentobler <marco.hugentobler at sourcepole.ch>	2016-12-01
+
+    WMS server: parse bounding box only if the BBOX parameter is really there
+
+Marco Hugentobler <marco.hugentobler at sourcepole.ch>	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 <marco.hugentobler at sourcepole.ch>	2016-11-29
+
+    Exception format is XML, not capabilities format
+
+Marco Hugentobler <marco.hugentobler at sourcepole.ch>	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 <marco.hugentobler at sourcepole.ch>	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 <marco.hugentobler at sourcepole.ch>	2016-11-29
+
+    WMS 1.3.0 compliance: throw exception if bbox is empty
+
+Marco Hugentobler <marco.hugentobler at sourcepole.ch>	2016-11-29
+
+    Fix typo
+
+Marco Hugentobler <marco.hugentobler at sourcepole.ch>	2016-11-29
+
+    WMS 1.3.0 compliance: exception format must be advertized as 'XML', not 'text/xml'
+
+Marco Hugentobler <marco.hugentobler at sourcepole.ch>	2016-11-29
+
+    WMS 1.3.0 compliance: CRS:84  needs to be supported
+
+Marco Hugentobler <marco.hugentobler at sourcepole.ch>	2016-11-29
+
+    WMS 1.3.0 compliance: support BGCOLOR parameter
+
+Marco Hugentobler <marco.hugentobler at sourcepole.ch>	2016-11-29
+
+    WMS 1.3.0 compliance: throw exception if feature info point is not within the WIDTH/HEIGHT parameters
+
+Marco Hugentobler <marco.hugentobler at sourcepole.ch>	2016-11-29
+
+    WMS 1.3.0 compliance: use the reserved word 'None' if no fees
+
+nirvn <nirvn.asia at gmail.com>	2016-12-08
+
+    Revert "[style dock] emit widgetChanged() when raster palette labels updated"
+
+    This reverts commit f92928d4da7ece907b94713e8706e550e6ab4c5e.
+
+nirvn <nirvn.asia at gmail.com>	2016-12-08
+
+    [style dock] emit widgetChanged() when raster palette labels updated
+
+Sandro Mani <manisandro at gmail.com>	2016-12-06
+
+    [Geometry Checker] Don't add geometry-less features to feature-pool
+
+Hugo Mercier <hugo.mercier at oslandia.com>	2016-12-05
+
+    [virtual layer] Fix xFilter for null value comparisons
+
+Merge: b3742fe 8dc7799
+volaya <volayaf at gmail.com>	2016-12-02
+
+    Merge pull request #3826 from alexbruy/processing-models
+
+    fix loading of models containing user-defined scripts
+
+Alexander Bruy <alexander.bruy at gmail.com>	2016-12-02
+
+    fix loading of models containing user-defined scripts
+
+Sandro Mani <manisandro at gmail.com>	2016-12-01
+
+    [Geometry checker] Fix possible use of deleted geometry
+
+rldhont <rldhont at gmail.com>	2016-11-30
+
+    Update QgsPointDisplacementRenderer::legendKeysForFeature note
+
+rldhont <rldhont at gmail.com>	2016-11-30
+
+    [BUGFIX] Filter Legend By Map Content doesn't maintain point displacement legend
+
+    Fixed #11572
+    Manually cherry-picked 4d71cf968c4608359514637ceabcf4f3dcfb09ce
+
+borys <info at borysjurgiel.pl>	2016-11-29
+
+    [bugfix] Fix broken docks customization. Fixes #8055
+
+volaya <volayaf at gmail.com>	2016-11-27
+
+    [processing] fixed file extension when exporting layer
+
+    fixes #15898
+
+Juergen E. Fischer <jef at norbit.de>	2016-11-25
+
+    Release of 2.14.9
+
 Matthias Kuhn <matthias at opengis.ch>	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 <jef at norbit.de>  Fri, 16 Dec 2016 13:00:16 +0100
+
+qgis (2.14.9) unstable; urgency=medium
 
   * Release of 2.14.9
 
- -- Jürgen E. Fischer <jef at norbit.de>  Fri, 25 Nov 2016 14:11:24 +0100
+ -- Jürgen E. Fischer <jef at norbit.de>  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



More information about the Pkg-grass-devel mailing list