34 #include <QNetworkReply> 35 #include <QThreadStorage> 36 #include <QAuthenticator> 39 #include <QSslConfiguration> 48 class QgsNetworkProxyFactory :
public QNetworkProxyFactory
51 QgsNetworkProxyFactory() =
default;
53 QList<QNetworkProxy> queryProxy(
const QNetworkProxyQuery &query = QNetworkProxyQuery() )
override 60 QList<QNetworkProxy> systemproxies = f->systemProxyForQuery( query );
61 if ( !systemproxies.isEmpty() )
64 QList<QNetworkProxy> proxies = f->queryProxy( query );
65 if ( !proxies.isEmpty() )
70 if ( query.queryType() != QNetworkProxyQuery::UrlRequest )
73 QString url = query.url().toString();
75 Q_FOREACH (
const QString &exclude, nam->
excludeList() )
77 if ( url.startsWith( exclude ) )
79 QgsDebugMsgLevel( QString(
"using default proxy for %1 [exclude %2]" ).arg( url, exclude ), 4 );
80 return QList<QNetworkProxy>() << QNetworkProxy();
86 QgsDebugMsgLevel( QString(
"requesting system proxy for query %1" ).arg( url ), 4 );
87 QList<QNetworkProxy> proxies = QNetworkProxyFactory::systemProxyForQuery( query );
88 if ( !proxies.isEmpty() )
91 .arg( proxies.first().hostName() ).arg( proxies.first().port() ), 4 );
107 static QThreadStorage<QgsNetworkAccessManager> sInstances;
110 if ( nam->thread() == qApp->thread() )
113 if ( !nam->mInitialized )
120 : QNetworkAccessManager( parent )
122 setProxyFactory(
new QgsNetworkProxyFactory() );
127 mProxyFactories.insert( 0, factory );
132 mProxyFactories.removeAll( factory );
137 return mProxyFactories;
142 return mExcludedURLs;
147 return mFallbackProxy;
152 QgsDebugMsg( QString(
"proxy settings: (type:%1 host: %2:%3, user:%4, password:%5" )
153 .arg( proxy.type() == QNetworkProxy::DefaultProxy ?
"DefaultProxy" :
154 proxy.type() == QNetworkProxy::Socks5Proxy ?
"Socks5Proxy" :
155 proxy.type() == QNetworkProxy::NoProxy ?
"NoProxy" :
156 proxy.type() == QNetworkProxy::HttpProxy ?
"HttpProxy" :
157 proxy.type() == QNetworkProxy::HttpCachingProxy ?
"HttpCachingProxy" :
158 proxy.type() == QNetworkProxy::FtpCachingProxy ?
"FtpCachingProxy" :
163 proxy.password().isEmpty() ?
"not set" :
"set" ) );
165 mFallbackProxy = proxy;
166 mExcludedURLs = excludes;
173 QNetworkRequest *pReq( const_cast< QNetworkRequest * >( &req ) );
175 QString userAgent = s.
value( QStringLiteral(
"/qgis/networkAndProxy/userAgent" ),
"Mozilla/5.0" ).toString();
176 if ( !userAgent.isEmpty() )
179 pReq->setRawHeader(
"User-Agent", userAgent.toUtf8() );
182 bool ishttps = pReq->url().scheme().toLower() == QLatin1String(
"https" );
186 QSslConfiguration sslconfig( pReq->sslConfiguration() );
190 QString hostport( QStringLiteral(
"%1:%2" )
191 .arg( pReq->url().host().trimmed() )
192 .arg( pReq->url().port() != -1 ? pReq->url().port() : 443 ) );
194 if ( !servconfig.
isNull() )
196 QgsDebugMsg( QString(
"Adding SSL custom config to request for %1" ).arg( hostport ) );
202 pReq->setSslConfiguration( sslconfig );
207 QNetworkReply *reply = QNetworkAccessManager::createRequest( op, req, outgoingData );
214 QTimer *timer =
new QTimer( reply );
215 timer->setObjectName( QStringLiteral(
"timeoutTimer" ) );
216 connect( timer, &QTimer::timeout,
this, &QgsNetworkAccessManager::abortRequest );
217 timer->setSingleShot(
true );
218 timer->start( s.
value( QStringLiteral(
"/qgis/networkAndProxy/networkTimeout" ),
"60000" ).toInt() );
220 connect( reply, &QNetworkReply::downloadProgress, timer, [timer] { timer->start(); } );
221 connect( reply, &QNetworkReply::uploadProgress, timer, [timer] { timer->start(); } );
222 connect( reply, &QNetworkReply::finished, timer, &QTimer::stop );
223 QgsDebugMsgLevel( QString(
"Created [reply:%1]" ).arg( ( qint64 ) reply, 0, 16 ), 3 );
228 void QgsNetworkAccessManager::abortRequest()
230 QTimer *timer = qobject_cast<QTimer *>( sender() );
233 QNetworkReply *reply = qobject_cast<QNetworkReply *>( timer->parent() );
237 QgsDebugMsgLevel( QString(
"Abort [reply:%1] %2" ).arg( ( qint64 ) reply, 0, 16 ).arg( reply->url().toString() ), 3 );
249 case QNetworkRequest::AlwaysNetwork:
250 return QStringLiteral(
"AlwaysNetwork" );
251 case QNetworkRequest::PreferNetwork:
252 return QStringLiteral(
"PreferNetwork" );
253 case QNetworkRequest::PreferCache:
254 return QStringLiteral(
"PreferCache" );
255 case QNetworkRequest::AlwaysCache:
256 return QStringLiteral(
"AlwaysCache" );
260 return QStringLiteral(
"PreferNetwork" );
265 if ( name == QLatin1String(
"AlwaysNetwork" ) )
267 return QNetworkRequest::AlwaysNetwork;
269 else if ( name == QLatin1String(
"PreferNetwork" ) )
271 return QNetworkRequest::PreferNetwork;
273 else if ( name == QLatin1String(
"PreferCache" ) )
275 return QNetworkRequest::PreferCache;
277 else if ( name == QLatin1String(
"AlwaysCache" ) )
279 return QNetworkRequest::AlwaysCache;
281 return QNetworkRequest::PreferNetwork;
287 mUseSystemProxy =
false;
289 Q_ASSERT( sMainNAM );
291 if ( sMainNAM !=
this )
293 connect(
this, &QNetworkAccessManager::authenticationRequired,
294 sMainNAM, &QNetworkAccessManager::authenticationRequired,
295 Qt::BlockingQueuedConnection );
297 connect(
this, &QNetworkAccessManager::proxyAuthenticationRequired,
298 sMainNAM, &QNetworkAccessManager::proxyAuthenticationRequired,
299 Qt::BlockingQueuedConnection );
305 connect(
this, &QNetworkAccessManager::sslErrors,
306 sMainNAM, &QNetworkAccessManager::sslErrors,
307 Qt::BlockingQueuedConnection );
314 QStringList excludes;
316 bool proxyEnabled = settings.
value( QStringLiteral(
"proxy/proxyEnabled" ),
false ).toBool();
319 excludes = settings.
value( QStringLiteral(
"proxy/proxyExcludedUrls" ),
"" ).toString().split(
'|', QString::SkipEmptyParts );
322 QString proxyHost = settings.
value( QStringLiteral(
"proxy/proxyHost" ),
"" ).toString();
323 int proxyPort = settings.
value( QStringLiteral(
"proxy/proxyPort" ),
"" ).toString().toInt();
325 QString proxyUser = settings.
value( QStringLiteral(
"proxy/proxyUser" ),
"" ).toString();
326 QString proxyPassword = settings.
value( QStringLiteral(
"proxy/proxyPassword" ),
"" ).toString();
328 QString proxyTypeString = settings.
value( QStringLiteral(
"proxy/proxyType" ),
"" ).toString();
330 if ( proxyTypeString == QLatin1String(
"DefaultProxy" ) )
332 mUseSystemProxy =
true;
333 QNetworkProxyFactory::setUseSystemConfiguration(
true );
334 QList<QNetworkProxy> proxies = QNetworkProxyFactory::systemProxyForQuery();
335 if ( !proxies.isEmpty() )
337 proxy = proxies.first();
343 QNetworkProxy::ProxyType proxyType = QNetworkProxy::DefaultProxy;
344 if ( proxyTypeString == QLatin1String(
"Socks5Proxy" ) )
346 proxyType = QNetworkProxy::Socks5Proxy;
348 else if ( proxyTypeString == QLatin1String(
"HttpProxy" ) )
350 proxyType = QNetworkProxy::HttpProxy;
352 else if ( proxyTypeString == QLatin1String(
"HttpCachingProxy" ) )
354 proxyType = QNetworkProxy::HttpCachingProxy;
356 else if ( proxyTypeString == QLatin1String(
"FtpCachingProxy" ) )
358 proxyType = QNetworkProxy::FtpCachingProxy;
360 QgsDebugMsg( QStringLiteral(
"setting proxy %1 %2:%3 %4/%5" )
362 .arg( proxyHost ).arg( proxyPort )
363 .arg( proxyUser, proxyPassword )
365 proxy = QNetworkProxy( proxyType, proxyHost, proxyPort, proxyUser, proxyPassword );
368 QString authcfg = settings.
value( QStringLiteral(
"proxy/authcfg" ),
"" ).toString();
369 if ( !authcfg.isEmpty( ) )
371 QgsDebugMsg( QStringLiteral(
"setting proxy from stored authentication configuration %1" ).arg( authcfg ) );
384 QString cacheDirectory = settings.
value( QStringLiteral(
"cache/directory" ) ).toString();
385 if ( cacheDirectory.isEmpty() )
387 qint64 cacheSize = settings.
value( QStringLiteral(
"cache/size" ), 50 * 1024 * 1024 ).toULongLong();
393 if ( cache() != newcache )
394 setCache( newcache );
bool isNull() const
Whether configuration is null (missing components)
void requestCreated(QNetworkReply *)
static QList< QSslCertificate > casMerge(const QList< QSslCertificate > &bundle1, const QList< QSslCertificate > &bundle2)
casMerge merges two certificate bundles in a single one removing duplicates, the certificates from th...
static const QString QGIS_VERSION
Version string.
static QString cacheLoadControlName(QNetworkRequest::CacheLoadControl control)
Get name for QNetworkRequest::CacheLoadControl.
int sslPeerVerifyDepth() const
Number or SSL client's peer to verify in connections.
static QString qgisSettingsDirPath()
Returns the path to the settings directory in user's home dir.
This class is a composition of two QSettings instances:
bool updateNetworkProxy(QNetworkProxy &proxy, const QString &authcfg, const QString &dataprovider=QString())
Provider call to update a QNetworkProxy with an authentication config.
void setCacheDirectory(const QString &cacheDir)
Configuration container for SSL server connection exceptions or overrides.
void setupDefaultProxyAndCache()
Setup the NAM according to the user's settings.
QStringList excludeList() const
retrieve exclude list (urls shouldn't use the fallback proxy)
QSsl::SslProtocol sslProtocol() const
SSL server protocol to use in connections.
QNetworkReply * createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest &req, QIODevice *outgoingData=nullptr) override
static QNetworkRequest::CacheLoadControl cacheLoadControlFromName(const QString &name)
Get QNetworkRequest::CacheLoadControl from name.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::Warning)
add a message to the instance (and create it if necessary)
QgsNetworkAccessManager(QObject *parent=nullptr)
QSslSocket::PeerVerifyMode sslPeerVerifyMode() const
SSL client's peer verify mode to use in connections.
#define QgsDebugMsgLevel(str, level)
void requestTimedOut(QNetworkReply *)
QString cacheDirectory() const
void removeProxyFactory(QNetworkProxyFactory *factory)
remove a factory from the proxy factories list
const QgsAuthConfigSslServer sslCertCustomConfigByHost(const QString &hostport)
sslCertCustomConfigByHost get an SSL certificate custom config by hostport (host:port) ...
void insertProxyFactory(QNetworkProxyFactory *factory)
insert a factory into the proxy factories list
static QgsAuthManager * authManager()
Returns the application's authentication manager instance.
static QgsNetworkAccessManager * instance()
returns a pointer to the single instance
qint64 maximumCacheSize() const
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), const Section section=NoSection) const
Returns the value for setting key.
const QNetworkProxy & fallbackProxy() const
retrieve fall back proxy (for urls that no factory returned proxies for)
bool useSystemProxy() const
return whether the system proxy should be used
void requestAboutToBeCreated(QNetworkAccessManager::Operation, const QNetworkRequest &, QIODevice *)
network access manager for QGIS
void setFallbackProxyAndExcludes(const QNetworkProxy &proxy, const QStringList &excludes)
set fallback proxy and URL that shouldn't use it.
void setMaximumCacheSize(qint64 size)
Wrapper implementation of QNetworkDiskCache with all methods guarded by a mutex soly for internal use...
const QList< QNetworkProxyFactory * > proxyFactories() const
retrieve proxy factory list