34#include <QRegularExpression>
37using namespace Qt::StringLiterals;
43 void appendOwsLayerStyles( QDomDocument &doc, QDomElement &layerElem, QgsMapLayer *currentLayer );
45 void appendOwsLayersFromTreeGroup(
47 QDomElement &parentLayer,
48 QgsServerInterface *serverIface,
49 const QgsProject *project,
51 const QgsLayerTreeGroup *layerTreeGroup,
52 QgsRectangle &combinedBBox,
53 const QString &strGroup
56 void appendOwsGeneralAndResourceList( QDomDocument &doc, QDomElement &parentElement, QgsServerInterface *serverIface,
const QgsProject *project,
const QgsWmsRequest &request );
61#ifdef HAVE_SERVER_PYTHON_PLUGINS
66 const QDomDocument *contextDocument =
nullptr;
68#ifdef HAVE_SERVER_PYTHON_PLUGINS
70 if ( cacheManager && cacheManager->
getCachedDocument( &doc, project, request, accessControl ) )
72 contextDocument = &doc;
76 doc =
getContext( serverIface, project, request );
82 contextDocument = &doc;
85 doc =
getContext( serverIface, project, request );
86 contextDocument = &doc;
88 response.
setHeader( u
"Content-Type"_s, u
"text/xml; charset=utf-8"_s );
89 response.
write( contextDocument->toByteArray() );
96 const QDomProcessingInstruction xmlDeclaration = doc.createProcessingInstruction( u
"xml"_s, u
"version=\"1.0\" encoding=\"utf-8\""_s );
98 doc.appendChild( xmlDeclaration );
100 QDomElement owsContextElem = doc.createElement( u
"OWSContext"_s );
101 owsContextElem.setAttribute( u
"xmlns"_s, u
"http://www.opengis.net/ows-context"_s );
102 owsContextElem.setAttribute( u
"xmlns:ows-context"_s, u
"http://www.opengis.net/ows-context"_s );
103 owsContextElem.setAttribute( u
"xmlns:context"_s, u
"http://www.opengis.net/context"_s );
104 owsContextElem.setAttribute( u
"xmlns:ows"_s, u
"http://www.opengis.net/ows"_s );
105 owsContextElem.setAttribute( u
"xmlns:sld"_s, u
"http://www.opengis.net/sld"_s );
106 owsContextElem.setAttribute( u
"xmlns:ogc"_s, u
"http://www.opengis.net/ogc"_s );
107 owsContextElem.setAttribute( u
"xmlns:gml"_s, u
"http://www.opengis.net/gml"_s );
108 owsContextElem.setAttribute( u
"xmlns:kml"_s, u
"http://www.opengis.net/kml/2.2"_s );
109 owsContextElem.setAttribute( u
"xmlns:xlink"_s, u
"http://www.w3.org/1999/xlink"_s );
110 owsContextElem.setAttribute( u
"xmlns:ns9"_s, u
"http://www.w3.org/2005/Atom"_s );
111 owsContextElem.setAttribute( u
"xmlns:xal"_s, u
"urn:oasis:names:tc:ciq:xsdschema:xAL:2.0"_s );
112 owsContextElem.setAttribute( u
"xmlns:ins"_s, u
"http://www.inspire.org"_s );
113 owsContextElem.setAttribute( u
"version"_s, u
"0.3.1"_s );
114 doc.appendChild( owsContextElem );
116 appendOwsGeneralAndResourceList( doc, owsContextElem, serverIface, project, request );
122 void appendOwsGeneralAndResourceList( QDomDocument &doc, QDomElement &parentElement,
QgsServerInterface *serverIface,
const QgsProject *project,
const QgsWmsRequest &request )
124 parentElement.setAttribute( u
"id"_s,
"ows-context-" + project->
baseName() );
127 QDomElement generalElem = doc.createElement( u
"General"_s );
130 QDomElement windowElem = doc.createElement( u
"Window"_s );
131 windowElem.setAttribute( u
"height"_s, u
"600"_s );
132 windowElem.setAttribute( u
"width"_s, u
"800"_s );
133 generalElem.appendChild( windowElem );
137 QDomElement titleElem = doc.createElement( u
"ows:Title"_s );
138 const QDomText titleText = doc.createTextNode( title );
139 titleElem.appendChild( titleText );
140 generalElem.appendChild( titleElem );
144 if ( !abstract.isEmpty() )
146 QDomElement abstractElem = doc.createElement( u
"ows:Abstract"_s );
147 const QDomText abstractText = doc.createCDATASection( abstract );
148 abstractElem.appendChild( abstractText );
149 generalElem.appendChild( abstractElem );
154 if ( !keywords.isEmpty() )
158 QDomElement keywordsElem = doc.createElement( u
"ows:Keywords"_s );
160 for (
int i = 0; i < keywords.size(); ++i )
162 const QString keyword = keywords.at( i );
163 if ( !keyword.isEmpty() )
165 QDomElement keywordElem = doc.createElement( u
"ows:Keyword"_s );
166 const QDomText keywordText = doc.createTextNode( keyword );
167 keywordElem.appendChild( keywordText );
170 keywordElem.setAttribute( u
"vocabulary"_s, u
"SIA_Geo405"_s );
172 keywordsElem.appendChild( keywordElem );
175 generalElem.appendChild( keywordsElem );
179 parentElement.appendChild( generalElem );
182 QDomElement resourceListElem = doc.createElement( u
"ResourceList"_s );
183 const QgsLayerTree *projectLayerTreeRoot = project->
layerTreeRoot();
184 QgsRectangle combinedBBox;
185 appendOwsLayersFromTreeGroup( doc, resourceListElem, serverIface, project, request, projectLayerTreeRoot, combinedBBox, QString() );
186 parentElement.appendChild( resourceListElem );
189 const QgsCoordinateReferenceSystem projectCrs = project->
crs();
193 mapRect = combinedBBox;
195 QDomElement bboxElem = doc.createElement( u
"ows:BoundingBox"_s );
196 bboxElem.setAttribute( u
"crs"_s, projectCrs.
authid() );
201 QDomElement lowerCornerElem = doc.createElement( u
"ows:LowerCorner"_s );
202 const QDomText lowerCornerText = doc.createTextNode( QString::number( mapRect.
xMinimum() ) +
" " + QString::number( mapRect.
yMinimum() ) );
203 lowerCornerElem.appendChild( lowerCornerText );
204 bboxElem.appendChild( lowerCornerElem );
205 QDomElement upperCornerElem = doc.createElement( u
"ows:UpperCorner"_s );
206 const QDomText upperCornerText = doc.createTextNode( QString::number( mapRect.
xMaximum() ) +
" " + QString::number( mapRect.
yMaximum() ) );
207 upperCornerElem.appendChild( upperCornerText );
208 bboxElem.appendChild( upperCornerElem );
209 generalElem.appendChild( bboxElem );
212 void appendOwsLayersFromTreeGroup(
214 QDomElement &parentLayer,
215 QgsServerInterface *serverIface,
216 const QgsProject *project,
218 const QgsLayerTreeGroup *layerTreeGroup,
219 QgsRectangle &combinedBBox,
220 const QString &strGroup
225 const QList<QgsLayerTreeNode *> layerTreeGroupChildren = layerTreeGroup->
children();
226 for (
int i = 0; i < layerTreeGroupChildren.size(); ++i )
228 QgsLayerTreeNode *treeNode = layerTreeGroupChildren.at( i );
232 QgsLayerTreeGroup *treeGroupChild =
static_cast<QgsLayerTreeGroup *
>( treeNode );
234 const QString name = treeGroupChild->
name();
235 if ( restrictedLayers.contains( name ) )
241 if ( strGroup.isEmpty() )
247 group = strGroup +
"/" + name;
250 appendOwsLayersFromTreeGroup( doc, parentLayer, serverIface, project, request, treeGroupChild, combinedBBox, group );
254 QgsLayerTreeLayer *treeLayer =
static_cast<QgsLayerTreeLayer *
>( treeNode );
255 QgsMapLayer *l = treeLayer->
layer();
256 if ( restrictedLayers.contains( l->
name() ) )
260#ifdef HAVE_SERVER_PYTHON_PLUGINS
267 QDomElement layerElem = doc.createElement( u
"Layer"_s );
272 layerElem.setAttribute( u
"queryable"_s, u
"false"_s );
276 layerElem.setAttribute( u
"queryable"_s, u
"true"_s );
282 layerElem.setAttribute( u
"hidden"_s, u
"false"_s );
286 layerElem.setAttribute( u
"hidden"_s, u
"true"_s );
290 if ( !strGroup.isEmpty() )
292 layerElem.setAttribute( u
"group"_s, strGroup );
297 layerElem.setAttribute( u
"opacity"_s, 1 );
299 QString wmsName = l->
name();
309 layerElem.setAttribute( u
"name"_s, wmsName );
311 const thread_local QRegularExpression sRegEx( u
"[\\W]"_s, QRegularExpression::UseUnicodePropertiesOption );
312 layerElem.setAttribute( u
"id"_s, wmsName.replace( sRegEx, u
"_"_s ) );
315 QDomElement titleElem = doc.createElement( u
"ows:Title"_s );
317 if ( title.isEmpty() )
321 const QDomText titleText = doc.createTextNode( title );
322 titleElem.appendChild( titleText );
323 layerElem.appendChild( titleElem );
326 QDomElement formatElem = doc.createElement( u
"ows:OutputFormat"_s );
327 const QDomText formatText = doc.createTextNode( u
"image/png"_s );
328 formatElem.appendChild( formatText );
329 layerElem.appendChild( formatElem );
335 QString hrefString = href.toString();
336 hrefString.append( href.hasQuery() ?
"&" :
"?" );
339 QDomElement serverElem = doc.createElement( u
"Server"_s );
340 serverElem.setAttribute( u
"service"_s, u
"urn:ogc:serviceType:WMS"_s );
341 serverElem.setAttribute( u
"version"_s, u
"1.3.0"_s );
342 serverElem.setAttribute( u
"default"_s, u
"true"_s );
343 QDomElement orServerElem = doc.createElement( u
"OnlineResource"_s );
344 orServerElem.setAttribute( u
"xlink:href"_s, hrefString );
345 serverElem.appendChild( orServerElem );
346 layerElem.appendChild( serverElem );
349 if ( !abstract.isEmpty() )
351 QDomElement abstractElem = doc.createElement( u
"ows:Abstract"_s );
352 const QDomText abstractText = doc.createTextNode( abstract );
353 abstractElem.appendChild( abstractText );
354 layerElem.appendChild( abstractElem );
360 const QString minScaleString = QString::number( l->
maximumScale() );
361 const QString maxScaleString = QString::number( l->
minimumScale() );
362 QDomElement minScaleElem = doc.createElement( u
"sld:MinScaleDenominator"_s );
363 const QDomText minScaleText = doc.createTextNode( minScaleString );
364 minScaleElem.appendChild( minScaleText );
365 layerElem.appendChild( minScaleElem );
366 QDomElement maxScaleElem = doc.createElement( u
"sld:MaxScaleDenominator"_s );
367 const QDomText maxScaleText = doc.createTextNode( maxScaleString );
368 maxScaleElem.appendChild( maxScaleText );
369 layerElem.appendChild( maxScaleElem );
373 appendOwsLayerStyles( doc, layerElem, l );
381 QDomElement keywordsElem = doc.createElement( u
"ows:Keywords"_s );
382 for (
int i = 0; i < keywordStringList.size(); ++i )
384 QDomElement keywordElem = doc.createElement( u
"ows:Keyword"_s );
385 const QDomText keywordText = doc.createTextNode( keywordStringList.at( i ).trimmed() );
386 keywordElem.appendChild( keywordText );
389 keywordElem.setAttribute( u
"vocabulary"_s, u
"SIA_Geo405"_s );
391 keywordsElem.appendChild( keywordElem );
393 layerElem.appendChild( keywordsElem );
398 if ( !dataUrl.isEmpty() )
400 QDomElement dataUrlElem = doc.createElement( u
"DataURL"_s );
402 dataUrlElem.setAttribute( u
"format"_s, dataUrlFormat );
403 QDomElement dataORElem = doc.createElement( u
"OnlineResource"_s );
404 dataORElem.setAttribute( u
"xmlns:xlink"_s, u
"http://www.w3.org/1999/xlink"_s );
405 dataORElem.setAttribute( u
"xlink:type"_s, u
"simple"_s );
406 dataORElem.setAttribute( u
"xlink:href"_s, dataUrl );
407 dataUrlElem.appendChild( dataORElem );
408 layerElem.appendChild( dataUrlElem );
413 for (
const QgsMapLayerServerProperties::MetadataUrl &url : urls )
415 QDomElement metaUrlElem = doc.createElement( u
"MetadataURL"_s );
416 metaUrlElem.setAttribute( u
"format"_s, url.format );
417 QDomElement metaUrlORElem = doc.createElement( u
"OnlineResource"_s );
418 metaUrlORElem.setAttribute( u
"xmlns:xlink"_s, u
"http://www.w3.org/1999/xlink"_s );
419 metaUrlORElem.setAttribute( u
"xlink:type"_s, u
"simple"_s );
420 metaUrlORElem.setAttribute( u
"xlink:href"_s, url.url );
421 metaUrlElem.appendChild( metaUrlORElem );
422 layerElem.appendChild( metaUrlElem );
428 const QgsCoordinateTransform t( l->
crs(), project->
crs(), project );
429 const QgsRectangle BBox = t.transformBoundingBox( l->
extent() );
439 catch (
const QgsCsException &cse )
444 if ( parentLayer.hasChildNodes() )
446 parentLayer.insertBefore( layerElem, parentLayer.firstChild() );
450 parentLayer.appendChild( layerElem );
456 void appendOwsLayerStyles( QDomDocument &doc, QDomElement &layerElem, QgsMapLayer *currentLayer )
460 QDomElement styleListElem = doc.createElement( u
"StyleList"_s );
462 QDomElement styleElem = doc.createElement( u
"Style"_s );
463 styleElem.setAttribute( u
"current"_s, u
"true"_s );
464 QDomElement styleNameElem = doc.createElement( u
"Name"_s );
465 const QDomText styleNameText = doc.createTextNode( styleName );
466 styleNameElem.appendChild( styleNameText );
467 QDomElement styleTitleElem = doc.createElement( u
"Title"_s );
468 const QDomText styleTitleText = doc.createTextNode( styleName );
469 styleTitleElem.appendChild( styleTitleText );
470 styleElem.appendChild( styleNameElem );
471 styleElem.appendChild( styleTitleElem );
472 styleListElem.appendChild( styleElem );
473 layerElem.appendChild( styleListElem );
A helper class that centralizes restrictions given by all the access control filter plugins.
bool layerReadPermission(const QgsMapLayer *layer) const
Returns the layer read right.
bool hasAxisInverted() const
Returns whether the axis order is inverted for the CRS compared to the order east/north (longitude/la...
QString name() const override
Returns the group's name.
QgsMapLayer * layer() const
Returns the map layer associated with this node.
@ NodeGroup
Container of other groups and layers.
QList< QgsLayerTreeNode * > children()
Gets list of children of the node. Children are owned by the parent.
NodeType nodeType() const
Find out about type of the node. It is usually shorter to use convenience functions from QgsLayerTree...
bool itemVisibilityChecked() const
Returns whether a node is checked (independently of its ancestors or children).
QString dataUrlFormat() const
Returns the DataUrl format of the layer used by QGIS Server in GetCapabilities request.
QString title() const
Returns the title of the layer used by QGIS Server in GetCapabilities request.
QString dataUrl() const
Returns the DataUrl of the layer used by QGIS Server in GetCapabilities request.
QString keywordList() const
Returns the keyword list of the layerused by QGIS Server in GetCapabilities request.
QString shortName() const
Returns the short name of the layer used by QGIS Server to identify the layer.
QString abstract() const
Returns the abstract of the layerused by QGIS Server in GetCapabilities request.
QStringList styles() const
Returns list of all defined style names.
virtual QgsRectangle extent() const
Returns the extent of the layer.
QgsCoordinateReferenceSystem crs
QgsMapLayerServerProperties * serverProperties()
Returns QGIS Server Properties for the map layer.
QgsMapLayer::LayerFlags flags
bool hasScaleBasedVisibility() const
Returns whether scale based visibility is enabled for the layer.
@ Identifiable
If the layer is identifiable using the identify map tool and as a WMS layer.
double minimumScale() const
Returns the minimum map scale (i.e.
QgsMapLayerStyleManager * styleManager() const
Gets access to the layer's style manager.
double maximumScale() const
Returns the maximum map scale (i.e.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
QString baseName() const
Returns the base name of the project file without the path and without extension - derived from fileN...
QgsLayerTree * layerTreeRoot() const
Returns pointer to the root (invisible) node of the project's layer tree.
QgsCoordinateReferenceSystem crs
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle.
void invert()
Swap x/y coordinates in the rectangle.
A helper class that centralizes caches accesses given by all the server cache filter plugins.
bool setCachedDocument(const QDomDocument *doc, const QgsProject *project, const QgsServerRequest &request, QgsAccessControl *accessControl) const
Updates or inserts the document in cache like capabilities.
bool getCachedDocument(QDomDocument *doc, const QgsProject *project, const QgsServerRequest &request, QgsAccessControl *accessControl) const
Returns cached document (or 0 if document not in cache) like capabilities.
Defines interfaces exposed by QGIS Server and made available to plugins.
virtual QgsServerCacheManager * cacheManager() const =0
Gets the registered server cache filters.
virtual QgsAccessControl * accessControls() const =0
Gets the registered access control filters.
virtual QgsServerSettings * serverSettings()=0
Returns the server settings.
static bool wmsInfoFormatSia2045(const QgsProject &project)
Returns if the info format is SIA20145.
static QgsRectangle wmsExtent(const QgsProject &project)
Returns the WMS Extent restriction.
static bool wmsUseLayerIds(const QgsProject &project)
Returns if layer ids are used as name in WMS.
static QStringList owsServiceKeywords(const QgsProject &project)
Returns the owsService keywords defined in project.
static QStringList wmsRestrictedLayers(const QgsProject &project)
Returns the restricted layer name list.
static QString owsServiceTitle(const QgsProject &project)
Returns the owsService title defined in project.
static QString owsServiceAbstract(const QgsProject &project)
Returns the owsService abstract defined in project.
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 Header entry Add Header entry to the response Note that it is usually an error to set Header afte...
Defines request interfaces passed to WMS service.
Median cut implementation.
void writeGetContext(QgsServerInterface *serverIface, const QgsProject *project, const QgsWmsRequest &request, QgsServerResponse &response)
Output GetContext response.
QDomDocument getContext(QgsServerInterface *serverIface, const QgsProject *project, const QgsWmsRequest &request)
Returns XML document for the 'GetContext' request.
QUrl serviceUrl(const QgsServerRequest &request, const QgsProject *project, const QgsServerSettings &settings)
Returns WMS service URL.