QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
qgswmsdescribelayer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgswmsdescribelayer.cpp
3  -------------------------
4  begin : December 20 , 2016
5  copyright : (C) 2007 by Marco Hugentobler (original code)
6  (C) 2014 by Alessandro Pasotti (original code)
7  (C) 2016 by David Marteau
8  email : marco dot hugentobler at karto dot baug dot ethz dot ch
9  a dot pasotti at itopen dot it
10  david dot marteau at 3liz dot com
11  ***************************************************************************/
12 
13 /***************************************************************************
14  * *
15  * This program is free software; you can redistribute it and/or modify *
16  * it under the terms of the GNU General Public License as published by *
17  * the Free Software Foundation; either version 2 of the License, or *
18  * (at your option) any later version. *
19  * *
20  ***************************************************************************/
21 
22 #include "qgswmsutils.h"
23 #include "qgswmsrequest.h"
24 #include "qgswmsserviceexception.h"
25 #include "qgswmsdescribelayer.h"
26 #include "qgsserverprojectutils.h"
27 #include "qgsproject.h"
28 
29 namespace QgsWms
30 {
31 
32  void writeDescribeLayer( QgsServerInterface *serverIface, const QgsProject *project,
33  const QgsWmsRequest &request, QgsServerResponse &response )
34  {
35  const QDomDocument doc = describeLayer( serverIface, project, request );
36  response.setHeader( QStringLiteral( "Content-Type" ), QStringLiteral( "text/xml; charset=utf-8" ) );
37  response.write( doc.toByteArray() );
38  }
39 
40  // DescribeLayer is defined for WMS1.1.1/SLD1.0 and in WMS 1.3.0 SLD Extension
41  QDomDocument describeLayer( QgsServerInterface *serverIface, const QgsProject *project,
42  const QgsWmsRequest &request )
43  {
44  const QgsServerRequest::Parameters parameters = request.parameters();
45 
46  if ( !parameters.contains( QStringLiteral( "SLD_VERSION" ) ) )
47  {
48  throw QgsServiceException( QStringLiteral( "MissingParameterValue" ),
49  QStringLiteral( "SLD_VERSION is mandatory for DescribeLayer operation" ), 400 );
50  }
51  if ( parameters[ QStringLiteral( "SLD_VERSION" )] != QLatin1String( "1.1.0" ) )
52  {
53  throw QgsServiceException( QStringLiteral( "InvalidParameterValue" ),
54  QStringLiteral( "SLD_VERSION = %1 is not supported" ).arg( parameters[ QStringLiteral( "SLD_VERSION" )] ), 400 );
55  }
56 
57  if ( !parameters.contains( QStringLiteral( "LAYERS" ) ) )
58  {
59  throw QgsServiceException( QStringLiteral( "MissingParameterValue" ),
60  QStringLiteral( "LAYERS is mandatory for DescribeLayer operation" ), 400 );
61  }
62 
63 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
64  QStringList layersList = parameters[ QStringLiteral( "LAYERS" )].split( ',', QString::SkipEmptyParts );
65 #else
66  const QStringList layersList = parameters[ QStringLiteral( "LAYERS" )].split( ',', Qt::SkipEmptyParts );
67 #endif
68  if ( layersList.isEmpty() )
69  {
70  throw QgsServiceException( QStringLiteral( "InvalidParameterValue" ), QStringLiteral( "Layers is empty" ), 400 );
71  }
72  QDomDocument myDocument = QDomDocument();
73 
74  const QDomNode header = myDocument.createProcessingInstruction( QStringLiteral( "xml" ), QStringLiteral( "version=\"1.0\" encoding=\"UTF-8\"" ) );
75  myDocument.appendChild( header );
76 
77  // Create the root element
78  QDomElement root = myDocument.createElementNS( QStringLiteral( "http://www.opengis.net/sld" ), QStringLiteral( "DescribeLayerResponse" ) );
79  root.setAttribute( QStringLiteral( "xsi:schemaLocation" ), QStringLiteral( "http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/DescribeLayer.xsd" ) );
80  root.setAttribute( QStringLiteral( "xmlns:ows" ), QStringLiteral( "http://www.opengis.net/ows" ) );
81  root.setAttribute( QStringLiteral( "xmlns:se" ), QStringLiteral( "http://www.opengis.net/se" ) );
82  root.setAttribute( QStringLiteral( "xmlns:xlink" ), QStringLiteral( "http://www.w3.org/1999/xlink" ) );
83  root.setAttribute( QStringLiteral( "xmlns:xsi" ), QStringLiteral( "http://www.w3.org/2001/XMLSchema-instance" ) );
84  myDocument.appendChild( root );
85 
86  // store the Version element
87  QDomElement versionNode = myDocument.createElement( QStringLiteral( "Version" ) );
88  versionNode.appendChild( myDocument.createTextNode( QStringLiteral( "1.1.0" ) ) );
89  root.appendChild( versionNode );
90 
91  // get the wms service url defined in project or keep the one from the
92  // request url
93  const QString wmsHrefString = serviceUrl( request, project, *serverIface->serverSettings() ).toString();
94 
95  // get the wfs service url defined in project or take the same as the
96  // wms service url
97  QString wfsHrefString = QgsServerProjectUtils::wfsServiceUrl( *project, request, *serverIface->serverSettings() );
98  if ( wfsHrefString.isEmpty() )
99  {
100  wfsHrefString = wmsHrefString;
101  }
102 
103  // get the wcs service url defined in project or take the same as the
104  // wms service url
105  QString wcsHrefString = QgsServerProjectUtils::wcsServiceUrl( *project, request, *serverIface->serverSettings() );
106  if ( wcsHrefString.isEmpty() )
107  {
108  wcsHrefString = wmsHrefString;
109  }
110 
111  // access control
112 #ifdef HAVE_SERVER_PYTHON_PLUGINS
113  QgsAccessControl *accessControl = serverIface->accessControls();
114 #else
115  ( void )serverIface;
116 #endif
117  // Use layer ids
118  const bool useLayerIds = QgsServerProjectUtils::wmsUseLayerIds( *project );
119  // WMS restricted layers
120  const QStringList restrictedLayers = QgsServerProjectUtils::wmsRestrictedLayers( *project );
121  // WFS layers
122  const QStringList wfsLayerIds = QgsServerProjectUtils::wfsLayerIds( *project );
123  // WCS layers
124  const QStringList wcsLayerIds = QgsServerProjectUtils::wcsLayerIds( *project );
125 
126  for ( QgsMapLayer *layer : project->mapLayers() )
127  {
128  QString name = layer->name();
129  if ( useLayerIds )
130  name = layer->id();
131  else if ( !layer->shortName().isEmpty() )
132  name = layer->shortName();
133 
134  if ( !layersList.contains( name ) )
135  {
136  continue;
137  }
138 
139  //unpublished layer
140  if ( restrictedLayers.contains( layer->name() ) )
141  {
142  throw QgsSecurityException( QStringLiteral( "You are not allowed to access to this layer" ) );
143  }
144 
145 #ifdef HAVE_SERVER_PYTHON_PLUGINS
146  if ( accessControl && !accessControl->layerReadPermission( layer ) )
147  {
148  throw QgsSecurityException( QStringLiteral( "You are not allowed to access to this layer" ) );
149  }
150 #endif
151 
152  // Create the NamedLayer element
153  QDomElement layerNode = myDocument.createElement( QStringLiteral( "LayerDescription" ) );
154  root.appendChild( layerNode );
155 
156  // store the owsType element
157  QDomElement typeNode = myDocument.createElement( QStringLiteral( "owsType" ) );
158  // store the se:OnlineResource element
159  QDomElement oResNode = myDocument.createElement( QStringLiteral( "se:OnlineResource" ) );
160  oResNode.setAttribute( QStringLiteral( "xlink:type" ), QStringLiteral( "simple" ) );
161  // store the TypeName element
162  QDomElement nameNode = myDocument.createElement( QStringLiteral( "TypeName" ) );
163  switch ( layer->type() )
164  {
166  {
167  typeNode.appendChild( myDocument.createTextNode( QStringLiteral( "wfs" ) ) );
168 
169  if ( wfsLayerIds.indexOf( layer->id() ) != -1 )
170  {
171  oResNode.setAttribute( QStringLiteral( "xlink:href" ), wfsHrefString );
172  }
173 
174  // store the se:FeatureTypeName element
175  QDomElement typeNameNode = myDocument.createElement( QStringLiteral( "se:FeatureTypeName" ) );
176  typeNameNode.appendChild( myDocument.createTextNode( name ) );
177  nameNode.appendChild( typeNameNode );
178  break;
179  }
181  {
182  typeNode.appendChild( myDocument.createTextNode( QStringLiteral( "wcs" ) ) );
183 
184  if ( wcsLayerIds.indexOf( layer->id() ) != -1 )
185  {
186  oResNode.setAttribute( QStringLiteral( "xlink:href" ), wcsHrefString );
187  }
188 
189  // store the se:CoverageTypeName element
190  QDomElement typeNameNode = myDocument.createElement( QStringLiteral( "se:CoverageTypeName" ) );
191  typeNameNode.appendChild( myDocument.createTextNode( name ) );
192  nameNode.appendChild( typeNameNode );
193  break;
194  }
195 
202  break;
203  }
204  layerNode.appendChild( typeNode );
205  layerNode.appendChild( oResNode );
206  layerNode.appendChild( nameNode );
207  }
208 
209  return myDocument;
210  }
211 
212 } // namespace QgsWms
QgsWms::QgsServiceException
Exception class for WMS service exceptions.
Definition: qgswmsserviceexception.h:49
QgsMapLayerType::MeshLayer
@ MeshLayer
Mesh layer. Added in QGIS 3.2.
QgsMapLayerType::VectorLayer
@ VectorLayer
Vector layer.
qgswmsutils.h
QgsProject::mapLayers
QMap< QString, QgsMapLayer * > mapLayers(const bool validOnly=false) const
Returns a map of all registered layers by layer ID.
Definition: qgsproject.cpp:3955
QgsWms::describeLayer
QDomDocument describeLayer(QgsServerInterface *serverIface, const QgsProject *project, const QgsWmsRequest &request)
DescribeLayer is defined for WMS1.1.1/SLD1.0 and in WMS 1.3.0 SLD Extension.
Definition: qgswmsdescribelayer.cpp:58
QgsMapLayerType::AnnotationLayer
@ AnnotationLayer
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
qgsserverprojectutils.h
QgsAccessControl::layerReadPermission
bool layerReadPermission(const QgsMapLayer *layer) const
Returns the layer read right.
Definition: qgsaccesscontrol.cpp:105
QgsServerInterface::accessControls
virtual QgsAccessControl * accessControls() const =0
Gets the registered access control filters.
QgsServerProjectUtils::wcsLayerIds
SERVER_EXPORT QStringList wcsLayerIds(const QgsProject &project)
Returns the Layer ids list defined in a QGIS project as published in WCS.
Definition: qgsserverprojectutils.cpp:507
QgsWms::serviceUrl
QUrl serviceUrl(const QgsServerRequest &request, const QgsProject *project, const QgsServerSettings &settings)
Returns WMS service URL.
Definition: qgswmsutils.cpp:55
QgsProject
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition: qgsproject.h:103
QgsServerRequest::Parameters
QMap< QString, QString > Parameters
Definition: qgsserverrequest.h:59
QgsServerResponse::write
virtual void write(const QString &data)
Write string This is a convenient method that will write directly to the underlying I/O device.
Definition: qgsserverresponse.cpp:25
QgsServerProjectUtils::wmsUseLayerIds
SERVER_EXPORT bool wmsUseLayerIds(const QgsProject &project)
Returns if layer ids are used as name in WMS.
Definition: qgsserverprojectutils.cpp:135
qgswmsdescribelayer.h
QgsServerProjectUtils::wfsLayerIds
SERVER_EXPORT QStringList wfsLayerIds(const QgsProject &project)
Returns the Layer ids list defined in a QGIS project as published in WFS.
Definition: qgsserverprojectutils.cpp:472
QgsMapLayerType::GroupLayer
@ GroupLayer
Composite group layer. Added in QGIS 3.24.
QgsMapLayerType::RasterLayer
@ RasterLayer
Raster layer.
QgsServerProjectUtils::wmsRestrictedLayers
SERVER_EXPORT QStringList wmsRestrictedLayers(const QgsProject &project)
Returns the restricted layer name list.
Definition: qgsserverprojectutils.cpp:441
QgsServerProjectUtils::wcsServiceUrl
SERVER_EXPORT QString wcsServiceUrl(const QgsProject &project, const QgsServerRequest &request=QgsServerRequest(), const QgsServerSettings &settings=QgsServerSettings())
Returns the WCS service url.
Definition: qgsserverprojectutils.cpp:497
QgsServerInterface::serverSettings
virtual QgsServerSettings * serverSettings()=0
Returns the server settings.
QgsAccessControl
A helper class that centralizes restrictions given by all the access control filter plugins.
Definition: qgsaccesscontrol.h:36
QgsWms
Median cut implementation.
Definition: qgsdxfwriter.cpp:22
QgsServerProjectUtils::wfsServiceUrl
SERVER_EXPORT QString wfsServiceUrl(const QgsProject &project, const QgsServerRequest &request=QgsServerRequest(), const QgsServerSettings &settings=QgsServerSettings())
Returns the WFS service url.
Definition: qgsserverprojectutils.cpp:462
QgsMapLayer
Base class for all map layer types. This is the base class for all map layer types (vector,...
Definition: qgsmaplayer.h:72
QgsMapLayerType::VectorTileLayer
@ VectorTileLayer
Vector tile layer. Added in QGIS 3.14.
qgswmsserviceexception.h
qgswmsrequest.h
QgsMapLayerType::PointCloudLayer
@ PointCloudLayer
Point cloud layer. Added in QGIS 3.18.
QgsServerInterface
QgsServerInterface Class defining interfaces exposed by QGIS Server and made available to plugins.
Definition: qgsserverinterface.h:60
qgsproject.h
QgsMapLayerType::PluginLayer
@ PluginLayer
Plugin based layer.
QgsServerResponse
QgsServerResponse Class defining response interface passed to services QgsService::executeRequest() m...
Definition: qgsserverresponse.h:43
QgsServerResponse::setHeader
virtual void setHeader(const QString &key, const QString &value)=0
Set Header entry Add Header entry to the response Note that it is usually an error to set Header afte...
QgsWms::writeDescribeLayer
void writeDescribeLayer(QgsServerInterface *serverIface, const QgsProject *project, const QgsWmsRequest &request, QgsServerResponse &response)
Output GetMap response in DXF format.
Definition: qgswmsdescribelayer.cpp:49