QGIS API Documentation 3.41.0-Master (fda2aa46e9a)
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//
34 const QVariant defaultValue )
35 : mType( type )
36 , mDefaultValue( defaultValue )
37{
38}
39
40QgsServerParameterDefinition::QgsServerParameterDefinition( const QVariant::Type type, const QVariant defaultValue )
41 : QgsServerParameterDefinition( QgsVariantUtils::variantTypeToMetaType( type ), defaultValue )
42{
43}
44
46{
47 return QVariant::typeToName( mType );
48}
49
51{
52 ok = true;
53 QColor color = mDefaultValue.value<QColor>();
54 QString cStr = mValue.toString();
55
56 if ( !cStr.isEmpty() )
57 {
58 // support hexadecimal notation to define colors
59 if ( cStr.startsWith( QLatin1String( "0x" ), Qt::CaseInsensitive ) )
60 {
61 cStr.replace( 0, 2, QStringLiteral( "#" ) );
62 }
63
64 color = QColor( cStr );
65
66 ok = color.isValid();
67 }
68
69 return color;
70}
71
72QString QgsServerParameterDefinition::toString( const bool defaultValue ) const
73{
74 QString value = mValue.toString();
75
76 if ( value.isEmpty() && defaultValue )
77 value = mDefaultValue.toString();
78
79 return value;
80}
81
82QStringList QgsServerParameterDefinition::toStringList( const char delimiter, const bool skipEmptyParts ) const
83{
84 if ( skipEmptyParts )
85 {
86 return toString().split( delimiter, Qt::SkipEmptyParts );
87 }
88 else
89 {
90 QStringList list;
91 if ( !toString().isEmpty() )
92 {
93 list = toString().split( delimiter, Qt::KeepEmptyParts );
94 }
95 return list;
96 }
97}
98
99QList<QgsGeometry> QgsServerParameterDefinition::toGeomList( bool &ok, const char delimiter ) const
100{
101 ok = true;
102 QList<QgsGeometry> geoms;
103
104 const auto constStringList( toStringList( delimiter ) );
105 for ( const auto &wkt : constStringList )
106 {
107 const QgsGeometry g( QgsGeometry::fromWkt( wkt ) );
108
109 if ( g.isGeosValid() )
110 {
111 geoms.append( g );
112 }
113 else
114 {
115 ok = false;
116 return QList<QgsGeometry>();
117 }
118 }
119
120 return geoms;
121}
122
124{
125 int pos = 0;
126 QStringList filters;
127 const QString filter = toString();
128
129 while ( pos < filter.size() )
130 {
131 if ( pos + 1 < filter.size() && filter[pos] == '(' && filter[pos + 1] == '<' )
132 {
133 // OGC filter on multiple layers
134 int posEnd = filter.indexOf( "Filter>)", pos );
135 if ( posEnd < 0 )
136 {
137 posEnd = filter.size();
138 }
139 filters.append( filter.mid( pos + 1, posEnd - pos + 6 ) );
140 pos = posEnd + 8;
141 }
142 else if ( pos + 1 < filter.size() && filter[pos] == '(' && filter[pos + 1] == ')' )
143 {
144 // empty OGC filter
145 filters.append( "" );
146 pos += 2;
147 }
148 else if ( filter[pos] == '<' && pos + 7 < filter.size() && filter.mid( pos + 1, 6 ).compare( QLatin1String( "Filter" ) ) == 0 )
149 {
150 // Single OGC filter
151 filters.append( filter.mid( pos ) );
152 break;
153 }
154 else
155 {
156 pos += 1;
157 }
158 }
159
160 return filters;
161}
162
164{
165 int pos = 0;
166 QStringList filters;
167 const QString filter = toString();
168
169 auto isOgcFilter = [filter]()
170 {
171 return filter.contains( QStringLiteral( "<Filter>" ) ) || filter.contains( QStringLiteral( "()" ) );
172 };
173
174 while ( pos < filter.size() )
175 {
176 int posEnd = filter.indexOf( ';', pos );
177
178 if ( posEnd == pos + 1 )
179 {
180 if ( ! isOgcFilter() )
181 filters.append( QString() );
182 pos = posEnd;
183 continue;
184 }
185
186 if ( ! isOgcFilter() )
187 filters.append( filter.mid( pos, posEnd - pos ) );
188
189 if ( posEnd < 0 )
190 {
191 pos = filter.size();
192 }
193 else
194 {
195 pos = posEnd + 1;
196 }
197 }
198
199 if ( ! filter.isEmpty() && filter.back() == ';' )
200 {
201 filters.append( QString() );
202 }
203
204 return filters;
205}
206
207QList<QColor> QgsServerParameterDefinition::toColorList( bool &ok, const char delimiter ) const
208{
209 ok = true;
210 QList<QColor> colors;
211
212 const auto constStringList( toStringList( delimiter ) );
213 for ( const auto &part : constStringList )
214 {
215 QString cStr( part );
216 if ( !cStr.isEmpty() )
217 {
218 // support hexadecimal notation to define colors
219 if ( cStr.startsWith( QLatin1String( "0x" ), Qt::CaseInsensitive ) )
220 {
221 cStr.replace( 0, 2, QStringLiteral( "#" ) );
222 }
223
224 const QColor color = QColor( cStr );
225 ok = color.isValid();
226
227 if ( !ok )
228 {
229 return QList<QColor>();
230 }
231
232 colors.append( color );
233 }
234 }
235
236 return colors;
237}
238
239QList<int> QgsServerParameterDefinition::toIntList( bool &ok, const char delimiter ) const
240{
241 ok = true;
242 QList<int> ints;
243
244 const auto constStringList( toStringList( delimiter ) );
245 for ( const auto &part : constStringList )
246 {
247 const int val = part.toInt( &ok );
248
249 if ( !ok )
250 {
251 return QList<int>();
252 }
253
254 ints.append( val );
255 }
256
257 return ints;
258}
259
260QList<double> QgsServerParameterDefinition::toDoubleList( bool &ok, const char delimiter ) const
261{
262 ok = true;
263 QList<double> vals;
264
265 const auto constStringList( toStringList( delimiter ) );
266 for ( const auto &part : constStringList )
267 {
268 const double val = part.toDouble( &ok );
269
270 if ( !ok )
271 {
272 return QList<double>();
273 }
274
275 vals.append( val );
276 }
277
278 return vals;
279}
280
282{
283 ok = true;
284 QgsRectangle extent;
285
286 if ( !mValue.toString().isEmpty() )
287 {
288 QStringList corners = mValue.toString().split( ',' );
289
290 if ( corners.size() == 4 )
291 {
292 double d[4];
293
294 for ( int i = 0; i < 4; i++ )
295 {
296 corners[i].replace( ' ', '+' );
297 d[i] = corners[i].toDouble( &ok );
298 if ( !ok )
299 {
300 return QgsRectangle();
301 }
302 }
303
304 if ( d[0] > d[2] || d[1] > d[3] )
305 {
306 ok = false;
307 return QgsRectangle();
308 }
309
310 extent = QgsRectangle( d[0], d[1], d[2], d[3] );
311 }
312 else
313 {
314 ok = false;
315 return QgsRectangle();
316 }
317 }
318
319 return extent;
320}
321
323{
324 ok = true;
325
326 // Get URL
327 const QUrl url = toUrl( ok );
328 if ( !ok )
329 {
330 return QString();
331 }
332
333 QNetworkRequest request( url );
334 request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache );
335 request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
336
337 // fetching content
339 const QgsBlockingNetworkRequest::ErrorCode errorCode = newReq.get( request, false );
340
341 if ( errorCode != QgsBlockingNetworkRequest::NoError )
342 {
343 ok = false;
345 QObject::tr( "Request failed [error: %1 - url: %2]" ).arg( newReq.errorMessage(), url.toString() ),
346 QStringLiteral( "Server" ) );
347 return QString();
348 }
349
350 QgsNetworkReplyContent reply = newReq.reply();
351
352 ok = !reply.content().isEmpty();
353 return reply.content();
354}
355
357{
358 ok = true;
359 QUrl val;
360
361 if ( !mValue.toString().isEmpty() )
362 {
363 val = mValue.toUrl();
364 }
365
366 ok = ( !val.isEmpty() && val.isValid() );
367 return val;
368}
369
371{
372 ok = true;
373 int val = mDefaultValue.toInt();
374
375 if ( !mValue.toString().isEmpty() )
376 {
377 val = mValue.toInt( &ok );
378 }
379
380 return val;
381}
382
384{
385 int val = mDefaultValue.toBool();
386
387 if ( !mValue.toString().isEmpty() )
388 {
389 val = mValue.toBool();
390 }
391
392 return val;
393}
394
396{
397 ok = true;
398 double val = mDefaultValue.toDouble();
399
400 if ( !mValue.toString().isEmpty() )
401 {
402 val = mValue.toDouble( &ok );
403 }
404
405 return val;
406}
407
409{
410 return mValue.canConvert( mType );
411}
412
414{
415 throw QgsBadRequestException( QStringLiteral( "Invalid Parameter" ), msg );
416}
417
418//
419// QgsServerParameter
420//
422 const QMetaType::Type type, const QVariant defaultValue )
423 : QgsServerParameterDefinition( type, defaultValue )
424 , mName( name )
425{
426}
427
429 const QVariant::Type type,
430 const QVariant defaultValue )
431 : QgsServerParameter( name, QgsVariantUtils::variantTypeToMetaType( type ), defaultValue )
432{
433}
434
436{
438 {
439 return QStringLiteral( "VERSION" );
440 }
441 else
442 {
443 const QMetaEnum metaEnum( QMetaEnum::fromType<QgsServerParameter::Name>() );
444 return metaEnum.valueToKey( name );
445 }
446}
447
449{
450 if ( name.compare( QLatin1String( "VERSION" ) ) == 0 )
451 {
453 }
454 else
455 {
456 const QMetaEnum metaEnum( QMetaEnum::fromType<QgsServerParameter::Name>() );
457 return ( QgsServerParameter::Name ) metaEnum.keyToValue( name.toUpper().toStdString().c_str() );
458 }
459}
460
462{
463 const QString msg = QString( "%1 ('%2') cannot be converted into %3" ).arg( name( mName ), mValue.toString(), typeName() );
465}
466
467//
468// QgsServerParameters
469//
478
481{
482 mUrlQuery = query;
483 load( query );
484}
485
486void QgsServerParameters::save( const QgsServerParameter &parameter )
487{
488 mParameters[ parameter.mName ] = parameter;
489}
490
491void QgsServerParameters::add( const QString &key, const QString &value )
492{
493 QUrlQuery query;
494 query.addQueryItem( key, value );
495 load( query );
496}
497
499{
500 QUrlQuery query = mUrlQuery;
501
502 if ( query.isEmpty() )
503 {
504 query.clear();
505
506 const auto constMap( toMap().toStdMap() );
507 for ( const auto &param : constMap )
508 {
509 const QString value = QUrl::toPercentEncoding( QString( param.second ) );
510 query.addQueryItem( param.first, value );
511 }
512 }
513
514 return query;
515}
516
521
522void QgsServerParameters::remove( const QString &key )
523{
524 if ( mUnmanagedParameters.contains( key ) )
525 {
526 mUnmanagedParameters.take( key );
527 }
528 else
529 {
530 const QgsServerParameter::Name paramName = QgsServerParameter::name( key );
531 if ( mParameters.contains( paramName ) )
532 {
533 mParameters.take( paramName );
534 }
535 }
536}
537
539{
540 return value( QgsServerParameter::MAP ).toString();
541}
542
544{
545 return value( QgsServerParameter::VERSION_SERVICE ).toString();
546}
547
549{
550 return value( QgsServerParameter::FILE_NAME ).toString();
551}
552
554{
555 QString serviceValue = value( QgsServerParameter::SERVICE ).toString();
556
557 if ( serviceValue.isEmpty() )
558 {
559 // SERVICE not mandatory for WMS 1.3.0 GetMap & GetFeatureInfo
560 if ( request() == QLatin1String( "GetMap" ) \
561 || request() == QLatin1String( "GetFeatureInfo" ) )
562 {
563 serviceValue = "WMS";
564 }
565 }
566
567 return serviceValue;
568}
569
570QMap<QString, QString> QgsServerParameters::toMap() const
571{
572 QMap<QString, QString> params = mUnmanagedParameters;
573
574 for ( const auto &parameter : mParameters.toStdMap() )
575 {
576 if ( QgsVariantUtils::isNull( parameter.second.mValue ) )
577 continue;
578
579 if ( parameter.second.mName == QgsServerParameter::VERSION_SERVICE )
580 {
581 params["VERSION"] = parameter.second.mValue.toString();
582 }
583 else
584 {
585 const QString paramName = QgsServerParameter::name( parameter.first );
586 params[paramName] = parameter.second.mValue.toString();
587 }
588 }
589
590 return params;
591}
592
594{
595 return value( QgsServerParameter::REQUEST ).toString();
596}
597
598QString QgsServerParameters::value( const QString &key ) const
599{
600 if ( ! mParameters.contains( QgsServerParameter::name( key ) ) )
601 {
602 return mUnmanagedParameters[key];
603 }
604 else
605 {
606 return value( QgsServerParameter::name( key ) ).toString();
607 }
608}
609
611{
612 return mParameters[name].mValue;
613}
614
615void QgsServerParameters::load( const QUrlQuery &query )
616{
617 // clean query string first
618 QUrlQuery cleanQuery( query );
619 cleanQuery.setQuery( query.query().replace( '+', QLatin1String( "%20" ) ) );
620
621 // load parameters
622 const auto constQueryItems( cleanQuery.queryItems( QUrl::FullyDecoded ) );
623 for ( const auto &item : constQueryItems )
624 {
625 const QgsServerParameter::Name name = QgsServerParameter::name( item.first );
626 if ( name >= 0 )
627 {
628 mParameters[name].mValue = item.second;
629 if ( ! mParameters[name].isValid() )
630 {
631 mParameters[name].raiseError();
632 }
633 }
634 else if ( item.first.compare( QLatin1String( "VERSION" ), Qt::CaseInsensitive ) == 0 )
635 {
637 mParameters[name].mValue = item.second;
638 if ( ! mParameters[name].isValid() )
639 {
640 mParameters[name].raiseError();
641 }
642 }
643 else if ( ! loadParameter( item.first, item.second ) )
644 {
645 mUnmanagedParameters[item.first.toUpper()] = item.second;
646 }
647 }
648}
649
650bool QgsServerParameters::loadParameter( const QString &, const QString & )
651{
652 return false;
653}
654
656{
657 mParameters.clear();
658 mUnmanagedParameters.clear();
659}
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.
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.