Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #1266 from rldhont/provider_wfs_authorization
[BUGFIX] 9234 - WFS client doesn't expose Header Authorization
  • Loading branch information
mhugent committed Apr 16, 2014
2 parents 10f9f55 + a98df93 commit a20652f
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 4 deletions.
6 changes: 5 additions & 1 deletion src/core/qgsgml.cpp
Expand Up @@ -65,7 +65,7 @@ QgsGml::~QgsGml()
{
}

int QgsGml::getFeatures( const QString& uri, QGis::WkbType* wkbType, QgsRectangle* extent )
int QgsGml::getFeatures( const QString& uri, QGis::WkbType* wkbType, QgsRectangle* extent, const QString& userName, const QString& password )
{
mUri = uri;
mWkbType = wkbType;
Expand All @@ -79,6 +79,10 @@ int QgsGml::getFeatures( const QString& uri, QGis::WkbType* wkbType, QgsRectangl
mExtent.setMinimal();

QNetworkRequest request( mUri );
if ( !userName.isNull() || !password.isNull() )
{
request.setRawHeader( "Authorization", "Basic " + QString( "%1:%2" ).arg( userName ).arg( password ).toAscii().toBase64() );
}
QNetworkReply* reply = QgsNetworkAccessManager::instance()->get( request );

connect( reply, SIGNAL( finished() ), this, SLOT( setFinished() ) );
Expand Down
2 changes: 1 addition & 1 deletion src/core/qgsgml.h
Expand Up @@ -56,7 +56,7 @@ class CORE_EXPORT QgsGml : public QObject
* @param extent retrieved extents
* @return 0 in case of success
*/
int getFeatures( const QString& uri, QGis::WkbType* wkbType, QgsRectangle* extent = 0 );
int getFeatures( const QString& uri, QGis::WkbType* wkbType, QgsRectangle* extent = 0, const QString& userName = QString(), const QString& password = QString() );

/** Read from GML data. Constructor uri param is ignored
* Supports only UTF-8, UTF-16, ISO-8859-1, ISO-8859-1 XML encodings.
Expand Down
18 changes: 18 additions & 0 deletions src/providers/wfs/qgswfscapabilities.cpp
Expand Up @@ -134,17 +134,34 @@ QString QgsWFSCapabilities::uriGetFeature( QString typeName, QString crsString,

//add a wfs layer to the map
uri += "SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=" + typeName + crsString + bBoxString + filterString;

//add authorization information
if ( mUri.hasParam( "username" ) && mUri.hasParam( "password" ) )
{
uri += "&username="+mUri.param( "username" );
uri += "&password="+mUri.param( "password" );
}
QgsDebugMsg( uri );
return uri;
}

void QgsWFSCapabilities::setAuthorization( QNetworkRequest &request ) const
{
QgsDebugMsg( "entered" );
if ( mUri.hasParam( "username" ) && mUri.hasParam( "password" ) )
{
QgsDebugMsg( "setAuthorization " + mUri.param( "username" ) );
request.setRawHeader( "Authorization", "Basic " + QString( "%1:%2" ).arg( mUri.param( "username" ) ).arg( mUri.param( "password" ) ).toAscii().toBase64() );
}
}

void QgsWFSCapabilities::requestCapabilities()
{
mErrorCode = QgsWFSCapabilities::NoError;
mErrorMessage.clear();

QNetworkRequest request( uriGetCapabilities() );
setAuthorization( request );
request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
mCapabilitiesReply = QgsNetworkAccessManager::instance()->get( request );
connect( mCapabilitiesReply, SIGNAL( finished() ), this, SLOT( capabilitiesReplyFinished() ) );
Expand All @@ -171,6 +188,7 @@ void QgsWFSCapabilities::capabilitiesReplyFinished()
{
QgsDebugMsg( "redirecting to " + redirect.toUrl().toString() );
QNetworkRequest request( redirect.toUrl() );
setAuthorization( request );
request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork );
request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );

Expand Down
10 changes: 10 additions & 0 deletions src/providers/wfs/qgswfscapabilities.h
Expand Up @@ -16,6 +16,7 @@
#define QGSWFSCAPABILITIES_H

#include <QObject>
#include <QNetworkRequest>

#include "qgsrectangle.h"
#include "qgsdatasourceuri.h"
Expand Down Expand Up @@ -72,6 +73,9 @@ class QgsWFSCapabilities : public QObject
//! return parsed capabilities - requestCapabilities() must be called before
GetCapabilities capabilities() { return mCaps; }

//! set authorization header
void setAuthorization( QNetworkRequest &request ) const;

signals:
void gotCapabilities();

Expand All @@ -90,6 +94,12 @@ class QgsWFSCapabilities : public QObject
GetCapabilities mCaps;
ErrorCode mErrorCode;
QString mErrorMessage;

//! Username for basic http authentication
QString mUserName;

//! Password for basic http authentication
QString mPassword;
};

#endif // QGSWFSCAPABILITIES_H
21 changes: 19 additions & 2 deletions src/providers/wfs/qgswfsprovider.cpp
Expand Up @@ -27,6 +27,7 @@
#include "qgscoordinatereferencesystem.h"
#include "qgswfsfeatureiterator.h"
#include "qgswfsprovider.h"
#include "qgsdatasourceuri.h"
#include "qgsspatialindex.h"
#include "qgslogger.h"
#include "qgsmessagelog.h"
Expand Down Expand Up @@ -89,6 +90,9 @@ QgsWFSProvider::QgsWFSProvider( const QString& uri )
mSourceCRS.createFromOgcWmsCrs( srsname );
}

mAuth.mUserName = parameterFromUrl( "username" );
mAuth.mPassword = parameterFromUrl( "password" );

//fetch attributes of layer and type of its geometry attribute
//WBC 111221: extracting geometry type here instead of getFeature allows successful
//layer creation even when no features are retrieved (due to, e.g., BBOX or FILTER)
Expand Down Expand Up @@ -682,7 +686,10 @@ int QgsWFSProvider::getFeatureGET( const QString& uri, const QString& geometryAt
}

//if ( dataReader.getWFSData() != 0 )
if ( dataReader.getFeatures( uri, &mWKBType, &mExtent ) != 0 )
QUrl getFeatureUrl( uri );
getFeatureUrl.removeQueryItem( "username" );
getFeatureUrl.removeQueryItem( "password" );
if ( dataReader.getFeatures( getFeatureUrl.toString(), &mWKBType, &mExtent, mAuth.mUserName, mAuth.mPassword ) != 0 )
{
QgsDebugMsg( "getWFSData returned with error" );
return 1;
Expand Down Expand Up @@ -751,10 +758,13 @@ int QgsWFSProvider::describeFeatureTypeGET( const QString& uri, QString& geometr
mNetworkRequestFinished = false;

QUrl describeFeatureUrl( uri );
describeFeatureUrl.removeQueryItem( "username" );
describeFeatureUrl.removeQueryItem( "password" );
describeFeatureUrl.removeQueryItem( "SRSNAME" );
describeFeatureUrl.removeQueryItem( "REQUEST" );
describeFeatureUrl.addQueryItem( "REQUEST", "DescribeFeatureType" );
QNetworkRequest request( describeFeatureUrl.toString() );
mAuth.setAuthorization( request );
QNetworkReply* reply = QgsNetworkAccessManager::instance()->get( request );

connect( reply, SIGNAL( finished() ), this, SLOT( networkRequestFinished() ) );
Expand Down Expand Up @@ -1338,6 +1348,8 @@ bool QgsWFSProvider::sendTransactionDocument( const QDomDocument& doc, QDomDocum
mNetworkRequestFinished = false;

QUrl typeDetectionUri( dataSourceUri() );
typeDetectionUri.removeQueryItem( "username" );
typeDetectionUri.removeQueryItem( "password" );
typeDetectionUri.removeQueryItem( "REQUEST" );
typeDetectionUri.removeQueryItem( "TYPENAME" );
typeDetectionUri.removeQueryItem( "BBOX" );
Expand All @@ -1349,6 +1361,7 @@ bool QgsWFSProvider::sendTransactionDocument( const QDomDocument& doc, QDomDocum
QString serverUrl = typeDetectionUri.toString();

QNetworkRequest request( serverUrl );
mAuth.setAuthorization( request );
request.setHeader( QNetworkRequest::ContentTypeHeader, "text/xml" );
QNetworkReply* reply = QgsNetworkAccessManager::instance()->post( request, doc.toByteArray( -1 ) );

Expand Down Expand Up @@ -1475,7 +1488,11 @@ void QgsWFSProvider::getLayerCapabilities()

QString uri = dataSourceUri();
uri.replace( QString( "GetFeature" ), QString( "GetCapabilities" ) );
QNetworkRequest request( uri );
QUrl getCapabilitiesUrl( uri );
getCapabilitiesUrl.removeQueryItem( "username" );
getCapabilitiesUrl.removeQueryItem( "password" );
QNetworkRequest request( getCapabilitiesUrl.toString() );
mAuth.setAuthorization( request );
QNetworkReply* reply = QgsNetworkAccessManager::instance()->get( request );

connect( reply, SIGNAL( finished() ), this, SLOT( networkRequestFinished() ) );
Expand Down
26 changes: 26 additions & 0 deletions src/providers/wfs/qgswfsprovider.h
Expand Up @@ -27,9 +27,32 @@
#include "qgsvectorlayer.h"
#include "qgswfsfeatureiterator.h"

#include <QNetworkRequest>

class QgsRectangle;
class QgsSpatialIndex;

// TODO: merge with QgsWmsAuthorization?
struct QgsWFSAuthorization
{
QgsWFSAuthorization( const QString& userName = QString(), const QString& password = QString() ) : mUserName( userName ), mPassword( password ) {}

//! set authorization header
void setAuthorization( QNetworkRequest &request ) const
{
if ( !mUserName.isNull() || !mPassword.isNull() )
{
request.setRawHeader( "Authorization", "Basic " + QString( "%1:%2" ).arg( mUserName ).arg( mPassword ).toAscii().toBase64() );
}
}

//! Username for basic http authentication
QString mUserName;

//! Password for basic http authentication
QString mPassword;
};

/**A provider reading features from a WFS server*/
class QgsWFSProvider: public QgsVectorDataProvider
{
Expand Down Expand Up @@ -130,6 +153,9 @@ class QgsWFSProvider: public QgsVectorDataProvider
private:
bool mNetworkRequestFinished;
friend class QgsWFSFeatureSource;

//! http authorization details
QgsWFSAuthorization mAuth;

protected:
/**Thematic attributes*/
Expand Down

0 comments on commit a20652f

Please sign in to comment.