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,
297 connect(
this, &QNetworkAccessManager::proxyAuthenticationRequired,
298 sMainNAM, &QNetworkAccessManager::proxyAuthenticationRequired,
305 connect(
this, &QNetworkAccessManager::sslErrors,
306 sMainNAM, &QNetworkAccessManager::sslErrors,
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)
Gets 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:
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
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.
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)
Gets QNetworkRequest::CacheLoadControl from name.
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 *)
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
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(Qt::ConnectionType connectionType=Qt::BlockingQueuedConnection)
Returns a pointer to the active QgsNetworkAccessManager for the current thread.
void setupDefaultProxyAndCache(Qt::ConnectionType connectionType=Qt::BlockingQueuedConnection)
Setup the QgsNetworkAccessManager (NAM) according to the user's settings.
qint64 maximumCacheSize() const
const QNetworkProxy & fallbackProxy() const
retrieve fall back proxy (for urls that no factory returned proxies for)
bool useSystemProxy() const
Returns whether the system proxy should be used.
void requestAboutToBeCreated(QNetworkAccessManager::Operation, const QNetworkRequest &, QIODevice *)
network access manager for QGISThis class implements the QGIS network access manager.
void setFallbackProxyAndExcludes(const QNetworkProxy &proxy, const QStringList &excludes)
Sets 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