mirror of
https://github.com/qgis/QGIS.git
synced 2025-12-16 00:06:09 -05:00
656 lines
15 KiB
C++
656 lines
15 KiB
C++
/***************************************************************************
|
|
qgsserverparameters.cpp
|
|
--------------------
|
|
begin : Jun 27, 2018
|
|
copyright : (C) 2018 by Paul Blottiere
|
|
email : paul dot blottiere at oslandia dot com
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include "qgsblockingnetworkrequest.h"
|
|
#include "qgsserverparameters.h"
|
|
#include "moc_qgsserverparameters.cpp"
|
|
#include "qgsserverexception.h"
|
|
#include "qgsmessagelog.h"
|
|
#include "qgsvariantutils.h"
|
|
#include <QObject>
|
|
#include <QUrl>
|
|
#include <QNetworkReply>
|
|
#include <QNetworkRequest>
|
|
#include <QEventLoop>
|
|
|
|
//
|
|
// QgsServerParameterDefinition
|
|
//
|
|
QgsServerParameterDefinition::QgsServerParameterDefinition( const QMetaType::Type type, const QVariant defaultValue )
|
|
: mType( type )
|
|
, mDefaultValue( defaultValue )
|
|
{
|
|
}
|
|
|
|
QgsServerParameterDefinition::QgsServerParameterDefinition( const QVariant::Type type, const QVariant defaultValue )
|
|
: QgsServerParameterDefinition( QgsVariantUtils::variantTypeToMetaType( type ), defaultValue )
|
|
{
|
|
}
|
|
|
|
QString QgsServerParameterDefinition::typeName() const
|
|
{
|
|
return QVariant::typeToName( mType );
|
|
}
|
|
|
|
QColor QgsServerParameterDefinition::toColor( bool &ok ) const
|
|
{
|
|
ok = true;
|
|
QColor color = mDefaultValue.value<QColor>();
|
|
QString cStr = mValue.toString();
|
|
|
|
if ( !cStr.isEmpty() )
|
|
{
|
|
// support hexadecimal notation to define colors
|
|
if ( cStr.startsWith( QLatin1String( "0x" ), Qt::CaseInsensitive ) )
|
|
{
|
|
cStr.replace( 0, 2, QStringLiteral( "#" ) );
|
|
}
|
|
|
|
color = QColor( cStr );
|
|
|
|
ok = color.isValid();
|
|
}
|
|
|
|
return color;
|
|
}
|
|
|
|
QString QgsServerParameterDefinition::toString( const bool defaultValue ) const
|
|
{
|
|
QString value = mValue.toString();
|
|
|
|
if ( value.isEmpty() && defaultValue )
|
|
value = mDefaultValue.toString();
|
|
|
|
return value;
|
|
}
|
|
|
|
QStringList QgsServerParameterDefinition::toStringList( const char delimiter, const bool skipEmptyParts ) const
|
|
{
|
|
if ( skipEmptyParts )
|
|
{
|
|
return toString().split( delimiter, Qt::SkipEmptyParts );
|
|
}
|
|
else
|
|
{
|
|
QStringList list;
|
|
if ( !toString().isEmpty() )
|
|
{
|
|
list = toString().split( delimiter, Qt::KeepEmptyParts );
|
|
}
|
|
return list;
|
|
}
|
|
}
|
|
|
|
QList<QgsGeometry> QgsServerParameterDefinition::toGeomList( bool &ok, const char delimiter, const bool skipEmptyParts ) const
|
|
{
|
|
ok = true;
|
|
QList<QgsGeometry> geoms;
|
|
|
|
const auto constStringList( toStringList( delimiter, skipEmptyParts ) );
|
|
for ( const auto &wkt : constStringList )
|
|
{
|
|
const QgsGeometry g( QgsGeometry::fromWkt( wkt ) );
|
|
|
|
if ( g.isGeosValid() )
|
|
{
|
|
geoms.append( g );
|
|
}
|
|
else
|
|
{
|
|
ok = false;
|
|
return QList<QgsGeometry>();
|
|
}
|
|
}
|
|
|
|
return geoms;
|
|
}
|
|
|
|
QStringList QgsServerParameterDefinition::toOgcFilterList() const
|
|
{
|
|
int pos = 0;
|
|
QStringList filters;
|
|
const QString filter = toString();
|
|
|
|
while ( pos < filter.size() )
|
|
{
|
|
if ( pos + 1 < filter.size() && filter[pos] == '(' && filter[pos + 1] == '<' )
|
|
{
|
|
// OGC filter on multiple layers
|
|
int posEnd = filter.indexOf( "Filter>)", pos );
|
|
if ( posEnd < 0 )
|
|
{
|
|
posEnd = filter.size();
|
|
}
|
|
filters.append( filter.mid( pos + 1, posEnd - pos + 6 ) );
|
|
pos = posEnd + 8;
|
|
}
|
|
else if ( pos + 1 < filter.size() && filter[pos] == '(' && filter[pos + 1] == ')' )
|
|
{
|
|
// empty OGC filter
|
|
filters.append( "" );
|
|
pos += 2;
|
|
}
|
|
else if ( filter[pos] == '<' && pos + 7 < filter.size() && filter.mid( pos + 1, 6 ).compare( QLatin1String( "Filter" ) ) == 0 )
|
|
{
|
|
// Single OGC filter
|
|
filters.append( filter.mid( pos ) );
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
pos += 1;
|
|
}
|
|
}
|
|
|
|
return filters;
|
|
}
|
|
|
|
QStringList QgsServerParameterDefinition::toExpressionList() const
|
|
{
|
|
int pos = 0;
|
|
QStringList filters;
|
|
const QString filter = toString();
|
|
|
|
auto isOgcFilter = [filter]() {
|
|
return filter.contains( QStringLiteral( "<Filter>" ) ) || filter.contains( QStringLiteral( "()" ) );
|
|
};
|
|
|
|
while ( pos < filter.size() )
|
|
{
|
|
int posEnd = filter.indexOf( ';', pos );
|
|
|
|
if ( posEnd == pos + 1 )
|
|
{
|
|
if ( !isOgcFilter() )
|
|
filters.append( QString() );
|
|
pos = posEnd;
|
|
continue;
|
|
}
|
|
|
|
if ( !isOgcFilter() )
|
|
filters.append( filter.mid( pos, posEnd - pos ) );
|
|
|
|
if ( posEnd < 0 )
|
|
{
|
|
pos = filter.size();
|
|
}
|
|
else
|
|
{
|
|
pos = posEnd + 1;
|
|
}
|
|
}
|
|
|
|
if ( !filter.isEmpty() && filter.back() == ';' )
|
|
{
|
|
filters.append( QString() );
|
|
}
|
|
|
|
return filters;
|
|
}
|
|
|
|
QList<QColor> QgsServerParameterDefinition::toColorList( bool &ok, const char delimiter, bool skipEmptyParts ) const
|
|
{
|
|
ok = true;
|
|
QList<QColor> colors;
|
|
|
|
const auto constStringList( toStringList( delimiter, skipEmptyParts ) );
|
|
for ( const auto &part : constStringList )
|
|
{
|
|
QString cStr( part );
|
|
if ( !cStr.isEmpty() )
|
|
{
|
|
// support hexadecimal notation to define colors
|
|
if ( cStr.startsWith( QLatin1String( "0x" ), Qt::CaseInsensitive ) )
|
|
{
|
|
cStr.replace( 0, 2, QStringLiteral( "#" ) );
|
|
}
|
|
|
|
const QColor color = QColor( cStr );
|
|
ok = color.isValid();
|
|
|
|
if ( !ok )
|
|
{
|
|
return QList<QColor>();
|
|
}
|
|
|
|
colors.append( color );
|
|
}
|
|
}
|
|
|
|
return colors;
|
|
}
|
|
|
|
QList<int> QgsServerParameterDefinition::toIntList( bool &ok, const char delimiter, bool skipEmptyParts ) const
|
|
{
|
|
ok = true;
|
|
QList<int> ints;
|
|
|
|
const auto constStringList( toStringList( delimiter, skipEmptyParts ) );
|
|
for ( const auto &part : constStringList )
|
|
{
|
|
const int val = part.toInt( &ok );
|
|
|
|
if ( !ok )
|
|
{
|
|
return QList<int>();
|
|
}
|
|
|
|
ints.append( val );
|
|
}
|
|
|
|
return ints;
|
|
}
|
|
|
|
QList<double> QgsServerParameterDefinition::toDoubleList( bool &ok, const char delimiter, bool skipEmptyParts ) const
|
|
{
|
|
ok = true;
|
|
QList<double> vals;
|
|
|
|
const auto constStringList( toStringList( delimiter, skipEmptyParts ) );
|
|
for ( const auto &part : constStringList )
|
|
{
|
|
const double val = part.toDouble( &ok );
|
|
|
|
if ( !ok )
|
|
{
|
|
return QList<double>();
|
|
}
|
|
|
|
vals.append( val );
|
|
}
|
|
|
|
return vals;
|
|
}
|
|
|
|
QgsRectangle QgsServerParameterDefinition::toRectangle( bool &ok ) const
|
|
{
|
|
ok = true;
|
|
QgsRectangle extent;
|
|
|
|
if ( !mValue.toString().isEmpty() )
|
|
{
|
|
QStringList corners = mValue.toString().split( ',' );
|
|
|
|
if ( corners.size() == 4 )
|
|
{
|
|
double d[4];
|
|
|
|
for ( int i = 0; i < 4; i++ )
|
|
{
|
|
corners[i].replace( ' ', '+' );
|
|
d[i] = corners[i].toDouble( &ok );
|
|
if ( !ok )
|
|
{
|
|
return QgsRectangle();
|
|
}
|
|
}
|
|
|
|
if ( d[0] > d[2] || d[1] > d[3] )
|
|
{
|
|
ok = false;
|
|
return QgsRectangle();
|
|
}
|
|
|
|
extent = QgsRectangle( d[0], d[1], d[2], d[3] );
|
|
}
|
|
else
|
|
{
|
|
ok = false;
|
|
return QgsRectangle();
|
|
}
|
|
}
|
|
|
|
return extent;
|
|
}
|
|
|
|
QString QgsServerParameterDefinition::loadUrl( bool &ok ) const
|
|
{
|
|
ok = true;
|
|
|
|
// Get URL
|
|
const QUrl url = toUrl( ok );
|
|
if ( !ok )
|
|
{
|
|
return QString();
|
|
}
|
|
|
|
QNetworkRequest request( url );
|
|
request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache );
|
|
request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
|
|
|
|
// fetching content
|
|
QgsBlockingNetworkRequest newReq;
|
|
const QgsBlockingNetworkRequest::ErrorCode errorCode = newReq.get( request, false );
|
|
|
|
if ( errorCode != QgsBlockingNetworkRequest::NoError )
|
|
{
|
|
ok = false;
|
|
QgsMessageLog::logMessage(
|
|
QObject::tr( "Request failed [error: %1 - url: %2]" ).arg( newReq.errorMessage(), url.toString() ),
|
|
QStringLiteral( "Server" )
|
|
);
|
|
return QString();
|
|
}
|
|
|
|
QgsNetworkReplyContent reply = newReq.reply();
|
|
|
|
ok = !reply.content().isEmpty();
|
|
return reply.content();
|
|
}
|
|
|
|
QUrl QgsServerParameterDefinition::toUrl( bool &ok ) const
|
|
{
|
|
ok = true;
|
|
QUrl val;
|
|
|
|
if ( !mValue.toString().isEmpty() )
|
|
{
|
|
val = mValue.toUrl();
|
|
}
|
|
|
|
ok = ( !val.isEmpty() && val.isValid() );
|
|
return val;
|
|
}
|
|
|
|
int QgsServerParameterDefinition::toInt( bool &ok ) const
|
|
{
|
|
ok = true;
|
|
int val = mDefaultValue.toInt();
|
|
|
|
if ( !mValue.toString().isEmpty() )
|
|
{
|
|
val = mValue.toInt( &ok );
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
bool QgsServerParameterDefinition::toBool() const
|
|
{
|
|
int val = mDefaultValue.toBool();
|
|
|
|
if ( !mValue.toString().isEmpty() )
|
|
{
|
|
val = mValue.toBool();
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
double QgsServerParameterDefinition::toDouble( bool &ok ) const
|
|
{
|
|
ok = true;
|
|
double val = mDefaultValue.toDouble();
|
|
|
|
if ( !mValue.toString().isEmpty() )
|
|
{
|
|
val = mValue.toDouble( &ok );
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
bool QgsServerParameterDefinition::isValid() const
|
|
{
|
|
return mValue.canConvert( mType );
|
|
}
|
|
|
|
void QgsServerParameterDefinition::raiseError( const QString &msg )
|
|
{
|
|
throw QgsBadRequestException( QStringLiteral( "Invalid Parameter" ), msg );
|
|
}
|
|
|
|
//
|
|
// QgsServerParameter
|
|
//
|
|
QgsServerParameter::QgsServerParameter( const QgsServerParameter::Name name, const QMetaType::Type type, const QVariant defaultValue )
|
|
: QgsServerParameterDefinition( type, defaultValue )
|
|
, mName( name )
|
|
{
|
|
}
|
|
|
|
QgsServerParameter::QgsServerParameter( const QgsServerParameter::Name name, const QVariant::Type type, const QVariant defaultValue )
|
|
: QgsServerParameter( name, QgsVariantUtils::variantTypeToMetaType( type ), defaultValue )
|
|
{
|
|
}
|
|
|
|
QString QgsServerParameter::name( const QgsServerParameter::Name name )
|
|
{
|
|
if ( name == QgsServerParameter::VERSION_SERVICE )
|
|
{
|
|
return QStringLiteral( "VERSION" );
|
|
}
|
|
else
|
|
{
|
|
const QMetaEnum metaEnum( QMetaEnum::fromType<QgsServerParameter::Name>() );
|
|
return metaEnum.valueToKey( name );
|
|
}
|
|
}
|
|
|
|
QgsServerParameter::Name QgsServerParameter::name( const QString &name )
|
|
{
|
|
if ( name.compare( QLatin1String( "VERSION" ) ) == 0 )
|
|
{
|
|
return QgsServerParameter::VERSION_SERVICE;
|
|
}
|
|
else
|
|
{
|
|
const QMetaEnum metaEnum( QMetaEnum::fromType<QgsServerParameter::Name>() );
|
|
return ( QgsServerParameter::Name ) metaEnum.keyToValue( name.toUpper().toStdString().c_str() );
|
|
}
|
|
}
|
|
|
|
void QgsServerParameter::raiseError() const
|
|
{
|
|
const QString msg = QString( "%1 ('%2') cannot be converted into %3" ).arg( name( mName ), mValue.toString(), typeName() );
|
|
QgsServerParameterDefinition::raiseError( msg );
|
|
}
|
|
|
|
//
|
|
// QgsServerParameters
|
|
//
|
|
QgsServerParameters::QgsServerParameters()
|
|
{
|
|
save( QgsServerParameter( QgsServerParameter::SERVICE ) );
|
|
save( QgsServerParameter( QgsServerParameter::REQUEST ) );
|
|
save( QgsServerParameter( QgsServerParameter::VERSION_SERVICE ) );
|
|
save( QgsServerParameter( QgsServerParameter::MAP ) );
|
|
save( QgsServerParameter( QgsServerParameter::FILE_NAME ) );
|
|
}
|
|
|
|
QgsServerParameters::QgsServerParameters( const QUrlQuery &query )
|
|
: QgsServerParameters()
|
|
{
|
|
mUrlQuery = query;
|
|
load( query );
|
|
}
|
|
|
|
void QgsServerParameters::save( const QgsServerParameter ¶meter )
|
|
{
|
|
mParameters[parameter.mName] = parameter;
|
|
}
|
|
|
|
void QgsServerParameters::add( const QString &key, const QString &value )
|
|
{
|
|
QUrlQuery query;
|
|
query.addQueryItem( key, value );
|
|
load( query );
|
|
}
|
|
|
|
QUrlQuery QgsServerParameters::urlQuery() const
|
|
{
|
|
QUrlQuery query = mUrlQuery;
|
|
|
|
if ( query.isEmpty() )
|
|
{
|
|
query.clear();
|
|
|
|
const auto constMap( toMap().toStdMap() );
|
|
for ( const auto ¶m : constMap )
|
|
{
|
|
const QString value = QUrl::toPercentEncoding( QString( param.second ) );
|
|
query.addQueryItem( param.first, value );
|
|
}
|
|
}
|
|
|
|
return query;
|
|
}
|
|
|
|
void QgsServerParameters::remove( QgsServerParameter::Name name )
|
|
{
|
|
remove( QgsServerParameter::name( name ) );
|
|
}
|
|
|
|
void QgsServerParameters::remove( const QString &key )
|
|
{
|
|
if ( mUnmanagedParameters.contains( key ) )
|
|
{
|
|
mUnmanagedParameters.take( key );
|
|
}
|
|
else
|
|
{
|
|
const QgsServerParameter::Name paramName = QgsServerParameter::name( key );
|
|
if ( mParameters.contains( paramName ) )
|
|
{
|
|
mParameters.take( paramName );
|
|
}
|
|
}
|
|
}
|
|
|
|
QString QgsServerParameters::map() const
|
|
{
|
|
return value( QgsServerParameter::MAP ).toString();
|
|
}
|
|
|
|
QString QgsServerParameters::version() const
|
|
{
|
|
return value( QgsServerParameter::VERSION_SERVICE ).toString();
|
|
}
|
|
|
|
QString QgsServerParameters::fileName() const
|
|
{
|
|
return value( QgsServerParameter::FILE_NAME ).toString();
|
|
}
|
|
|
|
QString QgsServerParameters::service() const
|
|
{
|
|
QString serviceValue = value( QgsServerParameter::SERVICE ).toString();
|
|
|
|
if ( serviceValue.isEmpty() )
|
|
{
|
|
// SERVICE not mandatory for WMS 1.3.0 GetMap & GetFeatureInfo
|
|
if ( request() == QLatin1String( "GetMap" )
|
|
|| request() == QLatin1String( "GetFeatureInfo" ) )
|
|
{
|
|
serviceValue = "WMS";
|
|
}
|
|
}
|
|
|
|
return serviceValue;
|
|
}
|
|
|
|
QMap<QString, QString> QgsServerParameters::toMap() const
|
|
{
|
|
QMap<QString, QString> params = mUnmanagedParameters;
|
|
|
|
for ( const auto ¶meter : mParameters.toStdMap() )
|
|
{
|
|
if ( QgsVariantUtils::isNull( parameter.second.mValue ) )
|
|
continue;
|
|
|
|
if ( parameter.second.mName == QgsServerParameter::VERSION_SERVICE )
|
|
{
|
|
params["VERSION"] = parameter.second.mValue.toString();
|
|
}
|
|
else
|
|
{
|
|
const QString paramName = QgsServerParameter::name( parameter.first );
|
|
params[paramName] = parameter.second.mValue.toString();
|
|
}
|
|
}
|
|
|
|
return params;
|
|
}
|
|
|
|
QString QgsServerParameters::request() const
|
|
{
|
|
return value( QgsServerParameter::REQUEST ).toString();
|
|
}
|
|
|
|
QString QgsServerParameters::value( const QString &key ) const
|
|
{
|
|
if ( !mParameters.contains( QgsServerParameter::name( key ) ) )
|
|
{
|
|
return mUnmanagedParameters[key];
|
|
}
|
|
else
|
|
{
|
|
return value( QgsServerParameter::name( key ) ).toString();
|
|
}
|
|
}
|
|
|
|
QVariant QgsServerParameters::value( QgsServerParameter::Name name ) const
|
|
{
|
|
return mParameters[name].mValue;
|
|
}
|
|
|
|
void QgsServerParameters::load( const QUrlQuery &query )
|
|
{
|
|
// clean query string first
|
|
QUrlQuery cleanQuery( query );
|
|
cleanQuery.setQuery( query.query().replace( '+', QLatin1String( "%20" ) ) );
|
|
|
|
// load parameters
|
|
const auto constQueryItems( cleanQuery.queryItems( QUrl::FullyDecoded ) );
|
|
for ( const auto &item : constQueryItems )
|
|
{
|
|
const QgsServerParameter::Name name = QgsServerParameter::name( item.first );
|
|
if ( name >= 0 )
|
|
{
|
|
mParameters[name].mValue = item.second;
|
|
if ( !mParameters[name].isValid() )
|
|
{
|
|
mParameters[name].raiseError();
|
|
}
|
|
}
|
|
else if ( item.first.compare( QLatin1String( "VERSION" ), Qt::CaseInsensitive ) == 0 )
|
|
{
|
|
const QgsServerParameter::Name name = QgsServerParameter::VERSION_SERVICE;
|
|
mParameters[name].mValue = item.second;
|
|
if ( !mParameters[name].isValid() )
|
|
{
|
|
mParameters[name].raiseError();
|
|
}
|
|
}
|
|
else if ( !loadParameter( item.first, item.second ) )
|
|
{
|
|
mUnmanagedParameters[item.first.toUpper()] = item.second;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool QgsServerParameters::loadParameter( const QString &, const QString & )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
void QgsServerParameters::clear()
|
|
{
|
|
mParameters.clear();
|
|
mUnmanagedParameters.clear();
|
|
}
|