Skip to content

Commit 2ca4ee5

Browse files
authoredNov 10, 2017
Merge pull request #5596 from boundlessgeo/bugfix-5212-ogr-proxy
[bugfix] Apply proxy configuration to OGR connections
2 parents f8cbc42 + f2abcf2 commit 2ca4ee5

File tree

7 files changed

+234
-20
lines changed

7 files changed

+234
-20
lines changed
 

‎src/core/qgsnetworkaccessmanager.cpp

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ class QgsNetworkProxyFactory : public QNetworkProxyFactory
6666
return proxies;
6767
}
6868

69-
// no proxies from the proxy factor list check for excludes
69+
// no proxies from the proxy factory list check for excludes
7070
if ( query.queryType() != QNetworkProxyQuery::UrlRequest )
7171
return QList<QNetworkProxy>() << nam->fallbackProxy();
7272

@@ -364,16 +364,15 @@ void QgsNetworkAccessManager::setupDefaultProxyAndCache()
364364
);
365365
proxy = QNetworkProxy( proxyType, proxyHost, proxyPort, proxyUser, proxyPassword );
366366
}
367-
}
368-
369-
// Setup network proxy authentication configuration
370-
QString authcfg = settings.value( QStringLiteral( "proxy/authcfg" ), "" ).toString();
371-
if ( !authcfg.isEmpty( ) )
372-
{
373-
QgsDebugMsg( QStringLiteral( "setting proxy from stored authentication configuration %1" ).arg( authcfg ) );
374-
// Never crash! Never.
375-
if ( QgsApplication::authManager() )
376-
QgsApplication::authManager()->updateNetworkProxy( proxy, authcfg );
367+
// Setup network proxy authentication configuration
368+
QString authcfg = settings.value( QStringLiteral( "proxy/authcfg" ), "" ).toString();
369+
if ( !authcfg.isEmpty( ) )
370+
{
371+
QgsDebugMsg( QStringLiteral( "setting proxy from stored authentication configuration %1" ).arg( authcfg ) );
372+
// Never crash! Never.
373+
if ( QgsApplication::authManager() )
374+
QgsApplication::authManager()->updateNetworkProxy( proxy, authcfg );
375+
}
377376
}
378377

379378
setFallbackProxyAndExcludes( proxy, excludes );

‎src/providers/ogr/CMakeLists.txt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
SET (OGR_SRCS
32
qgsogrprovider.cpp
43
qgsogrdataitems.cpp
@@ -40,12 +39,14 @@ QT5_WRAP_CPP(OGR_MOC_SRCS ${OGR_MOC_HDRS})
4039

4140
INCLUDE_DIRECTORIES(
4241
${CMAKE_SOURCE_DIR}/src/core
42+
${CMAKE_SOURCE_DIR}/src/core/auth
4343
${CMAKE_SOURCE_DIR}/src/core/raster
4444
${CMAKE_SOURCE_DIR}/src/core/geometry
4545
${CMAKE_SOURCE_DIR}/src/core/metadata
4646
${CMAKE_SOURCE_DIR}/src/core/symbology
4747
${CMAKE_SOURCE_DIR}/src/core/expression
4848
${CMAKE_SOURCE_DIR}/src/gui
49+
${CMAKE_SOURCE_DIR}/src/gui/auth
4950

5051
${CMAKE_BINARY_DIR}/src/core
5152
${CMAKE_BINARY_DIR}/src/gui
@@ -54,6 +55,8 @@ INCLUDE_DIRECTORIES(
5455
INCLUDE_DIRECTORIES(SYSTEM
5556
${GDAL_INCLUDE_DIR}
5657
${GEOS_INCLUDE_DIR}
58+
${QTKEYCHAIN_INCLUDE_DIR}
59+
${QCA_INCLUDE_DIR}
5760
${QSCINTILLA_INCLUDE_DIR}
5861
)
5962

@@ -86,5 +89,4 @@ ENDIF(CLANG_TIDY_EXE)
8689

8790
INSTALL (TARGETS ogrprovider
8891
RUNTIME DESTINATION ${QGIS_PLUGIN_DIR}
89-
LIBRARY DESTINATION ${QGIS_PLUGIN_DIR})
90-
92+
LIBRARY DESTINATION ${QGIS_PLUGIN_DIR})

‎src/providers/ogr/qgsogrprovider.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ email : sherman at mrcc.com
2424
#include "qgsfeedback.h"
2525
#include "qgssettings.h"
2626
#include "qgsapplication.h"
27+
#include "qgsauthmanager.h"
2728
#include "qgsdataitem.h"
2829
#include "qgsdataprovider.h"
2930
#include "qgsfeature.h"
@@ -35,6 +36,7 @@ email : sherman at mrcc.com
3536
#include "qgsogrdataitems.h"
3637
#include "qgsgeopackagedataitems.h"
3738
#include "qgswkbtypes.h"
39+
#include "qgsnetworkaccessmanager.h"
3840

3941
#ifdef HAVE_GUI
4042
#include "qgssourceselectprovider.h"
@@ -419,6 +421,10 @@ QgsOgrProvider::QgsOgrProvider( QString const &uri )
419421
QgsSettings settings;
420422
CPLSetConfigOption( "SHAPE_ENCODING", settings.value( QStringLiteral( "qgis/ignoreShapeEncoding" ), true ).toBool() ? "" : nullptr );
421423
424+
#ifndef QT_NO_NETWORKPROXY
425+
setupProxy();
426+
#endif
427+
422428
// make connection to the data source
423429
424430
QgsDebugMsg( "Data source uri is [" + uri + ']' );
@@ -1972,6 +1978,56 @@ bool QgsOgrProvider::doInitialActionsForEdition()
19721978
return true;
19731979
}
19741980

1981+
#ifndef QT_NO_NETWORKPROXY
1982+
void QgsOgrProvider::setupProxy()
1983+
{
1984+
// Check proxy configuration, they are application level but
1985+
// instead of adding an API and complex signal/slot connections
1986+
// given the limited cost of checking them on every provider instantiation
1987+
// we can do it here so that new settings are applied whenever a new layer
1988+
// is created.
1989+
QgsSettings settings;
1990+
// Check that proxy is enabled
1991+
if ( settings.value( QStringLiteral( "proxy/proxyEnabled" ), false ).toBool() )
1992+
{
1993+
// Get the first configured proxy
1994+
QList<QNetworkProxy> proxyes( QgsNetworkAccessManager::instance()->proxyFactory()->queryProxy( ) );
1995+
if ( ! proxyes.isEmpty() )
1996+
{
1997+
QNetworkProxy proxy( proxyes.first() );
1998+
// TODO/FIXME: check excludes (the GDAL config options are global, we need a per-connection config option)
1999+
//QStringList excludes;
2000+
//excludes = settings.value( QStringLiteral( "proxy/proxyExcludedUrls" ), "" ).toString().split( '|', QString::SkipEmptyParts );
2001+
2002+
QString proxyHost( proxy.hostName() );
2003+
qint16 proxyPort( proxy.port() );
2004+
2005+
QString proxyUser( proxy.user() );
2006+
QString proxyPassword( proxy.password() );
2007+
2008+
if ( ! proxyHost.isEmpty() )
2009+
{
2010+
QString connection( proxyHost );
2011+
if ( proxyPort )
2012+
{
2013+
connection += ':' + QString::number( proxyPort );
2014+
}
2015+
CPLSetConfigOption( "GDAL_HTTP_PROXY", connection.toUtf8() );
2016+
if ( ! proxyUser.isEmpty( ) )
2017+
{
2018+
QString credentials( proxyUser );
2019+
if ( ! proxyPassword.isEmpty( ) )
2020+
{
2021+
credentials += ':' + proxyPassword;
2022+
}
2023+
CPLSetConfigOption( "GDAL_HTTP_PROXYUSERPWD", credentials.toUtf8() );
2024+
}
2025+
}
2026+
}
2027+
}
2028+
}
2029+
#endif
2030+
19752031
QgsVectorDataProvider::Capabilities QgsOgrProvider::capabilities() const
19762032
{
19772033
return mCapabilities;

‎src/providers/ogr/qgsogrprovider.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,11 @@ class QgsOgrProvider : public QgsVectorDataProvider
266266
QgsVectorDataProvider::Capabilities mCapabilities;
267267

268268
bool doInitialActionsForEdition();
269+
270+
#ifndef QT_NO_NETWORKPROXY
271+
void setupProxy();
272+
#endif
273+
269274
};
270275

271276
/**

‎tests/src/providers/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ SET_TARGET_PROPERTIES(qgis_wcsprovidertest PROPERTIES
6666

6767
ADD_QGIS_TEST(gdalprovidertest testqgsgdalprovider.cpp)
6868

69+
ADD_QGIS_TEST(ogrprovidertest testqgsogrprovider.cpp)
70+
6971
ADD_QGIS_TEST(wmscapabilititestest
7072
testqgswmscapabilities.cpp)
7173
TARGET_LINK_LIBRARIES(qgis_wmscapabilititestest wmsprovider_a)
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/***************************************************************************
2+
testqgsogrprovider.cpp - TestQgsOgrProvider
3+
4+
---------------------
5+
begin : 10.11.2017
6+
copyright : (C) 2017 by Alessandro Pasotti
7+
email : apasotti at boundlessgeo dot com
8+
***************************************************************************
9+
* *
10+
* This program is free software; you can redistribute it and/or modify *
11+
* it under the terms of the GNU General Public License as published by *
12+
* the Free Software Foundation; either version 2 of the License, or *
13+
* (at your option) any later version. *
14+
* *
15+
***************************************************************************/
16+
17+
18+
#include "qgstest.h"
19+
20+
//qgis includes...
21+
#include <qgis.h>
22+
#include <qgssettings.h>
23+
#include <qgsapplication.h>
24+
#include <qgsproviderregistry.h>
25+
#include <qgsvectorlayer.h>
26+
#include <qgsnetworkaccessmanager.h>
27+
28+
#include <QObject>
29+
30+
#include <cpl_conv.h>
31+
32+
33+
/**
34+
* \ingroup UnitTests
35+
* This is a unit test for the ogr provider
36+
*/
37+
class TestQgsOgrProvider : public QObject
38+
{
39+
Q_OBJECT
40+
41+
private slots:
42+
void initTestCase();// will be called before the first testfunction is executed.
43+
void cleanupTestCase();// will be called after the last testfunction was executed.
44+
void init() {}// will be called before each testfunction is executed.
45+
void cleanup() {}// will be called after every testfunction.
46+
47+
void setupProxy();
48+
49+
private:
50+
QString mTestDataDir;
51+
QString mReport;
52+
signals:
53+
54+
public slots:
55+
};
56+
57+
58+
59+
//runs before all tests
60+
void TestQgsOgrProvider::initTestCase()
61+
{
62+
// init QGIS's paths - true means that all path will be inited from prefix
63+
QgsApplication::init();
64+
QgsApplication::initQgis();
65+
66+
mTestDataDir = QStringLiteral( TEST_DATA_DIR ) + '/'; //defined in CmakeLists.txt
67+
mReport = QStringLiteral( "<h1>OGR Provider Tests</h1>\n" );
68+
}
69+
70+
//runs after all tests
71+
void TestQgsOgrProvider::cleanupTestCase()
72+
{
73+
QgsApplication::exitQgis();
74+
QString myReportFile = QDir::tempPath() + "/qgistest.html";
75+
QFile myFile( myReportFile );
76+
if ( myFile.open( QIODevice::WriteOnly | QIODevice::Append ) )
77+
{
78+
QTextStream myQTextStream( &myFile );
79+
myQTextStream << mReport;
80+
myFile.close();
81+
}
82+
}
83+
84+
void TestQgsOgrProvider::setupProxy()
85+
{
86+
87+
QgsSettings settings;
88+
{
89+
settings.setValue( QStringLiteral( "proxy/proxyEnabled" ), true );
90+
settings.setValue( QStringLiteral( "proxy/proxyPort" ), QStringLiteral( "1234" ) );
91+
settings.setValue( QStringLiteral( "proxy/proxyHost" ), QStringLiteral( "myproxyhostname.com" ) );
92+
settings.setValue( QStringLiteral( "proxy/proxyUser" ), QStringLiteral( "username" ) );
93+
settings.setValue( QStringLiteral( "proxy/proxyPassword" ), QStringLiteral( "password" ) );
94+
settings.setValue( QStringLiteral( "proxy/proxyExcludedUrls" ), QStringLiteral( "http://www.myhost.com|http://www.myotherhost.com" ) );
95+
QgsNetworkAccessManager::instance()->setupDefaultProxyAndCache();
96+
QgsVectorLayer vl( mTestDataDir + '/' + QStringLiteral( "lines.shp" ), QStringLiteral( "proxy_test" ), QLatin1Literal( "ogr" ) );
97+
QVERIFY( vl.isValid() );
98+
const char *proxyConfig = CPLGetConfigOption( "GDAL_HTTP_PROXY", NULL );
99+
QCOMPARE( proxyConfig, "myproxyhostname.com:1234" );
100+
const char *proxyCredentials = CPLGetConfigOption( "GDAL_HTTP_PROXYUSERPWD", NULL );
101+
QCOMPARE( proxyCredentials, "username:password" );
102+
}
103+
104+
{
105+
// Test partial config
106+
settings.setValue( QStringLiteral( "proxy/proxyEnabled" ), true );
107+
settings.remove( QStringLiteral( "proxy/proxyPort" ) );
108+
settings.setValue( QStringLiteral( "proxy/proxyHost" ), QStringLiteral( "myproxyhostname.com" ) );
109+
settings.setValue( QStringLiteral( "proxy/proxyUser" ), QStringLiteral( "username" ) );
110+
settings.remove( QStringLiteral( "proxy/proxyPassword" ) );
111+
QgsNetworkAccessManager::instance()->setupDefaultProxyAndCache();
112+
QgsVectorLayer vl( mTestDataDir + '/' + QStringLiteral( "lines.shp" ), QStringLiteral( "proxy_test" ), QLatin1Literal( "ogr" ) );
113+
QVERIFY( vl.isValid() );
114+
const char *proxyConfig = CPLGetConfigOption( "GDAL_HTTP_PROXY", NULL );
115+
QCOMPARE( proxyConfig, "myproxyhostname.com" );
116+
const char *proxyCredentials = CPLGetConfigOption( "GDAL_HTTP_PROXYUSERPWD", NULL );
117+
QCOMPARE( proxyCredentials, "username" );
118+
}
119+
120+
}
121+
122+
123+
QGSTEST_MAIN( TestQgsOgrProvider )
124+
#include "testqgsogrprovider.moc"

‎tests/src/python/test_provider_ogr.py

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,12 @@
1717
import sys
1818
import tempfile
1919

20-
from qgis.core import QgsVectorLayer, QgsVectorDataProvider, QgsWkbTypes, QgsFeature, QgsFeatureRequest
21-
from qgis.testing import (
22-
start_app,
23-
unittest
24-
)
25-
from utilities import unitTestDataPath
2620
from osgeo import gdal, ogr # NOQA
21+
from qgis.core import (QgsFeature, QgsFeatureRequest, QgsSettings,
22+
QgsVectorDataProvider, QgsVectorLayer, QgsWkbTypes, QgsNetworkAccessManager)
23+
from qgis.testing import start_app, unittest
24+
25+
from utilities import unitTestDataPath
2726

2827
start_app()
2928
TEST_DATA_DIR = unitTestDataPath()
@@ -292,6 +291,33 @@ def testTriangleTINPolyhedralSurface(self):
292291
Triangle => mapped to Polygon
293292
"""
294293

294+
def testSetupProxy(self):
295+
"""Test proxy setup"""
296+
settings = QgsSettings()
297+
settings.setValue("proxy/proxyEnabled", True)
298+
settings.setValue("proxy/proxyPort", '1234')
299+
settings.setValue("proxy/proxyHost", 'myproxyhostname.com')
300+
settings.setValue("proxy/proxyUser", 'username')
301+
settings.setValue("proxy/proxyPassword", 'password')
302+
settings.setValue("proxy/proxyExcludedUrls", "http://www.myhost.com|http://www.myotherhost.com")
303+
QgsNetworkAccessManager.instance().setupDefaultProxyAndCache()
304+
vl = QgsVectorLayer(TEST_DATA_DIR + '/' + 'lines.shp', 'proxy_test', 'ogr')
305+
self.assertTrue(vl.isValid())
306+
self.assertEqual(gdal.GetConfigOption("GDAL_HTTP_PROXY"), "myproxyhostname.com:1234")
307+
self.assertEqual(gdal.GetConfigOption("GDAL_HTTP_PROXYUSERPWD"), "username:password")
308+
309+
settings.setValue("proxy/proxyEnabled", True)
310+
settings.remove("proxy/proxyPort")
311+
settings.setValue("proxy/proxyHost", 'myproxyhostname.com')
312+
settings.setValue("proxy/proxyUser", 'username')
313+
settings.remove("proxy/proxyPassword")
314+
settings.setValue("proxy/proxyExcludedUrls", "http://www.myhost.com|http://www.myotherhost.com")
315+
QgsNetworkAccessManager.instance().setupDefaultProxyAndCache()
316+
vl = QgsVectorLayer(TEST_DATA_DIR + '/' + 'lines.shp', 'proxy_test', 'ogr')
317+
self.assertTrue(vl.isValid())
318+
self.assertEqual(gdal.GetConfigOption("GDAL_HTTP_PROXY"), "myproxyhostname.com")
319+
self.assertEqual(gdal.GetConfigOption("GDAL_HTTP_PROXYUSERPWD"), "username")
320+
295321

296322
if __name__ == '__main__':
297323
unittest.main()

0 commit comments

Comments
 (0)
Please sign in to comment.