[server] WIP clean project parsing by using QgsProject

This commit is contained in:
Blottiere Paul 2016-12-26 15:25:23 +01:00
parent 8ba609e516
commit 5c8360dba2
72 changed files with 7615 additions and 389 deletions

View File

@ -86,10 +86,6 @@ class QgsServerProjectParser
@return name or a null string in case of error*/
QString layerName( const QDomElement& layerElem ) const;
QString serviceUrl() const;
QString wfsServiceUrl() const;
QString wcsServiceUrl() const;
QStringList wfsLayers() const;
QStringList wcsLayers() const;

View File

@ -0,0 +1,61 @@
/***************************************************************************
qgsserverprojectutils.sip
-------------------------
begin : December 19, 2016
copyright : (C) 2016 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. *
* *
***************************************************************************/
/** \ingroup server
* The QgsServerProjectUtils class provides a way to retrieve specific entries
* a QgsProject.
* @note added in QGIS 3.0
*/
class QgsServerProjectUtils
{
%TypeHeaderCode
#include "qgsserverprojectutils.h"
%End
public:
/** Returns the maximum width for WMS images defined in a QGIS project.
* @param project the QGIS project
* @return width if defined in project, -1 otherwise.
*/
static int wmsMaxWidth( const QgsProject& project );
/** Returns the maximum height for WMS images defined in a QGIS project.
* @param project the QGIS project
* @return height if defined in project, -1 otherwise.
*/
static int wmsMaxHeight( const QgsProject& project );
/** Returns the WMS service url defined in a QGIS project.
* @param project the QGIS project
* @return url if defined in project, an empty string otherwise.
*/
static QString wmsServiceUrl( const QgsProject& project );
/** Returns the WFS service url defined in a QGIS project.
* @param project the QGIS project
* @return url if defined in project, an empty string otherwise.
*/
static QString wfsServiceUrl( const QgsProject& project );
/** Returns the WCS service url defined in a QGIS project.
* @param project the QGIS project
* @return url if defined in project, an empty string otherwise.
*/
static QString wcsServiceUrl( const QgsProject& project );
};

View File

@ -64,6 +64,6 @@ class QgsService
* Execute the requests and set result in QgsServerRequest
*/
virtual void executeRequest( const QgsServerRequest& request, QgsServerResponse& response,
QgsProject* project = nullptr ) = 0;
const QgsProject* project ) = 0;
};

View File

@ -27,8 +27,6 @@ class QgsWCSProjectParser
~QgsWCSProjectParser();
void serviceCapabilities( QDomElement& parentElement, QDomDocument& doc ) const;
QString wcsServiceUrl() const;
QString serviceUrl() const;
void wcsContentMetadata( QDomElement& parentElement, QDomDocument& doc ) const;
QStringList wcsLayers() const;
void describeCoverage( const QString& aCoveName, QDomElement& parentElement, QDomDocument& doc ) const;

View File

@ -28,8 +28,6 @@ class QgsWfsProjectParser
~QgsWfsProjectParser();
void serviceCapabilities( QDomElement& parentElement, QDomDocument& doc ) const;
QString serviceUrl() const;
QString wfsServiceUrl() const;
void featureTypeList( QDomElement& parentElement, QDomDocument& doc ) const;
void describeFeatureType( const QString& aTypeName, QDomElement& parentElement, QDomDocument& doc ) const;

View File

@ -27,7 +27,7 @@ class QgsWmsConfigParser
/** Adds layer and style specific capabilities elements to the parent node. This includes the individual layers and styles, their description, native CRS, bounding boxes, etc.
@param fullProjectInformation If true: add extended project information (does not validate against WMS schema)*/
virtual void layersAndStylesCapabilities( QDomElement& parentElement, QDomDocument& doc, const QString& version, bool fullProjectSettings = false ) const = 0;
virtual void layersAndStylesCapabilities( QDomElement& parentElement, QDomDocument& doc, const QString& version, const QString& serviceUrl, bool fullProjectSettings = false ) const = 0;
/** Returns one or possibly several maplayers for a given layer name and style. If no layers/style are found, an empty list is returned*/
virtual QList<QgsMapLayer*> mapLayerFromStyle( const QString& lName, const QString& styleName, bool useCache = true ) const = 0;
@ -42,7 +42,7 @@ class QgsWmsConfigParser
virtual QDomDocument getStyles( QStringList& layerList ) const = 0;
/** Returns the xml fragment of layers styles description*/
virtual QDomDocument describeLayer( QStringList& layerList, const QString& hrefString ) const = 0;
virtual QDomDocument describeLayer( QStringList& layerList, const QString& wfsHrefString, const QString& wcsHrefString ) const = 0;
/** Returns if output are MM or PIXEL*/
virtual QgsUnitTypes::RenderUnit outputUnits() const = 0;
@ -74,8 +74,6 @@ class QgsWmsConfigParser
/** Load PAL engine settings into global project instance*/
virtual void loadLabelSettings() const = 0;
virtual QString serviceUrl() const = 0;
virtual QStringList wfsLayerNames() const = 0;
virtual void owsGeneralAndResourceList( QDomElement& parentElement, QDomDocument& doc, const QString& strHref ) const = 0;
@ -91,8 +89,6 @@ class QgsWmsConfigParser
virtual QFont legendLayerFont() const = 0;
virtual QFont legendItemFont() const = 0;
virtual double maxWidth() const = 0;
virtual double maxHeight() const = 0;
virtual double imageQuality() const = 0;
// WMS GetFeatureInfo precision (decimal places)

View File

@ -28,12 +28,10 @@ class QgsWmsProjectParser : public QgsWmsConfigParser
/** Adds layer and style specific capabilities elements to the parent node. This includes the individual layers and styles, their description, native CRS, bounding boxes, etc.
@param fullProjectInformation If true: add extended project information (does not validate against WMS schema)*/
void layersAndStylesCapabilities( QDomElement& parentElement, QDomDocument& doc, const QString& version, bool fullProjectSettings = false ) const /*override*/ ;
void layersAndStylesCapabilities( QDomElement& parentElement, QDomDocument& doc, const QString& version, const QString& serviceUrl, bool fullProjectSettings = false ) const /*override*/ ;
QList<QgsMapLayer*> mapLayerFromStyle( const QString& lName, const QString& styleName, bool useCache = true ) const /*override*/ ;
QString serviceUrl() const /*override*/ ;
QStringList wfsLayerNames() const /*override*/ ;
void owsGeneralAndResourceList( QDomElement& parentElement, QDomDocument& doc, const QString& strHref ) const /*override*/ ;
@ -49,8 +47,6 @@ class QgsWmsProjectParser : public QgsWmsConfigParser
QFont legendLayerFont() const /*override*/ ;
QFont legendItemFont() const /*override*/ ;
double maxWidth() const /*override*/ ;
double maxHeight() const /*override*/ ;
double imageQuality() const /*override*/ ;
int wmsPrecision() const /*override*/ ;
@ -75,7 +71,7 @@ class QgsWmsProjectParser : public QgsWmsConfigParser
QDomDocument getStyles( QStringList& layerList ) const /*override*/ ;
/** Returns the xml fragment of layers styles description*/
QDomDocument describeLayer( QStringList& layerList, const QString& hrefString ) const /*override*/ ;
QDomDocument describeLayer( QStringList& layerList, const QString& wfsHrefString, const QString& wcsHrefString ) const /*override*/ ;
/** Returns if output are MM or PIXEL*/
QgsUnitTypes::RenderUnit outputUnits() const /*override*/ ;

View File

@ -27,6 +27,7 @@
%Include qgswfsprojectparser.sip
%Include qgsconfigcache.sip
%Include qgsserversettings.sip
%Include qgsserverprojectutils.sip
%Include qgsserver.sip
%Include qgsserverrequest.sip

View File

@ -155,6 +155,12 @@ QPainter::CompositionMode QgsMapLayer::blendMode() const
bool QgsMapLayer::readLayerXml( const QDomElement& layerElement )
{
return readLayerXml( layerElement, QgsProject::instance() );
}
bool QgsMapLayer::readLayerXml( const QDomElement& layerElement, const QgsProject *project )
{
bool layerError;
@ -185,19 +191,19 @@ bool QgsMapLayer::readLayerXml( const QDomElement& layerElement )
if ( provider == QLatin1String( "spatialite" ) )
{
QgsDataSourceUri uri( mDataSource );
uri.setDatabase( QgsProject::instance()->readPath( uri.database() ) );
uri.setDatabase( project->readPath( uri.database() ) );
mDataSource = uri.uri();
}
else if ( provider == QLatin1String( "ogr" ) )
{
QStringList theURIParts = mDataSource.split( '|' );
theURIParts[0] = QgsProject::instance()->readPath( theURIParts[0] );
theURIParts[0] = project->readPath( theURIParts[0] );
mDataSource = theURIParts.join( QStringLiteral( "|" ) );
}
else if ( provider == QLatin1String( "gpx" ) )
{
QStringList theURIParts = mDataSource.split( '?' );
theURIParts[0] = QgsProject::instance()->readPath( theURIParts[0] );
theURIParts[0] = project->readPath( theURIParts[0] );
mDataSource = theURIParts.join( QStringLiteral( "?" ) );
}
else if ( provider == QLatin1String( "delimitedtext" ) )
@ -211,7 +217,7 @@ bool QgsMapLayer::readLayerXml( const QDomElement& layerElement )
urlSource.setPath( file.path() );
}
QUrl urlDest = QUrl::fromLocalFile( QgsProject::instance()->readPath( urlSource.toLocalFile() ) );
QUrl urlDest = QUrl::fromLocalFile( project->readPath( urlSource.toLocalFile() ) );
urlDest.setQueryItems( urlSource.queryItems() );
mDataSource = QString::fromAscii( urlDest.toEncoded() );
}
@ -309,7 +315,7 @@ bool QgsMapLayer::readLayerXml( const QDomElement& layerElement )
QString filename = r.cap( 1 );
if ( filename.startsWith( '"' ) && filename.endsWith( '"' ) )
filename = filename.mid( 1, filename.length() - 2 );
mDataSource = "NETCDF:\"" + QgsProject::instance()->readPath( filename ) + "\":" + r.cap( 2 );
mDataSource = "NETCDF:\"" + project->readPath( filename ) + "\":" + r.cap( 2 );
handled = true;
}
}
@ -323,7 +329,7 @@ bool QgsMapLayer::readLayerXml( const QDomElement& layerElement )
QString filename = r.cap( 2 );
if ( filename.startsWith( '"' ) && filename.endsWith( '"' ) )
filename = filename.mid( 1, filename.length() - 2 );
mDataSource = "HDF4_SDS:" + r.cap( 1 ) + ":\"" + QgsProject::instance()->readPath( filename ) + "\":" + r.cap( 3 );
mDataSource = "HDF4_SDS:" + r.cap( 1 ) + ":\"" + project->readPath( filename ) + "\":" + r.cap( 3 );
handled = true;
}
}
@ -337,7 +343,7 @@ bool QgsMapLayer::readLayerXml( const QDomElement& layerElement )
QString filename = r.cap( 1 );
if ( filename.startsWith( '"' ) && filename.endsWith( '"' ) )
filename = filename.mid( 1, filename.length() - 2 );
mDataSource = "HDF5:\"" + QgsProject::instance()->readPath( filename ) + "\":" + r.cap( 2 );
mDataSource = "HDF5:\"" + project->readPath( filename ) + "\":" + r.cap( 2 );
handled = true;
}
}
@ -348,14 +354,14 @@ bool QgsMapLayer::readLayerXml( const QDomElement& layerElement )
QRegExp r( "([^:]+):([^:]+):(.+)" );
if ( r.exactMatch( mDataSource ) )
{
mDataSource = r.cap( 1 ) + ':' + r.cap( 2 ) + ':' + QgsProject::instance()->readPath( r.cap( 3 ) );
mDataSource = r.cap( 1 ) + ':' + r.cap( 2 ) + ':' + project->readPath( r.cap( 3 ) );
handled = true;
}
}
}
if ( !handled )
mDataSource = QgsProject::instance()->readPath( mDataSource );
mDataSource = project->readPath( mDataSource );
}
// Set the CRS from project file, asking the user if necessary.

View File

@ -38,6 +38,7 @@
class QgsMapLayerLegend;
class QgsMapLayerRenderer;
class QgsMapLayerStyleManager;
class QgsProject;
class QDomDocument;
class QKeyEvent;
@ -364,6 +365,13 @@ class CORE_EXPORT QgsMapLayer : public QObject
*/
bool readLayerXml( const QDomElement& layerElement );
/** Sets state from Dom document for a specific project.
* @param layerElement The Dom element corresponding to ``maplayer'' tag
* @param project
* @returns true if successful
*/
bool readLayerXml( const QDomElement& layerElement, const QgsProject *project );
/** Stores state in Dom node
* @param layerElement is a Dom element corresponding to ``maplayer'' tag

View File

@ -733,7 +733,7 @@ bool QgsProject::addLayer( const QDomElement &layerElem, QList<QDomNode> &broken
Q_CHECK_PTR( mapLayer );
// have the layer restore state that is stored in Dom node
if ( mapLayer->readLayerXml( layerElem ) && mapLayer->isValid() )
if ( mapLayer->readLayerXml( layerElem, this ) && mapLayer->isValid() )
{
// postpone readMapLayer signal for vector layers with joins
QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer*>( mapLayer );

View File

@ -39,6 +39,7 @@ SET(qgis_mapserv_SRCS
qgswmsconfigparser.cpp
qgswmsprojectparser.cpp
qgsserverprojectparser.cpp
qgsserverprojectutils.cpp
qgssldconfigparser.cpp
qgsconfigparserutils.cpp
qgsserver.cpp

View File

@ -39,6 +39,7 @@
#include "qgsbufferserverresponse.h"
#include "qgsfilterresponsedecorator.h"
#include "qgsservice.h"
#include "qgsserverprojectutils.h"
#include <QDomDocument>
#include <QNetworkDiskCache>
@ -351,6 +352,24 @@ void QgsServer::handleRequest( QgsServerRequest& request, QgsServerResponse& res
//Config file path
QString configFilePath = configPath( *sConfigFilePath, parameterMap );
// load the project if needed and not empty
auto projectIt = mProjectStore.find( configFilePath );
if ( projectIt == mProjectStore.constEnd() )
{
// load the project
QgsProject* project = new QgsProject();
project->setFileName( configFilePath );
if ( project->read() )
{
projectIt = mProjectStore.insert( configFilePath, project );
}
else
{
throw QgsServerException( QStringLiteral( "Project file error" ) );
// theRequestHandler.setServiceException( QgsMapServiceException( QStringLiteral( "Project file error" ), QStringLiteral( "Error reading the project file" ) ) );
}
}
sServerInterface->setConfigFilePath( configFilePath );
//Service parameter
@ -379,7 +398,7 @@ void QgsServer::handleRequest( QgsServerRequest& request, QgsServerResponse& res
QgsService* service = sServiceRegistry.getService( serviceString, versionString );
if ( service )
{
service->executeRequest( request, theResponse );
service->executeRequest( request, theResponse, projectIt.value() );
}
else
{

View File

@ -43,6 +43,7 @@
class QgsServerRequest;
class QgsServerResponse;
class QgsProject;
/** \ingroup server
* The QgsServer class provides OGC web services.
@ -130,6 +131,9 @@ class SERVER_EXPORT QgsServer
static QgsServiceRegistry sServiceRegistry;
static QgsServerSettings sSettings;
// map of QgsProject
QMap<QString, const QgsProject*> mProjectStore;
};
#endif // QGSSERVER_H

View File

@ -644,69 +644,6 @@ QString QgsServerProjectParser::layerName( const QDomElement& layerElem ) const
return nameElem.text().replace( QLatin1String( "," ), QLatin1String( "%60" ) ); //commas are not allowed in layer names
}
QString QgsServerProjectParser::serviceUrl() const
{
QString url;
if ( !mXMLDoc )
{
return url;
}
QDomElement propertiesElement = propertiesElem();
if ( !propertiesElement.isNull() )
{
QDomElement wmsUrlElem = propertiesElement.firstChildElement( QStringLiteral( "WMSUrl" ) );
if ( !wmsUrlElem.isNull() )
{
url = wmsUrlElem.text();
}
}
return url;
}
QString QgsServerProjectParser::wfsServiceUrl() const
{
QString url;
if ( !mXMLDoc )
{
return url;
}
QDomElement propertiesElement = propertiesElem();
if ( !propertiesElement.isNull() )
{
QDomElement wfsUrlElem = propertiesElement.firstChildElement( QStringLiteral( "WFSUrl" ) );
if ( !wfsUrlElem.isNull() )
{
url = wfsUrlElem.text();
}
}
return url;
}
QString QgsServerProjectParser::wcsServiceUrl() const
{
QString url;
if ( !mXMLDoc )
{
return url;
}
QDomElement propertiesElement = propertiesElem();
if ( !propertiesElement.isNull() )
{
QDomElement wcsUrlElem = propertiesElement.firstChildElement( QStringLiteral( "WCSUrl" ) );
if ( !wcsUrlElem.isNull() )
{
url = wcsUrlElem.text();
}
}
return url;
}
void QgsServerProjectParser::combineExtentAndCrsOfGroupChildren( QDomElement& groupElem, QDomDocument& doc, bool considerMapExtent ) const
{
QgsRectangle combinedBBox;

View File

@ -105,10 +105,6 @@ class SERVER_EXPORT QgsServerProjectParser
@return name or a null string in case of error*/
QString layerName( const QDomElement& layerElem ) const;
QString serviceUrl() const;
QString wfsServiceUrl() const;
QString wcsServiceUrl() const;
QStringList wfsLayers() const;
QStringList wcsLayers() const;

View File

@ -0,0 +1,43 @@
/***************************************************************************
qgsserverprojectutils.cpp
-------------------------
begin : December 19, 2016
copyright : (C) 2016 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 "qgsserverprojectutils.h"
int QgsServerProjectUtils::wmsMaxWidth( const QgsProject& project )
{
return project.readNumEntry( QStringLiteral( "WMSMaxWidth" ), QStringLiteral( "/" ), -1 );
}
int QgsServerProjectUtils::wmsMaxHeight( const QgsProject& project )
{
return project.readNumEntry( QStringLiteral( "WMSMaxHeight" ), QStringLiteral( "/" ), -1 );
}
QString QgsServerProjectUtils::wmsServiceUrl( const QgsProject& project )
{
return project.readEntry( QStringLiteral( "WMSUrl" ), QStringLiteral( "/" ), "" );
}
QString QgsServerProjectUtils::wfsServiceUrl( const QgsProject& project )
{
return project.readEntry( QStringLiteral( "WFSUrl" ), QStringLiteral( "/" ), "" );
}
QString QgsServerProjectUtils::wcsServiceUrl( const QgsProject& project )
{
return project.readEntry( QStringLiteral( "WCSUrl" ), QStringLiteral( "/" ), "" );
}

View File

@ -0,0 +1,64 @@
/***************************************************************************
qgsserverprojectutils.h
-----------------------
begin : December 19, 2016
copyright : (C) 2016 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. *
* *
***************************************************************************/
#ifndef QGSSERVERPROJECTUTILS_H
#define QGSSERVERPROJECTUTILS_H
#include "qgis_server.h"
#include "qgsproject.h"
/** \ingroup server
* The QgsServerProjectUtils class provides a way to retrieve specific entries
* from a QgsProject.
* @note added in QGIS 3.0
*/
class SERVER_EXPORT QgsServerProjectUtils
{
public:
/** Returns the maximum width for WMS images defined in a QGIS project.
* @param project the QGIS project
* @return width if defined in project, -1 otherwise.
*/
static int wmsMaxWidth( const QgsProject& project );
/** Returns the maximum height for WMS images defined in a QGIS project.
* @param project the QGIS project
* @return height if defined in project, -1 otherwise.
*/
static int wmsMaxHeight( const QgsProject& project );
/** Returns the WMS service url defined in a QGIS project.
* @param project the QGIS project
* @return url if defined in project, an empty string otherwise.
*/
static QString wmsServiceUrl( const QgsProject& project );
/** Returns the WFS service url defined in a QGIS project.
* @param project the QGIS project
* @return url if defined in project, an empty string otherwise.
*/
static QString wfsServiceUrl( const QgsProject& project );
/** Returns the WCS service url defined in a QGIS project.
* @param project the QGIS project
* @return url if defined in project, an empty string otherwise.
*/
static QString wcsServiceUrl( const QgsProject& project );
};
#endif

View File

@ -65,8 +65,9 @@ class SERVER_EXPORT QgsService
/**
* Execute the requests and set result in QgsServerRequest
*/
virtual void executeRequest( const QgsServerRequest& request, QgsServerResponse& response,
QgsProject* project = nullptr ) = 0;
virtual void executeRequest( const QgsServerRequest& request,
QgsServerResponse& response,
const QgsProject* project ) = 0;
};
#endif

View File

@ -86,9 +86,10 @@ QgsSLDConfigParser::~QgsSLDConfigParser()
delete mXMLDoc;
}
void QgsSLDConfigParser::layersAndStylesCapabilities( QDomElement& parentElement, QDomDocument& doc, const QString& version, bool fullProjectSettings ) const
void QgsSLDConfigParser::layersAndStylesCapabilities( QDomElement& parentElement, QDomDocument& doc, const QString& version, const QString& serviceUrl, bool fullProjectSettings ) const
{
Q_UNUSED( version );
Q_UNUSED( serviceUrl );
Q_UNUSED( fullProjectSettings );
//iterate over all <UserLayer> nodes
@ -475,11 +476,11 @@ QDomDocument QgsSLDConfigParser::getStyles( QStringList& layerList ) const
return styleDoc;
}
QDomDocument QgsSLDConfigParser::describeLayer( QStringList& layerList, const QString& hrefString ) const
QDomDocument QgsSLDConfigParser::describeLayer( QStringList& layerList, const QString& wfsHrefString, const QString& wcsHrefString ) const
{
if ( mFallbackParser )
{
return mFallbackParser->describeLayer( layerList, hrefString );
return mFallbackParser->describeLayer( layerList, wfsHrefString, wcsHrefString );
}
return QDomDocument();
}
@ -566,15 +567,6 @@ void QgsSLDConfigParser::loadLabelSettings() const
}
}
QString QgsSLDConfigParser::serviceUrl() const
{
if ( mFallbackParser )
{
return mFallbackParser->serviceUrl();
}
return QString();
}
QStringList QgsSLDConfigParser::wfsLayerNames() const
{
if ( mFallbackParser )
@ -673,24 +665,6 @@ QFont QgsSLDConfigParser::legendItemFont() const
return mLegendItemFont;
}
double QgsSLDConfigParser::maxWidth() const
{
if ( mFallbackParser )
{
return mFallbackParser->maxWidth();
}
return -1;
}
double QgsSLDConfigParser::maxHeight() const
{
if ( mFallbackParser )
{
return mFallbackParser->maxHeight();
}
return -1;
}
double QgsSLDConfigParser::imageQuality() const
{
if ( mFallbackParser )

View File

@ -39,7 +39,7 @@ class SERVER_EXPORT QgsSLDConfigParser : public QgsWmsConfigParser
/** Adds layer and style specific capabilities elements to the parent node. This includes the individual layers and styles, their description, native CRS, bounding boxes, etc.
@param fullProjectInformation If true: add extended project information (does not validate against WMS schema)*/
void layersAndStylesCapabilities( QDomElement& parentElement, QDomDocument& doc, const QString& version, bool fullProjectSettings = false ) const override;
void layersAndStylesCapabilities( QDomElement& parentElement, QDomDocument& doc, const QString& version, const QString& serviceUrl, bool fullProjectSettings = false ) const override;
//! Returns one or possibly several maplayers for a given layer name and style. If no layers/style are found, an empty list is returned
QList<QgsMapLayer*> mapLayerFromStyle( const QString& lName, const QString& styleName, bool useCache = true ) const override;
@ -54,7 +54,7 @@ class SERVER_EXPORT QgsSLDConfigParser : public QgsWmsConfigParser
QDomDocument getStyles( QStringList& layerList ) const override;
//! Returns the xml fragment of layers styles description
QDomDocument describeLayer( QStringList& layerList, const QString& hrefString ) const override;
QDomDocument describeLayer( QStringList& layerList, const QString& wfsHrefString, const QString& wcsHrefString ) const override;
//! Returns if output are MM or PIXEL
QgsUnitTypes::RenderUnit outputUnits() const override;
@ -86,8 +86,6 @@ class SERVER_EXPORT QgsSLDConfigParser : public QgsWmsConfigParser
//! Load PAL engine settings into global project instance
void loadLabelSettings() const override;
QString serviceUrl() const override;
QStringList wfsLayerNames() const override;
void owsGeneralAndResourceList( QDomElement& parentElement, QDomDocument& doc, const QString& strHref ) const override;
@ -103,8 +101,6 @@ class SERVER_EXPORT QgsSLDConfigParser : public QgsWmsConfigParser
QFont legendLayerFont() const override;
QFont legendItemFont() const override;
double maxWidth() const override;
double maxHeight() const override;
double imageQuality() const override;
int wmsPrecision() const override;

View File

@ -51,32 +51,6 @@ void QgsWCSProjectParser::serviceCapabilities( QDomElement& parentElement, QDomD
mProjectParser->serviceCapabilities( parentElement, doc, QStringLiteral( "WCS" ) );
}
QString QgsWCSProjectParser::wcsServiceUrl() const
{
QString url;
if ( !mProjectParser->xmlDocument() )
{
return url;
}
QDomElement propertiesElem = mProjectParser->propertiesElem();
if ( !propertiesElem.isNull() )
{
QDomElement wcsUrlElem = propertiesElem.firstChildElement( QStringLiteral( "WCSUrl" ) );
if ( !wcsUrlElem.isNull() )
{
url = wcsUrlElem.text();
}
}
return url;
}
QString QgsWCSProjectParser::serviceUrl() const
{
return mProjectParser->serviceUrl();
}
void QgsWCSProjectParser::wcsContentMetadata( QDomElement& parentElement, QDomDocument& doc ) const
{
const QList<QDomElement>& projectLayerElements = mProjectParser->projectLayerElements();

View File

@ -36,8 +36,6 @@ class SERVER_EXPORT QgsWCSProjectParser
QgsWCSProjectParser& operator=( const QgsWCSProjectParser& rh ) = delete;
void serviceCapabilities( QDomElement& parentElement, QDomDocument& doc ) const;
QString wcsServiceUrl() const;
QString serviceUrl() const;
void wcsContentMetadata( QDomElement& parentElement, QDomDocument& doc ) const;
QStringList wcsLayers() const;
void describeCoverage( const QString& aCoveName, QDomElement& parentElement, QDomDocument& doc ) const;

481
src/server/qgswcsserver.cpp Normal file
View File

@ -0,0 +1,481 @@
/***************************************************************************
qgswcsserver.cpp
-------------------
begin : December 9, 2013
copyright : (C) 2013 by René-Luc D'Hont
email : rldhont at 3liz 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 "qgswcsserver.h"
#include "qgswcsprojectparser.h"
#include "qgsrasterdataprovider.h"
#include "qgsrasterlayer.h"
#include "qgsrasterpipe.h"
#include "qgsrasterprojector.h"
#include "qgsrasterfilewriter.h"
#include "qgslogger.h"
#include "qgsmapserviceexception.h"
#include "qgsaccesscontrol.h"
#include <QTemporaryFile>
#include <QUrl>
#ifndef Q_OS_WIN
#include <netinet/in.h>
#else
#include <winsock.h>
#endif
static const QString WCS_NAMESPACE = QStringLiteral( "http://www.opengis.net/wcs" );
static const QString GML_NAMESPACE = QStringLiteral( "http://www.opengis.net/gml" );
static const QString OGC_NAMESPACE = QStringLiteral( "http://www.opengis.net/ogc" );
QgsWCSServer::QgsWCSServer(
const QString& configFilePath
, QMap<QString, QString> &parameters
, QgsWCSProjectParser* pp
, QgsRequestHandler* rh
, const QgsProject* project
#ifdef HAVE_SERVER_PYTHON_PLUGINS
, const QgsAccessControl* accessControl
#endif
)
: QgsOWSServer(
configFilePath
, parameters
, rh
, project
#ifdef HAVE_SERVER_PYTHON_PLUGINS
, accessControl
#endif
)
, mConfigParser(
pp
)
{
}
void QgsWCSServer::executeRequest()
{
//request type
QString request = mParameters.value( QStringLiteral( "REQUEST" ) );
if ( request.isEmpty() )
{
//do some error handling
QgsDebugMsg( "unable to find 'REQUEST' parameter, exiting..." );
mRequestHandler->setServiceException( QgsMapServiceException( QStringLiteral( "OperationNotSupported" ), QStringLiteral( "Please check the value of the REQUEST parameter" ) ) );
return;
}
if ( request.compare( QLatin1String( "GetCapabilities" ), Qt::CaseInsensitive ) == 0 )
{
QDomDocument capabilitiesDocument;
try
{
capabilitiesDocument = getCapabilities();
}
catch ( QgsMapServiceException& ex )
{
mRequestHandler->setServiceException( ex );
return;
}
QgsDebugMsg( "seting GetCapabilities response" );
mRequestHandler->setGetCapabilitiesResponse( capabilitiesDocument );
return;
}
else if ( request.compare( QLatin1String( "DescribeCoverage" ), Qt::CaseInsensitive ) == 0 )
{
QDomDocument describeDocument;
try
{
describeDocument = describeCoverage();
}
catch ( QgsMapServiceException& ex )
{
mRequestHandler->setServiceException( ex );
return;
}
QgsDebugMsg( "seting GetCapabilities response" );
mRequestHandler->setGetCapabilitiesResponse( describeDocument );
return;
}
else if ( request.compare( QLatin1String( "GetCoverage" ), Qt::CaseInsensitive ) == 0 )
{
QByteArray* coverageOutput;
try
{
coverageOutput = getCoverage();
}
catch ( QgsMapServiceException& ex )
{
mRequestHandler->setServiceException( ex );
return;
}
if ( coverageOutput )
{
mRequestHandler->setGetCoverageResponse( coverageOutput );
}
return;
}
}
QDomDocument QgsWCSServer::getCapabilities()
{
QgsDebugMsg( "Entering." );
QDomDocument doc;
//wcs:WCS_Capabilities element
QDomElement wcsCapabilitiesElement = doc.createElement( QStringLiteral( "WCS_Capabilities" )/*wcs:WCS_Capabilities*/ );
wcsCapabilitiesElement.setAttribute( QStringLiteral( "xmlns" ), WCS_NAMESPACE );
wcsCapabilitiesElement.setAttribute( QStringLiteral( "xmlns:xsi" ), QStringLiteral( "http://www.w3.org/2001/XMLSchema-instance" ) );
wcsCapabilitiesElement.setAttribute( QStringLiteral( "xsi:schemaLocation" ), WCS_NAMESPACE + " http://schemas.opengis.net/wcs/1.0.0/wcsCapabilities.xsd" );
wcsCapabilitiesElement.setAttribute( QStringLiteral( "xmlns:gml" ), GML_NAMESPACE );
wcsCapabilitiesElement.setAttribute( QStringLiteral( "xmlns:xlink" ), QStringLiteral( "http://www.w3.org/1999/xlink" ) );
wcsCapabilitiesElement.setAttribute( QStringLiteral( "version" ), QStringLiteral( "1.0.0" ) );
wcsCapabilitiesElement.setAttribute( QStringLiteral( "updateSequence" ), QStringLiteral( "0" ) );
doc.appendChild( wcsCapabilitiesElement );
if ( mConfigParser )
{
mConfigParser->serviceCapabilities( wcsCapabilitiesElement, doc );
}
//INSERT Service
//wcs:Capability element
QDomElement capabilityElement = doc.createElement( QStringLiteral( "Capability" )/*wcs:Capability*/ );
wcsCapabilitiesElement.appendChild( capabilityElement );
//wcs:Request element
QDomElement requestElement = doc.createElement( QStringLiteral( "Request" )/*wcs:Request*/ );
capabilityElement.appendChild( requestElement );
//wcs:GetCapabilities
QDomElement getCapabilitiesElement = doc.createElement( QStringLiteral( "GetCapabilities" )/*wcs:GetCapabilities*/ );
requestElement.appendChild( getCapabilitiesElement );
QDomElement dcpTypeElement = doc.createElement( QStringLiteral( "DCPType" )/*wcs:DCPType*/ );
getCapabilitiesElement.appendChild( dcpTypeElement );
QDomElement httpElement = doc.createElement( QStringLiteral( "HTTP" )/*wcs:HTTP*/ );
dcpTypeElement.appendChild( httpElement );
//Prepare url
QString hrefString = QgsServerProjectUtils::wcsServiceUrl( *mProject );
if ( hrefString.isEmpty() )
{
hrefString = QgsServerProjectUtils::wmsServiceUrl( *mProject );
}
if ( hrefString.isEmpty() )
{
hrefString = serviceUrl();
}
QDomElement getElement = doc.createElement( QStringLiteral( "Get" )/*wcs:Get*/ );
httpElement.appendChild( getElement );
QDomElement onlineResourceElement = doc.createElement( QStringLiteral( "OnlineResource" )/*wcs:OnlineResource*/ );
onlineResourceElement.setAttribute( QStringLiteral( "xlink:type" ), QStringLiteral( "simple" ) );
onlineResourceElement.setAttribute( QStringLiteral( "xlink:href" ), hrefString );
getElement.appendChild( onlineResourceElement );
QDomElement getCapabilitiesDhcTypePostElement = dcpTypeElement.cloneNode().toElement();//this is the same as for 'GetCapabilities'
getCapabilitiesDhcTypePostElement.firstChild().firstChild().toElement().setTagName( QStringLiteral( "Post" ) );
getCapabilitiesElement.appendChild( getCapabilitiesDhcTypePostElement );
QDomElement describeCoverageElement = getCapabilitiesElement.cloneNode().toElement();//this is the same as 'GetCapabilities'
describeCoverageElement.setTagName( QStringLiteral( "DescribeCoverage" ) );
requestElement.appendChild( describeCoverageElement );
QDomElement getCoverageElement = getCapabilitiesElement.cloneNode().toElement();//this is the same as 'GetCapabilities'
getCoverageElement.setTagName( QStringLiteral( "GetCoverage" ) );
requestElement.appendChild( getCoverageElement );
/*
* Adding layer list in ContentMetadata
*/
QDomElement contentMetadataElement = doc.createElement( QStringLiteral( "ContentMetadata" )/*wcs:ContentMetadata*/ );
wcsCapabilitiesElement.appendChild( contentMetadataElement );
/*
* Adding layer list in contentMetadataElement
*/
if ( mConfigParser )
{
mConfigParser->wcsContentMetadata( contentMetadataElement, doc );
}
return doc;
}
QDomDocument QgsWCSServer::describeCoverage()
{
QgsDebugMsg( "Entering." );
QDomDocument doc;
//wcs:WCS_Capabilities element
QDomElement coveDescElement = doc.createElement( QStringLiteral( "CoverageDescription" )/*wcs:CoverageDescription*/ );
coveDescElement.setAttribute( QStringLiteral( "xmlns" ), WCS_NAMESPACE );
coveDescElement.setAttribute( QStringLiteral( "xmlns:xsi" ), QStringLiteral( "http://www.w3.org/2001/XMLSchema-instance" ) );
coveDescElement.setAttribute( QStringLiteral( "xsi:schemaLocation" ), WCS_NAMESPACE + " http://schemas.opengis.net/wcs/1.0.0/describeCoverage.xsd" );
coveDescElement.setAttribute( QStringLiteral( "xmlns:gml" ), GML_NAMESPACE );
coveDescElement.setAttribute( QStringLiteral( "xmlns:xlink" ), QStringLiteral( "http://www.w3.org/1999/xlink" ) );
coveDescElement.setAttribute( QStringLiteral( "version" ), QStringLiteral( "1.0.0" ) );
coveDescElement.setAttribute( QStringLiteral( "updateSequence" ), QStringLiteral( "0" ) );
doc.appendChild( coveDescElement );
//defining coverage name
QString coveName = QLatin1String( "" );
//read COVERAGE
QMap<QString, QString>::const_iterator cove_name_it = mParameters.constFind( QStringLiteral( "COVERAGE" ) );
if ( cove_name_it != mParameters.constEnd() )
{
coveName = cove_name_it.value();
}
if ( coveName == QLatin1String( "" ) )
{
QMap<QString, QString>::const_iterator cove_name_it = mParameters.constFind( QStringLiteral( "IDENTIFIER" ) );
if ( cove_name_it != mParameters.constEnd() )
{
coveName = cove_name_it.value();
}
}
mConfigParser->describeCoverage( coveName, coveDescElement, doc );
return doc;
}
QByteArray* QgsWCSServer::getCoverage()
{
QStringList wcsLayersId = mConfigParser->wcsLayers();
QList<QgsMapLayer*> layerList;
QStringList mErrors = QStringList();
//defining coverage name
QString coveName = QLatin1String( "" );
//read COVERAGE
QMap<QString, QString>::const_iterator cove_name_it = mParameters.constFind( QStringLiteral( "COVERAGE" ) );
if ( cove_name_it != mParameters.constEnd() )
{
coveName = cove_name_it.value();
}
if ( coveName == QLatin1String( "" ) )
{
QMap<QString, QString>::const_iterator cove_name_it = mParameters.constFind( QStringLiteral( "IDENTIFIER" ) );
if ( cove_name_it != mParameters.constEnd() )
{
coveName = cove_name_it.value();
}
}
if ( coveName == QLatin1String( "" ) )
{
mErrors << QStringLiteral( "COVERAGE is mandatory" );
}
layerList = mConfigParser->mapLayerFromCoverage( coveName );
if ( layerList.size() < 1 )
{
mErrors << QStringLiteral( "The layer for the COVERAGE '%1' is not found" ).arg( coveName );
}
bool conversionSuccess;
// BBOX
bool bboxOk = false;
double minx = 0.0, miny = 0.0, maxx = 0.0, maxy = 0.0;
// WIDTh and HEIGHT
int width = 0, height = 0;
// CRS
QString crs = QLatin1String( "" );
// read BBOX
QMap<QString, QString>::const_iterator bbIt = mParameters.constFind( QStringLiteral( "BBOX" ) );
if ( bbIt == mParameters.constEnd() )
{
minx = 0;
miny = 0;
maxx = 0;
maxy = 0;
}
else
{
bboxOk = true;
QString bbString = bbIt.value();
minx = bbString.section( QStringLiteral( "," ), 0, 0 ).toDouble( &conversionSuccess );
if ( !conversionSuccess ) {bboxOk = false;}
miny = bbString.section( QStringLiteral( "," ), 1, 1 ).toDouble( &conversionSuccess );
if ( !conversionSuccess ) {bboxOk = false;}
maxx = bbString.section( QStringLiteral( "," ), 2, 2 ).toDouble( &conversionSuccess );
if ( !conversionSuccess ) {bboxOk = false;}
maxy = bbString.section( QStringLiteral( "," ), 3, 3 ).toDouble( &conversionSuccess );
if ( !conversionSuccess ) {bboxOk = false;}
}
if ( !bboxOk )
{
mErrors << QStringLiteral( "The BBOX is mandatory and has to be xx.xxx,yy.yyy,xx.xxx,yy.yyy" );
}
// read WIDTH
width = mParameters.value( QStringLiteral( "WIDTH" ), QStringLiteral( "0" ) ).toInt( &conversionSuccess );
if ( !conversionSuccess )
width = 0;
// read HEIGHT
height = mParameters.value( QStringLiteral( "HEIGHT" ), QStringLiteral( "0" ) ).toInt( &conversionSuccess );
if ( !conversionSuccess )
{
height = 0;
}
if ( width < 0 || height < 0 )
{
mErrors << QStringLiteral( "The WIDTH and HEIGHT are mandatory and have to be integer" );
}
crs = mParameters.value( QStringLiteral( "CRS" ), QLatin1String( "" ) );
if ( crs == QLatin1String( "" ) )
{
mErrors << QStringLiteral( "The CRS is mandatory" );
}
if ( mErrors.count() != 0 )
{
throw QgsMapServiceException( QStringLiteral( "RequestNotWellFormed" ), mErrors.join( QStringLiteral( ". " ) ) );
}
QgsCoordinateReferenceSystem requestCRS = QgsCoordinateReferenceSystem::fromOgcWmsCrs( crs );
if ( !requestCRS.isValid() )
{
mErrors << QStringLiteral( "Could not create request CRS" );
throw QgsMapServiceException( QStringLiteral( "RequestNotWellFormed" ), mErrors.join( QStringLiteral( ". " ) ) );
}
QgsRectangle rect( minx, miny, maxx, maxy );
QgsMapLayer* layer = layerList.at( 0 );
QgsRasterLayer* rLayer = qobject_cast<QgsRasterLayer*>( layer );
if ( rLayer && wcsLayersId.contains( rLayer->id() ) )
{
#ifdef HAVE_SERVER_PYTHON_PLUGINS
if ( !mAccessControl->layerReadPermission( rLayer ) )
{
throw QgsMapServiceException( QStringLiteral( "Security" ), QStringLiteral( "You are not allowed to access to this coverage" ) );
}
#endif
// RESPONSE_CRS
QgsCoordinateReferenceSystem responseCRS = rLayer->crs();
crs = mParameters.value( QStringLiteral( "RESPONSE_CRS" ), QLatin1String( "" ) );
if ( crs != QLatin1String( "" ) )
{
responseCRS = QgsCoordinateReferenceSystem::fromOgcWmsCrs( crs );
if ( !responseCRS.isValid() )
{
responseCRS = rLayer->crs();
}
}
// transform rect
if ( requestCRS != rLayer->crs() )
{
QgsCoordinateTransform t( requestCRS, rLayer->crs() );
rect = t.transformBoundingBox( rect );
}
QTemporaryFile tempFile;
tempFile.open();
QgsRasterFileWriter fileWriter( tempFile.fileName() );
// clone pipe/provider
QgsRasterPipe* pipe = new QgsRasterPipe();
if ( !pipe->set( rLayer->dataProvider()->clone() ) )
{
mErrors << QStringLiteral( "Cannot set pipe provider" );
throw QgsMapServiceException( QStringLiteral( "RequestNotWellFormed" ), mErrors.join( QStringLiteral( ". " ) ) );
}
// add projector if necessary
if ( responseCRS != rLayer->crs() )
{
QgsRasterProjector * projector = new QgsRasterProjector;
projector->setCrs( rLayer->crs(), responseCRS );
if ( !pipe->insert( 2, projector ) )
{
mErrors << QStringLiteral( "Cannot set pipe projector" );
throw QgsMapServiceException( QStringLiteral( "RequestNotWellFormed" ), mErrors.join( QStringLiteral( ". " ) ) );
}
}
QgsRasterFileWriter::WriterError err = fileWriter.writeRaster( pipe, width, height, rect, responseCRS );
if ( err != QgsRasterFileWriter::NoError )
{
mErrors << QStringLiteral( "Cannot write raster error code: %1" ).arg( err );
throw QgsMapServiceException( QStringLiteral( "RequestNotWellFormed" ), mErrors.join( QStringLiteral( ". " ) ) );
}
delete pipe;
QByteArray* ba = nullptr;
ba = new QByteArray();
*ba = tempFile.readAll();
return ba;
}
return nullptr;
}
QString QgsWCSServer::serviceUrl() const
{
QUrl mapUrl( getenv( "REQUEST_URI" ) );
mapUrl.setHost( getenv( "SERVER_NAME" ) );
//Add non-default ports to url
QString portString = getenv( "SERVER_PORT" );
if ( !portString.isEmpty() )
{
bool portOk;
int portNumber = portString.toInt( &portOk );
if ( portOk )
{
if ( portNumber != 80 )
{
mapUrl.setPort( portNumber );
}
}
}
if ( QString( getenv( "HTTPS" ) ).compare( QLatin1String( "on" ), Qt::CaseInsensitive ) == 0 )
{
mapUrl.setScheme( QStringLiteral( "https" ) );
}
else
{
mapUrl.setScheme( QStringLiteral( "http" ) );
}
QList<QPair<QString, QString> > queryItems = mapUrl.queryItems();
QList<QPair<QString, QString> >::const_iterator queryIt = queryItems.constBegin();
for ( ; queryIt != queryItems.constEnd(); ++queryIt )
{
if ( queryIt->first.compare( QLatin1String( "REQUEST" ), Qt::CaseInsensitive ) == 0 )
{
mapUrl.removeQueryItem( queryIt->first );
}
else if ( queryIt->first.compare( QLatin1String( "VERSION" ), Qt::CaseInsensitive ) == 0 )
{
mapUrl.removeQueryItem( queryIt->first );
}
else if ( queryIt->first.compare( QLatin1String( "SERVICE" ), Qt::CaseInsensitive ) == 0 )
{
mapUrl.removeQueryItem( queryIt->first );
}
else if ( queryIt->first.compare( QLatin1String( "_DC" ), Qt::CaseInsensitive ) == 0 )
{
mapUrl.removeQueryItem( queryIt->first );
}
}
return mapUrl.toString();
}

View File

@ -47,16 +47,6 @@ void QgsWfsProjectParser::serviceCapabilities( QDomElement& parentElement, QDomD
mProjectParser->serviceCapabilities( parentElement, doc, QStringLiteral( "WFS" ) );
}
QString QgsWfsProjectParser::serviceUrl() const
{
return mProjectParser->serviceUrl();
}
QString QgsWfsProjectParser::wfsServiceUrl() const
{
return mProjectParser->wfsServiceUrl();
}
void QgsWfsProjectParser::featureTypeList( QDomElement& parentElement, QDomDocument& doc ) const
{
const QList<QDomElement>& projectLayerElements = mProjectParser->projectLayerElements();

View File

@ -38,8 +38,6 @@ class SERVER_EXPORT QgsWfsProjectParser
QgsWfsProjectParser& operator=( const QgsWfsProjectParser& rh ) = delete;
void serviceCapabilities( QDomElement& parentElement, QDomDocument& doc ) const;
QString serviceUrl() const;
QString wfsServiceUrl() const;
void featureTypeList( QDomElement& parentElement, QDomDocument& doc ) const;
void describeFeatureType( const QString& aTypeName, QDomElement& parentElement, QDomDocument& doc ) const;

2158
src/server/qgswfsserver.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -44,7 +44,7 @@ class SERVER_EXPORT QgsWmsConfigParser
/** Adds layer and style specific capabilities elements to the parent node. This includes the individual layers and styles, their description, native CRS, bounding boxes, etc.
@param fullProjectInformation If true: add extended project information (does not validate against WMS schema)*/
virtual void layersAndStylesCapabilities( QDomElement& parentElement, QDomDocument& doc, const QString& version, bool fullProjectSettings = false ) const = 0;
virtual void layersAndStylesCapabilities( QDomElement& parentElement, QDomDocument& doc, const QString& version, const QString& serviceUrl, bool fullProjectSettings = false ) const = 0;
//! Returns one or possibly several maplayers for a given layer name and style. If no layers/style are found, an empty list is returned
virtual QList<QgsMapLayer*> mapLayerFromStyle( const QString& lName, const QString& styleName, bool useCache = true ) const = 0;
@ -59,7 +59,7 @@ class SERVER_EXPORT QgsWmsConfigParser
virtual QDomDocument getStyles( QStringList& layerList ) const = 0;
//! Returns the xml fragment of layers styles description
virtual QDomDocument describeLayer( QStringList& layerList, const QString& hrefString ) const = 0;
virtual QDomDocument describeLayer( QStringList& layerList, const QString& wfsHrefString, const QString& wcsHrefString ) const = 0;
//! Returns if output are MM or PIXEL
virtual QgsUnitTypes::RenderUnit outputUnits() const = 0;
@ -91,8 +91,6 @@ class SERVER_EXPORT QgsWmsConfigParser
//! Load PAL engine settings into global project instance
virtual void loadLabelSettings() const = 0;
virtual QString serviceUrl() const = 0;
virtual QStringList wfsLayerNames() const = 0;
virtual void owsGeneralAndResourceList( QDomElement& parentElement, QDomDocument& doc, const QString& strHref ) const = 0;
@ -108,8 +106,6 @@ class SERVER_EXPORT QgsWmsConfigParser
virtual QFont legendLayerFont() const = 0;
virtual QFont legendItemFont() const = 0;
virtual double maxWidth() const = 0;
virtual double maxHeight() const = 0;
virtual double imageQuality() const = 0;
// WMS GetFeatureInfo precision (decimal places)

View File

@ -71,7 +71,7 @@ QgsWmsProjectParser::~QgsWmsProjectParser()
delete mProjectParser;
}
void QgsWmsProjectParser::layersAndStylesCapabilities( QDomElement& parentElement, QDomDocument& doc, const QString& version, bool fullProjectSettings ) const
void QgsWmsProjectParser::layersAndStylesCapabilities( QDomElement& parentElement, QDomDocument& doc, const QString& version, const QString& serviceUrl, bool fullProjectSettings ) const
{
QStringList nonIdentifiableLayers = identifyDisabledLayers();
@ -123,7 +123,7 @@ void QgsWmsProjectParser::layersAndStylesCapabilities( QDomElement& parentElemen
QHash<QString, QString> idNameMap;
QStringList layerIDList;
addLayers( doc, layerParentElem, legendElem, projectLayerTreeGroup(), layerMap, nonIdentifiableLayers, version, fullProjectSettings, idNameMap, layerIDList );
addLayers( doc, layerParentElem, legendElem, projectLayerTreeGroup(), layerMap, nonIdentifiableLayers, version, serviceUrl, fullProjectSettings, idNameMap, layerIDList );
parentElement.appendChild( layerParentElem );
mProjectParser->combineExtentAndCrsOfGroupChildren( layerParentElem, doc, true );
@ -320,10 +320,6 @@ void QgsWmsProjectParser::addLayersFromGroup( const QDomElement& legendGroupElem
}
}
QString QgsWmsProjectParser::serviceUrl() const
{
return mProjectParser->serviceUrl();
}
QStringList QgsWmsProjectParser::wfsLayerNames() const
{
@ -382,36 +378,6 @@ QFont QgsWmsProjectParser::legendItemFont() const
return mLegendItemFont;
}
double QgsWmsProjectParser::maxWidth() const
{
double maxWidth = -1;
QDomElement propertiesElem = mProjectParser->propertiesElem();
if ( !propertiesElem.isNull() )
{
QDomElement maxWidthElem = propertiesElem.firstChildElement( QStringLiteral( "WMSMaxWidth" ) );
if ( !maxWidthElem.isNull() )
{
maxWidth = maxWidthElem.text().toInt();
}
}
return maxWidth;
}
double QgsWmsProjectParser::maxHeight() const
{
double maxHeight = -1;
QDomElement propertiesElem = mProjectParser->propertiesElem();
if ( !propertiesElem.isNull() )
{
QDomElement maxWidthElem = propertiesElem.firstChildElement( QStringLiteral( "WMSMaxHeight" ) );
if ( !maxWidthElem.isNull() )
{
maxHeight = maxWidthElem.text().toInt();
}
}
return maxHeight;
}
double QgsWmsProjectParser::imageQuality() const
{
double imageQuality = -1;
@ -1002,7 +968,7 @@ void QgsWmsProjectParser::addDrawingOrder( QDomElement& parentElem, QDomDocument
}
}
void QgsWmsProjectParser::addLayerStyles( QgsMapLayer* currentLayer, QDomDocument& doc, QDomElement& layerElem, const QString& version ) const
void QgsWmsProjectParser::addLayerStyles( QgsMapLayer* currentLayer, QDomDocument& doc, QDomElement& layerElem, const QString& version, const QString& serviceUrl ) const
{
Q_FOREACH ( QString styleName, currentLayer->styleManager()->styles() )
{
@ -1030,7 +996,7 @@ void QgsWmsProjectParser::addLayerStyles( QgsMapLayer* currentLayer, QDomDocumen
else
{
customHrefString = false;
hrefString = serviceUrl();
hrefString = serviceUrl;
}
if ( hrefString.isEmpty() )
{
@ -1099,6 +1065,7 @@ void QgsWmsProjectParser::addLayers( QDomDocument &doc,
const QMap<QString, QgsMapLayer *> &layerMap,
const QStringList &nonIdentifiableLayers,
const QString& version, //1.1.1 or 1.3.0
const QString& serviceUrl,
bool fullProjectSettings,
QHash<QString, QString> &idNameMap,
QStringList &layerIDList ) const
@ -1219,12 +1186,12 @@ void QgsWmsProjectParser::addLayers( QDomDocument &doc,
pLayerMap.insert( pp->layerId( elem ), pp->createLayerFromElement( elem ) );
}
p->addLayers( doc, layerElem, embeddedGroupElem, embeddedLayerTreeGroup->findGroup( name ), pLayerMap, pIdDisabled, version, fullProjectSettings, idNameMap, layerIDList );
p->addLayers( doc, layerElem, embeddedGroupElem, embeddedLayerTreeGroup->findGroup( name ), pLayerMap, pIdDisabled, version, serviceUrl, fullProjectSettings, idNameMap, layerIDList );
}
}
else //normal (not embedded) legend group
{
addLayers( doc, layerElem, currentChildElem, ltGroup, layerMap, nonIdentifiableLayers, version, fullProjectSettings, idNameMap, layerIDList );
addLayers( doc, layerElem, currentChildElem, ltGroup, layerMap, nonIdentifiableLayers, version, serviceUrl, fullProjectSettings, idNameMap, layerIDList );
}
// combine bounding boxes of children (groups/layers)
@ -1346,7 +1313,7 @@ void QgsWmsProjectParser::addLayers( QDomDocument &doc,
}
// add details about supported styles of the layer
addLayerStyles( currentLayer, doc, layerElem, version );
addLayerStyles( currentLayer, doc, layerElem, version, serviceUrl );
//min/max scale denominatormScaleBasedVisibility
if ( currentLayer->hasScaleBasedVisibility() )
@ -1869,7 +1836,7 @@ QDomDocument QgsWmsProjectParser::getStyles( QStringList& layerList ) const
return myDocument;
}
QDomDocument QgsWmsProjectParser::describeLayer( QStringList& layerList, const QString& hrefString ) const
QDomDocument QgsWmsProjectParser::describeLayer( QStringList& layerList, const QString& wfsHrefString, const QString& wcsHrefString ) const
{
QDomDocument myDocument = QDomDocument();
@ -1890,18 +1857,6 @@ QDomDocument QgsWmsProjectParser::describeLayer( QStringList& layerList, const Q
versionNode.appendChild( myDocument.createTextNode( QStringLiteral( "1.1.0" ) ) );
root.appendChild( versionNode );
//Prepare url
QString wfsHrefString = mProjectParser->wfsServiceUrl();
if ( wfsHrefString.isEmpty() )
{
wfsHrefString = hrefString;
}
QString wcsHrefString = mProjectParser->wcsServiceUrl();
if ( wcsHrefString.isEmpty() )
{
wcsHrefString = hrefString;
}
//WFS layers
QStringList wfsLayers = wfsLayerNames();
//WCS layers

View File

@ -40,12 +40,10 @@ class SERVER_EXPORT QgsWmsProjectParser : public QgsWmsConfigParser
/** Adds layer and style specific capabilities elements to the parent node. This includes the individual layers and styles, their description, native CRS, bounding boxes, etc.
@param fullProjectInformation If true: add extended project information (does not validate against WMS schema)*/
void layersAndStylesCapabilities( QDomElement& parentElement, QDomDocument& doc, const QString& version, bool fullProjectSettings = false ) const override;
void layersAndStylesCapabilities( QDomElement& parentElement, QDomDocument& doc, const QString& version, const QString& serviceUrl, bool fullProjectSettings = false ) const override;
QList<QgsMapLayer*> mapLayerFromStyle( const QString& lName, const QString& styleName, bool useCache = true ) const override;
QString serviceUrl() const override;
QStringList wfsLayerNames() const override;
void owsGeneralAndResourceList( QDomElement& parentElement, QDomDocument& doc, const QString& strHref ) const override;
@ -61,8 +59,6 @@ class SERVER_EXPORT QgsWmsProjectParser : public QgsWmsConfigParser
QFont legendLayerFont() const override;
QFont legendItemFont() const override;
double maxWidth() const override;
double maxHeight() const override;
double imageQuality() const override;
int wmsPrecision() const override;
@ -90,7 +86,7 @@ class SERVER_EXPORT QgsWmsProjectParser : public QgsWmsConfigParser
QDomDocument getStyles( QStringList& layerList ) const override;
//! Returns the xml fragment of layers styles description
QDomDocument describeLayer( QStringList& layerList, const QString& hrefString ) const override;
QDomDocument describeLayer( QStringList& layerList, const QString& wfsHrefString, const QString& wcsHrefString ) const override;
//! Returns if output are MM or PIXEL
QgsUnitTypes::RenderUnit outputUnits() const override;
@ -145,7 +141,7 @@ class SERVER_EXPORT QgsWmsProjectParser : public QgsWmsConfigParser
//! Reads layer drawing order from the legend section of the project file and appends it to the parent elemen (usually the <Capability> element)
void addDrawingOrder( QDomElement& parentElem, QDomDocument& doc, const QHash<QString, QString> &idNameMap, const QStringList &layerIDList ) const;
void addLayerStyles( QgsMapLayer* currentLayer, QDomDocument& doc, QDomElement& layerElem, const QString& version ) const;
void addLayerStyles( QgsMapLayer* currentLayer, QDomDocument& doc, QDomElement& layerElem, const QString& version, const QString& serviceUrl ) const;
void addLayers( QDomDocument &doc,
QDomElement &parentLayer,
@ -154,6 +150,7 @@ class SERVER_EXPORT QgsWmsProjectParser : public QgsWmsConfigParser
const QMap<QString, QgsMapLayer *> &layerMap,
const QStringList &nonIdentifiableLayers,
const QString &version, //1.1.1 or 1.3.0
const QString& serviceUrl,
bool fullProjectSettings,
QHash<QString, QString> &idNameMap,
QStringList &layerIDList ) const;

3554
src/server/qgswmsserver.cpp Normal file

File diff suppressed because it is too large Load Diff

300
src/server/qgswmsserver.h Normal file
View File

@ -0,0 +1,300 @@
/***************************************************************************
qgswmsserver.h
-------------------
begin : May 14, 2006
copyright : (C) 2006 by Marco Hugentobler
email : marco dot hugentobler at karto dot baug dot ethz dot ch
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#ifndef QGSWMSSERVER_H
#define QGSWMSSERVER_H
#include "qgsowsserver.h"
#include "qgswmsconfigparser.h"
#include <QDomDocument>
#include <QMap>
#include <QPair>
#include <QString>
#include <map>
class QgsCapabilitiesCache;
class QgsCoordinateReferenceSystem;
class QgsComposition;
class QgsConfigParser;
class QgsFeature;
class QgsFeatureRenderer;
class QgsMapLayer;
class QgsMapSettings;
class QgsPoint;
class QgsRasterLayer;
class QgsRasterRenderer;
class QgsRectangle;
class QgsRenderContext;
class QgsVectorLayer;
class QgsSymbol;
class QgsSymbol;
class QgsAccessControl;
class QColor;
class QFile;
class QFont;
class QImage;
class QPaintDevice;
class QPainter;
class QStandardItem;
/** This class handles all the wms server requests. The parameters and values have to be passed in the form of
a map<QString, QString>. This map is usually generated by a subclass of QgsWMSRequestHandler, which makes QgsWMSServer
independent from any server side technology*/
class QgsWmsServer: public QgsOWSServer
{
public:
/** Constructor. Does _NOT_ take ownership of
QgsConfigParser and QgsCapabilitiesCache*/
QgsWmsServer(
const QString& configFilePath
, QMap<QString, QString> &parameters
, QgsWmsConfigParser* cp
, QgsRequestHandler* rh
, QgsCapabilitiesCache* capCache
, const QgsProject* project
#ifdef HAVE_SERVER_PYTHON_PLUGINS
, const QgsAccessControl* accessControl
#endif
);
void executeRequest() override;
/** Returns an XML file with the capabilities description (as described in the WMS specs)
@param version WMS version (1.1.1 or 1.3.0)
@param fullProjectInformation If true: add extended project information (does not validate against WMS schema)*/
QDomDocument getCapabilities( const QString &version = "1.3.0", bool fullProjectInformation = false );
QDomDocument getContext();
/** Returns the map legend as an image (or a null pointer in case of error). The caller takes ownership
of the image object*/
QImage* getLegendGraphics();
typedef QSet<QgsSymbol*> SymbolSet;
typedef QHash<QgsVectorLayer*, SymbolSet> HitTest;
/** Returns the map as an image (or a null pointer in case of error). The caller takes ownership
of the image object). If an instance to existing hit test structure is passed, instead of rendering
it will fill the structure with symbols that would be used for rendering */
QImage* getMap( HitTest* hitTest = nullptr );
/** Identical to getMap( HitTest* hitTest ) and updates the map settings actually used.
@note added in QGIS 3.0 */
QImage* getMap( QgsMapSettings &mapSettings, HitTest* hitTest = nullptr );
//! GetMap request with vector format output. This output is usually symbolized (difference to WFS GetFeature)
void getMapAsDxf();
//! Returns an SLD file with the style of the requested layer. Exception is raised in case of troubles :-)
QDomDocument getStyle();
//! Returns an SLD file with the styles of the requested layers. Exception is raised in case of troubles :-)
QDomDocument getStyles();
//! Returns a describeLayer file with the onlineResource of the requested layers. Exception is raised in case of troubles :-)
QDomDocument describeLayer();
/** Returns printed page as binary
@param formatString out: format of the print output (e.g. pdf, svg, png, ...)
@return printed page as binary or 0 in case of error*/
QByteArray* getPrint( const QString& formatString );
/** Creates an xml document that describes the result of the getFeatureInfo request.
* May throw an exception
*/
QDomDocument getFeatureInfo( const QString& version = "1.3.0" );
//! Sets configuration parser for administration settings. Does not take ownership
void setAdminConfigParser( QgsWmsConfigParser* parser ) { mConfigParser = parser; }
//! Returns the schemaExtension for WMS 1.3.0 capabilities
QDomDocument getSchemaExtension();
private:
/** Initializes WMS layers and configures rendering.
* @param layersList out: list with WMS layer names
* @param stylesList out: list with WMS style names
* @param layerIdList out: list with QGIS layer ids
* @return image configured. The calling function takes ownership of the image
* may throw an exception
*/
QImage* initializeRendering( QStringList& layersList, QStringList& stylesList, QStringList& layerIdList, QgsMapSettings& mapSettings );
/** Creates a QImage from the HEIGHT and WIDTH parameters
* @param width image width (or -1 if width should be taken from WIDTH wms parameter)
* @param height image height (or -1 if height should be taken from HEIGHT wms parameter)
* @param useBbox flag to indicate if the BBOX has to be used to adapt aspect ratio
* @return a non null pointer
* may throw an exception
*/
QImage* createImage( int width = -1, int height = -1, bool useBbox = true ) const;
/** Configures mapSettings to the parameters
* HEIGHT, WIDTH, BBOX, CRS.
* @param paintDevice the device that is used for painting (for dpi)
* may throw an exception
*/
void configureMapSettings( const QPaintDevice* paintDevice, QgsMapSettings& mapSettings ) const;
/** Reads the layers and style lists from the parameters LAYERS and STYLES
* may throw an exception
*/
void readLayersAndStyles( QStringList& layersList, QStringList& stylesList ) const;
/**
* If the parameter SLD exists, mSLDParser is configured appropriately. The lists are
* set to the layer and style names according to the SLD
* may throw an exception
*/
void initializeSLDParser( QStringList& layersList, QStringList& stylesList );
/** Appends feature info xml for the layer to the layer element of the feature info dom document
@param featureBBox the bounding box of the selected features in output CRS
@return true in case of success*/
bool featureInfoFromVectorLayer( QgsVectorLayer* layer,
const QgsPoint* infoPoint,
int nFeatures,
QDomDocument& infoDocument,
QDomElement& layerElement,
const QgsMapSettings& mapSettings,
QgsRenderContext& renderContext,
const QString& version,
const QString& infoFormat,
QgsRectangle* featureBBox = nullptr ) const;
//! Appends feature info xml for the layer to the layer element of the dom document
bool featureInfoFromRasterLayer( QgsRasterLayer* layer,
const QgsMapSettings& mapSettings,
const QgsPoint* infoPoint,
QDomDocument& infoDocument,
QDomElement& layerElement,
const QString& version,
const QString& infoFormat ) const;
/** Creates a layer set and returns a stringlist with layer ids that can be passed to a renderer. Usually used in conjunction with readLayersAndStyles
@param scaleDenominator Filter out layer if scale based visibility does not match (or use -1 if no scale restriction)*/
QStringList layerSet( const QStringList& layersList, const QStringList& stylesList, const QgsCoordinateReferenceSystem& destCRS, double scaleDenominator = -1 ) const;
//! Record which symbols would be used if the map was in the current configuration of renderer. This is useful for content-based legend
void runHitTest( const QgsMapSettings& mapSettings, QPainter* painter, HitTest& hitTest );
//! Record which symbols within one layer would be rendered with the given renderer context
void runHitTestLayer( QgsVectorLayer* vl, SymbolSet& usedSymbols, QgsRenderContext& context );
//! Read legend parameter from the request or from the first print composer in the project
void legendParameters( double& boxSpace, double& layerSpace, double& layerTitleSpace,
double& symbolSpace, double& iconLabelSpace, double& symbolWidth, double& symbolHeight, QFont& layerFont, QFont& itemFont, QColor& layerFontColor, QColor& itemFontColor );
/** Apply filter (subset) strings from the request to the layers. Example: '&FILTER=<layer1>:"AND property > 100",<layer2>:"AND bla = 'hallo!'" '
* @param layerList list of layer IDs to filter
* @param originalFilters hash of layer ID to original filter string
* @note It is strongly recommended that this method be called alongside use of QgsOWSServerFilterRestorer
* to ensure that the original filters are always correctly restored, regardless of whether exceptions
* are thrown or functions are terminated early.
*/
void applyRequestedLayerFilters( const QStringList& layerList, QgsMapSettings& mapSettings, QHash<QgsMapLayer*, QString>& originalFilters ) const;
#ifdef HAVE_SERVER_PYTHON_PLUGINS
/** Apply filter strings from the access control to the layers.
* @param layerList layers to filter
* @param originalLayerFilters the original layers filter dictionary
*/
void applyAccessControlLayersFilters( const QStringList& layerList, QHash<QgsMapLayer*, QString>& originalLayerFilters ) const;
#endif
/** Tests if a filter sql string is allowed (safe)
@return true in case of success, false if string seems unsafe*/
bool testFilterStringSafety( const QString& filter ) const;
//! Helper function for filter safety test. Groups stringlist to merge entries starting/ending with quotes
static void groupStringList( QStringList& list, const QString& groupString );
/** Select vector features with ids specified in parameter SELECTED, e.g. ...&SELECTED=layer1:1,2,9;layer2:3,5,10&...
@return list with layer ids where selections have been created*/
QStringList applyFeatureSelections( const QStringList& layerList ) const;
//! Clear all feature selections in the given layers
void clearFeatureSelections( const QStringList& layerIds ) const;
//! Applies opacity on layer/group level
void applyOpacities( const QStringList& layerList, QList< QPair< QgsVectorLayer*, QgsFeatureRenderer*> >& vectorRenderers,
QList< QPair< QgsRasterLayer*, QgsRasterRenderer* > >& rasterRenderers,
QList< QPair< QgsVectorLayer*, double > >& labelTransparencies,
QList< QPair< QgsVectorLayer*, double > >& labelBufferTransparencies
);
//! Restore original opacities
void restoreOpacities( QList< QPair <QgsVectorLayer*, QgsFeatureRenderer*> >& vectorRenderers,
QList< QPair < QgsRasterLayer*, QgsRasterRenderer* > >& rasterRenderers,
QList< QPair< QgsVectorLayer*, double > >& labelTransparencies,
QList< QPair< QgsVectorLayer*, double > >& labelBufferTransparencies );
void appendFormats( QDomDocument &doc, QDomElement &elem, const QStringList &formats );
/** Checks WIDTH/HEIGHT values agains MaxWidth and MaxHeight
@return true if width/height values are okay*/
bool checkMaximumWidthHeight() const;
//! Get service address from REQUEST_URI if not specified in the configuration
QString serviceUrl() const;
//! Add '<?xml version="1.0" ?>'. Some clients need an xml declaration (though it is not strictly required)
void addXmlDeclaration( QDomDocument& doc ) const;
//! Converts a feature info xml document to SIA2045 norm
void convertFeatureInfoToSIA2045( QDomDocument& doc );
//! Cleanup temporary objects (e.g. SLD parser objects or temporary files) after request
void cleanupAfterRequest();
//! Map containing the WMS parameters
QgsCapabilitiesCache* mCapabilitiesCache;
QgsWmsConfigParser* mConfigParser;
bool mOwnsConfigParser; //delete config parser after request (e.g. sent SLD)
// speficy if layer or rule item labels should be drawn in the legend graphic with GetLegendGraphics
bool mDrawLegendLayerLabel;
bool mDrawLegendItemLabel;
QDomElement createFeatureGML(
QgsFeature* feat,
QgsVectorLayer* layer,
QDomDocument& doc,
QgsCoordinateReferenceSystem& crs,
const QgsMapSettings& mapSettings,
const QString& typeName,
bool withGeom,
int version,
QStringList* attributes = nullptr ) const;
//! Replaces attribute value with ValueRelation or ValueRelation if defined. Otherwise returns the original value
static QString replaceValueMapAndRelation( QgsVectorLayer* vl, int idx, const QString& attributeVal );
//! Return the image quality to use for getMap request
int getImageQuality() const;
//! Return precision to use for GetFeatureInfo request
int getWMSPrecision( int defaultValue ) const;
//! Gets layer search rectangle (depending on request parameter, layer type, map and layer crs)
QgsRectangle featureInfoSearchRect( QgsVectorLayer* ml, const QgsMapSettings& ms, const QgsRenderContext& rct, const QgsPoint& infoPoint ) const;
//! Reads and extracts the different options in the FORMAT_OPTIONS parameter
void readFormatOptions( QMap<QString, QString>& formatOptions ) const;
void readDxfLayerSettings( QList< QPair<QgsVectorLayer *, int > >& layers, const QMap<QString, QString>& formatOptionsMap ) const;
};
#endif

View File

@ -32,7 +32,7 @@ class SampleService: public QgsService
}
void executeRequest( const QgsServerRequest& request, QgsServerResponse& response,
QgsProject* project )
const QgsProject* project )
{
Q_UNUSED( project );
Q_UNUSED( request );

View File

@ -46,7 +46,7 @@ namespace QgsWcs
}
void executeRequest( const QgsServerRequest& request, QgsServerResponse& response,
QgsProject* project )
const QgsProject* project )
{
Q_UNUSED( project );
@ -69,7 +69,7 @@ namespace QgsWcs
if ( QSTR_COMPARE( req, "GetCapabilities" ) )
{
writeGetCapabilities( mServerIface, versionString, request, response );
writeGetCapabilities( mServerIface, project, versionString, request, response );
}
else if ( QSTR_COMPARE( req, "DescribeCoverage" ) )
{

View File

@ -25,17 +25,17 @@ namespace QgsWcs
/**
* Output WCS GetCapabilities response
*/
void writeGetCapabilities( QgsServerInterface* serverIface, const QString& version,
void writeGetCapabilities( QgsServerInterface* serverIface, const QgsProject* project, const QString& version,
const QgsServerRequest& request, QgsServerResponse& response )
{
QDomDocument doc = createGetCapabilitiesDocument( serverIface, version, request );
QDomDocument doc = createGetCapabilitiesDocument( serverIface, project, version, request );
response.setHeader( "Content-Type", "text/xml; charset=utf-8" );
response.write( doc.toByteArray() );
}
QDomDocument createGetCapabilitiesDocument( QgsServerInterface* serverIface, const QString& version,
QDomDocument createGetCapabilitiesDocument( QgsServerInterface* serverIface, const QgsProject* project, const QString& version,
const QgsServerRequest& request )
{
Q_UNUSED( version );
@ -77,7 +77,7 @@ namespace QgsWcs
dcpTypeElement.appendChild( httpElement );
//Prepare url
QString hrefString = serviceUrl( request, configParser );
QString hrefString = serviceUrl( request, project );
QDomElement getElement = doc.createElement( QStringLiteral( "Get" )/*wcs:Get*/ );
httpElement.appendChild( getElement );

View File

@ -27,13 +27,16 @@ namespace QgsWcs
/**
* Create get capabilities document
*/
QDomDocument createGetCapabilitiesDocument( QgsServerInterface* serverIface, const QString& version,
const QgsServerRequest& request );
QDomDocument createGetCapabilitiesDocument( QgsServerInterface* serverIface,
const QgsProject* project,
const QString& version,
const QgsServerRequest& request );
/** Output WCS GetCapabilities response
*/
void writeGetCapabilities( QgsServerInterface* serverIface, const QString& version,
const QgsServerRequest& request, QgsServerResponse& response );
void writeGetCapabilities( QgsServerInterface* serverIface, const QgsProject* project,
const QString& version, const QgsServerRequest& request,
QgsServerResponse& response );
} // samespace QgsWcs

View File

@ -17,6 +17,7 @@
#include "qgswcsutils.h"
#include "qgsconfigcache.h"
#include "qgsserverprojectutils.h"
namespace QgsWcs
{
@ -40,16 +41,12 @@ namespace QgsWcs
return parser;
}
QString serviceUrl( const QgsServerRequest& request, QgsWCSProjectParser* parser )
QString serviceUrl( const QgsServerRequest& request, const QgsProject* project )
{
QString href;
if ( parser )
if ( project )
{
href = parser->wcsServiceUrl();
if ( href.isEmpty() )
{
href = parser->serviceUrl();
}
href = QgsServerProjectUtils::wcsServiceUrl( *project );
}
// Build default url

View File

@ -50,7 +50,7 @@ namespace QgsWcs
/**
* Service URL string
*/
QString serviceUrl( const QgsServerRequest& request, QgsWCSProjectParser* parser = nullptr );
QString serviceUrl( const QgsServerRequest& request, const QgsProject* project );
/**
* Parse bounding box

View File

@ -49,10 +49,8 @@ namespace QgsWfs
}
void executeRequest( const QgsServerRequest& request, QgsServerResponse& response,
QgsProject* project )
const QgsProject* project )
{
Q_UNUSED( project );
QgsServerRequest::Parameters params = request.parameters();
QString versionString = params.value( "VERSION" );
@ -72,11 +70,11 @@ namespace QgsWfs
if ( QSTR_COMPARE( req, "GetCapabilities" ) )
{
writeGetCapabilities( mServerIface, versionString, request, response );
writeGetCapabilities( mServerIface, project, versionString, request, response );
}
else if ( QSTR_COMPARE( req, "GetFeature" ) )
{
writeGetFeature( mServerIface, versionString, request, response );
writeGetFeature( mServerIface, project, versionString, request, response );
}
else if ( QSTR_COMPARE( req, "DescribeFeatureType" ) )
{

View File

@ -27,17 +27,17 @@ namespace QgsWfs
/**
* Output WFS GetCapabilities response
*/
void writeGetCapabilities( QgsServerInterface* serverIface, const QString& version,
void writeGetCapabilities( QgsServerInterface* serverIface, const QgsProject* project, const QString& version,
const QgsServerRequest& request, QgsServerResponse& response )
{
QDomDocument doc = createGetCapabilitiesDocument( serverIface, version, request );
QDomDocument doc = createGetCapabilitiesDocument( serverIface, project, version, request );
response.setHeader( "Content-Type", "text/xml; charset=utf-8" );
response.write( doc.toByteArray() );
}
QDomDocument createGetCapabilitiesDocument( QgsServerInterface* serverIface, const QString& version,
QDomDocument createGetCapabilitiesDocument( QgsServerInterface* serverIface, const QgsProject* project, const QString& version,
const QgsServerRequest& request )
{
Q_UNUSED( version );
@ -78,7 +78,7 @@ namespace QgsWfs
dcpTypeElement.appendChild( httpElement );
//Prepare url
QString hrefString = serviceUrl( request, configParser );
QString hrefString = serviceUrl( request, project );
//only Get supported for the moment
QDomElement getElement = doc.createElement( QStringLiteral( "Get" )/*wfs:Get*/ );

View File

@ -29,14 +29,17 @@ namespace QgsWfs
/**
* Create get capabilities document
*/
QDomDocument createGetCapabilitiesDocument( QgsServerInterface* serverIface, const QString& version,
const QgsServerRequest& request );
QDomDocument createGetCapabilitiesDocument( QgsServerInterface* serverIface,
const QgsProject* project,
const QString& version,
const QgsServerRequest& request );
/**
* Output WFS GetCapabilities response
*/
void writeGetCapabilities( QgsServerInterface* serverIface, const QString& version,
const QgsServerRequest& request, QgsServerResponse& response );
void writeGetCapabilities( QgsServerInterface* serverIface, const QgsProject* project,
const QString& version, const QgsServerRequest& request,
QgsServerResponse& response );
} // samespace QgsWfs

View File

@ -54,7 +54,7 @@ namespace QgsWfs
const QgsAttributeList& attrIndexes, const QSet<QString>& excludedAttributes, const QString& typeName,
bool withGeom, const QString geometryName );
void startGetFeature( const QgsServerRequest& request, QgsServerResponse& response, QgsWfsProjectParser* configParser, const QString& format,
void startGetFeature( const QgsServerRequest& request, QgsServerResponse& response, const QgsProject* project, const QString& format,
int prec, QgsCoordinateReferenceSystem& crs, QgsRectangle* rect, const QStringList& typeNames );
void setGetFeature( QgsServerResponse& response, const QString& format, QgsFeature* feat, int featIdx, int prec,
@ -67,8 +67,9 @@ namespace QgsWfs
/** Output WFS GetCapabilities response
*/
void writeGetFeature( QgsServerInterface* serverIface, const QString& version,
const QgsServerRequest& request, QgsServerResponse& response )
void writeGetFeature( QgsServerInterface* serverIface, const QgsProject* project,
const QString& version, const QgsServerRequest& request,
QgsServerResponse& response )
{
Q_UNUSED( version );
@ -284,7 +285,7 @@ namespace QgsWfs
).nextFeature( feature );
if ( featureCounter == 0 )
startGetFeature( request, response, configParser, format, layerPrec, layerCrs, &searchRect, typeNames );
startGetFeature( request, response, project, format, layerPrec, layerCrs, &searchRect, typeNames );
setGetFeature( response, format, &feature, featCounter, layerPrec, layerCrs, attrIndexes, layerExcludedAttributes,
typeName, withGeom, geometryName );
@ -321,7 +322,7 @@ namespace QgsWfs
while ( fit.nextFeature( feature ) && ( !hasFeatureLimit || featureCounter < maxFeatures + startIndex ) )
{
if ( featureCounter == startIndex )
startGetFeature( request, response, configParser, format, layerPrec, layerCrs, &searchRect, typeNames );
startGetFeature( request, response, project, format, layerPrec, layerCrs, &searchRect, typeNames );
if ( featureCounter >= startIndex )
{
@ -378,7 +379,7 @@ namespace QgsWfs
if ( res.toInt() != 0 )
{
if ( featureCounter == startIndex )
startGetFeature( request, response, configParser, format, layerPrec, layerCrs, &searchRect, typeNames );
startGetFeature( request, response, project, format, layerPrec, layerCrs, &searchRect, typeNames );
if ( featureCounter >= startIndex )
{
@ -397,7 +398,7 @@ namespace QgsWfs
while ( fit.nextFeature( feature ) && ( !hasFeatureLimit || featureCounter < maxFeatures + startIndex ) )
{
if ( featureCounter == startIndex )
startGetFeature( request, response, configParser, format, layerPrec, layerCrs, &searchRect, typeNames );
startGetFeature( request, response, project, format, layerPrec, layerCrs, &searchRect, typeNames );
if ( featureCounter >= startIndex )
{
@ -423,7 +424,7 @@ namespace QgsWfs
QgsProject::instance()->removeAllMapLayers();
if ( featureCounter <= startIndex )
startGetFeature( request, response, configParser, format, layerPrec, layerCrs, &searchRect, typeNames );
startGetFeature( request, response, project, format, layerPrec, layerCrs, &searchRect, typeNames );
endGetFeature( response, format );
return;
}
@ -663,7 +664,7 @@ namespace QgsWfs
).nextFeature( feature );
if ( featureCounter == 0 )
startGetFeature( request, response, configParser, format, layerPrec, layerCrs, &searchRect, typeNames );
startGetFeature( request, response, project, format, layerPrec, layerCrs, &searchRect, typeNames );
setGetFeature( response, format, &feature, featCounter, layerPrec, layerCrs, attrIndexes, layerExcludedAttributes,
typeName, withGeom, geometryName );
@ -711,7 +712,7 @@ namespace QgsWfs
if ( res.toInt() != 0 )
{
if ( featureCounter == startIndex )
startGetFeature( request, response, configParser, format, layerPrec, layerCrs, &searchRect, typeNames );
startGetFeature( request, response, project, format, layerPrec, layerCrs, &searchRect, typeNames );
if ( featureCounter >= startIndex )
{
@ -751,7 +752,7 @@ namespace QgsWfs
).nextFeature( feature );
if ( featureCounter == 0 )
startGetFeature( request, response, configParser, format, layerPrec, layerCrs, &searchRect, typeNames );
startGetFeature( request, response, project, format, layerPrec, layerCrs, &searchRect, typeNames );
setGetFeature( response, format, &feature, featCounter, layerPrec, layerCrs, attrIndexes, layerExcludedAttributes,
typeName, withGeom, geometryName );
@ -788,7 +789,7 @@ namespace QgsWfs
while ( fit.nextFeature( feature ) && ( !hasFeatureLimit || featureCounter < maxFeatures + startIndex ) )
{
if ( featureCounter == startIndex )
startGetFeature( request, response, configParser, format, layerPrec, layerCrs, &searchRect, typeNames );
startGetFeature( request, response, project, format, layerPrec, layerCrs, &searchRect, typeNames );
if ( featureCounter >= startIndex )
{
@ -838,7 +839,7 @@ namespace QgsWfs
if ( res.toInt() != 0 )
{
if ( featureCounter == startIndex )
startGetFeature( request, response, configParser, format, layerPrec, layerCrs, &searchRect, typeNames );
startGetFeature( request, response, project, format, layerPrec, layerCrs, &searchRect, typeNames );
if ( featureCounter >= startIndex )
{
@ -878,7 +879,7 @@ namespace QgsWfs
{
errors << QStringLiteral( "The feature %2 of layer for the TypeName '%1'" ).arg( tnStr ).arg( featureCounter );
if ( featureCounter == startIndex )
startGetFeature( request, response, configParser, format, layerPrec, layerCrs, &searchRect, typeNames );
startGetFeature( request, response, project, format, layerPrec, layerCrs, &searchRect, typeNames );
if ( featureCounter >= startIndex )
{
@ -900,7 +901,7 @@ namespace QgsWfs
QgsProject::instance()->removeAllMapLayers();
if ( featureCounter <= startIndex )
startGetFeature( request, response, configParser, format, layerPrec, layerCrs, &searchRect, typeNames );
startGetFeature( request, response, project, format, layerPrec, layerCrs, &searchRect, typeNames );
endGetFeature( response, format );
}
@ -908,7 +909,7 @@ namespace QgsWfs
namespace
{
void startGetFeature( const QgsServerRequest& request, QgsServerResponse& response, QgsWfsProjectParser* configParser, const QString& format,
void startGetFeature( const QgsServerRequest& request, QgsServerResponse& response, const QgsProject* project, const QString& format,
int prec, QgsCoordinateReferenceSystem& crs, QgsRectangle* rect, const QStringList& typeNames )
{
QString fcString;
@ -948,7 +949,7 @@ namespace QgsWfs
response.setHeader( "Content-Type", "text/xml; charset=utf-8" );
//Prepare url
QString hrefString = serviceUrl( request, configParser );
QString hrefString = serviceUrl( request, project );
QUrl mapUrl( hrefString );

View File

@ -27,8 +27,9 @@ namespace QgsWfs
/** Output WFS GetFeature response
*/
void writeGetFeature( QgsServerInterface* serverIface, const QString& version,
const QgsServerRequest& request, QgsServerResponse& response );
void writeGetFeature( QgsServerInterface* serverIface, const QgsProject* project,
const QString& version, const QgsServerRequest& request,
QgsServerResponse& response );
} // samespace QgsWfs

View File

@ -21,6 +21,7 @@
#include "qgswfsutils.h"
#include "qgsconfigcache.h"
#include "qgsserverprojectutils.h"
namespace QgsWfs
{
@ -44,16 +45,12 @@ namespace QgsWfs
return parser;
}
QString serviceUrl( const QgsServerRequest& request, QgsWfsProjectParser* parser )
QString serviceUrl( const QgsServerRequest& request, const QgsProject* project )
{
QString href;
if ( parser )
if ( project )
{
href = parser->wfsServiceUrl();
if ( href.isEmpty() )
{
href = parser->serviceUrl();
}
href = QgsServerProjectUtils::wfsServiceUrl( *project );
}
// Build default url
@ -69,7 +66,6 @@ namespace QgsWfs
url.setQuery( q );
href = url.toString( QUrl::FullyDecoded );
}
return href;

View File

@ -51,7 +51,7 @@ namespace QgsWfs
/**
* Service URL string
*/
QString serviceUrl( const QgsServerRequest& request, QgsWfsProjectParser* parser = nullptr );
QString serviceUrl( const QgsServerRequest& request, const QgsProject* project );
// Define namespaces used in WFS documents
const QString WFS_NAMESPACE = QStringLiteral( "http://www.opengis.net/wfs" );

View File

@ -57,10 +57,8 @@ namespace QgsWms
}
void executeRequest( const QgsServerRequest& request, QgsServerResponse& response,
QgsProject* project )
const QgsProject* project )
{
Q_UNUSED( project );
QgsServerRequest::Parameters params = request.parameters();
QString versionString = params.value( "VERSION" );
if ( versionString.isEmpty() )
@ -86,13 +84,13 @@ namespace QgsWms
if (( QSTR_COMPARE( mVersion, "1.1.1" ) && QSTR_COMPARE( req, "capabilities" ) )
|| QSTR_COMPARE( req, "GetCapabilities" ) )
{
writeGetCapabilities( mServerIface, versionString, request, response, false );
writeGetCapabilities( mServerIface, project, versionString, request, response, false );
}
else if ( QSTR_COMPARE( req, "GetProjectSettings" ) )
{
//getProjectSettings extends WMS 1.3.0 capabilities
versionString = QStringLiteral( "1.3.0" );
writeGetCapabilities( mServerIface, versionString, request, response, true );
writeGetCapabilities( mServerIface, project, versionString, request, response, true );
}
else if ( QSTR_COMPARE( req, "GetMap" ) )
{
@ -103,16 +101,16 @@ namespace QgsWms
}
else
{
writeGetMap( mServerIface, versionString, request, response );
writeGetMap( mServerIface, project, versionString, request, response );
}
}
else if ( QSTR_COMPARE( req, "GetFeatureInfo" ) )
{
writeGetFeatureInfo( mServerIface, versionString, request, response );
writeGetFeatureInfo( mServerIface, project, versionString, request, response );
}
else if ( QSTR_COMPARE( req, "GetContext" ) )
{
writeGetContext( mServerIface, versionString, request, response );
writeGetContext( mServerIface, project, versionString, request, response );
}
else if ( QSTR_COMPARE( req, "GetSchemaExtension" ) )
{
@ -128,15 +126,15 @@ namespace QgsWms
}
else if ( QSTR_COMPARE( req, "DescribeLayer" ) )
{
writeDescribeLayer( mServerIface, versionString, request, response );
writeDescribeLayer( mServerIface, project, versionString, request, response );
}
else if ( QSTR_COMPARE( req, "GetLegendGraphic" ) || QSTR_COMPARE( req, "GetLegendGraphics" ) )
{
writeGetLegendGraphics( mServerIface, versionString, request, response );
writeGetLegendGraphics( mServerIface, project, versionString, request, response );
}
else if ( QSTR_COMPARE( req, "GetPrint" ) )
{
writeGetPrint( mServerIface, versionString, request, response );
writeGetPrint( mServerIface, project, versionString, request, response );
}
else
{

View File

@ -20,20 +20,21 @@
***************************************************************************/
#include "qgswmsutils.h"
#include "qgswmsdescribelayer.h"
#include "qgsserverprojectutils.h"
namespace QgsWms
{
void writeDescribeLayer( QgsServerInterface* serverIface, const QString& version,
void writeDescribeLayer( QgsServerInterface* serverIface, const QgsProject* project, const QString& version,
const QgsServerRequest& request, QgsServerResponse& response )
{
QDomDocument doc = describeLayer( serverIface, version, request );
QDomDocument doc = describeLayer( serverIface, project, version, request );
response.setHeader( QStringLiteral( "Content-Type" ), QStringLiteral( "text/xml; charset=utf-8" ) );
response.write( doc.toByteArray() );
}
// DescribeLayer is defined for WMS1.1.1/SLD1.0 and in WMS 1.3.0 SLD Extension
QDomDocument describeLayer( QgsServerInterface* serverIface, const QString& version,
QDomDocument describeLayer( QgsServerInterface* serverIface, const QgsProject* project, const QString& version,
const QgsServerRequest& request )
{
Q_UNUSED( version );
@ -64,11 +65,27 @@ namespace QgsWms
throw QgsServiceException( QStringLiteral( "InvalidParameterValue" ), QStringLiteral( "Layers is empty" ), 400 );
}
QString hrefString = serviceUrl( request, configParser ).toString( QUrl::FullyDecoded );
return configParser->describeLayer( layersList, hrefString );
// get the wms service url defined in project or keep the one from the
// request url
QString wmsHrefString = serviceUrl( request, project ).toString( QUrl::FullyDecoded );
// get the wfs service url defined in project or take the same as the
// wms service url
QString wfsHrefString = QgsServerProjectUtils::wfsServiceUrl( *project );
if ( wfsHrefString.isEmpty() )
{
wfsHrefString = wmsHrefString;
}
// get the wcs service url defined in project or take the same as the
// wms service url
QString wcsHrefString = QgsServerProjectUtils::wcsServiceUrl( *project );
if ( wcsHrefString.isEmpty() )
{
wcsHrefString = wmsHrefString;
}
return configParser->describeLayer( layersList, wfsHrefString, wcsHrefString );
}
} // samespace QgsWms

View File

@ -24,14 +24,15 @@ namespace QgsWms
/** Output GetMap response in Dfx format
*/
void writeDescribeLayer( QgsServerInterface* serverIface, const QString& version,
const QgsServerRequest& request, QgsServerResponse& response );
void writeDescribeLayer( QgsServerInterface* serverIface, const QgsProject* project,
const QString& version, const QgsServerRequest& request,
QgsServerResponse& response );
/**
* DescribeLayer is defined for WMS1.1.1/SLD1.0 and in WMS 1.3.0 SLD Extension
*/
QDomDocument describeLayer( QgsServerInterface* serverIface, const QString& version,
const QgsServerRequest& request );
QDomDocument describeLayer( QgsServerInterface* serverIface, const QgsProject* project,
const QString& version, const QgsServerRequest& request );
} // samespace QgsWms

View File

@ -20,12 +20,13 @@
***************************************************************************/
#include "qgswmsutils.h"
#include "qgswmsgetcapabilities.h"
#include "qgsserverprojectutils.h"
namespace QgsWms
{
void writeGetCapabilities( QgsServerInterface* serverIface, const QString& version,
const QgsServerRequest& request, QgsServerResponse& response,
bool projectSettings )
void writeGetCapabilities( QgsServerInterface* serverIface, const QgsProject* project,
const QString& version, const QgsServerRequest& request,
QgsServerResponse& response, bool projectSettings )
{
QString configFilePath = serverIface->configFilePath();
QgsCapabilitiesCache* capabilitiesCache = serverIface->capabilitiesCache();
@ -48,7 +49,7 @@ namespace QgsWms
QgsMessageLog::logMessage( QStringLiteral( "Capabilities document not found in cache" ) );
QDomDocument doc;
doc = getCapabilities( serverIface, version, request, projectSettings );
doc = getCapabilities( serverIface, project, version, request, projectSettings );
if ( cache )
{
@ -70,8 +71,9 @@ namespace QgsWms
response.write( capabilitiesDocument->toByteArray() );
}
QDomDocument getCapabilities( QgsServerInterface* serverIface, const QString& version,
const QgsServerRequest& request, bool projectSettings )
QDomDocument getCapabilities( QgsServerInterface* serverIface, const QgsProject* project,
const QString& version, const QgsServerRequest& request,
bool projectSettings )
{
QDomDocument doc;
QDomElement wmsCapabilitiesElement;
@ -81,7 +83,7 @@ namespace QgsWms
QgsServerRequest::Parameters parameters = request.parameters();
// Get service URL
QUrl href = serviceUrl( request, configParser );
QUrl href = serviceUrl( request, project );
//href needs to be a prefix
QString hrefString = href.toString( QUrl::FullyDecoded );
@ -271,13 +273,14 @@ namespace QgsWms
}
//add the xml content for the individual layers/styles
configParser->layersAndStylesCapabilities( capabilityElement, doc, version, projectSettings );
QString wmsServiceUrl = QgsServerProjectUtils::wmsServiceUrl( *project );
configParser->layersAndStylesCapabilities( capabilityElement, doc, version,
wmsServiceUrl, projectSettings );
return doc;
}
} // samespace QgsWms
} // namespace QgsWms

View File

@ -26,9 +26,9 @@ namespace QgsWms
/** Output GetCapabilities response
*/
void writeGetCapabilities( QgsServerInterface* serverIface, const QString& version,
const QgsServerRequest& request, QgsServerResponse& response,
bool projectSettings = false );
void writeGetCapabilities( QgsServerInterface* serverIface, const QgsProject* project,
const QString& version, const QgsServerRequest& request,
QgsServerResponse& response, bool projectSettings = false );
/**
* Create WMS GetCapabilities document
@ -37,8 +37,9 @@ namespace QgsWms
* @param version WMS version
* @param projectSettings If true: add extended project information (does not validate against WMS schema)
*/
QDomDocument getCapabilities( QgsServerInterface* serverIface, const QString& version,
const QgsServerRequest& request, bool projectSettings );
QDomDocument getCapabilities( QgsServerInterface* serverIface, const QgsProject* project,
const QString& version, const QgsServerRequest& request,
bool projectSettings );
} // samespace QgsWms

View File

@ -24,18 +24,19 @@
namespace QgsWms
{
void writeGetContext( QgsServerInterface* serverIface, const QString& version,
const QgsServerRequest& request, QgsServerResponse& response )
void writeGetContext( QgsServerInterface* serverIface, const QgsProject* project,
const QString& version, const QgsServerRequest& request,
QgsServerResponse& response )
{
QDomDocument doc = getContext( serverIface, version, request );
QDomDocument doc = getContext( serverIface, project, version, request );
response.setHeader( QStringLiteral( "Content-Type" ), QStringLiteral( "text/xml; charset=utf-8" ) );
response.write( doc.toByteArray() );
}
QDomDocument getContext( QgsServerInterface* serverIface, const QString& version,
const QgsServerRequest& request )
QDomDocument getContext( QgsServerInterface* serverIface, const QgsProject* project,
const QString& version, const QgsServerRequest& request )
{
Q_UNUSED( version );
@ -63,7 +64,7 @@ namespace QgsWms
owsContextElem.setAttribute( QStringLiteral( "version" ), QStringLiteral( "0.3.1" ) );
doc.appendChild( owsContextElem );
QString hrefString = serviceUrl( request, configParser ).toString( QUrl::FullyDecoded );
QString hrefString = serviceUrl( request, project ).toString( QUrl::FullyDecoded );
configParser->owsGeneralAndResourceList( owsContextElem, doc, hrefString );
return doc;

View File

@ -24,14 +24,15 @@ namespace QgsWms
/** Output GetContext response
*/
void writeGetContext( QgsServerInterface* serverIface, const QString& version,
const QgsServerRequest& request, QgsServerResponse& response );
void writeGetContext( QgsServerInterface* serverIface, const QgsProject* project,
const QString& version, const QgsServerRequest& request,
QgsServerResponse& response );
/**
* Return XML document for the 'GetContext' request
*/
QDomDocument getContext( QgsServerInterface* serverIface, const QString& version,
const QgsServerRequest& request );
QDomDocument getContext( QgsServerInterface* serverIface, const QgsProject* project,
const QString& version, const QgsServerRequest& request );
} // samespace QgsWms

View File

@ -155,12 +155,13 @@ namespace QgsWms
}
void writeGetFeatureInfo( QgsServerInterface* serverIface, const QString& version,
const QgsServerRequest& request, QgsServerResponse& response )
void writeGetFeatureInfo( QgsServerInterface* serverIface, const QgsProject* project,
const QString& version, const QgsServerRequest& request,
QgsServerResponse& response )
{
Q_UNUSED( version );
QgsServerRequest::Parameters params = request.parameters();
QgsRenderer renderer( serverIface, params, getConfigParser( serverIface ) );
QgsRenderer renderer( serverIface, project, params, getConfigParser( serverIface ) );
QDomDocument doc = renderer.getFeatureInfo( version );
QString outputFormat = params.value( QStringLiteral( "INFO_FORMAT" ), QStringLiteral( "text/plain" ) );

View File

@ -24,8 +24,9 @@ namespace QgsWms
/** Output GetFeatureInfo response
*/
void writeGetFeatureInfo( QgsServerInterface* serverIface, const QString& version,
const QgsServerRequest& request, QgsServerResponse& response );
void writeGetFeatureInfo( QgsServerInterface* serverIface, const QgsProject* project,
const QString& version, const QgsServerRequest& request,
QgsServerResponse& response );
} // samespace QgsWms

View File

@ -25,13 +25,14 @@
namespace QgsWms
{
void writeGetLegendGraphics( QgsServerInterface* serverIface, const QString& version,
const QgsServerRequest& request, QgsServerResponse& response )
void writeGetLegendGraphics( QgsServerInterface* serverIface, const QgsProject* project,
const QString& version, const QgsServerRequest& request,
QgsServerResponse& response )
{
Q_UNUSED( version );
QgsServerRequest::Parameters params = request.parameters();
QgsRenderer renderer( serverIface, params, getConfigParser( serverIface ) );
QgsRenderer renderer( serverIface, project, params, getConfigParser( serverIface ) );
QScopedPointer<QImage> result( renderer.getLegendGraphics() );

View File

@ -24,8 +24,9 @@ namespace QgsWms
/** Output GetLegendGRaphics response
*/
void writeGetLegendGraphics( QgsServerInterface* serverIface, const QString& version,
const QgsServerRequest& request, QgsServerResponse& response );
void writeGetLegendGraphics( QgsServerInterface* serverIface, const QgsProject* project,
const QString& version, const QgsServerRequest& request,
QgsServerResponse& response );
} // samespace QgsWms

View File

@ -25,14 +25,14 @@
namespace QgsWms
{
void writeGetMap( QgsServerInterface* serverIface, const QString& version,
const QgsServerRequest& request,
void writeGetMap( QgsServerInterface* serverIface, const QgsProject* project,
const QString& version, const QgsServerRequest& request,
QgsServerResponse& response )
{
Q_UNUSED( version );
QgsServerRequest::Parameters params = request.parameters();
QgsRenderer renderer( serverIface, params, getConfigParser( serverIface ) );
QgsRenderer renderer( serverIface, project, params, getConfigParser( serverIface ) );
QScopedPointer<QImage> result( renderer.getMap() );
if ( !result.isNull() )

View File

@ -24,7 +24,8 @@ namespace QgsWms
/** Output GetMap response in Dfx format
*/
void writeGetMap( QgsServerInterface* serverIface, const QString& version, const QgsServerRequest& request,
void writeGetMap( QgsServerInterface* serverIface, const QgsProject* project,
const QString& version, const QgsServerRequest& request,
QgsServerResponse& response );
} // samespace QgsWms

View File

@ -24,14 +24,15 @@
namespace QgsWms
{
void writeGetPrint( QgsServerInterface* serverIface, const QString& version,
const QgsServerRequest& request, QgsServerResponse& response )
void writeGetPrint( QgsServerInterface* serverIface, const QgsProject* project,
const QString& version, const QgsServerRequest& request,
QgsServerResponse& response )
{
QgsServerRequest::Parameters params = request.parameters();
Q_UNUSED( version );
QgsRenderer renderer( serverIface, params, getConfigParser( serverIface ) );
QgsRenderer renderer( serverIface, project, params, getConfigParser( serverIface ) );
QString format = params.value( "FORMAT" );
QString contentType;

View File

@ -24,8 +24,9 @@ namespace QgsWms
/** Output GetPrint response
*/
void writeGetPrint( QgsServerInterface* serverIface, const QString& version,
const QgsServerRequest& request, QgsServerResponse& response );
void writeGetPrint( QgsServerInterface* serverIface, const QgsProject* project,
const QString& version, const QgsServerRequest& request,
QgsServerResponse& response );
} // samespace QgsWms

View File

@ -78,10 +78,4 @@ namespace QgsWms
return xsdDoc;
}
} // samespace QgsWms
} // namespace QgsWms

View File

@ -56,6 +56,7 @@
#include "qgsfeaturerequest.h"
#include "qgsmaprendererjobproxy.h"
#include "qgswmsserviceexception.h"
#include "qgsserverprojectutils.h"
#include <QImage>
#include <QPainter>
@ -95,6 +96,7 @@ namespace QgsWms
QgsRenderer::QgsRenderer( QgsServerInterface* serverIface,
const QgsProject* project,
const QgsServerRequest::Parameters& parameters,
QgsWmsConfigParser* parser )
: mParameters( parameters )
@ -104,6 +106,7 @@ namespace QgsWms
, mConfigParser( parser )
, mAccessControl( serverIface->accessControls() )
, mSettings( *serverIface->serverSettings() )
, mProject( project )
{
}
@ -2260,23 +2263,26 @@ namespace QgsWms
bool QgsRenderer::checkMaximumWidthHeight() const
{
//test if maxWidth / maxHeight set and WIDTH / HEIGHT parameter is in the range
if ( mConfigParser->maxWidth() != -1 )
int wmsMaxWidth = QgsServerProjectUtils::wmsMaxWidth( *mProject );
if ( wmsMaxWidth != -1 )
{
QMap<QString, QString>::const_iterator widthIt = mParameters.find( QStringLiteral( "WIDTH" ) );
if ( widthIt != mParameters.constEnd() )
{
if ( widthIt->toInt() > mConfigParser->maxWidth() )
if ( widthIt->toInt() > wmsMaxWidth )
{
return false;
}
}
}
if ( mConfigParser->maxHeight() != -1 )
int wmsMaxHeight = QgsServerProjectUtils::wmsMaxHeight( *mProject );
if ( wmsMaxHeight != -1 )
{
QMap<QString, QString>::const_iterator heightIt = mParameters.find( QStringLiteral( "HEIGHT" ) );
if ( heightIt != mParameters.constEnd() )
{
if ( heightIt->toInt() > mConfigParser->maxHeight() )
if ( heightIt->toInt() > wmsMaxHeight )
{
return false;
}

View File

@ -76,6 +76,7 @@ namespace QgsWms
/** Constructor. Does _NOT_ take ownership of
QgsConfigParser and QgsCapabilitiesCache*/
QgsRenderer( QgsServerInterface* serverIface,
const QgsProject* project,
const QgsServerRequest::Parameters& parameters,
QgsWmsConfigParser* parser );
@ -261,6 +262,7 @@ namespace QgsWms
QgsAccessControl* mAccessControl;
const QgsServerSettings& mSettings;
const QgsProject* mProject;
public:

View File

@ -23,6 +23,7 @@
#include "qgswmsutils.h"
#include "qgsmediancut.h"
#include "qgsconfigcache.h"
#include "qgsserverprojectutils.h"
namespace QgsWms
{
@ -46,12 +47,12 @@ namespace QgsWms
return parser;
}
QUrl serviceUrl( const QgsServerRequest& request, QgsWmsConfigParser* parser )
QUrl serviceUrl( const QgsServerRequest& request, const QgsProject* project )
{
QUrl href;
if ( parser )
if ( project )
{
href.setUrl( parser->serviceUrl() );
href.setUrl( QgsServerProjectUtils::wmsServiceUrl( *project ) );
}
// Build default url

View File

@ -53,7 +53,7 @@ namespace QgsWms
/** Return WMS service URL
*/
QUrl serviceUrl( const QgsServerRequest& request, QgsWmsConfigParser* parser );
QUrl serviceUrl( const QgsServerRequest& request, const QgsProject* project );
/**
* Return the wms config parser (Transitional)

View File

@ -169,6 +169,7 @@ ENDIF (WITH_APIDOC)
IF (WITH_SERVER)
ADD_PYTHON_TEST(PyQgsServer test_qgsserver.py)
ADD_PYTHON_TEST(PyQgsServerSettings test_qgsserver_settings.py)
ADD_PYTHON_TEST(PyQgsServerProjectUtils test_qgsserver_projectutils.py)
ADD_PYTHON_TEST(PyQgsServerAccessControl test_qgsserver_accesscontrol.py)
ADD_PYTHON_TEST(PyQgsServerWFST test_qgsserver_wfst.py)
ADD_PYTHON_TEST(PyQgsOfflineEditingWFS test_offline_editing_wfs.py)

View File

@ -29,6 +29,12 @@ import osgeo.gdal
import tempfile
import base64
try:
import xml.etree.cElementTree as ET
except ImportError:
import xml.etree.ElementTree as ET
# Strip path and content length because path may vary
RE_STRIP_UNCHECKABLE = b'MAP=[^"]+|Content-Length: \d+'
RE_ATTRIBUTES = b'[^>\s]+=[^>\s]+'
@ -113,10 +119,21 @@ class TestQgsServer(unittest.TestCase):
# Test as a whole
header, body = [_v for _v in self.server.handleRequest("")]
response = self.strip_version_xmlns(header + body)
expected = self.strip_version_xmlns(b'Content-Length: 54\nContent-Type: text/xml; charset=utf-8\n\n<ServerException>Project file error</ServerException>\n')
self.assertEqual(response, expected)
expected = b'Content-Length: 54\nContent-Type: text/xml; charset=utf-8\n\n'
self.assertEqual(header, expected)
# Test response when project is specified but without service
project = self.testdata_path + "test_project_wfs.qgs"
qs = 'MAP=%s' % (urllib.parse.quote(project))
header, body = [_v for _v in self.server.handleRequest(qs)]
response = self.strip_version_xmlns(header + body)
expected = self.strip_version_xmlns(b'Content-Length: 206\nContent-Type: text/xml; charset=utf-8\n\n<ServiceExceptionReport version="1.3.0" xmlns="http://www.opengis.net/ogc">\n <ServiceException code="Service configuration error">Service unknown or unsupported</ServiceException>\n</ServiceExceptionReport>\n')
self.assertEqual(response, expected)
expected = b'Content-Length: 206\nContent-Type: text/xml; charset=utf-8\n\n'
self.assertEqual(header, expected)
# Test body
expected = self.strip_version_xmlns(b'<ServiceExceptionReport version="1.3.0" xmlns="http://www.opengis.net/ogc">\n <ServiceException code="Service configuration error">Service unknown or unsupported</ServiceException>\n</ServiceExceptionReport>\n')
self.assertEqual(self.strip_version_xmlns(body), expected)
@ -334,6 +351,40 @@ class TestQgsServer(unittest.TestCase):
header, body
)
def test_wfs_getcapabilities_url(self):
# empty url in project
project = os.path.join(self.testdata_path, "test_project_without_urls.qgs")
qs = "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(project),
"SERVICE": "WFS",
"VERSION": "1.3.0",
"REQUEST": "GetCapabilities",
"STYLES": ""
}.items())])
r, h = self._result(self.server.handleRequest(qs))
for item in str(r).split("\\n"):
if "onlineResource" in item:
self.assertEqual("onlineResource=\"?" in item, True)
# url well defined in project
project = os.path.join(self.testdata_path, "test_project_with_urls.qgs")
qs = "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(project),
"SERVICE": "WFS",
"VERSION": "1.3.0",
"REQUEST": "GetCapabilities",
"STYLES": ""
}.items())])
r, h = self._result(self.server.handleRequest(qs))
for item in str(r).split("\\n"):
if "onlineResource" in item:
print("onlineResource: ", item)
self.assertEqual("onlineResource=\"my_wfs_advertised_url\"" in item, True)
def result_compare(self, file_name, error_msg_header, header, body):
self.assert_headers(header, body)
response = header + body
@ -483,6 +534,64 @@ class TestQgsServer(unittest.TestCase):
r, h = self._result(self.server.handleRequest(qs))
self._img_diff_error(r, h, "WMS_GetMap_Background_Hex")
def test_wms_getcapabilities_url(self):
# empty url in project
project = os.path.join(self.testdata_path, "test_project_without_urls.qgs")
qs = "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(project),
"SERVICE": "WMS",
"VERSION": "1.3.0",
"REQUEST": "GetCapabilities",
"STYLES": ""
}.items())])
r, h = self._result(self.server.handleRequest(qs))
item_found = False
for item in str(r).split("\\n"):
if "OnlineResource" in item:
self.assertEqual("xlink:href=\"?" in item, True)
item_found = True
self.assertTrue(item_found)
# url well defined in project
project = os.path.join(self.testdata_path, "test_project_with_urls.qgs")
qs = "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(project),
"SERVICE": "WMS",
"VERSION": "1.3.0",
"REQUEST": "GetCapabilities",
"STYLES": ""
}.items())])
r, h = self._result(self.server.handleRequest(qs))
item_found = False
for item in str(r).split("\\n"):
if "OnlineResource" in item:
self.assertEqual("xlink:href=\"my_wms_advertised_url?" in item, True)
item_found = True
self.assertTrue(item_found)
def test_wms_getmap_invalid_size(self):
project = os.path.join(self.testdata_path, "test_project_with_size.qgs")
qs = "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(project),
"SERVICE": "WMS",
"VERSION": "1.3.0",
"REQUEST": "GetMap",
"LAYERS": "Hello",
"STYLES": "",
"FORMAT": "image/png",
"HEIGHT": "5001",
"WIDTH": "5000"
}.items())])
expected = self.strip_version_xmlns(b'<ServiceExceptionReport version="1.3.0" xmlns="http://www.opengis.net/ogc">\n <ServiceException code="Size error">The requested map size is too large</ServiceException>\n</ServiceExceptionReport>\n')
r, h = self._result(self.server.handleRequest(qs))
self.assertEqual(self.strip_version_xmlns(r), expected)
def test_wms_getmap_order(self):
qs = "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(self.projectPath),
@ -520,7 +629,7 @@ class TestQgsServer(unittest.TestCase):
self._img_diff_error(r, h, "WMS_GetMap_SRS")
def test_wms_getmap_style(self):
# default style
# default style
qs = "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(self.projectPath),
"SERVICE": "WMS",
@ -538,7 +647,7 @@ class TestQgsServer(unittest.TestCase):
r, h = self._result(self.server.handleRequest(qs))
self._img_diff_error(r, h, "WMS_GetMap_StyleDefault")
# custom style
# custom style
qs = "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(self.projectPath),
"SERVICE": "WMS",
@ -954,6 +1063,46 @@ class TestQgsServer(unittest.TestCase):
r, h = self._result(self.server.handleRequest(qs))
self._img_diff_error(r, h, "WMS_GetLegendGraphic_BBox2")
def test_wcs_getcapabilities_url(self):
# empty url in project
project = os.path.join(self.testdata_path, "test_project_without_urls.qgs")
qs = "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(project),
"SERVICE": "WCS",
"VERSION": "1.3.0",
"REQUEST": "GetCapabilities",
"STYLES": ""
}.items())])
r, h = self._result(self.server.handleRequest(qs))
item_found = False
for item in str(r).split("\\n"):
if "OnlineResource" in item:
self.assertEqual("=\"?" in item, True)
item_found = True
self.assertTrue(item_found)
# url well defined in project
project = os.path.join(self.testdata_path, "test_project_with_urls.qgs")
qs = "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(project),
"SERVICE": "WCS",
"VERSION": "1.3.0",
"REQUEST": "GetCapabilities",
"STYLES": ""
}.items())])
r, h = self._result(self.server.handleRequest(qs))
item_found = False
for item in str(r).split("\\n"):
if "OnlineResource" in item:
print("OnlineResource: ", item)
self.assertEqual("\"my_wcs_advertised_url" in item, True)
item_found = True
self.assertTrue(item_found)
def _result(self, data):
headers = {}
for line in data[0].decode('UTF-8').split("\n"):

View File

@ -0,0 +1,47 @@
# -*- coding: utf-8 -*-
"""QGIS Unit tests for QgsServerProject.
.. note:: 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.
"""
__author__ = 'Paul Blottiere'
__date__ = '26/12/2016'
__copyright__ = 'Copyright 2016, The QGIS Project'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
import os
from qgis.server import QgsServerProjectUtils
from qgis.core import QgsApplication, QgsProject
from qgis.testing import unittest
from utilities import unitTestDataPath
class TestQgsServerProjectUtils(unittest.TestCase):
def setUp(self):
self.testdata_path = unitTestDataPath('qgis_server_project') + '/'
self.prj = QgsProject()
prjPath = os.path.join(self.testdata_path, "project.qgs")
self.prj.setFileName(prjPath)
self.prj.read()
def tearDown(self):
pass
def test_size(self):
self.assertEqual(QgsServerProjectUtils.wmsMaxWidth(self.prj), 400)
self.assertEqual(QgsServerProjectUtils.wmsMaxHeight(self.prj), 500)
def test_url(self):
self.assertEqual(QgsServerProjectUtils.wmsServiceUrl(self.prj), "my_wms_advertised_url")
self.assertEqual(QgsServerProjectUtils.wcsServiceUrl(self.prj), "my_wcs_advertised_url")
self.assertEqual(QgsServerProjectUtils.wfsServiceUrl(self.prj), "my_wfs_advertised_url")
if __name__ == '__main__':
unittest.main()

View File

@ -0,0 +1,124 @@
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
<qgis version="2.99.0-Master" projectname="">
<title></title>
<autotransaction active="0"/>
<evaluateDefaultValues active="0"/>
<layer-tree-group name="" expanded="1" checked="Qt::Checked">
<customproperties/>
</layer-tree-group>
<snapping-settings enabled="0" unit="2" intersection-snapping="0" mode="2" type="1" tolerance="0">
<individual-layer-settings/>
</snapping-settings>
<relations/>
<mapcanvas>
<units>degrees</units>
<extent>
<xmin>-1</xmin>
<ymin>-1</ymin>
<xmax>1</xmax>
<ymax>1</ymax>
</extent>
<rotation>0</rotation>
<projections>0</projections>
<destinationsrs>
<spatialrefsys>
<proj4>+proj=longlat +datum=WGS84 +no_defs</proj4>
<srsid>3452</srsid>
<srid>4326</srid>
<authid>EPSG:4326</authid>
<description>WGS 84</description>
<projectionacronym>longlat</projectionacronym>
<ellipsoidacronym>WGS84</ellipsoidacronym>
<geographicflag>true</geographicflag>
</spatialrefsys>
</destinationsrs>
<rendermaptile>0</rendermaptile>
<layer_coordinate_transform_info/>
</mapcanvas>
<layer-tree-canvas>
<custom-order enabled="0"/>
</layer-tree-canvas>
<legend updateDrawingOrder="true"/>
<projectlayers/>
<properties>
<WMSAddWktGeometry type="bool">false</WMSAddWktGeometry>
<WMSSegmentizeFeatureInfoGeometry type="bool">false</WMSSegmentizeFeatureInfoGeometry>
<WMSMaxWidth type="int">5000</WMSMaxWidth>
<WFSUrl type="QString">my_wfs_advertised_url</WFSUrl>
<WMSContactPhone type="QString"></WMSContactPhone>
<WMSPrecision type="QString">8</WMSPrecision>
<WMSContactPerson type="QString"></WMSContactPerson>
<WCSLayers type="QStringList"/>
<Legend>
<filterByMap type="bool">false</filterByMap>
</Legend>
<Gui>
<CanvasColorBluePart type="int">255</CanvasColorBluePart>
<SelectionColorBluePart type="int">0</SelectionColorBluePart>
<SelectionColorAlphaPart type="int">255</SelectionColorAlphaPart>
<CanvasColorRedPart type="int">255</CanvasColorRedPart>
<SelectionColorRedPart type="int">255</SelectionColorRedPart>
<CanvasColorGreenPart type="int">255</CanvasColorGreenPart>
<SelectionColorGreenPart type="int">255</SelectionColorGreenPart>
</Gui>
<WFSTLayers>
<Insert type="QStringList"/>
<Update type="QStringList"/>
<Delete type="QStringList"/>
</WFSTLayers>
<WMSOnlineResource type="QString"></WMSOnlineResource>
<PositionPrecision>
<DegreeFormat type="QString">MU</DegreeFormat>
<DecimalPlaces type="int">2</DecimalPlaces>
<Automatic type="bool">true</Automatic>
</PositionPrecision>
<WMSUrl type="QString">my_wms_advertised_url</WMSUrl>
<Macros>
<pythonCode type="QString"></pythonCode>
</Macros>
<WMSServiceTitle type="QString"></WMSServiceTitle>
<WMSRequestDefinedDataSources type="bool">false</WMSRequestDefinedDataSources>
<WCSUrl type="QString">my_wcs_advertised_url</WCSUrl>
<WMSImageQuality type="int">90</WMSImageQuality>
<WMSMaxHeight type="int">5000</WMSMaxHeight>
<DefaultStyles>
<Line type="QString"></Line>
<RandomColors type="bool">true</RandomColors>
<ColorRamp type="QString"></ColorRamp>
<Fill type="QString"></Fill>
<AlphaInt type="int">255</AlphaInt>
<Marker type="QString"></Marker>
</DefaultStyles>
<WFSLayers type="QStringList"/>
<Identify>
<disabledLayers type="QStringList"/>
</Identify>
<WMSAccessConstraints type="QString">None</WMSAccessConstraints>
<WMSUseLayerIDs type="bool">false</WMSUseLayerIDs>
<WMSContactMail type="QString"></WMSContactMail>
<Measure>
<Ellipsoid type="QString">NONE</Ellipsoid>
</Measure>
<WMSServiceAbstract type="QString"></WMSServiceAbstract>
<Paths>
<Absolute type="bool">false</Absolute>
</Paths>
<WMSContactOrganization type="QString"></WMSContactOrganization>
<Measurement>
<DistanceUnits type="QString">meters</DistanceUnits>
<AreaUnits type="QString">m2</AreaUnits>
</Measurement>
<WMSContactPosition type="QString"></WMSContactPosition>
<WMSKeywordList type="QStringList">
<value></value>
</WMSKeywordList>
<SpatialRefSys>
<ProjectCRSProj4String type="QString">+proj=longlat +datum=WGS84 +no_defs</ProjectCRSProj4String>
<ProjectCRSID type="int">3452</ProjectCRSID>
<ProjectCrs type="QString">EPSG:4326</ProjectCrs>
</SpatialRefSys>
<WMSFees type="QString">conditions unknown</WMSFees>
<WMSServiceCapabilities type="bool">false</WMSServiceCapabilities>
</properties>
<visibility-presets/>
</qgis>

View File

@ -0,0 +1,122 @@
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
<qgis projectname="" version="2.99.0-Master">
<title></title>
<autotransaction active="0"/>
<evaluateDefaultValues active="0"/>
<layer-tree-group expanded="1" name="" checked="Qt::Checked">
<customproperties/>
</layer-tree-group>
<snapping-settings unit="2" mode="2" type="1" enabled="0" tolerance="0" intersection-snapping="0">
<individual-layer-settings/>
</snapping-settings>
<relations/>
<mapcanvas>
<units>degrees</units>
<extent>
<xmin>-1</xmin>
<ymin>-1</ymin>
<xmax>1</xmax>
<ymax>1</ymax>
</extent>
<rotation>0</rotation>
<projections>0</projections>
<destinationsrs>
<spatialrefsys>
<proj4>+proj=longlat +datum=WGS84 +no_defs</proj4>
<srsid>3452</srsid>
<srid>4326</srid>
<authid>EPSG:4326</authid>
<description>WGS 84</description>
<projectionacronym>longlat</projectionacronym>
<ellipsoidacronym>WGS84</ellipsoidacronym>
<geographicflag>true</geographicflag>
</spatialrefsys>
</destinationsrs>
<rendermaptile>0</rendermaptile>
<layer_coordinate_transform_info/>
</mapcanvas>
<layer-tree-canvas>
<custom-order enabled="0"/>
</layer-tree-canvas>
<legend updateDrawingOrder="true"/>
<projectlayers/>
<properties>
<WMSImageQuality type="int">90</WMSImageQuality>
<WMSContactPerson type="QString"></WMSContactPerson>
<WMSContactMail type="QString"></WMSContactMail>
<WMSServiceAbstract type="QString"></WMSServiceAbstract>
<Macros>
<pythonCode type="QString"></pythonCode>
</Macros>
<WMSSegmentizeFeatureInfoGeometry type="bool">false</WMSSegmentizeFeatureInfoGeometry>
<Legend>
<filterByMap type="bool">false</filterByMap>
</Legend>
<WMSAddWktGeometry type="bool">false</WMSAddWktGeometry>
<WCSUrl type="QString">my_wcs_advertised_url</WCSUrl>
<WMSUseLayerIDs type="bool">false</WMSUseLayerIDs>
<Paths>
<Absolute type="bool">false</Absolute>
</Paths>
<WMSContactPhone type="QString"></WMSContactPhone>
<WMSServiceTitle type="QString"></WMSServiceTitle>
<WMSKeywordList type="QStringList">
<value></value>
</WMSKeywordList>
<WFSLayers type="QStringList"/>
<Measurement>
<AreaUnits type="QString">m2</AreaUnits>
<DistanceUnits type="QString">meters</DistanceUnits>
</Measurement>
<WMSServiceCapabilities type="bool">false</WMSServiceCapabilities>
<Identify>
<disabledLayers type="QStringList"/>
</Identify>
<Measure>
<Ellipsoid type="QString">NONE</Ellipsoid>
</Measure>
<DefaultStyles>
<ColorRamp type="QString"></ColorRamp>
<Fill type="QString"></Fill>
<AlphaInt type="int">255</AlphaInt>
<Marker type="QString"></Marker>
<Line type="QString"></Line>
<RandomColors type="bool">true</RandomColors>
</DefaultStyles>
<WMSContactPosition type="QString"></WMSContactPosition>
<WMSOnlineResource type="QString"></WMSOnlineResource>
<WMSUrl type="QString">my_wms_advertised_url</WMSUrl>
<WMSFees type="QString">conditions unknown</WMSFees>
<WMSPrecision type="QString">8</WMSPrecision>
<WMSAccessConstraints type="QString">None</WMSAccessConstraints>
<WFSTLayers>
<Update type="QStringList"/>
<Insert type="QStringList"/>
<Delete type="QStringList"/>
</WFSTLayers>
<PositionPrecision>
<Automatic type="bool">true</Automatic>
<DegreeFormat type="QString">MU</DegreeFormat>
<DecimalPlaces type="int">2</DecimalPlaces>
</PositionPrecision>
<WMSRequestDefinedDataSources type="bool">false</WMSRequestDefinedDataSources>
<WCSLayers type="QStringList"/>
<SpatialRefSys>
<ProjectCRSID type="int">3452</ProjectCRSID>
<ProjectCRSProj4String type="QString">+proj=longlat +datum=WGS84 +no_defs</ProjectCRSProj4String>
<ProjectCrs type="QString">EPSG:4326</ProjectCrs>
</SpatialRefSys>
<WFSUrl type="QString">my_wfs_advertised_url</WFSUrl>
<Gui>
<SelectionColorRedPart type="int">255</SelectionColorRedPart>
<CanvasColorRedPart type="int">255</CanvasColorRedPart>
<SelectionColorAlphaPart type="int">255</SelectionColorAlphaPart>
<SelectionColorGreenPart type="int">255</SelectionColorGreenPart>
<CanvasColorGreenPart type="int">255</CanvasColorGreenPart>
<CanvasColorBluePart type="int">255</CanvasColorBluePart>
<SelectionColorBluePart type="int">0</SelectionColorBluePart>
</Gui>
<WMSContactOrganization type="QString"></WMSContactOrganization>
</properties>
<visibility-presets/>
</qgis>

View File

@ -0,0 +1,124 @@
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
<qgis projectname="" version="2.99.0-Master">
<title></title>
<autotransaction active="0"/>
<evaluateDefaultValues active="0"/>
<layer-tree-group expanded="1" name="" checked="Qt::Checked">
<customproperties/>
</layer-tree-group>
<snapping-settings unit="2" mode="2" type="1" enabled="0" tolerance="0" intersection-snapping="0">
<individual-layer-settings/>
</snapping-settings>
<relations/>
<mapcanvas>
<units>degrees</units>
<extent>
<xmin>-1</xmin>
<ymin>-1</ymin>
<xmax>1</xmax>
<ymax>1</ymax>
</extent>
<rotation>0</rotation>
<projections>0</projections>
<destinationsrs>
<spatialrefsys>
<proj4>+proj=longlat +datum=WGS84 +no_defs</proj4>
<srsid>3452</srsid>
<srid>4326</srid>
<authid>EPSG:4326</authid>
<description>WGS 84</description>
<projectionacronym>longlat</projectionacronym>
<ellipsoidacronym>WGS84</ellipsoidacronym>
<geographicflag>true</geographicflag>
</spatialrefsys>
</destinationsrs>
<rendermaptile>0</rendermaptile>
<layer_coordinate_transform_info/>
</mapcanvas>
<layer-tree-canvas>
<custom-order enabled="0"/>
</layer-tree-canvas>
<legend updateDrawingOrder="true"/>
<projectlayers/>
<properties>
<WMSImageQuality type="int">90</WMSImageQuality>
<WMSContactPerson type="QString"></WMSContactPerson>
<WMSContactMail type="QString"></WMSContactMail>
<WMSServiceAbstract type="QString"></WMSServiceAbstract>
<Macros>
<pythonCode type="QString"></pythonCode>
</Macros>
<WMSSegmentizeFeatureInfoGeometry type="bool">false</WMSSegmentizeFeatureInfoGeometry>
<Legend>
<filterByMap type="bool">false</filterByMap>
</Legend>
<WMSAddWktGeometry type="bool">false</WMSAddWktGeometry>
<WCSUrl type="QString"></WCSUrl>
<WMSUseLayerIDs type="bool">false</WMSUseLayerIDs>
<Paths>
<Absolute type="bool">false</Absolute>
</Paths>
<WMSContactPhone type="QString"></WMSContactPhone>
<WMSServiceTitle type="QString"></WMSServiceTitle>
<WMSKeywordList type="QStringList">
<value></value>
</WMSKeywordList>
<WMSMaxWidth type="int">5000</WMSMaxWidth>
<WFSLayers type="QStringList"/>
<Measurement>
<AreaUnits type="QString">m2</AreaUnits>
<DistanceUnits type="QString">meters</DistanceUnits>
</Measurement>
<WMSServiceCapabilities type="bool">false</WMSServiceCapabilities>
<Identify>
<disabledLayers type="QStringList"/>
</Identify>
<Measure>
<Ellipsoid type="QString">NONE</Ellipsoid>
</Measure>
<DefaultStyles>
<ColorRamp type="QString"></ColorRamp>
<Fill type="QString"></Fill>
<AlphaInt type="int">255</AlphaInt>
<Marker type="QString"></Marker>
<Line type="QString"></Line>
<RandomColors type="bool">true</RandomColors>
</DefaultStyles>
<WMSContactPosition type="QString"></WMSContactPosition>
<WMSOnlineResource type="QString"></WMSOnlineResource>
<WMSUrl type="QString"></WMSUrl>
<WMSFees type="QString">conditions unknown</WMSFees>
<WMSPrecision type="QString">8</WMSPrecision>
<WMSAccessConstraints type="QString">None</WMSAccessConstraints>
<WFSTLayers>
<Update type="QStringList"/>
<Insert type="QStringList"/>
<Delete type="QStringList"/>
</WFSTLayers>
<PositionPrecision>
<Automatic type="bool">true</Automatic>
<DegreeFormat type="QString">MU</DegreeFormat>
<DecimalPlaces type="int">2</DecimalPlaces>
</PositionPrecision>
<WMSRequestDefinedDataSources type="bool">false</WMSRequestDefinedDataSources>
<WCSLayers type="QStringList"/>
<SpatialRefSys>
<ProjectCRSID type="int">3452</ProjectCRSID>
<ProjectCRSProj4String type="QString">+proj=longlat +datum=WGS84 +no_defs</ProjectCRSProj4String>
<ProjectCrs type="QString">EPSG:4326</ProjectCrs>
</SpatialRefSys>
<WMSMaxHeight type="int">5000</WMSMaxHeight>
<WFSUrl type="QString"></WFSUrl>
<Gui>
<SelectionColorRedPart type="int">255</SelectionColorRedPart>
<CanvasColorRedPart type="int">255</CanvasColorRedPart>
<SelectionColorAlphaPart type="int">255</SelectionColorAlphaPart>
<SelectionColorGreenPart type="int">255</SelectionColorGreenPart>
<CanvasColorGreenPart type="int">255</CanvasColorGreenPart>
<CanvasColorBluePart type="int">255</CanvasColorBluePart>
<SelectionColorBluePart type="int">0</SelectionColorBluePart>
</Gui>
<WMSContactOrganization type="QString"></WMSContactOrganization>
</properties>
<visibility-presets/>
</qgis>

View File

@ -0,0 +1,132 @@
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
<qgis version="2.99.0-Master" projectname="">
<title></title>
<autotransaction active="0"/>
<evaluateDefaultValues active="0"/>
<layer-tree-group expanded="1" name="" checked="Qt::Checked">
<customproperties/>
</layer-tree-group>
<snapping-settings enabled="0" unit="2" mode="2" intersection-snapping="0" type="1" tolerance="0">
<individual-layer-settings/>
</snapping-settings>
<relations/>
<mapcanvas>
<units>degrees</units>
<extent>
<xmin>-1.4879649890590807</xmin>
<ymin>-0.64989059080962797</ymin>
<xmax>0.5120350109409193</xmax>
<ymax>1.35010940919037203</ymax>
</extent>
<rotation>0</rotation>
<projections>0</projections>
<destinationsrs>
<spatialrefsys>
<proj4>+proj=longlat +datum=WGS84 +no_defs</proj4>
<srsid>3452</srsid>
<srid>4326</srid>
<authid>EPSG:4326</authid>
<description>WGS 84</description>
<projectionacronym>longlat</projectionacronym>
<ellipsoidacronym>WGS84</ellipsoidacronym>
<geographicflag>true</geographicflag>
</spatialrefsys>
</destinationsrs>
<rendermaptile>0</rendermaptile>
<layer_coordinate_transform_info/>
</mapcanvas>
<layer-tree-canvas>
<custom-order enabled="0"/>
</layer-tree-canvas>
<legend updateDrawingOrder="true"/>
<projectlayers/>
<properties>
<WMSServiceAbstract type="QString"></WMSServiceAbstract>
<WMSContactPosition type="QString"></WMSContactPosition>
<Legend>
<filterByMap type="bool">false</filterByMap>
</Legend>
<WMSUrl type="QString">my_wms_advertised_url</WMSUrl>
<WMSKeywordList type="QStringList">
<value></value>
</WMSKeywordList>
<WMSRestrictedLayers type="QStringList"/>
<WMSRequestDefinedDataSources type="bool">false</WMSRequestDefinedDataSources>
<WMSImageQuality type="int">90</WMSImageQuality>
<WMSContactOrganization type="QString"></WMSContactOrganization>
<WMSPrecision type="QString">8</WMSPrecision>
<SpatialRefSys>
<ProjectCRSProj4String type="QString">+proj=longlat +datum=WGS84 +no_defs</ProjectCRSProj4String>
<ProjectCRSID type="int">3452</ProjectCRSID>
<ProjectCrs type="QString">EPSG:4326</ProjectCrs>
</SpatialRefSys>
<WMSFees type="QString">conditions unknown</WMSFees>
<WMSContactPhone type="QString"></WMSContactPhone>
<WFSLayers type="QStringList"/>
<WFSTLayers>
<Insert type="QStringList"/>
<Delete type="QStringList"/>
<Update type="QStringList"/>
</WFSTLayers>
<Measurement>
<DistanceUnits type="QString">meters</DistanceUnits>
<AreaUnits type="QString">m2</AreaUnits>
</Measurement>
<WMSContactPerson type="QString"></WMSContactPerson>
<WMSMaxWidth type="int">400</WMSMaxWidth>
<Gui>
<CanvasColorRedPart type="int">255</CanvasColorRedPart>
<CanvasColorBluePart type="int">255</CanvasColorBluePart>
<SelectionColorRedPart type="int">255</SelectionColorRedPart>
<SelectionColorGreenPart type="int">255</SelectionColorGreenPart>
<CanvasColorGreenPart type="int">255</CanvasColorGreenPart>
<SelectionColorBluePart type="int">0</SelectionColorBluePart>
<SelectionColorAlphaPart type="int">255</SelectionColorAlphaPart>
</Gui>
<Macros>
<pythonCode type="QString"></pythonCode>
</Macros>
<DefaultStyles>
<Line type="QString"></Line>
<Fill type="QString"></Fill>
<RandomColors type="bool">true</RandomColors>
<AlphaInt type="int">255</AlphaInt>
<ColorRamp type="QString"></ColorRamp>
<Marker type="QString"></Marker>
</DefaultStyles>
<WMSAddWktGeometry type="bool">false</WMSAddWktGeometry>
<Paths>
<Absolute type="bool">false</Absolute>
</Paths>
<WMSSegmentizeFeatureInfoGeometry type="bool">false</WMSSegmentizeFeatureInfoGeometry>
<WMSMaxHeight type="int">500</WMSMaxHeight>
<WMSServiceTitle type="QString"></WMSServiceTitle>
<WFSUrl type="QString">my_wfs_advertised_url</WFSUrl>
<WCSUrl type="QString">my_wcs_advertised_url</WCSUrl>
<WMSRestrictedComposers type="QStringList"/>
<WMSExtent type="QStringList">
<value></value>
<value></value>
<value></value>
<value></value>
</WMSExtent>
<Identify>
<disabledLayers type="QStringList"/>
</Identify>
<WMSServiceCapabilities type="bool">false</WMSServiceCapabilities>
<WMSUseLayerIDs type="bool">false</WMSUseLayerIDs>
<WMSAccessConstraints type="QString">None</WMSAccessConstraints>
<WCSLayers type="QStringList"/>
<WMSContactMail type="QString"></WMSContactMail>
<WMSOnlineResource type="QString"></WMSOnlineResource>
<PositionPrecision>
<DecimalPlaces type="int">2</DecimalPlaces>
<DegreeFormat type="QString">MU</DegreeFormat>
<Automatic type="bool">true</Automatic>
</PositionPrecision>
<Measure>
<Ellipsoid type="QString">NONE</Ellipsoid>
</Measure>
</properties>
<visibility-presets/>
</qgis>