34 #include <QNetworkReply> 35 #include <QThreadStorage> 36 #include <QAuthenticator> 37 #include <QStandardPaths> 40 #include <QSslConfiguration> 49 class QgsNetworkProxyFactory :
public QNetworkProxyFactory
52 QgsNetworkProxyFactory() =
default;
54 QList<QNetworkProxy> queryProxy(
const QNetworkProxyQuery &query = QNetworkProxyQuery() )
override 61 QList<QNetworkProxy> systemproxies = f->systemProxyForQuery( query );
62 if ( !systemproxies.isEmpty() )
65 QList<QNetworkProxy> proxies = f->queryProxy( query );
66 if ( !proxies.isEmpty() )
71 if ( query.queryType() != QNetworkProxyQuery::UrlRequest )
74 QString url = query.url().toString();
76 Q_FOREACH (
const QString &exclude, nam->
excludeList() )
78 if ( !exclude.trimmed().isEmpty() && url.startsWith( exclude ) )
80 QgsDebugMsgLevel( QStringLiteral(
"using default proxy for %1 [exclude %2]" ).arg( url, exclude ), 4 );
81 return QList<QNetworkProxy>() << QNetworkProxy();
87 QgsDebugMsgLevel( QStringLiteral(
"requesting system proxy for query %1" ).arg( url ), 4 );
88 QList<QNetworkProxy> proxies = QNetworkProxyFactory::systemProxyForQuery( query );
89 if ( !proxies.isEmpty() )
92 .arg( proxies.first().hostName() ).arg( proxies.first().port() ), 4 );
97 QgsDebugMsgLevel( QStringLiteral(
"using fallback proxy for %1" ).arg( url ), 4 );
108 static QThreadStorage<QgsNetworkAccessManager> sInstances;
111 if ( nam->thread() == qApp->thread() )
114 if ( !nam->mInitialized )
121 : QNetworkAccessManager( parent )
123 setProxyFactory(
new QgsNetworkProxyFactory() );
128 mProxyFactories.insert( 0, factory );
133 mProxyFactories.removeAll( factory );
138 return mProxyFactories;
143 return mExcludedURLs;
148 return mFallbackProxy;
153 QgsDebugMsgLevel( QStringLiteral(
"proxy settings: (type:%1 host: %2:%3, user:%4, password:%5" )
154 .arg( proxy.type() == QNetworkProxy::DefaultProxy ? QStringLiteral(
"DefaultProxy" ) :
155 proxy.type() == QNetworkProxy::Socks5Proxy ? QStringLiteral(
"Socks5Proxy" ) :
156 proxy.type() == QNetworkProxy::NoProxy ? QStringLiteral(
"NoProxy" ) :
157 proxy.type() == QNetworkProxy::HttpProxy ? QStringLiteral(
"HttpProxy" ) :
158 proxy.type() == QNetworkProxy::HttpCachingProxy ? QStringLiteral(
"HttpCachingProxy" ) :
159 proxy.type() == QNetworkProxy::FtpCachingProxy ? QStringLiteral(
"FtpCachingProxy" ) :
160 QStringLiteral(
"Undefined" ),
164 proxy.password().isEmpty() ? QStringLiteral(
"not set" ) : QStringLiteral(
"set" ) ), 4 );
166 mFallbackProxy = proxy;
167 mExcludedURLs = excludes;
169 mExcludedURLs.erase( std::remove_if( mExcludedURLs.begin(), mExcludedURLs.end(),
170 [](
const QString & url )
172 return url.trimmed().isEmpty();
173 } ), mExcludedURLs.end() );
181 QNetworkRequest *pReq( const_cast< QNetworkRequest * >( &req ) );
183 QString userAgent = s.
value( QStringLiteral(
"/qgis/networkAndProxy/userAgent" ),
"Mozilla/5.0" ).toString();
184 if ( !userAgent.isEmpty() )
187 pReq->setRawHeader(
"User-Agent", userAgent.toUtf8() );
190 bool ishttps = pReq->url().scheme().compare( QLatin1String(
"https" ), Qt::CaseInsensitive ) == 0;
193 QgsDebugMsgLevel( QStringLiteral(
"Adding trusted CA certs to request" ), 3 );
194 QSslConfiguration sslconfig( pReq->sslConfiguration() );
198 QString hostport( QStringLiteral(
"%1:%2" )
199 .arg( pReq->url().host().trimmed() )
200 .arg( pReq->url().port() != -1 ? pReq->url().port() : 443 ) );
202 if ( !servconfig.
isNull() )
204 QgsDebugMsg( QStringLiteral(
"Adding SSL custom config to request for %1" ).arg( hostport ) );
210 pReq->setSslConfiguration( sslconfig );
215 QNetworkReply *reply = QNetworkAccessManager::createRequest( op, req, outgoingData );
222 QTimer *timer =
new QTimer( reply );
223 timer->setObjectName( QStringLiteral(
"timeoutTimer" ) );
224 connect( timer, &QTimer::timeout,
this, &QgsNetworkAccessManager::abortRequest );
225 timer->setSingleShot(
true );
226 timer->start( s.
value( QStringLiteral(
"/qgis/networkAndProxy/networkTimeout" ),
"60000" ).toInt() );
228 connect( reply, &QNetworkReply::downloadProgress, timer, [timer] { timer->start(); } );
229 connect( reply, &QNetworkReply::uploadProgress, timer, [timer] { timer->start(); } );
230 connect( reply, &QNetworkReply::finished, timer, &QTimer::stop );
231 QgsDebugMsgLevel( QStringLiteral(
"Created [reply:%1]" ).arg( reinterpret_cast< qint64 >( reply ), 0, 16 ), 3 );
236 void QgsNetworkAccessManager::abortRequest()
238 QTimer *timer = qobject_cast<QTimer *>( sender() );
241 QNetworkReply *reply = qobject_cast<QNetworkReply *>( timer->parent() );
245 QgsDebugMsgLevel( QStringLiteral(
"Abort [reply:%1] %2" ).arg( reinterpret_cast< qint64 >( reply ), 0, 16 ).arg( reply->url().toString() ), 3 );
257 case QNetworkRequest::AlwaysNetwork:
258 return QStringLiteral(
"AlwaysNetwork" );
259 case QNetworkRequest::PreferNetwork:
260 return QStringLiteral(
"PreferNetwork" );
261 case QNetworkRequest::PreferCache:
262 return QStringLiteral(
"PreferCache" );
263 case QNetworkRequest::AlwaysCache:
264 return QStringLiteral(
"AlwaysCache" );
268 return QStringLiteral(
"PreferNetwork" );
273 if ( name == QLatin1String(
"AlwaysNetwork" ) )
275 return QNetworkRequest::AlwaysNetwork;
277 else if ( name == QLatin1String(
"PreferNetwork" ) )
279 return QNetworkRequest::PreferNetwork;
281 else if ( name == QLatin1String(
"PreferCache" ) )
283 return QNetworkRequest::PreferCache;
285 else if ( name == QLatin1String(
"AlwaysCache" ) )
287 return QNetworkRequest::AlwaysCache;
289 return QNetworkRequest::PreferNetwork;
295 mUseSystemProxy =
false;
297 Q_ASSERT( sMainNAM );
299 if ( sMainNAM !=
this )
301 connect(
this, &QNetworkAccessManager::authenticationRequired,
302 sMainNAM, &QNetworkAccessManager::authenticationRequired,
305 connect(
this, &QNetworkAccessManager::proxyAuthenticationRequired,
306 sMainNAM, &QNetworkAccessManager::proxyAuthenticationRequired,
313 connect(
this, &QNetworkAccessManager::sslErrors,
314 sMainNAM, &QNetworkAccessManager::sslErrors,
322 QStringList excludes;
324 bool proxyEnabled = settings.
value( QStringLiteral(
"proxy/proxyEnabled" ),
false ).toBool();
327 excludes = settings.
value( QStringLiteral(
"proxy/proxyExcludedUrls" ), QStringList() ).toStringList();
330 QString proxyHost = settings.
value( QStringLiteral(
"proxy/proxyHost" ),
"" ).toString();
331 int proxyPort = settings.
value( QStringLiteral(
"proxy/proxyPort" ),
"" ).toString().toInt();
333 QString proxyUser = settings.
value( QStringLiteral(
"proxy/proxyUser" ),
"" ).toString();
334 QString proxyPassword = settings.
value( QStringLiteral(
"proxy/proxyPassword" ),
"" ).toString();
336 QString proxyTypeString = settings.
value( QStringLiteral(
"proxy/proxyType" ),
"" ).toString();
338 if ( proxyTypeString == QLatin1String(
"DefaultProxy" ) )
340 mUseSystemProxy =
true;
341 QNetworkProxyFactory::setUseSystemConfiguration(
true );
342 QList<QNetworkProxy> proxies = QNetworkProxyFactory::systemProxyForQuery();
343 if ( !proxies.isEmpty() )
345 proxy = proxies.first();
351 QNetworkProxy::ProxyType proxyType = QNetworkProxy::DefaultProxy;
352 if ( proxyTypeString == QLatin1String(
"Socks5Proxy" ) )
354 proxyType = QNetworkProxy::Socks5Proxy;
356 else if ( proxyTypeString == QLatin1String(
"HttpProxy" ) )
358 proxyType = QNetworkProxy::HttpProxy;
360 else if ( proxyTypeString == QLatin1String(
"HttpCachingProxy" ) )
362 proxyType = QNetworkProxy::HttpCachingProxy;
364 else if ( proxyTypeString == QLatin1String(
"FtpCachingProxy" ) )
366 proxyType = QNetworkProxy::FtpCachingProxy;
368 QgsDebugMsg( QStringLiteral(
"setting proxy %1 %2:%3 %4/%5" )
370 .arg( proxyHost ).arg( proxyPort )
371 .arg( proxyUser, proxyPassword )
373 proxy = QNetworkProxy( proxyType, proxyHost, proxyPort, proxyUser, proxyPassword );
376 QString authcfg = settings.
value( QStringLiteral(
"proxy/authcfg" ),
"" ).toString();
377 if ( !authcfg.isEmpty( ) )
379 QgsDebugMsg( QStringLiteral(
"setting proxy from stored authentication configuration %1" ).arg( authcfg ) );
392 QString cacheDirectory = settings.
value( QStringLiteral(
"cache/directory" ) ).toString();
393 if ( cacheDirectory.isEmpty() )
394 cacheDirectory = QStandardPaths::writableLocation( QStandardPaths::CacheLocation );
395 qint64 cacheSize = settings.
value( QStringLiteral(
"cache/size" ), 50 * 1024 * 1024 ).toLongLong();
401 if ( cache() != newcache )
402 setCache( newcache );
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.
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)
bool isNull() const
Whether configuration is null (missing components)
const QNetworkProxy & fallbackProxy() const
retrieve fall back proxy (for urls that no factory returned proxies for)
Configuration container for SSL server connection exceptions or overrides.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
QString cacheDirectory() const
QNetworkReply * createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest &req, QIODevice *outgoingData=nullptr) override
const QList< QNetworkProxyFactory * > proxyFactories() const
retrieve proxy factory list
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 *)
QSsl::SslProtocol sslProtocol() const
SSL server protocol to use in connections.
bool useSystemProxy() const
Returns whether the system proxy should be used.
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).
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.
int sslPeerVerifyDepth() const
Number or SSL client's peer to verify in connections.
void requestAboutToBeCreated(QNetworkAccessManager::Operation, const QNetworkRequest &, QIODevice *)
qint64 maximumCacheSize() const
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)
QStringList excludeList() const
retrieve exclude list (urls shouldn't use the fallback proxy)
Wrapper implementation of QNetworkDiskCache with all methods guarded by a mutex soly for internal use...