QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
qgsserverapiutils.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsserverapiutils.cpp
3 
4  Class defining utilities for QGIS server APIs.
5  -------------------
6  begin : 2019-04-16
7  copyright : (C) 2019 by Alessandro Pasotti
8  email : elpaso at itopen dot it
9  ***************************************************************************/
10 
11 /***************************************************************************
12  * *
13  * This program is free software; you can redistribute it and/or modify *
14  * it under the terms of the GNU General Public License as published by *
15  * the Free Software Foundation; either version 2 of the License, or *
16  * (at your option) any later version. *
17  * *
18  ***************************************************************************/
19 
20 #include "qgsserverapiutils.h"
21 #include "qgsrectangle.h"
22 #include "qgsvectorlayer.h"
24 #include "qgsserverprojectutils.h"
25 #include "qgsmessagelog.h"
26 
27 #include "nlohmann/json.hpp"
28 
29 #include <QUrl>
30 
32 {
33  const auto parts { bbox.split( ',', QString::SplitBehavior::SkipEmptyParts ) };
34  // Note: Z is ignored
35  auto ok { true };
36  if ( parts.count() == 4 || parts.count() == 6 )
37  {
38  const auto hasZ { parts.count() == 6 };
39  auto toDouble = [ & ]( const int i ) -> double
40  {
41  if ( ! ok )
42  return 0;
43  return parts[i].toDouble( &ok );
44  };
45  QgsRectangle rect;
46  if ( hasZ )
47  {
48  rect = QgsRectangle( toDouble( 0 ), toDouble( 1 ),
49  toDouble( 3 ), toDouble( 4 ) );
50  }
51  else
52  {
53  rect = QgsRectangle( toDouble( 0 ), toDouble( 1 ),
54  toDouble( 2 ), toDouble( 3 ) );
55  }
56  if ( ok )
57  {
58  return rect;
59  }
60  }
61  return QgsRectangle();
62 }
63 
65 {
66  auto extent { layer->extent() };
67  if ( layer->crs().postgisSrid() != 4326 )
68  {
69  static const QgsCoordinateReferenceSystem targetCrs { 4326 };
70  const QgsCoordinateTransform ct( layer->crs(), targetCrs, layer->transformContext() );
71  extent = ct.transform( extent );
72  }
73  return {{ extent.xMinimum(), extent.yMinimum(), extent.xMaximum(), extent.yMaximum() }};
74 }
75 
77 {
79  // We get this:
80  // http://www.opengis.net/def/crs/OGC/1.3/CRS84
81  // We want this:
82  // "urn:ogc:def:crs:<auth>:[<version>]:<code>"
83  const auto parts { QUrl( bboxCrs ).path().split( '/' ) };
84  if ( parts.count() == 6 )
85  {
86  return crs.fromOgcWmsCrs( QStringLiteral( "urn:ogc:def:crs:%1:%2:%3" ).arg( parts[3], parts[4], parts[5] ) );
87  }
88  else
89  {
90  return crs;
91  }
92 }
93 
94 const QVector<QgsMapLayer *> QgsServerApiUtils::publishedWfsLayers( const QgsProject *project )
95 {
96  const QStringList wfsLayerIds = QgsServerProjectUtils::wfsLayerIds( *project );
97  const QStringList wfstUpdateLayersId = QgsServerProjectUtils::wfstUpdateLayerIds( *project );
98  const QStringList wfstInsertLayersId = QgsServerProjectUtils::wfstInsertLayerIds( *project );
99  const QStringList wfstDeleteLayersId = QgsServerProjectUtils::wfstDeleteLayerIds( *project );
100  QVector<QgsMapLayer *> result;
101  const auto constLayers { project->mapLayers() };
102  for ( auto it = project->mapLayers().constBegin(); it != project->mapLayers().constEnd(); it++ )
103  {
104  if ( wfstUpdateLayersId.contains( it.value()->id() ) ||
105  wfstInsertLayersId.contains( it.value()->id() ) ||
106  wfstDeleteLayersId.contains( it.value()->id() ) )
107  {
108  result.push_back( it.value() );
109  }
110 
111  }
112  return result;
113 }
114 
115 QString QgsServerApiUtils::sanitizedFieldValue( const QString &value )
116 {
117  QString result { QUrl( value ).toString() };
118  static const QRegularExpression re( R"raw(;.*(DROP|DELETE|INSERT|UPDATE|CREATE|INTO))raw" );
119  if ( re.match( result.toUpper() ).hasMatch() )
120  {
121  result = QString();
122  }
123  return result.replace( '\'', QStringLiteral( "\'" ) );
124 }
125 
126 QStringList QgsServerApiUtils::publishedCrsList( const QgsProject *project )
127 {
128  // This must be always available in OGC APIs
129  QStringList result { { QStringLiteral( "http://www.opengis.net/def/crs/OGC/1.3/CRS84" )}};
130  if ( project )
131  {
132  const QStringList outputCrsList = QgsServerProjectUtils::wmsOutputCrsList( *project );
133  for ( const QString &crsId : outputCrsList )
134  {
135  const auto crsUri { crsToOgcUri( QgsCoordinateReferenceSystem::fromOgcWmsCrs( crsId ) ) };
136  if ( ! crsUri.isEmpty() )
137  {
138  result.push_back( crsUri );
139  }
140  }
141  }
142  return result;
143 }
144 
146 {
147  const auto parts { crs.authid().split( ':' ) };
148  if ( parts.length() == 2 )
149  {
150  if ( parts[0] == QStringLiteral( "EPSG" ) )
151  return QStringLiteral( "http://www.opengis.net/def/crs/EPSG/9.6.2/%1" ).arg( parts[1] ) ;
152  else if ( parts[0] == QStringLiteral( "OGC" ) )
153  {
154  return QStringLiteral( "http://www.opengis.net/def/crs/OGC/1.3/%1" ).arg( parts[1] ) ;
155  }
156  else
157  {
158  QgsMessageLog::logMessage( QStringLiteral( "Error converting published CRS to URI %1: (not OGC or EPSG)" ).arg( crs.authid() ), QStringLiteral( "Server" ), Qgis::Critical );
159  }
160  }
161  else
162  {
163  QgsMessageLog::logMessage( QStringLiteral( "Error converting published CRS to URI: %1" ).arg( crs.authid() ), QStringLiteral( "Server" ), Qgis::Critical );
164  }
165  return QString();
166 }
167 
168 QString QgsServerApiUtils::appendMapParameter( const QString &path, const QUrl &requestUrl )
169 {
170  QList<QPair<QString, QString> > qi;
171  QString result { path };
172  const auto constItems { requestUrl.queryItems( ) };
173  for ( const auto &i : constItems )
174  {
175  if ( i.first.compare( QStringLiteral( "MAP" ), Qt::CaseSensitivity::CaseInsensitive ) == 0 )
176  {
177  qi.push_back( i );
178  }
179  }
180  if ( ! qi.empty() )
181  {
182  if ( ! path.endsWith( '?' ) )
183  {
184  result += '?';
185  }
186  result.append( QStringLiteral( "MAP=%1" ).arg( qi.first().second ) );
187  }
188  return result;
189 }
190 
SERVER_EXPORT QStringList wmsOutputCrsList(const QgsProject &project)
Returns the WMS output CRS list.
A rectangle specified with double values.
Definition: qgsrectangle.h:41
SERVER_EXPORT QStringList wfstUpdateLayerIds(const QgsProject &project)
Returns the Layer ids list defined in a QGIS project as published as WFS-T with update capabilities...
static QString sanitizedFieldValue(const QString &value)
Sanitizes the input value by removing URL encoding and checking for malicious content.
QgsPointXY transform(const QgsPointXY &point, TransformDirection direction=ForwardTransform) const SIP_THROW(QgsCsException)
Transform the point from the source CRS to the destination CRS.
static QStringList publishedCrsList(const QgsProject *project)
Returns the list of CRSs (format: http://www.opengis.net/def/crs/OGC/1.3/CRS84) available for this pr...
const QgsCoordinateReferenceSystem & crs
static QgsCoordinateReferenceSystem parseCrs(const QString &bboxCrs)
Parses the CRS URI bboxCrs (example: "http://www.opengis.net/def/crs/OGC/1.3/CRS84") into a QGIS CRS ...
SERVER_EXPORT QStringList wfstDeleteLayerIds(const QgsProject &project)
Returns the Layer ids list defined in a QGIS project as published as WFS-T with delete capabilities...
long postgisSrid() const
Returns PostGIS SRID for the CRS.
static json layerExtent(const QgsVectorLayer *layer)
layerExtent returns json array with [xMin,yMin,xMax,yMax] CRS84 extent for the given layer FIXME: the...
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
static const QVector< QgsMapLayer * > publishedWfsLayers(const QgsProject *project)
Returns the list of layers accessible to the service for a given project.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts, annotations, canvases, etc.
Definition: qgsproject.h:89
static QString appendMapParameter(const QString &path, const QUrl &requestUrl)
Appends MAP query string parameter from current requestUrl to the given path.
QgsCoordinateTransformContext transformContext() const
Returns the layer data provider coordinate transform context or a default transform context if the la...
QMap< QString, QgsMapLayer * > mapLayers(const bool validOnly=false) const
Returns a map of all registered layers by layer ID.
QgsRectangle extent() const FINAL
Returns the extent of the layer.
static QString crsToOgcUri(const QgsCoordinateReferenceSystem &crs)
Returns a crs as OGC URI (format: http://www.opengis.net/def/crs/OGC/1.3/CRS84) Returns an empty stri...
static QgsCoordinateReferenceSystem fromOgcWmsCrs(const QString &ogcCrs)
Creates a CRS from a given OGC WMS-format Coordinate Reference System string.
SERVER_EXPORT QStringList wfsLayerIds(const QgsProject &project)
Returns the Layer ids list defined in a QGIS project as published in WFS.
This class represents a coordinate reference system (CRS).
static QgsRectangle parseBbox(const QString &bbox)
Parses a comma separated bbox into a (possibily empty) QgsRectangle.
Class for doing transforms between two map coordinate systems.
SERVER_EXPORT QStringList wfstInsertLayerIds(const QgsProject &project)
Returns the Layer ids list defined in a QGIS project as published as WFS-T with insert capabilities...
Represents a vector layer which manages a vector based data sets.
QString authid() const
Returns the authority identifier for the CRS.
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:86