Skip to content

Commit e875e5e

Browse files
committed
[FEATURE][ogr/gdal] Add UI to expose HTTP(S) and cloud datasets
1 parent 4e175fd commit e875e5e

12 files changed

+608
-57
lines changed

src/auth/basic/qgsauthbasicmethod.cpp

+6-2
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ QgsAuthBasicMethod::QgsAuthBasicMethod()
4343
<< QStringLiteral( "wcs" )
4444
<< QStringLiteral( "wms" )
4545
<< QStringLiteral( "ogr" )
46+
<< QStringLiteral( "gdal" )
4647
<< QStringLiteral( "proxy" ) );
4748

4849
}
@@ -120,7 +121,7 @@ bool QgsAuthBasicMethod::updateDataSourceUriItems( QStringList &connectionItems,
120121
}
121122

122123
// Branch for OGR
123-
if ( dataprovider == QStringLiteral( "ogr" ) )
124+
if ( dataprovider == QStringLiteral( "ogr" ) || dataprovider == QStringLiteral( "gdal" ) )
124125
{
125126
if ( ! password.isEmpty() )
126127
{
@@ -215,8 +216,11 @@ bool QgsAuthBasicMethod::updateDataSourceUriItems( QStringList &connectionItems,
215216
else if ( uri.startsWith( QStringLiteral( "couchdb" ) )
216217
|| uri.startsWith( QStringLiteral( "DODS" ) )
217218
|| uri.startsWith( "http://" )
219+
|| uri.startsWith( "/vsicurl/http://" )
218220
|| uri.startsWith( "https://" )
219-
|| uri.startsWith( "ftp://" ) // not really sure that this is supported ...
221+
|| uri.startsWith( "/vsicurl/https://" )
222+
|| uri.startsWith( "ftp://" )
223+
|| uri.startsWith( "/vsicurl/ftp://" )
220224
)
221225
{
222226
uri = uri.replace( QStringLiteral( "://" ), QStringLiteral( "://%1:%2@" ).arg( username, password ) );

src/gui/ogr/qgsogrhelperfunctions.cpp

+36-1
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,42 @@ QString createDatabaseURI( const QString &connectionType, const QString &host, c
221221
QString createProtocolURI( const QString &type, const QString &url, const QString &configId, const QString &username, const QString &password, bool expandAuthConfig )
222222
{
223223
QString uri;
224-
if ( type == QLatin1String( "GeoJSON" ) )
224+
if ( type == QLatin1String( "HTTP/HTTPS/FTP" ) )
225+
{
226+
uri = url;
227+
// If no protocol is provided in the URL, default to HTTP
228+
if ( !uri.startsWith( "http://" ) && !uri.startsWith( "https://" ) && !uri.startsWith( "ftp://" ) )
229+
{
230+
uri.prepend( QStringLiteral( "http://" ) );
231+
}
232+
uri.prepend( QStringLiteral( "/vsicurl/" ) );
233+
}
234+
else if ( type == QLatin1String( "AWS S3" ) )
235+
{
236+
uri = url;
237+
uri.prepend( QStringLiteral( "/vsis3/" ) );
238+
}
239+
else if ( type == QLatin1String( "Google Cloud Storage" ) )
240+
{
241+
uri = url;
242+
uri.prepend( QStringLiteral( "/vsigs/" ) );
243+
}
244+
else if ( type == QLatin1String( "Microsoft Azure Blob" ) )
245+
{
246+
uri = url;
247+
uri.prepend( QStringLiteral( "/vsiaz/" ) );
248+
}
249+
else if ( type == QLatin1String( "Alibaba Cloud OSS" ) )
250+
{
251+
uri = url;
252+
uri.prepend( QStringLiteral( "/vsioss/" ) );
253+
}
254+
else if ( type == QLatin1String( "OpenStack Swift Object Storage" ) )
255+
{
256+
uri = url;
257+
uri.prepend( QStringLiteral( "/vsiswift/" ) );
258+
}
259+
else if ( type == QLatin1String( "GeoJSON" ) )
225260
{
226261
uri = url;
227262
}

src/providers/gdal/CMakeLists.txt

+4
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,13 @@ ENDIF ()
2121

2222
INCLUDE_DIRECTORIES (
2323
${CMAKE_SOURCE_DIR}/src/core
24+
${CMAKE_SOURCE_DIR}/src/core/auth
2425
${CMAKE_SOURCE_DIR}/src/core/expression
2526
${CMAKE_SOURCE_DIR}/src/core/raster
2627
${CMAKE_SOURCE_DIR}/src/core/geometry
2728
${CMAKE_SOURCE_DIR}/src/core/metadata
2829
${CMAKE_SOURCE_DIR}/src/gui
30+
${CMAKE_SOURCE_DIR}/src/gui/auth
2931

3032
${CMAKE_BINARY_DIR}/src/core
3133
${CMAKE_BINARY_DIR}/src/gui
@@ -34,6 +36,8 @@ INCLUDE_DIRECTORIES (
3436
INCLUDE_DIRECTORIES (SYSTEM
3537
${GDAL_INCLUDE_DIR}
3638
${GEOS_INCLUDE_DIR}
39+
${QTKEYCHAIN_INCLUDE_DIR}
40+
${QCA_INCLUDE_DIR}
3741
)
3842

3943
QT5_WRAP_CPP(GDAL_MOC_SRCS ${GDAL_MOC_HDRS})

src/providers/gdal/qgsgdalprovider.cpp

+37-9
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "qgsconfig.h"
2323

2424
#include "qgsapplication.h"
25+
#include "qgsauthmanager.h"
2526
#include "qgscoordinatetransform.h"
2627
#include "qgsdataitem.h"
2728
#include "qgsdatasourceuri.h"
@@ -255,6 +256,33 @@ QgsGdalProvider::QgsGdalProvider( const QgsGdalProvider &other )
255256
copyBaseSettings( other );
256257
}
257258

259+
QString QgsGdalProvider::dataSourceUri( bool expandAuthConfig ) const
260+
{
261+
if ( expandAuthConfig && QgsDataProvider::dataSourceUri( ).contains( QLatin1String( "authcfg" ) ) )
262+
{
263+
QString uri( QgsDataProvider::dataSourceUri() );
264+
// Check for authcfg
265+
QRegularExpression authcfgRe( " authcfg='([^']+)'" );
266+
QRegularExpressionMatch match;
267+
if ( uri.contains( authcfgRe, &match ) )
268+
{
269+
uri = uri.replace( match.captured( 0 ), QString() );
270+
QString configId( match.captured( 1 ) );
271+
QStringList connectionItems;
272+
connectionItems << uri;
273+
if ( QgsApplication::authManager()->updateDataSourceUriItems( connectionItems, configId, QStringLiteral( "gdal" ) ) )
274+
{
275+
uri = connectionItems.first( );
276+
}
277+
}
278+
return uri;
279+
}
280+
else
281+
{
282+
return QgsDataProvider::dataSourceUri();
283+
}
284+
}
285+
258286
QgsGdalProvider *QgsGdalProvider::clone() const
259287
{
260288
return new QgsGdalProvider( *this );
@@ -1723,7 +1751,7 @@ QString QgsGdalProvider::buildPyramids( const QList<QgsRasterPyramid> &rasterPyr
17231751

17241752
// test if the file is writable
17251753
//QFileInfo myQFile( mDataSource );
1726-
QFileInfo myQFile( dataSourceUri() );
1754+
QFileInfo myQFile( dataSourceUri( true ) );
17271755

17281756
if ( !myQFile.isWritable() )
17291757
{
@@ -1753,12 +1781,12 @@ QString QgsGdalProvider::buildPyramids( const QList<QgsRasterPyramid> &rasterPyr
17531781
GDALClose( mGdalDataset );
17541782
//mGdalBaseDataset = GDALOpen( QFile::encodeName( dataSourceUri() ).constData(), GA_Update );
17551783

1756-
mGdalBaseDataset = gdalOpen( dataSourceUri().toUtf8().constData(), GA_Update );
1784+
mGdalBaseDataset = gdalOpen( dataSourceUri( true ).toUtf8().constData(), GA_Update );
17571785

17581786
// if the dataset couldn't be opened in read / write mode, tell the user
17591787
if ( !mGdalBaseDataset )
17601788
{
1761-
mGdalBaseDataset = gdalOpen( dataSourceUri().toUtf8().constData(), GA_ReadOnly );
1789+
mGdalBaseDataset = gdalOpen( dataSourceUri( true ).toUtf8().constData(), GA_ReadOnly );
17621790
//Since we are not a virtual warped dataset, mGdalDataSet and mGdalBaseDataset are supposed to be the same
17631791
mGdalDataset = mGdalBaseDataset;
17641792
return QStringLiteral( "ERROR_WRITE_FORMAT" );
@@ -1859,7 +1887,7 @@ QString QgsGdalProvider::buildPyramids( const QList<QgsRasterPyramid> &rasterPyr
18591887
//something bad happenend
18601888
//QString myString = QString (CPLGetLastError());
18611889
GDALClose( mGdalBaseDataset );
1862-
mGdalBaseDataset = gdalOpen( dataSourceUri().toUtf8().constData(), mUpdate ? GA_Update : GA_ReadOnly );
1890+
mGdalBaseDataset = gdalOpen( dataSourceUri( true ).toUtf8().constData(), mUpdate ? GA_Update : GA_ReadOnly );
18631891
//Since we are not a virtual warped dataset, mGdalDataSet and mGdalBaseDataset are supposed to be the same
18641892
mGdalDataset = mGdalBaseDataset;
18651893

@@ -1911,7 +1939,7 @@ QString QgsGdalProvider::buildPyramids( const QList<QgsRasterPyramid> &rasterPyr
19111939
QgsDebugMsg( "Reopening dataset ..." );
19121940
//close the gdal dataset and reopen it in read only mode
19131941
GDALClose( mGdalBaseDataset );
1914-
mGdalBaseDataset = gdalOpen( dataSourceUri().toUtf8().constData(), mUpdate ? GA_Update : GA_ReadOnly );
1942+
mGdalBaseDataset = gdalOpen( dataSourceUri( true ).toUtf8().constData(), mUpdate ? GA_Update : GA_ReadOnly );
19151943
//Since we are not a virtual warped dataset, mGdalDataSet and mGdalBaseDataset are supposed to be the same
19161944
mGdalDataset = mGdalBaseDataset;
19171945
}
@@ -2625,7 +2653,7 @@ bool QgsGdalProvider::initIfNeeded()
26252653

26262654
mHasInit = true;
26272655

2628-
QString gdalUri = dataSourceUri();
2656+
QString gdalUri = dataSourceUri( true );
26292657

26302658
// Try to open using VSIFileHandler (see qgsogrprovider.cpp)
26312659
QString vsiPrefix = QgsZipItem::vsiPrefix( gdalUri );
@@ -2636,7 +2664,7 @@ bool QgsGdalProvider::initIfNeeded()
26362664
QgsDebugMsg( QString( "Trying %1 syntax, uri= %2" ).arg( vsiPrefix, dataSourceUri() ) );
26372665
}
26382666

2639-
gdalUri = dataSourceUri();
2667+
gdalUri = dataSourceUri( true );
26402668

26412669
CPLErrorReset();
26422670
mGdalBaseDataset = gdalOpen( gdalUri.toUtf8().constData(), mUpdate ? GA_Update : GA_ReadOnly );
@@ -3041,7 +3069,7 @@ bool QgsGdalProvider::remove()
30413069
mGdalDataset = nullptr;
30423070

30433071
CPLErrorReset();
3044-
CPLErr err = GDALDeleteDataset( driver, dataSourceUri().toUtf8().constData() );
3072+
CPLErr err = GDALDeleteDataset( driver, dataSourceUri( true ).toUtf8().constData() );
30453073
if ( err != CPLE_None )
30463074
{
30473075
QgsLogger::warning( "RasterIO error: " + QString::fromUtf8( CPLGetLastErrorMsg() ) );
@@ -3240,7 +3268,7 @@ bool QgsGdalProvider::setEditable( bool enabled )
32403268
mUpdate = enabled;
32413269

32423270
// reopen the dataset
3243-
mGdalBaseDataset = gdalOpen( dataSourceUri().toUtf8().constData(), mUpdate ? GA_Update : GA_ReadOnly );
3271+
mGdalBaseDataset = gdalOpen( dataSourceUri( true ).toUtf8().constData(), mUpdate ? GA_Update : GA_ReadOnly );
32443272
if ( !mGdalBaseDataset )
32453273
{
32463274
QString msg = QStringLiteral( "Cannot reopen GDAL dataset %1:\n%2" ).arg( dataSourceUri(), QString::fromUtf8( CPLGetLastErrorMsg() ) );

src/providers/gdal/qgsgdalprovider.h

+11
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,17 @@ class QgsGdalProvider : public QgsRasterDataProvider, QgsGdalProviderBase
7878

7979
~QgsGdalProvider() override;
8080

81+
/**
82+
* Get the data source specification. This may be a path or a protocol
83+
* connection string
84+
* \param expandAuthConfig Whether to expand any assigned authentication configuration
85+
* \returns data source specification
86+
* \note The default authentication configuration expansion is FALSE. This keeps credentials
87+
* out of layer data source URIs and project files. Expansion should be specifically done
88+
* only when needed within a provider
89+
*/
90+
QString dataSourceUri( bool expandAuthConfig = false ) const override;
91+
8192
/**
8293
* Clone the provider.
8394
*

0 commit comments

Comments
 (0)