diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index fa7968fa7ab..aa4cc0feb6a 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -84,11 +84,16 @@ IF(WITH_APIDOC) ${DOXYGEN_INPUT} ${CMAKE_SOURCE_DIR}/src/server/qgsserver.h ${CMAKE_SOURCE_DIR}/src/server/qgscapabilitiescache.h - ${CMAKE_SOURCE_DIR}/src/server/qgsmapserviceexception.h + ${CMAKE_SOURCE_DIR}/src/server/qgsserverexception.h ${CMAKE_SOURCE_DIR}/src/server/qgsrequesthandler.h ${CMAKE_SOURCE_DIR}/src/server/qgsserverfilter.h ${CMAKE_SOURCE_DIR}/src/server/qgsaccesscontrolfilter.h ${CMAKE_SOURCE_DIR}/src/server/qgsserverinterface.h + ${CMAKE_SOURCE_DIR}/src/server/qgsserverrequest.h + ${CMAKE_SOURCE_DIR}/src/server/qgsserverresponse.h + ${CMAKE_SOURCE_DIR}/src/server/qgsserverrequest.h + ${CMAKE_SOURCE_DIR}/src/server/qgsservice.h + ${CMAKE_SOURCE_DIR}/src/server/qgsserviceregistry.h ) ENDIF(WITH_SERVER_PLUGINS) diff --git a/doc/api_break.dox b/doc/api_break.dox index c8a5089667a..a83b2c0a454 100644 --- a/doc/api_break.dox +++ b/doc/api_break.dox @@ -1898,6 +1898,13 @@ optional property map passing down layer level properties to the SLD encoders. I - usedAttributes is now a const method and returns QSet instead of QStringList +QgsRequestHandler {#qgis_api_break_3_0_QgsRequestHandler} +----------------- + +- Removed infoFormat and setInfoFormat methods: the format of the response is given and set with the "Content-Type" header. +- Removed setCoverageResponse + + Processing {#qgis_api_break_3_0_Processing} ---------- diff --git a/python/server/qgsrequesthandler.sip b/python/server/qgsrequesthandler.sip index b213b1761a4..f60190491d2 100644 --- a/python/server/qgsrequesthandler.sip +++ b/python/server/qgsrequesthandler.sip @@ -29,9 +29,6 @@ class QgsRequestHandler /Abstract/ /** Allow plugins to return a QgsServerException*/ void setServiceException( const QgsServerException& ex ); - //! @note not available in Python bindings - void setGetCoverageResponse( QByteArray* ba ); - /** Set an HTTP header*/ void setHeader( const QString &name, const QString &value ); @@ -50,9 +47,6 @@ class QgsRequestHandler /Abstract/ /** Append the bytestream to response body*/ void appendBody( const QByteArray &body ); - /** Set the info format string such as "text/xml"*/ - void setInfoFormat( const QString &format ); - /** Send out HTTP headers and flush output buffer*/ void sendResponse(); @@ -77,9 +71,6 @@ class QgsRequestHandler /Abstract/ /** Return the requested format string*/ QString format() const; - /** Return the mime type for the response*/ - QString infoFormat() const; - /** Return true if the HTTP headers were already sent to the client*/ bool headersSent() const; }; diff --git a/python/server/qgsserverexception.sip b/python/server/qgsserverexception.sip index 4baa3ea4190..c962c4eadbc 100644 --- a/python/server/qgsserverexception.sip +++ b/python/server/qgsserverexception.sip @@ -47,6 +47,7 @@ class QgsOgcServiceException QString message() const; QString code() const; QString locator() const; + QString version() const; virtual QByteArray formatResponse( QString& responseFormat / Out / ) const; }; diff --git a/python/server/qgsserverrequest.sip b/python/server/qgsserverrequest.sip index 93702090bac..03691eae8d6 100644 --- a/python/server/qgsserverrequest.sip +++ b/python/server/qgsserverrequest.sip @@ -79,6 +79,21 @@ class QgsServerRequest */ QMap parameters() const; + /** + * Set a parameter + */ + void setParameter( const QString& key, const QString& value ); + + /** + * Get a parameter value + */ + QString getParameter( const QString& key ) const; + + /** + * Remove a parameter + */ + void removeParameter( const QString& key ); + /** * Return post/put data * Check for QByteArray::isNull() to check if data diff --git a/src/server/CMakeLists.txt b/src/server/CMakeLists.txt index 63a6c7674e5..dc39db86343 100644 --- a/src/server/CMakeLists.txt +++ b/src/server/CMakeLists.txt @@ -24,8 +24,6 @@ SET ( qgis_mapserv_SRCS qgscapabilitiescache.cpp qgsconfigcache.cpp qgsrequesthandler.cpp - qgsowsserver.cpp - qgswcsserver.cpp qgsserversettings.cpp qgsserverexception.cpp qgsmslayercache.cpp diff --git a/src/server/qgsowsserver.cpp b/src/server/qgsowsserver.cpp deleted file mode 100644 index 841d0d11bdc..00000000000 --- a/src/server/qgsowsserver.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/*************************************************************************** - qgsowsserver.cpp - ------------------- - begin : February 27, 2012 - copyright : (C) 2012 by René-Luc D'Hont & Marco Hugentobler - 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 "qgsowsserver.h" -#include "qgsmessagelog.h" -#include "qgsvectorlayer.h" -#include "qgsvectordataprovider.h" - -#ifdef HAVE_SERVER_PYTHON_PLUGINS -//! Apply filter from AccessControl -void QgsOWSServer::applyAccessControlLayerFilters( QgsMapLayer* mapLayer, QHash& originalLayerFilters ) const -{ - if ( QgsVectorLayer* layer = qobject_cast( mapLayer ) ) - { - QString sql = mAccessControl->extraSubsetString( layer ); - if ( !sql.isEmpty() ) - { - if ( !originalLayerFilters.contains( layer ) ) - { - originalLayerFilters.insert( layer, layer->subsetString() ); - } - if ( !layer->subsetString().isEmpty() ) - { - sql.prepend( " AND " ); - sql.prepend( layer->subsetString() ); - } - if ( !layer->setSubsetString( sql ) ) - { - QgsMessageLog::logMessage( QStringLiteral( "Layer does not support Subset String" ) ); - } - } - } -} -#endif - -//! Restore layer filter as original -void QgsOWSServer::restoreLayerFilters( const QHash& filterMap ) -{ - QHash::const_iterator filterIt = filterMap.constBegin(); - for ( ; filterIt != filterMap.constEnd(); ++filterIt ) - { - QgsVectorLayer* filteredLayer = qobject_cast( filterIt.key() ); - if ( filteredLayer ) - { - QgsVectorDataProvider* dp = filteredLayer->dataProvider(); - if ( dp ) - { - dp->setSubsetString( filterIt.value() ); - } - } - } -} diff --git a/src/server/qgsowsserver.h b/src/server/qgsowsserver.h deleted file mode 100644 index 36de1f425b4..00000000000 --- a/src/server/qgsowsserver.h +++ /dev/null @@ -1,110 +0,0 @@ -/*************************************************************************** - qgsowsserver.h - -------------- - begin : March 24, 2014 - copyright : (C) 2006 by Marco Hugentobler - email : marco dot hugentobler at sourcepole 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 QGSOWSSERVER_H -#define QGSOWSSERVER_H - -#include "qgsconfig.h" -#include "qgsrequesthandler.h" -#include "qgsserversettings.h" -#ifdef HAVE_SERVER_PYTHON_PLUGINS -#include "qgsaccesscontrol.h" -#else -class QgsAccessControl; -#endif - -#include - -class QgsMapLayer; - -class QgsOWSServer -{ - public: - QgsOWSServer( - const QString& configFilePath - , const QgsServerSettings& settings - , const QMap& parameters - , QgsRequestHandler* rh - , QgsAccessControl* ac - ) - : mSettings( settings ) - , mParameters( parameters ) - , mRequestHandler( rh ) - , mConfigFilePath( configFilePath ) - , mAccessControl( ac ) - {} - virtual ~QgsOWSServer() = default; - - virtual void executeRequest() = 0; - - /** Restores the original layer filters - * @param filterMap the original layer filter - */ - static void restoreLayerFilters( const QHash < QgsMapLayer*, QString >& filterMap ); - - private: - QgsOWSServer() {} - - protected: - QgsServerSettings mSettings; - QMap mParameters; - QgsRequestHandler* mRequestHandler; - QString mConfigFilePath; - - //! The access control helper - QgsAccessControl* mAccessControl; - -#ifdef HAVE_SERVER_PYTHON_PLUGINS - - /** Apply filter strings from the access control to the layers. - * @param layer the concerned layer - * @param originalLayerFilters the original layer filter - * - */ - void applyAccessControlLayerFilters( QgsMapLayer* layer, QHash& originalLayerFilters ) const; -#endif - -}; - -/** RAII class to restore layer filters on destruction - */ -class QgsOWSServerFilterRestorer -{ - public: - - QgsOWSServerFilterRestorer() = default; - - QgsOWSServerFilterRestorer( const QgsOWSServerFilterRestorer& rh ) = delete; - QgsOWSServerFilterRestorer& operator=( const QgsOWSServerFilterRestorer& rh ) = delete; - - //! Destructor. When object is destroyed all original layer filters will be restored. - ~QgsOWSServerFilterRestorer() - { - QgsOWSServer::restoreLayerFilters( mOriginalLayerFilters ); - } - - /** Returns a reference to the object's hash of layers to original subsetString filters. - * Original layer subsetString filters MUST be inserted into this hash before modifying them. - */ - QHash& originalFilters() { return mOriginalLayerFilters; } - - private: - QHash mOriginalLayerFilters; - -}; - -#endif // QGSOWSSERVER_H diff --git a/src/server/qgsrequesthandler.cpp b/src/server/qgsrequesthandler.cpp index 9e416692c84..1c0a75eaf08 100644 --- a/src/server/qgsrequesthandler.cpp +++ b/src/server/qgsrequesthandler.cpp @@ -53,20 +53,6 @@ QMap QgsRequestHandler::parameterMap() const return mRequest.parameters(); } -void QgsRequestHandler::setHttpResponse( const QByteArray& ba, const QString &format ) -{ - QgsMessageLog::logMessage( QStringLiteral( "Checking byte array is ok to set..." ) ); - - if ( ba.size() < 1 ) - { - return; - } - - QgsMessageLog::logMessage( QStringLiteral( "Byte array looks good, setting response..." ) ); - appendBody( ba ); - setInfoFormat( format ); -} - bool QgsRequestHandler::exceptionRaised() const { return mExceptionRaised; @@ -107,55 +93,12 @@ void QgsRequestHandler::appendBody( const QByteArray &body ) mResponse.write( body ); } -void QgsRequestHandler::setInfoFormat( const QString &format ) -{ - mInfoFormat = format; - - // Update header - QString fmt = mInfoFormat; - if ( mInfoFormat.startsWith( QLatin1String( "text/" ) ) || mInfoFormat.startsWith( QLatin1String( "application/vnd.ogc.gml" ) ) ) - { - fmt.append( "; charset=utf-8" ); - } - setHeader( QStringLiteral( "Content-Type" ), fmt ); - -} - void QgsRequestHandler::sendResponse() { // Send data to output mResponse.flush(); } - - -QString QgsRequestHandler::formatToMimeType( const QString& format ) const -{ - if ( format.compare( QLatin1String( "png" ), Qt::CaseInsensitive ) == 0 ) - { - return QStringLiteral( "image/png" ); - } - else if ( format.compare( QLatin1String( "jpg" ), Qt::CaseInsensitive ) == 0 ) - { - return QStringLiteral( "image/jpeg" ); - } - else if ( format.compare( QLatin1String( "svg" ), Qt::CaseInsensitive ) == 0 ) - { - return QStringLiteral( "image/svg+xml" ); - } - else if ( format.compare( QLatin1String( "pdf" ), Qt::CaseInsensitive ) == 0 ) - { - return QStringLiteral( "application/pdf" ); - } - return format; -} - -void QgsRequestHandler::setGetCapabilitiesResponse( const QDomDocument& doc ) -{ - QByteArray ba = doc.toByteArray(); - setHttpResponse( ba, QStringLiteral( "text/xml" ) ); -} - void QgsRequestHandler::setServiceException( const QgsServerException& ex ) { // Safety measure to avoid potential leaks if called repeatedly @@ -163,14 +106,6 @@ void QgsRequestHandler::setServiceException( const QgsServerException& ex ) mResponse.write( ex ); } -void QgsRequestHandler::setGetCoverageResponse( QByteArray* ba ) -{ - if ( ba ) - { - setHttpResponse( *ba, QStringLiteral( "image/tiff" ) ); - } -} - void QgsRequestHandler::setupParameters() { const QgsServerRequest::Parameters parameters = mRequest.parameters(); diff --git a/src/server/qgsrequesthandler.h b/src/server/qgsrequesthandler.h index ba5267820f1..8250f1db091 100644 --- a/src/server/qgsrequesthandler.h +++ b/src/server/qgsrequesthandler.h @@ -54,15 +54,9 @@ class SERVER_EXPORT QgsRequestHandler explicit QgsRequestHandler( QgsServerRequest& request, QgsServerResponse& response ); ~QgsRequestHandler(); - //! @note not available in Python bindings - void setGetCapabilitiesResponse( const QDomDocument& doc ); - //! Allow plugins to return a QgsMapServiceException void setServiceException( const QgsServerException &ex ); - //! @note not available in Python bindings - void setGetCoverageResponse( QByteArray* ba ); - /** Send out HTTP headers and flush output buffer * * This method is intended only for streaming @@ -88,9 +82,6 @@ class SERVER_EXPORT QgsRequestHandler //! Set the info format string such as "text/xml" void appendBody( const QByteArray &body ); - //! Set the info format string such as "text/xml" - void setInfoFormat( const QString &format ); - //! Pointer to last raised exception bool exceptionRaised() const; @@ -117,19 +108,9 @@ class SERVER_EXPORT QgsRequestHandler //! Return the requested format string QString format() const { return mFormat; } - //! Return the mime type for the response - QString infoFormat() const { return mInfoFormat; } - //! Return true if the HTTP headers were already sent to the client bool headersSent() const; - private: - void setHttpResponse( const QByteArray& ba, const QString &format ); - - /** Converts format to official mimetype (e.g. 'jpg' to 'image/jpeg') - @return mime string (or the entered string if not found)*/ - QString formatToMimeType( const QString& format ) const; - private: void setupParameters(); @@ -138,7 +119,6 @@ class SERVER_EXPORT QgsRequestHandler QString mFormat; QString mFormatString; //format string as it is passed in the request (with base) QString mService; - QString mInfoFormat; bool mExceptionRaised; QgsServerRequest& mRequest; diff --git a/src/server/qgsserver.cpp b/src/server/qgsserver.cpp index 113ec2db7eb..6d57d70ed06 100644 --- a/src/server/qgsserver.cpp +++ b/src/server/qgsserver.cpp @@ -22,7 +22,6 @@ #include "qgsconfig.h" #include "qgsserver.h" #include "qgsmslayercache.h" - #include "qgsmapsettings.h" #include "qgsauthmanager.h" #include "qgscapabilitiescache.h" @@ -31,7 +30,6 @@ #include "qgsproject.h" #include "qgsproviderregistry.h" #include "qgslogger.h" -#include "qgswcsserver.h" #include "qgsmapserviceexception.h" #include "qgspallabeling.h" #include "qgsnetworkaccessmanager.h" @@ -403,8 +401,6 @@ void QgsServer::handleRequest( QgsServerRequest& request, QgsServerResponse& res QMap parameterMap = request.parameters(); printRequestParameters( parameterMap, logLevel ); - QgsAccessControl* accessControl = sServerInterface->accessControls(); - //Config file path QString configFilePath = configPath( *sConfigFilePath, parameterMap ); @@ -438,31 +434,6 @@ void QgsServer::handleRequest( QgsServerRequest& request, QgsServerResponse& res { service->executeRequest( request, theResponse ); } - else if ( serviceString == QLatin1String( "WCS" ) ) - { - - QgsWCSProjectParser* p = QgsConfigCache::instance()->wcsConfiguration( - configFilePath - , accessControl - ); - if ( !p ) - { - theRequestHandler.setServiceException( QgsMapServiceException( QStringLiteral( "Project file error" ), - QStringLiteral( "Error reading the project file" ) ) ); - } - else - { - QgsWCSServer wcsServer( - configFilePath - , sSettings - , parameterMap - , p - , &theRequestHandler - , accessControl - ); - wcsServer.executeRequest(); - } - } else { throw QgsOgcServiceException( QStringLiteral( "Service configuration error" ), diff --git a/src/server/qgsserverexception.h b/src/server/qgsserverexception.h index 4bd6764087e..68b789c353b 100644 --- a/src/server/qgsserverexception.h +++ b/src/server/qgsserverexception.h @@ -27,10 +27,13 @@ /** \ingroup server * \class QgsServerException * \brief Exception base class for server exceptions. + * + * @note added in QGIS 3.0 */ class SERVER_EXPORT QgsServerException : public QgsException { public: + //! Constructor QgsServerException( const QString& message, int responseCode = 500 ); /** @@ -52,23 +55,34 @@ class SERVER_EXPORT QgsServerException : public QgsException }; /** \ingroup server - * \class QgsOcgServiceException + * \class QgsOgcServiceException * \brief Exception base class for service exceptions. * - * Note that this exception is assaciated with a default return code 200 which may be + * Note that this exception is associated with a default return code 200 which may be * not appropriate in some situations. + * + * @note added in QGIS 3.0 */ class SERVER_EXPORT QgsOgcServiceException : public QgsServerException { public: + //! Construction QgsOgcServiceException( const QString& code, const QString& message, const QString& locator = QString(), int responseCode = 200, const QString& version = QStringLiteral( "1.3.0" ) ); + //! @return message QString message() const { return mMessage; } + + //! @return code QString code() const { return mCode; } + + //! @return locator QString locator() const { return mLocator; } + + //!return exception version QString version() const { return mVersion; } + //! Overrided from QgsServerException virtual QByteArray formatResponse( QString& responseFormat ) const override; private: @@ -76,8 +90,6 @@ class SERVER_EXPORT QgsOgcServiceException : public QgsServerException QString mMessage; QString mLocator; QString mVersion; - - }; #endif diff --git a/src/server/qgsserverrequest.h b/src/server/qgsserverrequest.h index 8f6c694872f..23342ebee7e 100644 --- a/src/server/qgsserverrequest.h +++ b/src/server/qgsserverrequest.h @@ -27,6 +27,8 @@ * \ingroup server * QgsServerRequest * Class defining request interface passed to services QgsService::executeRequest() method + * + * @note added in QGIS 3.0 */ // Note about design: this interface must be passed along to python and thus signatures methods must be @@ -38,6 +40,9 @@ class SERVER_EXPORT QgsServerRequest typedef QMap Parameters; + /** + * HTTP Method (or equivalent) used for the request + */ enum Method { HeadMethod, PutMethod, GetMethod, PostMethod, DeleteMethod diff --git a/src/server/qgsserverresponse.h b/src/server/qgsserverresponse.h index dd4261d3333..1e42ae86072 100644 --- a/src/server/qgsserverresponse.h +++ b/src/server/qgsserverresponse.h @@ -30,6 +30,8 @@ class QgsServerException; * \ingroup server * QgsServerResponse * Class defining response interface passed to services QgsService::executeRequest() method + * + * @note added in QGIS 3.0 */ // Note: diff --git a/src/server/qgsservice.h b/src/server/qgsservice.h index 9eeb164bfa7..f5bc8eb87b2 100644 --- a/src/server/qgsservice.h +++ b/src/server/qgsservice.h @@ -35,6 +35,7 @@ class QgsProject; * This class provides methods for executing server requests * They are registered at runtime for a given service name. * + * @note added in QGIS 3.0 */ class SERVER_EXPORT QgsService { diff --git a/src/server/qgsserviceregistry.h b/src/server/qgsserviceregistry.h index d11830f68d9..8ce27866089 100644 --- a/src/server/qgsserviceregistry.h +++ b/src/server/qgsserviceregistry.h @@ -41,6 +41,7 @@ class QgsServerInterface; * IMPORTANT: The registry hold ownership of registered services and * will call 'delete' on cleanup * + * @note added in QGIS 3.0 */ class SERVER_EXPORT QgsServiceRegistry { diff --git a/src/server/qgswcsserver.cpp b/src/server/qgswcsserver.cpp deleted file mode 100644 index e40114b39b0..00000000000 --- a/src/server/qgswcsserver.cpp +++ /dev/null @@ -1,493 +0,0 @@ -/*************************************************************************** - 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 -#include - -#ifndef Q_OS_WIN -#include -#else -#include -#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 - , const QgsServerSettings& settings - , QMap ¶meters - , QgsWCSProjectParser* pp - , QgsRequestHandler* rh - , QgsAccessControl* accessControl -) - : QgsOWSServer( - configFilePath - , settings - , parameters - , rh - , accessControl - ) - , mConfigParser( - pp - ) -{ -} - -QgsWCSServer::QgsWCSServer() - : QgsOWSServer( - QString() - , QgsServerSettings() - , QMap() - , nullptr - , nullptr - ) - , mConfigParser( nullptr ) -{ -} - -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; - if ( mConfigParser ) - { - hrefString = mConfigParser->wcsServiceUrl(); - if ( hrefString.isEmpty() ) - { - hrefString = mConfigParser->serviceUrl(); - } - } - 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::const_iterator cove_name_it = mParameters.constFind( QStringLiteral( "COVERAGE" ) ); - if ( cove_name_it != mParameters.constEnd() ) - { - coveName = cove_name_it.value(); - } - if ( coveName == QLatin1String( "" ) ) - { - QMap::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 layerList; - - QStringList mErrors = QStringList(); - - //defining coverage name - QString coveName = QLatin1String( "" ); - //read COVERAGE - QMap::const_iterator cove_name_it = mParameters.constFind( QStringLiteral( "COVERAGE" ) ); - if ( cove_name_it != mParameters.constEnd() ) - { - coveName = cove_name_it.value(); - } - if ( coveName == QLatin1String( "" ) ) - { - QMap::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::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( 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 > queryItems = mapUrl.queryItems(); - QList >::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(); -} diff --git a/src/server/qgswcsserver.h b/src/server/qgswcsserver.h deleted file mode 100644 index 0facebacb60..00000000000 --- a/src/server/qgswcsserver.h +++ /dev/null @@ -1,73 +0,0 @@ -/*************************************************************************** - qgswcsserver.h - ------------------- - 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. * - * * - ***************************************************************************/ - -#ifndef QGSWCSSERVER_H -#define QGSWCSSERVER_H - -#include -#include -#include -#include -#include "qgis.h" -#include "qgsowsserver.h" - -class QgsWCSProjectParser; -class QgsRequestHandler; - -/** This class handles all the wcs server requests. The parameters and values have to be passed in the form of -a map. This map is usually generated by a subclass of QgsWMSRequestHandler, which makes QgsWCSServer -independent from any server side technology*/ - -class QgsWCSServer: public QgsOWSServer -{ - public: - //! Constructor. Takes parameter map and a pointer to a renderer object (does not take ownership) - QgsWCSServer( - const QString& configFilePath - , const QgsServerSettings& settings - , QMap& parameters - , QgsWCSProjectParser* pp - , QgsRequestHandler* rh - , QgsAccessControl* accessControl - ); - - void executeRequest() override; - - //! Returns an XML file with the capabilities description (as described in the WFS specs) - QDomDocument getCapabilities(); - - //! Returns an XML file with the describe Coverage (as described in the WCS specs) - QDomDocument describeCoverage(); - - //! Creates a file which is the result of the getCoverage request. - QByteArray* getCoverage(); - - //! Sets configuration parser for administration settings. Does not take ownership - void setAdminConfigParser( QgsWCSProjectParser* parser ) { mConfigParser = parser; } - - private: - //! Don't use the default constructor - QgsWCSServer(); - - //! Get service address from REQUEST_URI if not specified in the configuration - QString serviceUrl() const; - - QgsWCSProjectParser* mConfigParser; - -}; - -#endif diff --git a/src/server/services/CMakeLists.txt b/src/server/services/CMakeLists.txt index 7df93a9a024..470eff3bd02 100644 --- a/src/server/services/CMakeLists.txt +++ b/src/server/services/CMakeLists.txt @@ -9,4 +9,5 @@ SET (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${QGIS_OUTPUT_DIRECTORY}/${QGIS_SERVER_MODUL ADD_SUBDIRECTORY(DummyService) ADD_SUBDIRECTORY(wms) ADD_SUBDIRECTORY(wfs) +ADD_SUBDIRECTORY(wcs) diff --git a/src/server/services/wcs/CMakeLists.txt b/src/server/services/wcs/CMakeLists.txt new file mode 100644 index 00000000000..8a7a327598b --- /dev/null +++ b/src/server/services/wcs/CMakeLists.txt @@ -0,0 +1,59 @@ + +######################################################## +# Files + +SET (wcs_SRCS + qgswcs.cpp + qgswcsutils.cpp + qgswcsgetcapabilities.cpp + qgswcsdescribecoverage.cpp + qgswcsgetcoverage.cpp +) + +######################################################## +# Build + +ADD_LIBRARY (wcs MODULE ${wcs_SRCS}) + + +INCLUDE_DIRECTORIES(SYSTEM + ${GDAL_INCLUDE_DIR} + ${GEOS_INCLUDE_DIR} + ${PROJ_INCLUDE_DIR} + ${POSTGRES_INCLUDE_DIR} +) + +INCLUDE_DIRECTORIES( + ${CMAKE_BINARY_DIR}/src/core + ${CMAKE_BINARY_DIR}/src/python + ${CMAKE_BINARY_DIR}/src/analysis + ${CMAKE_BINARY_DIR}/src/server + ${CMAKE_CURRENT_BINARY_DIR} + ../../../core + ../../../core/dxf + ../../../core/geometry + ../../../core/raster + ../../../core/symbology-ng + ../../../core/composer + ../../../core/layertree + ../.. + .. + . +) + + +#endif +TARGET_LINK_LIBRARIES(wcs + qgis_core + qgis_server +) + + +######################################################## +# Install + +INSTALL(TARGETS wcs + RUNTIME DESTINATION ${QGIS_SERVER_MODULE_DIR} + LIBRARY DESTINATION ${QGIS_SERVER_MODULE_DIR} +) + diff --git a/src/server/services/wcs/qgswcs.cpp b/src/server/services/wcs/qgswcs.cpp new file mode 100644 index 00000000000..b30858ff273 --- /dev/null +++ b/src/server/services/wcs/qgswcs.cpp @@ -0,0 +1,124 @@ +/*************************************************************************** + qgswcs.cpp + ------------------------- + begin : January 16 , 2017 + copyright : (C) 2013 by René-Luc D'Hont ( parts from qgswcsserver ) + (C) 2017 by David Marteau + email : rldhont at 3liz dot com + david dot marteau 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 "qgsmodule.h" +#include "qgswcsutils.h" +#include "qgswcsgetcapabilities.h" +#include "qgswcsdescribecoverage.h" +#include "qgswcsgetcoverage.h" + +#define QSTR_COMPARE( str, lit )\ + (str.compare( QStringLiteral( lit ), Qt::CaseInsensitive ) == 0) + +namespace QgsWcs +{ + + class Service: public QgsService + { + public: + // Constructor + Service( QgsServerInterface* serverIface ) + : mServerIface( serverIface ) + {} + + QString name() const { return QStringLiteral( "WCS" ); } + QString version() const { return implementationVersion(); } + + bool allowMethod( QgsServerRequest::Method method ) const + { + return method == QgsServerRequest::GetMethod || method == QgsServerRequest::PostMethod; + } + + void executeRequest( const QgsServerRequest& request, QgsServerResponse& response, + QgsProject* project ) + { + Q_UNUSED( project ); + + QgsServerRequest::Parameters params = request.parameters(); + QString versionString = params.value( "VERSION" ); + + // Set the default version + if ( versionString.isEmpty() ) + { + versionString = version(); + } + + // Get the request + QString req = params.value( QStringLiteral( "REQUEST" ) ); + if ( req.isEmpty() ) + { + throw QgsServiceException( QStringLiteral( "OperationNotSupported" ), + QStringLiteral( "Please check the value of the REQUEST parameter" ) ); + } + + if ( QSTR_COMPARE( req, "GetCapabilities" ) ) + { + writeGetCapabilities( mServerIface, versionString, request, response ); + } + else if ( QSTR_COMPARE( req, "DescribeCoverage" ) ) + { + writeDescribeCoverage( mServerIface, versionString, request, response ); + } + else if ( QSTR_COMPARE( req, "GetCoverage" ) ) + { + writeGetCoverage( mServerIface, versionString, request, response ); + } + else + { + // Operation not supported + throw QgsServiceException( QStringLiteral( "OperationNotSupported" ), + QStringLiteral( "Request %1 is not supported" ).arg( req ) ); + } + } + + private: + QgsServerInterface* mServerIface; + }; + + +} // namespace QgsWfs + + +// Module +class QgsWcsModule: public QgsServiceModule +{ + public: + void registerSelf( QgsServiceRegistry& registry, QgsServerInterface* serverIface ) + { + QgsDebugMsg( "WCSModule::registerSelf called" ); + registry.registerService( new QgsWcs::Service( serverIface ) ); + } +}; + + +// Entry points +QGISEXTERN QgsServiceModule* QGS_ServiceModule_Init() +{ + static QgsWcsModule module; + return &module; +} +QGISEXTERN void QGS_ServiceModule_Exit( QgsServiceModule* ) +{ + // Nothing to do +} + + + + + diff --git a/src/server/services/wcs/qgswcsdescribecoverage.cpp b/src/server/services/wcs/qgswcsdescribecoverage.cpp new file mode 100644 index 00000000000..2c7fb75ff5a --- /dev/null +++ b/src/server/services/wcs/qgswcsdescribecoverage.cpp @@ -0,0 +1,83 @@ +/*************************************************************************** + qgswcsdescribecoverage.cpp + ------------------------- + begin : January 16 , 2017 + copyright : (C) 2013 by René-Luc D'Hont ( parts from qgswcsserver ) + (C) 2017 by David Marteau + email : rldhont at 3liz dot com + david dot marteau 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 "qgswcsutils.h" +#include "qgswcsdescribecoverage.h" + +namespace QgsWcs +{ + + /** + * Output WCS DescribeCoverage response + */ + void writeDescribeCoverage( QgsServerInterface* serverIface, const QString& version, + const QgsServerRequest& request, QgsServerResponse& response ) + { + QDomDocument doc = createDescribeCoverageDocument( serverIface, version, request ); + + response.setHeader( "Content-Type", "text/xml; charset=utf-8" ); + response.write( doc.toByteArray() ); + } + + + QDomDocument createDescribeCoverageDocument( QgsServerInterface* serverIface, const QString& version, + const QgsServerRequest& request ) + { + Q_UNUSED( version ); + + QDomDocument doc; + + QgsServerRequest::Parameters parameters = request.parameters(); + + QgsWCSProjectParser* configParser = getConfigParser( serverIface ); + + //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; + //read COVERAGE + QMap::const_iterator cove_name_it = parameters.constFind( QStringLiteral( "COVERAGE" ) ); + if ( cove_name_it != parameters.constEnd() ) + { + coveName = cove_name_it.value(); + } + if ( coveName.isEmpty() ) + { + QMap::const_iterator cove_name_it = parameters.constFind( QStringLiteral( "IDENTIFIER" ) ); + if ( cove_name_it != parameters.constEnd() ) + { + coveName = cove_name_it.value(); + } + } + configParser->describeCoverage( coveName, coveDescElement, doc ); + return doc; + } + +} // namespace QgsWcs + + + diff --git a/src/server/services/wcs/qgswcsdescribecoverage.h b/src/server/services/wcs/qgswcsdescribecoverage.h new file mode 100644 index 00000000000..345462b36b1 --- /dev/null +++ b/src/server/services/wcs/qgswcsdescribecoverage.h @@ -0,0 +1,41 @@ +/*************************************************************************** + qgswcsdescribecoverage.h + ------------------------- + begin : January 16 , 2017 + copyright : (C) 2013 by René-Luc D'Hont ( parts from qgswcsserver ) + (C) 2017 by David Marteau + email : rldhont at 3liz dot com + david dot marteau 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. * + * * + ***************************************************************************/ +#ifndef QGSWCSDESCRIBECOVERAGE_H +#define QGSWCSDESCRIBECOVERAGE_H + +#include + +namespace QgsWcs +{ + + /** + * Create describe coverage document + */ + QDomDocument createDescribeCoverageDocument( QgsServerInterface* serverIface, const QString& version, + const QgsServerRequest& request ); + + /** Output WCS DescribeCoverage response + */ + void writeDescribeCoverage( QgsServerInterface* serverIface, const QString& version, + const QgsServerRequest& request, QgsServerResponse& response ); + +} // samespace QgsWcs + +#endif + diff --git a/src/server/services/wcs/qgswcsgetcapabilities.cpp b/src/server/services/wcs/qgswcsgetcapabilities.cpp new file mode 100644 index 00000000000..b5a6a89b604 --- /dev/null +++ b/src/server/services/wcs/qgswcsgetcapabilities.cpp @@ -0,0 +1,121 @@ +/*************************************************************************** + qgswcsgecapabilities.cpp + ------------------------- + begin : January 16 , 2017 + copyright : (C) 2013 by René-Luc D'Hont ( parts from qgswcsserver ) + (C) 2017 by David Marteau + email : rldhont at 3liz dot com + david dot marteau 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 "qgswcsutils.h" +#include "qgswcsgetcapabilities.h" + +namespace QgsWcs +{ + + /** + * Output WCS GetCapabilities response + */ + void writeGetCapabilities( QgsServerInterface* serverIface, const QString& version, + const QgsServerRequest& request, QgsServerResponse& response ) + { + QDomDocument doc = createGetCapabilitiesDocument( serverIface, version, request ); + + response.setHeader( "Content-Type", "text/xml; charset=utf-8" ); + response.write( doc.toByteArray() ); + } + + + QDomDocument createGetCapabilitiesDocument( QgsServerInterface* serverIface, const QString& version, + const QgsServerRequest& request ) + { + Q_UNUSED( version ); + + QDomDocument doc; + + QgsWCSProjectParser* configParser = getConfigParser( serverIface ); + + //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" ), implementationVersion() ); + wcsCapabilitiesElement.setAttribute( QStringLiteral( "updateSequence" ), QStringLiteral( "0" ) ); + doc.appendChild( wcsCapabilitiesElement ); + + configParser->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 = serviceUrl( request, configParser ); + + 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 ( configParser ) + { + configParser->wcsContentMetadata( contentMetadataElement, doc ); + } + + return doc; + + } + +} // namespace QgsWcs + + + diff --git a/src/server/services/wcs/qgswcsgetcapabilities.h b/src/server/services/wcs/qgswcsgetcapabilities.h new file mode 100644 index 00000000000..7096d2e5763 --- /dev/null +++ b/src/server/services/wcs/qgswcsgetcapabilities.h @@ -0,0 +1,41 @@ +/*************************************************************************** + qgswcsgecapabilities.h + ------------------------- + begin : January 16 , 2017 + copyright : (C) 2013 by René-Luc D'Hont ( parts from qgswcsserver ) + (C) 2017 by David Marteau + email : rldhont at 3liz dot com + david dot marteau 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. * + * * + ***************************************************************************/ +#ifndef QGSWCSGETCAPABILITIES_H +#define QGSWCSGETCAPABILITIES_H + +#include + +namespace QgsWcs +{ + + /** + * Create get capabilities document + */ + QDomDocument createGetCapabilitiesDocument( QgsServerInterface* serverIface, const QString& version, + const QgsServerRequest& request ); + + /** Output WCS GetCapabilities response + */ + void writeGetCapabilities( QgsServerInterface* serverIface, const QString& version, + const QgsServerRequest& request, QgsServerResponse& response ); + +} // samespace QgsWcs + +#endif + diff --git a/src/server/services/wcs/qgswcsgetcoverage.cpp b/src/server/services/wcs/qgswcsgetcoverage.cpp new file mode 100644 index 00000000000..3a69e5dfd3d --- /dev/null +++ b/src/server/services/wcs/qgswcsgetcoverage.cpp @@ -0,0 +1,205 @@ +/*************************************************************************** + qgswcsgetcoverage.cpp + ------------------------- + begin : January 16 , 2017 + copyright : (C) 2013 by René-Luc D'Hont ( parts from qgswcsserver ) + (C) 2017 by David Marteau + email : rldhont at 3liz dot com + david dot marteau 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 "qgswcsutils.h" +#include "qgsrasterlayer.h" +#include "qgsrasterdataprovider.h" +#include "qgsrasterpipe.h" +#include "qgsrasterprojector.h" +#include "qgsrasterfilewriter.h" +#include "qgswcsgetcoverage.h" + +#include + +namespace QgsWcs +{ + + /** + * Output WCS DescribeCoverage response + */ + void writeGetCoverage( QgsServerInterface* serverIface, const QString& version, + const QgsServerRequest& request, QgsServerResponse& response ) + { + Q_UNUSED( version ); + + response.write( getCoverageData( serverIface, request ) ); + response.setHeader( "Content-Type", "image/tiff" ); + } + + QByteArray getCoverageData( QgsServerInterface* serverIface, const QgsServerRequest& request ) + { + QgsWCSProjectParser* configParser = getConfigParser( serverIface ); + + QgsAccessControl* accessControl = serverIface->accessControls(); + + QStringList wcsLayersId = configParser->wcsLayers(); + + QList layerList; + + QgsServerRequest::Parameters parameters = request.parameters(); + + //defining coverage name + QString coveName; + //read COVERAGE + QMap::const_iterator cove_name_it = parameters.constFind( QStringLiteral( "COVERAGE" ) ); + if ( cove_name_it != parameters.constEnd() ) + { + coveName = cove_name_it.value(); + } + if ( coveName.isEmpty() ) + { + QMap::const_iterator cove_name_it = parameters.constFind( QStringLiteral( "IDENTIFIER" ) ); + if ( cove_name_it != parameters.constEnd() ) + { + coveName = cove_name_it.value(); + } + } + + if ( coveName.isEmpty() ) + { + throw QgsRequestNotWellFormedException( QStringLiteral( "COVERAGE is mandatory" ) ); + } + + layerList = configParser->mapLayerFromCoverage( coveName ); + if ( layerList.size() < 1 ) + { + throw QgsRequestNotWellFormedException( QStringLiteral( "The layer for the COVERAGE '%1' is not found" ).arg( coveName ) ); + } + + double minx = 0.0, miny = 0.0, maxx = 0.0, maxy = 0.0; + // WIDTh and HEIGHT + int width = 0, height = 0; + // CRS + QString crs; + + // read BBOX + QgsRectangle bbox = parseBbox( parameters.value( QStringLiteral( "BBOX" ) ) ); + if ( !bbox.isEmpty() ) + { + minx = bbox.xMinimum(); + miny = bbox.yMinimum(); + maxx = bbox.xMaximum(); + maxy = bbox.yMaximum(); + } + else + { + throw QgsRequestNotWellFormedException( QStringLiteral( "The BBOX is mandatory and has to be xx.xxx,yy.yyy,xx.xxx,yy.yyy" ) ); + } + + // read WIDTH + bool conversionSuccess = false; + width = parameters.value( QStringLiteral( "WIDTH" ), QStringLiteral( "0" ) ).toInt( &conversionSuccess ); + if ( !conversionSuccess ) + { + width = 0; + } + // read HEIGHT + height = parameters.value( QStringLiteral( "HEIGHT" ), QStringLiteral( "0" ) ).toInt( &conversionSuccess ); + if ( !conversionSuccess ) + { + height = 0; + } + + if ( width < 0 || height < 0 ) + { + throw QgsRequestNotWellFormedException( QStringLiteral( "The WIDTH and HEIGHT are mandatory and have to be integer" ) ); + } + + crs = parameters.value( QStringLiteral( "CRS" ) ); + if ( crs.isEmpty() ) + { + throw QgsRequestNotWellFormedException( QStringLiteral( "The CRS is mandatory" ) ); + } + + QgsCoordinateReferenceSystem requestCRS = QgsCoordinateReferenceSystem::fromOgcWmsCrs( crs ); + if ( !requestCRS.isValid() ) + { + throw QgsRequestNotWellFormedException( QStringLiteral( "Invalid CRS" ) ); + } + + QgsRectangle rect( minx, miny, maxx, maxy ); + + QgsMapLayer* layer = layerList.at( 0 ); + QgsRasterLayer* rLayer = qobject_cast( layer ); + if ( rLayer && wcsLayersId.contains( rLayer->id() ) ) + { +#ifdef HAVE_SERVER_PYTHON_PLUGINS + if ( !accessControl->layerReadPermission( rLayer ) ) + { + throw QgsSecurityAccessException( QStringLiteral( "You are not allowed to access to this coverage" ) ); + } +#endif + + // RESPONSE_CRS + QgsCoordinateReferenceSystem responseCRS = rLayer->crs(); + crs = parameters.value( QStringLiteral( "RESPONSE_CRS" ) ); + if ( crs.isEmpty() ) + { + 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; + if ( !pipe.set( rLayer->dataProvider()->clone() ) ) + { + throw QgsRequestNotWellFormedException( QStringLiteral( "Cannet set pipe provider" ) ); + } + + // add projector if necessary + if ( responseCRS != rLayer->crs() ) + { + QgsRasterProjector * projector = new QgsRasterProjector; + projector->setCrs( rLayer->crs(), responseCRS ); + if ( !pipe.insert( 2, projector ) ) + { + throw QgsRequestNotWellFormedException( QStringLiteral( "Cannot set pipe projector" ) ); + } + } + + QgsRasterFileWriter::WriterError err = fileWriter.writeRaster( &pipe, width, height, rect, responseCRS ); + if ( err != QgsRasterFileWriter::NoError ) + { + throw QgsRequestNotWellFormedException( QStringLiteral( "Cannot write raster error code: %1" ).arg( err ) ); + } + return tempFile.readAll(); + } + else + { + return QByteArray(); + } + } + +} // namespace QgsWcs + + + diff --git a/src/server/services/wcs/qgswcsgetcoverage.h b/src/server/services/wcs/qgswcsgetcoverage.h new file mode 100644 index 00000000000..bf4f33886ee --- /dev/null +++ b/src/server/services/wcs/qgswcsgetcoverage.h @@ -0,0 +1,40 @@ +/*************************************************************************** + qgswcsgetcoverage.h + ------------------------- + begin : January 16 , 2017 + copyright : (C) 2013 by René-Luc D'Hont ( parts from qgswcsserver ) + (C) 2017 by David Marteau + email : rldhont at 3liz dot com + david dot marteau 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. * + * * + ***************************************************************************/ +#ifndef QGSWCSGETCOVERAGE_H +#define QGSWCSGETCOVERAGE_H + +#include + +namespace QgsWcs +{ + + /** Output WCS GetCoverage response + */ + void writeGetCoverage( QgsServerInterface* serverIface, const QString& version, + const QgsServerRequest& request, QgsServerResponse& response ); + + /** + * Compute coverage data + */ + QByteArray getCoverageData( QgsServerInterface* serverIface, const QgsServerRequest& request ); + +} // samespace QgsWcs + +#endif + diff --git a/src/server/services/wcs/qgswcsserviceexception.h b/src/server/services/wcs/qgswcsserviceexception.h new file mode 100644 index 00000000000..0fdf3e5d58c --- /dev/null +++ b/src/server/services/wcs/qgswcsserviceexception.h @@ -0,0 +1,80 @@ +/*************************************************************************** + qgswcsserviceexception.h + ------------------------ + begin : January 17, 2017 + copyright : (C) 2017 by David Marteau + email : david dot marteau 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. * + * * + ***************************************************************************/ + +#ifndef QGSWCSSERVICEEXCEPTION_H +#define QGSWCSSERVICEEXCEPTION_H + +#include + +#include "qgsserverexception.h" + +namespace QgsWcs +{ + + /** \ingroup server + * \class QgsserviceException + * \brief Exception class for WFS service exceptions. + */ + class QgsServiceException : public QgsOgcServiceException + { + public: + QgsServiceException( const QString& code, const QString& message, + int responseCode = 200 ) + : QgsOgcServiceException( code, message, QString(), responseCode, QStringLiteral( "1.2.0" ) ) + {} + + QgsServiceException( const QString& code, const QString& message, const QString& locator, + int responseCode = 200 ) + : QgsOgcServiceException( code, message, locator, responseCode, QStringLiteral( "1.2.0" ) ) + {} + + }; + + + /** \ingroup server + * \class QgsSecurityAccessException + * \brief Exception thrown when data access violates access controls + */ + class QgsSecurityAccessException: public QgsServiceException + { + public: + QgsSecurityAccessException( const QString& message, const QString& locator = QString() ) + : QgsServiceException( QStringLiteral( "Security" ), message, locator, 403 ) + {} + }; + + /** \ingroup server + * \class QgsRequestNotWellFormedException + * \brief Exception thrown in case of malformed request + */ + class QgsRequestNotWellFormedException: public QgsServiceException + { + public: + QgsRequestNotWellFormedException( const QString& message, const QString& locator = QString() ) + : QgsServiceException( QStringLiteral( "RequestNotWellFormed" ), message, locator, 400 ) + {} + }; + + + + + + +} // namespace QgsWcs + +#endif + diff --git a/src/server/services/wcs/qgswcsutils.cpp b/src/server/services/wcs/qgswcsutils.cpp new file mode 100644 index 00000000000..95746014c39 --- /dev/null +++ b/src/server/services/wcs/qgswcsutils.cpp @@ -0,0 +1,94 @@ +/*************************************************************************** + qgswcsutils.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 "qgswcsutils.h" +#include "qgsconfigcache.h" + +namespace QgsWcs +{ + QString implementationVersion() + { + return QStringLiteral( "1.0.0" ); + } + + // Return the wms config parser (Transitional) + QgsWCSProjectParser* getConfigParser( QgsServerInterface* serverIface ) + { + QString configFilePath = serverIface->configFilePath(); + + QgsWCSProjectParser* parser = QgsConfigCache::instance()->wcsConfiguration( configFilePath, serverIface->accessControls() ); + if ( !parser ) + { + throw QgsServiceException( + QStringLiteral( "WFS configuration error" ), + QStringLiteral( "There was an error reading the project file or the SLD configuration" ) ); + } + return parser; + } + + QString serviceUrl( const QgsServerRequest& request, QgsWCSProjectParser* parser ) + { + QString href; + if ( parser ) + { + href = parser->wcsServiceUrl(); + if ( href.isEmpty() ) + { + href = parser->serviceUrl(); + } + } + + // Build default url + if ( href.isEmpty() ) + { + QUrl url = request.url(); + QUrlQuery q( url ); + + q.removeAllQueryItems( QStringLiteral( "REQUEST" ) ); + q.removeAllQueryItems( QStringLiteral( "VERSION" ) ); + q.removeAllQueryItems( QStringLiteral( "SERVICE" ) ); + q.removeAllQueryItems( QStringLiteral( "_DC" ) ); + + url.setQuery( q ); + href = url.toString( QUrl::FullyDecoded ); + + } + + return href; + } + + QgsRectangle parseBbox( const QString& bboxStr ) + { + QStringList lst = bboxStr.split( QStringLiteral( "," ) ); + if ( lst.count() != 4 ) + return QgsRectangle(); + + double d[4]; + bool ok; + for ( int i = 0; i < 4; i++ ) + { + lst[i].replace( QLatin1String( " " ), QLatin1String( "+" ) ); + d[i] = lst[i].toDouble( &ok ); + if ( !ok ) + return QgsRectangle(); + } + return QgsRectangle( d[0], d[1], d[2], d[3] ); + } + +} // namespace QgsWfs + + diff --git a/src/server/services/wcs/qgswcsutils.h b/src/server/services/wcs/qgswcsutils.h new file mode 100644 index 00000000000..132b4911fa5 --- /dev/null +++ b/src/server/services/wcs/qgswcsutils.h @@ -0,0 +1,70 @@ +/*************************************************************************** + qgswcsutils.h + + Define WCS service utility functions + ------------------------------------ + begin : January 16 , 2017 + copyright : (C) 2013 by René-Luc D'Hont ( parts from qgswcsserver ) + (C) 2017 by David Marteau + email : rldhont at 3liz dot com + david dot marteau 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. * + * * + ***************************************************************************/ +#ifndef QGSWCSUTILS_H +#define QGSWCSUTILS_H + +#include "qgsmodule.h" +#include "qgswcsprojectparser.h" +#include "qgswcsserviceexception.h" + +/** + * \ingroup server + * WCS implementation + */ + +//! WCS implementation +namespace QgsWcs +{ + + /** + * Return the highest version supported by this implementation + */ + QString implementationVersion(); + + /** + * Return the wms config parser (Transitional) + * + * XXX This is needed in the current implementation. + * This should disappear as soon we get rid of singleton. + */ + QgsWCSProjectParser* getConfigParser( QgsServerInterface* serverIface ); + + /** + * Service URL string + */ + QString serviceUrl( const QgsServerRequest& request, QgsWCSProjectParser* parser = nullptr ); + + /** + * Parse bounding box + */ + //XXX At some point, should be moved to common library + QgsRectangle parseBbox( const QString& bboxStr ); + + // Define namespaces used in WFS documents + const QString WCS_NAMESPACE = QStringLiteral( "http://www.opengis.net/wcs" ); + const QString GML_NAMESPACE = QStringLiteral( "http://www.opengis.net/gml" ); + const QString OGC_NAMESPACE = QStringLiteral( "http://www.opengis.net/ogc" ); + +} // namespace QgsWcs + +#endif + + diff --git a/src/server/services/wfs/CMakeLists.txt b/src/server/services/wfs/CMakeLists.txt index 9bfa78d709a..e35277887fc 100644 --- a/src/server/services/wfs/CMakeLists.txt +++ b/src/server/services/wfs/CMakeLists.txt @@ -26,7 +26,6 @@ INCLUDE_DIRECTORIES(SYSTEM INCLUDE_DIRECTORIES( ${CMAKE_BINARY_DIR}/src/core - ${CMAKE_BINARY_DIR}/src/gui ${CMAKE_BINARY_DIR}/src/python ${CMAKE_BINARY_DIR}/src/analysis ${CMAKE_BINARY_DIR}/src/server @@ -38,9 +37,6 @@ INCLUDE_DIRECTORIES( ../../../core/symbology-ng ../../../core/composer ../../../core/layertree - ../../../gui - ../../../gui/editorwidgets - ../../../gui/editorwidgets/core ../.. .. . diff --git a/src/server/services/wfs/qgswfsdescribefeaturetype.h b/src/server/services/wfs/qgswfsdescribefeaturetype.h index 79b08619262..02116ae479f 100644 --- a/src/server/services/wfs/qgswfsdescribefeaturetype.h +++ b/src/server/services/wfs/qgswfsdescribefeaturetype.h @@ -25,6 +25,7 @@ namespace QgsWfs { + /** * Create get capabilities document */ diff --git a/src/server/services/wfs/qgswfsgetcapabilities.h b/src/server/services/wfs/qgswfsgetcapabilities.h index 8abfc628593..efdd5a5e93b 100644 --- a/src/server/services/wfs/qgswfsgetcapabilities.h +++ b/src/server/services/wfs/qgswfsgetcapabilities.h @@ -25,6 +25,7 @@ namespace QgsWfs { + /** * Create get capabilities document */ diff --git a/src/server/services/wfs/qgswfsutils.h b/src/server/services/wfs/qgswfsutils.h index 25311fe9a3f..dae7aa6f092 100644 --- a/src/server/services/wfs/qgswfsutils.h +++ b/src/server/services/wfs/qgswfsutils.h @@ -35,6 +35,7 @@ //! WMS implementation namespace QgsWfs { + /** Return the highest version supported by this implementation */ QString implementationVersion(); diff --git a/src/server/services/wms/qgswms.cpp b/src/server/services/wms/qgswms.cpp index bc1f61eb410..70943482d5c 100644 --- a/src/server/services/wms/qgswms.cpp +++ b/src/server/services/wms/qgswms.cpp @@ -88,13 +88,13 @@ namespace QgsWms { writeGetCapabilities( mServerIface, versionString, request, response, false ); } - else if( QSTR_COMPARE( req, "GetProjectSettings" ) ) + else if ( QSTR_COMPARE( req, "GetProjectSettings" ) ) { //getProjectSettings extends WMS 1.3.0 capabilities versionString = QStringLiteral( "1.3.0" ); writeGetCapabilities( mServerIface, versionString, request, response, true ); } - else if( QSTR_COMPARE( req, "GetMap" ) ) + else if ( QSTR_COMPARE( req, "GetMap" ) ) { QString format = params.value( QStringLiteral( "FORMAT" ) ); if QSTR_COMPARE( format, "application/dxf" ) @@ -106,35 +106,35 @@ namespace QgsWms writeGetMap( mServerIface, versionString, request, response ); } } - else if( QSTR_COMPARE( req, "GetFeatureInfo" ) ) + else if ( QSTR_COMPARE( req, "GetFeatureInfo" ) ) { writeGetFeatureInfo( mServerIface, versionString, request, response ); } - else if( QSTR_COMPARE( req, "GetContext" ) ) + else if ( QSTR_COMPARE( req, "GetContext" ) ) { writeGetContext( mServerIface, versionString, request, response ); } - else if( QSTR_COMPARE( req, "GetSchemaExtension" ) ) + else if ( QSTR_COMPARE( req, "GetSchemaExtension" ) ) { writeGetSchemaExtension( mServerIface, versionString, request, response ); } - else if( QSTR_COMPARE( req, "GetStyle" ) ) + else if ( QSTR_COMPARE( req, "GetStyle" ) ) { writeGetStyle( mServerIface, versionString, request, response ); } - else if( QSTR_COMPARE( req, "GetStyles" ) ) + else if ( QSTR_COMPARE( req, "GetStyles" ) ) { writeGetStyles( mServerIface, versionString, request, response ); } - else if( QSTR_COMPARE( req, "DescribeLayer" ) ) + else if ( QSTR_COMPARE( req, "DescribeLayer" ) ) { writeDescribeLayer( mServerIface, versionString, request, response ); } - else if( QSTR_COMPARE( req, "GetLegendGraphic" ) || QSTR_COMPARE( req, "GetLegendGraphics" ) ) + else if ( QSTR_COMPARE( req, "GetLegendGraphic" ) || QSTR_COMPARE( req, "GetLegendGraphics" ) ) { writeGetLegendGraphics( mServerIface, versionString, request, response ); } - else if( QSTR_COMPARE( req, "GetPrint" ) ) + else if ( QSTR_COMPARE( req, "GetPrint" ) ) { writeGetPrint( mServerIface, versionString, request, response ); }