QGIS API Documentation  3.6.0-Noosa (5873452)
qgswmsgetstyles.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgswmsgetstyles.h
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 
23 #include "qgswmsutils.h"
24 #include "qgswmsserviceexception.h"
25 #include "qgswmsgetstyles.h"
26 #include "qgsserverprojectutils.h"
27 
28 #include "qgsproject.h"
29 #include "qgsrenderer.h"
30 #include "qgsvectorlayer.h"
32 
33 
34 namespace QgsWms
35 {
36 
37  namespace
38  {
39  QDomDocument getStyledLayerDescriptorDocument( QgsServerInterface *serverIface, const QgsProject *project,
40  QStringList &layerList );
41  }
42 
43  void writeGetStyles( QgsServerInterface *serverIface, const QgsProject *project, const QString &version,
44  const QgsServerRequest &request, QgsServerResponse &response )
45  {
46  QDomDocument doc = getStyles( serverIface, project, version, request );
47  response.setHeader( QStringLiteral( "Content-Type" ), QStringLiteral( "text/xml; charset=utf-8" ) );
48  response.write( doc.toByteArray() );
49  }
50 
51  QDomDocument getStyles( QgsServerInterface *serverIface, const QgsProject *project, const QString &version,
52  const QgsServerRequest &request )
53  {
54  Q_UNUSED( version );
55 
56  QgsServerRequest::Parameters parameters = request.parameters();
57 
58  QString layersName = parameters.value( "LAYERS" );
59 
60  if ( layersName.isEmpty() )
61  {
62  throw QgsBadRequestException( QStringLiteral( "LayerNotSpecified" ),
63  QStringLiteral( "Layers is mandatory for GetStyles operation" ) );
64  }
65 
66  QStringList layerList = layersName.split( ',', QString::SkipEmptyParts );
67  if ( layerList.isEmpty() )
68  {
69  throw QgsBadRequestException( QStringLiteral( "LayerNotSpecified" ),
70  QStringLiteral( "Layers is mandatory for GetStyles operation" ) );
71  }
72 
73  return getStyledLayerDescriptorDocument( serverIface, project, layerList );
74  }
75 
76  //GetStyle for compatibility with earlier QGIS versions
77  void writeGetStyle( QgsServerInterface *serverIface, const QgsProject *project, const QString &version,
78  const QgsServerRequest &request, QgsServerResponse &response )
79  {
80  QDomDocument doc = getStyle( serverIface, project, version, request );
81  response.setHeader( QStringLiteral( "Content-Type" ), QStringLiteral( "text/xml; charset=utf-8" ) );
82  response.write( doc.toByteArray() );
83  }
84 
85  QDomDocument getStyle( QgsServerInterface *serverIface, const QgsProject *project, const QString &version,
86  const QgsServerRequest &request )
87  {
88  Q_UNUSED( version );
89 
90  QgsServerRequest::Parameters parameters = request.parameters();
91 
92  QDomDocument doc;
93 
94  QString styleName = parameters.value( QStringLiteral( "STYLE" ) );
95  QString layerName = parameters.value( QStringLiteral( "LAYER" ) );
96 
97  if ( styleName.isEmpty() )
98  {
99  throw QgsServiceException( QStringLiteral( "StyleNotSpecified" ),
100  QStringLiteral( "Style is mandatory for GetStyle operation" ), 400 );
101  }
102 
103  if ( layerName.isEmpty() )
104  {
105  throw QgsServiceException( QStringLiteral( "LayerNotSpecified" ),
106  QStringLiteral( "Layer is mandatory for GetStyle operation" ), 400 );
107  }
108 
109  QStringList layerList;
110  layerList.append( layerName );
111  return getStyledLayerDescriptorDocument( serverIface, project, layerList );
112  }
113 
114  namespace
115  {
116  QDomDocument getStyledLayerDescriptorDocument( QgsServerInterface *serverIface, const QgsProject *project,
117  QStringList &layerList )
118  {
119  QDomDocument myDocument = QDomDocument();
120 
121  QDomNode header = myDocument.createProcessingInstruction( QStringLiteral( "xml" ), QStringLiteral( "version=\"1.0\" encoding=\"UTF-8\"" ) );
122  myDocument.appendChild( header );
123 
124  // Create the root element
125  QDomElement root = myDocument.createElementNS( QStringLiteral( "http://www.opengis.net/sld" ), QStringLiteral( "StyledLayerDescriptor" ) );
126  root.setAttribute( QStringLiteral( "version" ), QStringLiteral( "1.1.0" ) );
127  root.setAttribute( QStringLiteral( "xsi:schemaLocation" ), QStringLiteral( "http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/StyledLayerDescriptor.xsd" ) );
128  root.setAttribute( QStringLiteral( "xmlns:ogc" ), QStringLiteral( "http://www.opengis.net/ogc" ) );
129  root.setAttribute( QStringLiteral( "xmlns:se" ), QStringLiteral( "http://www.opengis.net/se" ) );
130  root.setAttribute( QStringLiteral( "xmlns:xlink" ), QStringLiteral( "http://www.w3.org/1999/xlink" ) );
131  root.setAttribute( QStringLiteral( "xmlns:xsi" ), QStringLiteral( "http://www.w3.org/2001/XMLSchema-instance" ) );
132  myDocument.appendChild( root );
133 
134  // access control
135  QgsAccessControl *accessControl = serverIface->accessControls();
136  // Use layer ids
137  bool useLayerIds = QgsServerProjectUtils::wmsUseLayerIds( *project );
138  // WMS restricted layers
139  QStringList restrictedLayers = QgsServerProjectUtils::wmsRestrictedLayers( *project );
140 
141  for ( QgsMapLayer *layer : project->mapLayers() )
142  {
143  QString name = layer->name();
144  if ( useLayerIds )
145  name = layer->id();
146  else if ( !layer->shortName().isEmpty() )
147  name = layer->shortName();
148 
149  if ( !layerList.contains( name ) )
150  {
151  continue;
152  }
153 
154  //unpublished layer
155  if ( restrictedLayers.contains( layer->name() ) )
156  {
157  throw QgsSecurityException( QStringLiteral( "You are not allowed to access to this layer" ) );
158  }
159 
160  if ( accessControl && !accessControl->layerReadPermission( layer ) )
161  {
162  throw QgsSecurityException( QStringLiteral( "You are not allowed to access to this layer" ) );
163  }
164 
165  // Create the NamedLayer element
166  QDomElement namedLayerNode = myDocument.createElement( QStringLiteral( "NamedLayer" ) );
167  root.appendChild( namedLayerNode );
168 
169  // store the Name element
170  QDomElement nameNode = myDocument.createElement( QStringLiteral( "se:Name" ) );
171  nameNode.appendChild( myDocument.createTextNode( name ) );
172  namedLayerNode.appendChild( nameNode );
173 
174  if ( layer->type() == QgsMapLayer::VectorLayer )
175  {
176  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
177  if ( vlayer->isSpatial() )
178  {
179  QString currentStyle = vlayer->styleManager()->currentStyle();
180  for ( const QString &styleName : vlayer->styleManager()->styles() )
181  {
182  vlayer->styleManager()->setCurrentStyle( styleName );
183  QDomElement styleElem = vlayer->renderer()->writeSld( myDocument, styleName );
184  namedLayerNode.appendChild( styleElem );
185  }
186  vlayer->styleManager()->setCurrentStyle( currentStyle );
187  }
188  }
189  }
190 
191  return myDocument;
192  }
193  }
194 
195 
196 } // namespace QgsWms
197 
198 
199 
200 
QDomDocument getStyle(QgsServerInterface *serverIface, const QgsProject *project, const QString &version, const QgsServerRequest &request)
Returns an SLD file with the style of the requested layer.
void writeGetStyles(QgsServerInterface *serverIface, const QgsProject *project, const QString &version, const QgsServerRequest &request, QgsServerResponse &response)
Output GetStyles response.
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...
Base class for all map layer types.
Definition: qgsmaplayer.h:64
QStringList styles() const
Returns list of all defined style names.
Exception thrown in case of malformed request.
virtual void write(const QString &data)
Write string This is a convenient method that will write directly to the underlying I/O device...
bool isSpatial() const FINAL
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
QgsMapLayerStyleManager * styleManager() const
Gets access to the layer&#39;s style manager.
Exception class for WMS service exceptions.
QgsServerRequest::Parameters parameters() const
Returns a map of query parameters with keys converted to uppercase.
Reads and writes project states.
Definition: qgsproject.h:89
QgsFeatureRenderer * renderer()
Returns renderer.
QMap< QString, QgsMapLayer * > mapLayers(const bool validOnly=false) const
Returns a map of all registered layers by layer ID.
void writeGetStyle(QgsServerInterface *serverIface, const QgsProject *project, const QString &version, const QgsServerRequest &request, QgsServerResponse &response)
Output GetStyle response.
Median cut implementation.
QgsServerRequest Class defining request interface passed to services QgsService::executeRequest() met...
QString currentStyle() const
Returns name of the current style.
bool layerReadPermission(const QgsMapLayer *layer) const
Returns the layer read right.
QgsServerInterface Class defining interfaces exposed by QGIS Server and made available to plugins...
Exception thrown when data access violates access controls.
QDomDocument getStyles(QgsServerInterface *serverIface, const QgsProject *project, const QString &version, const QgsServerRequest &request)
Returns an SLD file with the styles of the requested layers.
virtual QDomElement writeSld(QDomDocument &doc, const QString &styleName, const QgsStringMap &props=QgsStringMap()) const
create the SLD UserStyle element following the SLD v1.1 specs with the given name ...
A helper class that centralizes restrictions given by all the access control filter plugins...
QgsServerResponse Class defining response interface passed to services QgsService::executeRequest() m...
virtual QgsAccessControl * accessControls() const =0
Gets the registered access control filters.
SERVER_EXPORT QStringList wmsRestrictedLayers(const QgsProject &project)
Returns the restricted layer name list.
Represents a vector layer which manages a vector based data sets.
bool setCurrentStyle(const QString &name)
Set a different style as the current style - will apply it to the layer.
QMap< QString, QString > Parameters
SERVER_EXPORT bool wmsUseLayerIds(const QgsProject &project)
Returns if layer ids are used as name in WMS.