QGIS API Documentation 3.41.0-Master (af5edcb665c)
Loading...
Searching...
No Matches
qgsserverparameters.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsserverparameters.cpp
3 --------------------
4 begin : Jun 27, 2018
5 copyright : (C) 2018 by Paul Blottiere
6 email : paul dot blottiere at oslandia dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
19#include "qgsserverparameters.h"
20#include "moc_qgsserverparameters.cpp"
21#include "qgsserverexception.h"
22#include "qgsmessagelog.h"
23#include "qgsvariantutils.h"
24#include <QObject>
25#include <QUrl>
26#include <QNetworkReply>
27#include <QNetworkRequest>
28#include <QEventLoop>
29
30//
31// QgsServerParameterDefinition
32//
33QgsServerParameterDefinition::QgsServerParameterDefinition( const QMetaType::Type type, const QVariant defaultValue )
34 : mType( type )
35 , mDefaultValue( defaultValue )
36{
37}
38
39QgsServerParameterDefinition::QgsServerParameterDefinition( const QVariant::Type type, const QVariant defaultValue )
40 : QgsServerParameterDefinition( QgsVariantUtils::variantTypeToMetaType( type ), defaultValue )
41{
42}
43
45{
46 return QVariant::typeToName( mType );
47}
48
50{
51 ok = true;
52 QColor color = mDefaultValue.value<QColor>();
53 QString cStr = mValue.toString();
54
55 if ( !cStr.isEmpty() )
56 {
57 // support hexadecimal notation to define colors
58 if ( cStr.startsWith( QLatin1String( "0x" ), Qt::CaseInsensitive ) )
59 {
60 cStr.replace( 0, 2, QStringLiteral( "#" ) );
61 }
62
63 color = QColor( cStr );
64
65 ok = color.isValid();
66 }
67
68 return color;
69}
70
71QString QgsServerParameterDefinition::toString( const bool defaultValue ) const
72{
73 QString value = mValue.toString();
74
75 if ( value.isEmpty() && defaultValue )
76 value = mDefaultValue.toString();
77
78 return value;
79}
80
81QStringList QgsServerParameterDefinition::toStringList( const char delimiter, const bool skipEmptyParts ) const
82{
83 if ( skipEmptyParts )
84 {
85 return toString().split( delimiter, Qt::SkipEmptyParts );
86 }
87 else
88 {
89 QStringList list;
90 if ( !toString().isEmpty() )
91 {
92 list = toString().split( delimiter, Qt::KeepEmptyParts );
93 }
94 return list;
95 }
96}
97
98QList<QgsGeometry> QgsServerParameterDefinition::toGeomList( bool &ok, const char delimiter ) const
99{
100 ok = true;
101 QList<QgsGeometry> geoms;
102
103 const auto constStringList( toStringList( delimiter ) );
104 for ( const auto &wkt : constStringList )
105 {
106 const QgsGeometry g( QgsGeometry::fromWkt( wkt ) );
107
108 if ( g.isGeosValid() )
109 {
110 geoms.append( g );
111 }
112 else
113 {
114 ok = false;
115 return QList<QgsGeometry>();
116 }
117 }
118
119 return geoms;
120}
121
123{
124 int pos = 0;
125 QStringList filters;
126 const QString filter = toString();
127
128 while ( pos < filter.size() )
129 {
130 if ( pos + 1 < filter.size() && filter[pos] == '(' && filter[pos + 1] == '<' )
131 {
132 // OGC filter on multiple layers
133 int posEnd = filter.indexOf( "Filter>)", pos );
134 if ( posEnd < 0 )
135 {
136 posEnd = filter.size();
137 }
138 filters.append( filter.mid( pos + 1, posEnd - pos + 6 ) );
139 pos = posEnd + 8;
140 }
141 else if ( pos + 1 < filter.size() && filter[pos] == '(' && filter[pos + 1] == ')' )
142 {
143 // empty OGC filter
144 filters.append( "" );
145 pos += 2;
146 }
147 else if ( filter[pos] == '<' && pos + 7 < filter.size() && filter.mid( pos + 1, 6 ).compare( QLatin1String( "Filter" ) ) == 0 )
148 {
149 // Single OGC filter
150 filters.append( filter.mid( pos ) );
151 break;
152 }
153 else
154 {
155 pos += 1;
156 }
157 }
158
159 return filters;
160}
161
163{
164 int pos = 0;
165 QStringList filters;
166 const QString filter = toString();
167
168 auto isOgcFilter = [filter]() {
169 return filter.contains( QStringLiteral( "<Filter>" ) ) || filter.contains( QStringLiteral( "()" ) );
170 };
171
172 while ( pos < filter.size() )
173 {
174 int posEnd = filter.indexOf( ';', pos );
175
176 if ( posEnd == pos + 1 )
177 {
178 if ( !isOgcFilter() )
179 filters.append( QString() );
180 pos = posEnd;
181 continue;
182 }
183
184 if ( !isOgcFilter() )
185 filters.append( filter.mid( pos, posEnd - pos ) );
186
187 if ( posEnd < 0 )
188 {
189 pos = filter.size();
190 }
191 else
192 {
193 pos = posEnd + 1;
194 }
195 }
196
197 if ( !filter.isEmpty() && filter.back() == ';' )
198 {
199 filters.append( QString() );
200 }
201
202 return filters;
203}
204
205QList<QColor> QgsServerParameterDefinition::toColorList( bool &ok, const char delimiter ) const
206{
207 ok = true;
208 QList<QColor> colors;
209
210 const auto constStringList( toStringList( delimiter ) );
211 for ( const auto &part : constStringList )
212 {
213 QString cStr( part );
214 if ( !cStr.isEmpty() )
215 {
216 // support hexadecimal notation to define colors
217 if ( cStr.startsWith( QLatin1String( "0x" ), Qt::CaseInsensitive ) )
218 {
219 cStr.replace( 0, 2, QStringLiteral( "#" ) );
220 }
221
222 const QColor color = QColor( cStr );
223 ok = color.isValid();
224
225 if ( !ok )
226 {
227 return QList<QColor>();
228 }
229
230 colors.append( color );
231 }
232 }
233
234 return colors;
235}
236
237QList<int> QgsServerParameterDefinition::toIntList( bool &ok, const char delimiter ) const
238{
239 ok = true;
240 QList<int> ints;
241
242 const auto constStringList( toStringList( delimiter ) );
243 for ( const auto &part : constStringList )
244 {
245 const int val = part.toInt( &ok );
246
247 if ( !ok )
248 {
249 return QList<int>();
250 }
251
252 ints.append( val );
253 }
254
255 return ints;
256}
257
258QList<double> QgsServerParameterDefinition::toDoubleList( bool &ok, const char delimiter ) const
259{
260 ok = true;
261 QList<double> vals;
262
263 const auto constStringList( toStringList( delimiter ) );
264 for ( const auto &part : constStringList )
265 {
266 const double val = part.toDouble( &ok );
267
268 if ( !ok )
269 {
270 return QList<double>();
271 }
272
273 vals.append( val );
274 }
275
276 return vals;
277}
278
280{
281 ok = true;
282 QgsRectangle extent;
283
284 if ( !mValue.toString().isEmpty() )
285 {
286 QStringList corners = mValue.toString().split( ',' );
287
288 if ( corners.size() == 4 )
289 {
290 double d[4];
291
292 for ( int i = 0; i < 4; i++ )
293 {
294 corners[i].replace( ' ', '+' );
295 d[i] = corners[i].toDouble( &ok );
296 if ( !ok )
297 {
298 return QgsRectangle();
299 }
300 }
301
302 if ( d[0] > d[2] || d[1] > d[3] )
303 {
304 ok = false;
305 return QgsRectangle();
306 }
307
308 extent = QgsRectangle( d[0], d[1], d[2], d[3] );
309 }
310 else
311 {
312 ok = false;
313 return QgsRectangle();
314 }
315 }
316
317 return extent;
318}
319
321{
322 ok = true;
323
324 // Get URL
325 const QUrl url = toUrl( ok );
326 if ( !ok )
327 {
328 return QString();
329 }
330
331 QNetworkRequest request( url );
332 request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache );
333 request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
334
335 // fetching content
337 const QgsBlockingNetworkRequest::ErrorCode errorCode = newReq.get( request, false );
338
339 if ( errorCode != QgsBlockingNetworkRequest::NoError )
340 {
341 ok = false;
343 QObject::tr( "Request failed [error: %1 - url: %2]" ).arg( newReq.errorMessage(), url.toString() ),
344 QStringLiteral( "Server" )
345 );
346 return QString();
347 }
348
349 QgsNetworkReplyContent reply = newReq.reply();
350
351 ok = !reply.content().isEmpty();
352 return reply.content();
353}
354
356{
357 ok = true;
358 QUrl val;
359
360 if ( !mValue.toString().isEmpty() )
361 {
362 val = mValue.toUrl();
363 }
364
365 ok = ( !val.isEmpty() && val.isValid() );
366 return val;
367}
368
370{
371 ok = true;
372 int val = mDefaultValue.toInt();
373
374 if ( !mValue.toString().isEmpty() )
375 {
376 val = mValue.toInt( &ok );
377 }
378
379 return val;
380}
381
383{
384 int val = mDefaultValue.toBool();
385
386 if ( !mValue.toString().isEmpty() )
387 {
388 val = mValue.toBool();
389 }
390
391 return val;
392}
393
395{
396 ok = true;
397 double val = mDefaultValue.toDouble();
398
399 if ( !mValue.toString().isEmpty() )
400 {
401 val = mValue.toDouble( &ok );
402 }
403
404 return val;
405}
406
408{
409 return mValue.canConvert( mType );
410}
411
413{
414 throw QgsBadRequestException( QStringLiteral( "Invalid Parameter" ), msg );
415}
416
417//
418// QgsServerParameter
419//
420QgsServerParameter::QgsServerParameter( const QgsServerParameter::Name name, const QMetaType::Type type, const QVariant defaultValue )
421 : QgsServerParameterDefinition( type, defaultValue )
422 , mName( name )
423{
424}
425
426QgsServerParameter::QgsServerParameter( const QgsServerParameter::Name name, const QVariant::Type type, const QVariant defaultValue )
427 : QgsServerParameter( name, QgsVariantUtils::variantTypeToMetaType( type ), defaultValue )
428{
429}
430
432{
434 {
435 return QStringLiteral( "VERSION" );
436 }
437 else
438 {
439 const QMetaEnum metaEnum( QMetaEnum::fromType<QgsServerParameter::Name>() );
440 return metaEnum.valueToKey( name );
441 }
442}
443
445{
446 if ( name.compare( QLatin1String( "VERSION" ) ) == 0 )
447 {
449 }
450 else
451 {
452 const QMetaEnum metaEnum( QMetaEnum::fromType<QgsServerParameter::Name>() );
453 return ( QgsServerParameter::Name ) metaEnum.keyToValue( name.toUpper().toStdString().c_str() );
454 }
455}
456
458{
459 const QString msg = QString( "%1 ('%2') cannot be converted into %3" ).arg( name( mName ), mValue.toString(), typeName() );
461}
462
463//
464// QgsServerParameters
465//
474
477{
478 mUrlQuery = query;
479 load( query );
480}
481
482void QgsServerParameters::save( const QgsServerParameter &parameter )
483{
484 mParameters[parameter.mName] = parameter;
485}
486
487void QgsServerParameters::add( const QString &key, const QString &value )
488{
489 QUrlQuery query;
490 query.addQueryItem( key, value );
491 load( query );
492}
493
495{
496 QUrlQuery query = mUrlQuery;
497
498 if ( query.isEmpty() )
499 {
500 query.clear();
501
502 const auto constMap( toMap().toStdMap() );
503 for ( const auto &param : constMap )
504 {
505 const QString value = QUrl::toPercentEncoding( QString( param.second ) );
506 query.addQueryItem( param.first, value );
507 }
508 }
509
510 return query;
511}
512
517
518void QgsServerParameters::remove( const QString &key )
519{
520 if ( mUnmanagedParameters.contains( key ) )
521 {
522 mUnmanagedParameters.take( key );
523 }
524 else
525 {
526 const QgsServerParameter::Name paramName = QgsServerParameter::name( key );
527 if ( mParameters.contains( paramName ) )
528 {
529 mParameters.take( paramName );
530 }
531 }
532}
533
535{
536 return value( QgsServerParameter::MAP ).toString();
537}
538
540{
541 return value( QgsServerParameter::VERSION_SERVICE ).toString();
542}
543
545{
546 return value( QgsServerParameter::FILE_NAME ).toString();
547}
548
550{
551 QString serviceValue = value( QgsServerParameter::SERVICE ).toString();
552
553 if ( serviceValue.isEmpty() )
554 {
555 // SERVICE not mandatory for WMS 1.3.0 GetMap & GetFeatureInfo
556 if ( request() == QLatin1String( "GetMap" )
557 || request() == QLatin1String( "GetFeatureInfo" ) )
558 {
559 serviceValue = "WMS";
560 }
561 }
562
563 return serviceValue;
564}
565
566QMap<QString, QString> QgsServerParameters::toMap() const
567{
568 QMap<QString, QString> params = mUnmanagedParameters;
569
570 for ( const auto &parameter : mParameters.toStdMap() )
571 {
572 if ( QgsVariantUtils::isNull( parameter.second.mValue ) )
573 continue;
574
575 if ( parameter.second.mName == QgsServerParameter::VERSION_SERVICE )
576 {
577 params["VERSION"] = parameter.second.mValue.toString();
578 }
579 else
580 {
581 const QString paramName = QgsServerParameter::name( parameter.first );
582 params[paramName] = parameter.second.mValue.toString();
583 }
584 }
585
586 return params;
587}
588
590{
591 return value( QgsServerParameter::REQUEST ).toString();
592}
593
594QString QgsServerParameters::value( const QString &key ) const
595{
596 if ( !mParameters.contains( QgsServerParameter::name( key ) ) )
597 {
598 return mUnmanagedParameters[key];
599 }
600 else
601 {
602 return value( QgsServerParameter::name( key ) ).toString();
603 }
604}
605
607{
608 return mParameters[name].mValue;
609}
610
611void QgsServerParameters::load( const QUrlQuery &query )
612{
613 // clean query string first
614 QUrlQuery cleanQuery( query );
615 cleanQuery.setQuery( query.query().replace( '+', QLatin1String( "%20" ) ) );
616
617 // load parameters
618 const auto constQueryItems( cleanQuery.queryItems( QUrl::FullyDecoded ) );
619 for ( const auto &item : constQueryItems )
620 {
621 const QgsServerParameter::Name name = QgsServerParameter::name( item.first );
622 if ( name >= 0 )
623 {
624 mParameters[name].mValue = item.second;
625 if ( !mParameters[name].isValid() )
626 {
627 mParameters[name].raiseError();
628 }
629 }
630 else if ( item.first.compare( QLatin1String( "VERSION" ), Qt::CaseInsensitive ) == 0 )
631 {
633 mParameters[name].mValue = item.second;
634 if ( !mParameters[name].isValid() )
635 {
636 mParameters[name].raiseError();
637 }
638 }
639 else if ( !loadParameter( item.first, item.second ) )
640 {
641 mUnmanagedParameters[item.first.toUpper()] = item.second;
642 }
643 }
644}
645
646bool QgsServerParameters::loadParameter( const QString &, const QString & )
647{
648 return false;
649}
650
652{
653 mParameters.clear();
654 mUnmanagedParameters.clear();
655}
Exception thrown in case of malformed request.
A thread safe class for performing blocking (sync) network requests, with full support for QGIS proxy...
QString errorMessage() const
Returns the error message string, after a get(), post(), head() or put() request has been made.
ErrorCode get(QNetworkRequest &request, bool forceRefresh=false, QgsFeedback *feedback=nullptr, RequestFlags requestFlags=QgsBlockingNetworkRequest::RequestFlags())
Performs a "get" operation on the specified request.
@ NoError
No error was encountered.
QgsNetworkReplyContent reply() const
Returns the content of the network reply, after a get(), post(), head() or put() request has been mad...
A geometry is the spatial representation of a feature.
static Q_INVOKABLE QgsGeometry fromWkt(const QString &wkt)
Creates a new geometry from a WKT string.
bool isGeosValid(Qgis::GeometryValidityFlags flags=Qgis::GeometryValidityFlags()) const
Checks validity of the geometry using GEOS.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
Encapsulates a network reply within a container which is inexpensive to copy and safe to pass between...
QByteArray content() const
Returns the reply content.
A rectangle specified with double values.
Q_INVOKABLE QString toString(int precision=16) const
Returns a string representation of form xmin,ymin : xmax,ymax Coordinates will be truncated to the sp...
Definition of a parameter with basic conversion methods.
QList< QgsGeometry > toGeomList(bool &ok, char delimiter=',') const
Converts the parameter into a list of geometries.
QString loadUrl(bool &ok) const
Loads the data associated to the parameter converted into an url.
QUrl toUrl(bool &ok) const
Converts the parameter into an url.
QString toString(bool defaultValue=false) const
Converts the parameter into a string.
bool toBool() const
Converts the parameter into a boolean.
QgsServerParameterDefinition(const QMetaType::Type type=QMetaType::Type::QString, const QVariant defaultValue=QVariant(""))
Constructor for QgsServerParameterDefinition.
QList< double > toDoubleList(bool &ok, char delimiter=',') const
Converts the parameter into a list of doubles.
QStringList toStringList(char delimiter=',', bool skipEmptyParts=true) const
Converts the parameter into a list of strings.
virtual bool isValid() const
Returns true if the parameter is valid, false otherwise.
QString typeName() const
Returns the type of the parameter as a string.
static void raiseError(const QString &msg)
Raises an exception in case of an invalid parameters.
QStringList toExpressionList() const
Converts the parameter into a list of QGIS expressions.
int toInt(bool &ok) const
Converts the parameter into an integer.
QList< int > toIntList(bool &ok, char delimiter=',') const
Converts the parameter into a list of integers.
QColor toColor(bool &ok) const
Converts the parameter into a color.
double toDouble(bool &ok) const
Converts the parameter into a double.
QgsRectangle toRectangle(bool &ok) const
Converts the parameter into a rectangle.
QList< QColor > toColorList(bool &ok, char delimiter=',') const
Converts the parameter into a list of colors.
QStringList toOgcFilterList() const
Converts the parameter into a list of OGC filters.
Parameter common to all services (WMS, WFS, ...)
QgsServerParameter::Name mName
QgsServerParameter(const QgsServerParameter::Name name=QgsServerParameter::UNKNOWN, const QMetaType::Type type=QMetaType::Type::QString, const QVariant defaultValue=QVariant(""))
Constructor for QgsServerParameter.
Name
Parameter's name common to all services.
void raiseError() const
Raises an error in case of an invalid conversion.
static QString name(const QgsServerParameter::Name name)
Converts a parameter's name into its string representation.
QgsServerParameters provides an interface to retrieve and manipulate global parameters received from ...
QMap< QString, QString > toMap() const
Returns all parameters in a map.
QString map() const
Returns MAP parameter as a string or an empty string if not defined.
void add(const QString &key, const QString &value)
Adds a parameter.
QString service() const
Returns SERVICE parameter as a string or an empty string if not defined.
virtual QString request() const
Returns REQUEST parameter as a string or an empty string if not defined.
void clear()
Removes all parameters.
QString fileName() const
Returns FILE_NAME parameter as a string or an empty string if not defined.
virtual bool loadParameter(const QString &name, const QString &value)
Loads a parameter with a specific value.
QUrlQuery urlQuery() const
Returns a url query with underlying parameters.
QMap< QString, QString > mUnmanagedParameters
void load(const QUrlQuery &query)
Loads new parameters.
void remove(const QString &key)
Removes a parameter.
virtual QString version() const
Returns VERSION parameter as a string or an empty string if not defined.
QString value(const QString &key) const
Returns the value of a parameter.
Contains utility functions for working with QVariants and QVariant types.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.