QGIS API Documentation 4.1.0-Master (31622b25bb0)
Loading...
Searching...
No Matches
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#include "qgswmsdescribelayer.h"
22
23#include "qgslayertree.h"
24#include "qgsproject.h"
26#include "qgswmsrequest.h"
28#include "qgswmsutils.h"
29
30#include <QString>
31
32using namespace Qt::StringLiterals;
33
34namespace QgsWms
35{
36
37 void writeDescribeLayer( QgsServerInterface *serverIface, const QgsProject *project, const QgsWmsRequest &request, QgsServerResponse &response )
38 {
39 const QDomDocument doc = describeLayer( serverIface, project, request );
40 response.setHeader( u"Content-Type"_s, u"text/xml; charset=utf-8"_s );
41 response.write( doc.toByteArray() );
42 }
43
44 // DescribeLayer is defined for WMS1.1.1/SLD1.0 and in WMS 1.3.0 SLD Extension
45 QDomDocument describeLayer( QgsServerInterface *serverIface, const QgsProject *project, const QgsWmsRequest &request )
46 {
47 const QgsServerRequest::Parameters parameters = request.parameters();
48
49 if ( !parameters.contains( u"SLD_VERSION"_s ) )
50 {
51 throw QgsServiceException( u"MissingParameterValue"_s, u"SLD_VERSION is mandatory for DescribeLayer operation"_s, 400 );
52 }
53 if ( parameters[u"SLD_VERSION"_s] != "1.1.0"_L1 )
54 {
55 throw QgsServiceException( u"InvalidParameterValue"_s, u"SLD_VERSION = %1 is not supported"_s.arg( parameters[u"SLD_VERSION"_s] ), 400 );
56 }
57
58 if ( !parameters.contains( u"LAYERS"_s ) && !parameters.contains( u"LAYER"_s ) )
59 {
60 throw QgsServiceException( u"MissingParameterValue"_s, u"LAYERS or LAYER is mandatory for DescribeLayer operation"_s, 400 );
61 }
62
63 QStringList layersList;
64
65 if ( parameters.contains( u"LAYERS"_s ) )
66 {
67 layersList = parameters[u"LAYERS"_s].split( ',', Qt::SkipEmptyParts );
68 }
69 else
70 {
71 layersList = parameters[u"LAYER"_s].split( ',', Qt::SkipEmptyParts );
72 }
73 if ( layersList.isEmpty() )
74 {
75 throw QgsServiceException( u"InvalidParameterValue"_s, u"Layers is empty"_s, 400 );
76 }
77
78 // Throw a LayerNotDefined when one of the requested layers or groups is not leading to a result
79 QHash<const QgsMapLayer *, QStringList> acceptableLayersAndRequestNames;
80 collectAcceptableLayersAndRequestNames( acceptableLayersAndRequestNames, *project, layersList );
81 auto firstFoundInacceptableLayer = std::find_if( layersList.cbegin(), layersList.cend(), [&]( const QString &layerName ) {
82 //return when the requested layer has not been found as a acceptable layer
83 return !std::any_of( acceptableLayersAndRequestNames.cbegin(), acceptableLayersAndRequestNames.cend(), [&]( const QStringList &requestedNames ) { return requestedNames.contains( layerName ); } );
84 } );
85 if ( firstFoundInacceptableLayer != layersList.cend() )
86 {
87 QgsWmsParameter param( QgsWmsParameter::LAYER );
88 param.mValue = *firstFoundInacceptableLayer;
90 }
91
92 QDomDocument myDocument = QDomDocument();
93
94 const QDomNode header = myDocument.createProcessingInstruction( u"xml"_s, u"version=\"1.0\" encoding=\"UTF-8\""_s );
95 myDocument.appendChild( header );
96
97 // Create the root element
98 QDomElement root = myDocument.createElementNS( u"http://www.opengis.net/sld"_s, u"DescribeLayerResponse"_s );
99 root.setAttribute( u"xsi:schemaLocation"_s, u"http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/DescribeLayer.xsd"_s );
100 root.setAttribute( u"xmlns:ows"_s, u"http://www.opengis.net/ows"_s );
101 root.setAttribute( u"xmlns:se"_s, u"http://www.opengis.net/se"_s );
102 root.setAttribute( u"xmlns:xlink"_s, u"http://www.w3.org/1999/xlink"_s );
103 root.setAttribute( u"xmlns:xsi"_s, u"http://www.w3.org/2001/XMLSchema-instance"_s );
104 myDocument.appendChild( root );
105
106 // store the Version element
107 QDomElement versionNode = myDocument.createElement( u"Version"_s );
108 versionNode.appendChild( myDocument.createTextNode( u"1.1.0"_s ) );
109 root.appendChild( versionNode );
110
111 // get the wms service url defined in project or keep the one from the
112 // request url
113 const QString wmsHrefString = serviceUrl( request, project, *serverIface->serverSettings() ).toString();
114
115 // get the wfs service url defined in project or take the same as the
116 // wms service url
117 QString wfsHrefString = QgsServerProjectUtils::wfsServiceUrl( *project, request, *serverIface->serverSettings() );
118 if ( wfsHrefString.isEmpty() )
119 {
120 wfsHrefString = wmsHrefString;
121 }
122
123 // get the wcs service url defined in project or take the same as the
124 // wms service url
125 QString wcsHrefString = QgsServerProjectUtils::wcsServiceUrl( *project, request, *serverIface->serverSettings() );
126 if ( wcsHrefString.isEmpty() )
127 {
128 wcsHrefString = wmsHrefString;
129 }
130
131 // access control
132#ifdef HAVE_SERVER_PYTHON_PLUGINS
133 QgsAccessControl *accessControl = serverIface->accessControls();
134#else
135 ( void ) serverIface;
136#endif
137 // Use layer ids
138 const bool useLayerIds = QgsServerProjectUtils::wmsUseLayerIds( *project );
139 // WMS restricted layers
140 const QStringList restrictedLayers = QgsServerProjectUtils::wmsRestrictedLayers( *project );
141 // WFS layers
142 const QStringList wfsLayerIds = QgsServerProjectUtils::wfsLayerIds( *project );
143 // WCS layers
144 const QStringList wcsLayerIds = QgsServerProjectUtils::wcsLayerIds( *project );
145
146
147 for ( QgsMapLayer *layer : project->mapLayers() )
148 {
149 QString name = layer->name();
150 if ( useLayerIds )
151 name = layer->id();
152 else if ( !layer->serverProperties()->shortName().isEmpty() )
153 name = layer->serverProperties()->shortName();
154
155 if ( !layersList.contains( name ) )
156 {
157 continue;
158 }
159
160 //unpublished layer
161 if ( restrictedLayers.contains( layer->name() ) )
162 {
163 throw QgsSecurityException( u"You are not allowed to access to this layer"_s );
164 }
165
166#ifdef HAVE_SERVER_PYTHON_PLUGINS
167 if ( accessControl && !accessControl->layerReadPermission( layer ) )
168 {
169 throw QgsSecurityException( u"You are not allowed to access to this layer"_s );
170 }
171#endif
172
173 // Create the NamedLayer element
174 QDomElement layerNode = myDocument.createElement( u"LayerDescription"_s );
175 root.appendChild( layerNode );
176
177 // store the owsType element
178 QDomElement typeNode = myDocument.createElement( u"owsType"_s );
179 // store the se:OnlineResource element
180 QDomElement oResNode = myDocument.createElement( u"se:OnlineResource"_s );
181 oResNode.setAttribute( u"xlink:type"_s, u"simple"_s );
182 // store the TypeName element
183 QDomElement nameNode = myDocument.createElement( u"TypeName"_s );
184 switch ( layer->type() )
185 {
187 {
188 typeNode.appendChild( myDocument.createTextNode( u"wfs"_s ) );
189
190 if ( wfsLayerIds.indexOf( layer->id() ) != -1 )
191 {
192 oResNode.setAttribute( u"xlink:href"_s, wfsHrefString );
193 }
194
195 // store the se:FeatureTypeName element
196 QDomElement typeNameNode = myDocument.createElement( u"se:FeatureTypeName"_s );
197 typeNameNode.appendChild( myDocument.createTextNode( name ) );
198 nameNode.appendChild( typeNameNode );
199 break;
200 }
202 {
203 typeNode.appendChild( myDocument.createTextNode( u"wcs"_s ) );
204
205 if ( wcsLayerIds.indexOf( layer->id() ) != -1 )
206 {
207 oResNode.setAttribute( u"xlink:href"_s, wcsHrefString );
208 }
209
210 // store the se:CoverageTypeName element
211 QDomElement typeNameNode = myDocument.createElement( u"se:CoverageTypeName"_s );
212 typeNameNode.appendChild( myDocument.createTextNode( name ) );
213 nameNode.appendChild( typeNameNode );
214 break;
215 }
216
224 break;
225 }
226 layerNode.appendChild( typeNode );
227 layerNode.appendChild( oResNode );
228 layerNode.appendChild( nameNode );
229 }
230
231 return myDocument;
232 }
233
234} // namespace QgsWms
@ Group
Composite group layer. Added in QGIS 3.24.
Definition qgis.h:214
@ Plugin
Plugin based layer.
Definition qgis.h:209
@ TiledScene
Tiled scene layer. Added in QGIS 3.34.
Definition qgis.h:215
@ Annotation
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
Definition qgis.h:212
@ Vector
Vector layer.
Definition qgis.h:207
@ VectorTile
Vector tile layer. Added in QGIS 3.14.
Definition qgis.h:211
@ Mesh
Mesh layer. Added in QGIS 3.2.
Definition qgis.h:210
@ Raster
Raster layer.
Definition qgis.h:208
@ PointCloud
Point cloud layer. Added in QGIS 3.18.
Definition qgis.h:213
bool layerReadPermission(const QgsMapLayer *layer) const
Returns the layer read right.
Exception thrown in case of malformed requests.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition qgsproject.h:114
Defines interfaces exposed by QGIS Server and made available to plugins.
static QString wcsServiceUrl(const QgsProject &project, const QgsServerRequest &request=QgsServerRequest(), const QgsServerSettings &settings=QgsServerSettings())
Returns the WCS service url.
static bool wmsUseLayerIds(const QgsProject &project)
Returns if layer ids are used as name in WMS.
static QStringList wfsLayerIds(const QgsProject &project)
Returns the Layer ids list defined in a QGIS project as published in WFS.
static QStringList wmsRestrictedLayers(const QgsProject &project)
Returns the restricted layer name list.
static QString wfsServiceUrl(const QgsProject &project, const QgsServerRequest &request=QgsServerRequest(), const QgsServerSettings &settings=QgsServerSettings())
Returns the WFS service url.
static QStringList wcsLayerIds(const QgsProject &project)
Returns the Layer ids list defined in a QGIS project as published in WCS.
QgsServerRequest::Parameters parameters() const
Returns a map of query parameters with keys converted to uppercase.
QMap< QString, QString > Parameters
Defines the response interface passed to QgsService.
virtual void write(const QString &data)
Write string This is a convenient method that will write directly to the underlying I/O device.
virtual void setHeader(const QString &key, const QString &value)=0
Set a single header value replacing any existing value(s) for the same key.
Exception thrown when data access violates access controls.
Exception class for WMS service exceptions.
Defines request interfaces passed to WMS service.
Median cut implementation.
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.
void collectAcceptableLayersAndRequestNames(QHash< const QgsMapLayer *, QStringList > &acceptableLayersAndRequestNames, const QgsProject &project, const QStringList &requestedLayerNames)
Collects the acceptableLayersAndRequestNames, a hash of all the layers that can be rendered and for e...
void writeDescribeLayer(QgsServerInterface *serverIface, const QgsProject *project, const QgsWmsRequest &request, QgsServerResponse &response)
Output GetMap response in DXF format.
QUrl serviceUrl(const QgsServerRequest &request, const QgsProject *project, const QgsServerSettings &settings)
Returns WMS service URL.