37 #include <QNetworkReply> 
   38 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) 
   41 #include <QRecursiveMutex> 
   43 #include <QThreadStorage> 
   44 #include <QAuthenticator> 
   45 #include <QStandardPaths> 
   49 #include <QSslConfiguration> 
   57 static std::vector< std::pair< QString, std::function< void( QNetworkRequest * ) > > > sCustomPreprocessors;
 
   58 static std::vector< std::pair< QString, std::function< void( 
const QNetworkRequest &, QNetworkReply * ) > > > sCustomReplyPreprocessors;
 
   61 class QgsNetworkProxyFactory : 
public QNetworkProxyFactory
 
   64     QgsNetworkProxyFactory() = 
default;
 
   66     QList<QNetworkProxy> queryProxy( 
const QNetworkProxyQuery &query = QNetworkProxyQuery() )
 override 
   72       for ( QNetworkProxyFactory *f : constProxyFactories )
 
   74         QList<QNetworkProxy> systemproxies = QNetworkProxyFactory::systemProxyForQuery( query );
 
   75         if ( !systemproxies.isEmpty() )
 
   78         QList<QNetworkProxy> proxies = f->queryProxy( query );
 
   79         if ( !proxies.isEmpty() )
 
   84       if ( query.queryType() != QNetworkProxyQuery::UrlRequest )
 
   87       const QString url = query.url().toString();
 
   90       for ( 
const QString &noProxy : constNoProxyList )
 
   92         if ( !noProxy.trimmed().isEmpty() && url.startsWith( noProxy ) )
 
   94           QgsDebugMsgLevel( QStringLiteral( 
"don't using any proxy for %1 [exclude %2]" ).arg( url, noProxy ), 4 );
 
   95           return QList<QNetworkProxy>() << QNetworkProxy( QNetworkProxy::NoProxy );
 
  100       for ( 
const QString &exclude : constExcludeList )
 
  102         if ( !exclude.trimmed().isEmpty() && url.startsWith( exclude ) )
 
  104           QgsDebugMsgLevel( QStringLiteral( 
"using default proxy for %1 [exclude %2]" ).arg( url, exclude ), 4 );
 
  105           return QList<QNetworkProxy>() << QNetworkProxy( QNetworkProxy::DefaultProxy );
 
  111         QgsDebugMsgLevel( QStringLiteral( 
"requesting system proxy for query %1" ).arg( url ), 4 );
 
  112         QList<QNetworkProxy> proxies = QNetworkProxyFactory::systemProxyForQuery( query );
 
  113         if ( !proxies.isEmpty() )
 
  116                             .arg( proxies.first().hostName() ).arg( proxies.first().port() ), 4 );
 
  121       QgsDebugMsgLevel( QStringLiteral( 
"using fallback proxy for %1" ).arg( url ), 4 );
 
  128 class QgsNetworkCookieJar : 
public QNetworkCookieJar
 
  134       : QNetworkCookieJar( parent )
 
  136 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
 
  137       , mMutex( QMutex::Recursive )
 
  141     bool deleteCookie( 
const QNetworkCookie &cookie )
 override 
  143       const QMutexLocker locker( &mMutex );
 
  144       if ( QNetworkCookieJar::deleteCookie( cookie ) )
 
  146         emit mNam->cookiesChanged( allCookies() );
 
  151     bool insertCookie( 
const QNetworkCookie &cookie )
 override 
  153       const QMutexLocker locker( &mMutex );
 
  154       if ( QNetworkCookieJar::insertCookie( cookie ) )
 
  156         emit mNam->cookiesChanged( allCookies() );
 
  161     bool setCookiesFromUrl( 
const QList<QNetworkCookie> &cookieList, 
const QUrl &url )
 override 
  163       const QMutexLocker locker( &mMutex );
 
  164       return QNetworkCookieJar::setCookiesFromUrl( cookieList, url );
 
  166     bool updateCookie( 
const QNetworkCookie &cookie )
 override 
  168       const QMutexLocker locker( &mMutex );
 
  169       if ( QNetworkCookieJar::updateCookie( cookie ) )
 
  171         emit mNam->cookiesChanged( allCookies() );
 
  178     QList<QNetworkCookie> allCookies()
 const 
  180       const QMutexLocker locker( &mMutex );
 
  181       return QNetworkCookieJar::allCookies();
 
  183     void setAllCookies( 
const QList<QNetworkCookie> &cookieList )
 
  185       const QMutexLocker locker( &mMutex );
 
  186       QNetworkCookieJar::setAllCookies( cookieList );
 
  190 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) 
  191     mutable QMutex mMutex;
 
  193     mutable QRecursiveMutex mMutex;
 
  204   static QThreadStorage<QgsNetworkAccessManager> sInstances;
 
  207   if ( nam->thread() == qApp->thread() )
 
  210   if ( !nam->mInitialized )
 
  220   : QNetworkAccessManager( parent )
 
  221   , mAuthRequestHandlerSemaphore( 1 )
 
  223   setProxyFactory( 
new QgsNetworkProxyFactory() );
 
  224   setCookieJar( 
new QgsNetworkCookieJar( 
this ) );
 
  229   Q_ASSERT( sMainNAM == 
this );
 
  230   mSslErrorHandler = std::move( handler );
 
  235   Q_ASSERT( sMainNAM == 
this );
 
  236   mAuthHandler = std::move( handler );
 
  241   mProxyFactories.insert( 0, factory );
 
  246   mProxyFactories.removeAll( factory );
 
  251   return mProxyFactories;
 
  256   return mExcludedURLs;
 
  266   return mFallbackProxy;
 
  271   QgsDebugMsgLevel( QStringLiteral( 
"proxy settings: (type:%1 host: %2:%3, user:%4, password:%5" )
 
  272                     .arg( proxy.type() == QNetworkProxy::DefaultProxy ? QStringLiteral( 
"DefaultProxy" ) :
 
  273                           proxy.type() == QNetworkProxy::Socks5Proxy ? QStringLiteral( 
"Socks5Proxy" ) :
 
  274                           proxy.type() == QNetworkProxy::NoProxy ? QStringLiteral( 
"NoProxy" ) :
 
  275                           proxy.type() == QNetworkProxy::HttpProxy ? QStringLiteral( 
"HttpProxy" ) :
 
  276                           proxy.type() == QNetworkProxy::HttpCachingProxy ? QStringLiteral( 
"HttpCachingProxy" ) :
 
  277                           proxy.type() == QNetworkProxy::FtpCachingProxy ? QStringLiteral( 
"FtpCachingProxy" ) :
 
  278                           QStringLiteral( 
"Undefined" ),
 
  282                           proxy.password().isEmpty() ? QStringLiteral( 
"not set" ) : QStringLiteral( 
"set" ) ), 4 );
 
  284   mFallbackProxy = proxy;
 
  285   mExcludedURLs = excludes;
 
  287   mExcludedURLs.erase( std::remove_if( mExcludedURLs.begin(), mExcludedURLs.end(), 
 
  288                                        []( 
const QString & url )
 
  290     return url.trimmed().isEmpty();
 
  291   } ), mExcludedURLs.end() ); 
 
  293   mNoProxyURLs = noProxyURLs;
 
  294   mNoProxyURLs.erase( std::remove_if( mNoProxyURLs.begin(), mNoProxyURLs.end(), 
 
  295                                       []( 
const QString & url )
 
  297     return url.trimmed().isEmpty();
 
  298   } ), mNoProxyURLs.end() ); 
 
  305   QNetworkRequest *pReq( 
const_cast< QNetworkRequest * 
>( &req ) ); 
 
  307   QString userAgent = s.
value( QStringLiteral( 
"/qgis/networkAndProxy/userAgent" ), 
"Mozilla/5.0" ).toString();
 
  308   if ( !userAgent.isEmpty() )
 
  310   userAgent += QStringLiteral( 
"QGIS/%1/%2" ).arg( 
Qgis::versionInt() ).arg( QSysInfo::prettyProductName() );
 
  311   pReq->setRawHeader( 
"User-Agent", userAgent.toLatin1() );
 
  314   const bool ishttps = pReq->url().scheme().compare( QLatin1String( 
"https" ), Qt::CaseInsensitive ) == 0;
 
  317     QgsDebugMsgLevel( QStringLiteral( 
"Adding trusted CA certs to request" ), 3 );
 
  318     QSslConfiguration sslconfig( pReq->sslConfiguration() );
 
  322     const QString hostport( QStringLiteral( 
"%1:%2" )
 
  323                             .arg( pReq->url().host().trimmed() )
 
  324                             .arg( pReq->url().port() != -1 ? pReq->url().port() : 443 ) );
 
  326     if ( !servconfig.
isNull() )
 
  328       QgsDebugMsg( QStringLiteral( 
"Adding SSL custom config to request for %1" ).arg( hostport ) );
 
  334     pReq->setSslConfiguration( sslconfig );
 
  338   if ( sMainNAM->mCacheDisabled )
 
  341     pReq->setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork );
 
  342     pReq->setAttribute( QNetworkRequest::CacheSaveControlAttribute, 
false );
 
  345   for ( 
const auto &preprocessor :  sCustomPreprocessors )
 
  347     preprocessor.second( pReq );
 
  350   static QAtomicInt sRequestId = 0;
 
  351   const int requestId = ++sRequestId;
 
  353   if ( QBuffer *buffer = qobject_cast<QBuffer *>( outgoingData ) )
 
  355     content = buffer->buffer();
 
  362   QNetworkReply *reply = QNetworkAccessManager::createRequest( op, req, outgoingData );
 
  363   reply->setProperty( 
"requestId", requestId );
 
  369   connect( reply, &QNetworkReply::downloadProgress, 
this, &QgsNetworkAccessManager::onReplyDownloadProgress );
 
  371   connect( reply, &QNetworkReply::sslErrors, 
this, &QgsNetworkAccessManager::onReplySslErrors );
 
  374   for ( 
const auto &replyPreprocessor :  sCustomReplyPreprocessors )
 
  376     replyPreprocessor.second( req, reply );
 
  384     QTimer *timer = 
new QTimer( reply );
 
  385     timer->setObjectName( QStringLiteral( 
"timeoutTimer" ) );
 
  386     connect( timer, &QTimer::timeout, 
this, &QgsNetworkAccessManager::abortRequest );
 
  387     timer->setSingleShot( 
true );
 
  390     connect( reply, &QNetworkReply::downloadProgress, timer, [timer] { timer->start(); } );
 
  391     connect( reply, &QNetworkReply::uploadProgress, timer, [timer] { timer->start(); } );
 
  392     connect( reply, &QNetworkReply::finished, timer, &QTimer::stop );
 
  394   QgsDebugMsgLevel( QStringLiteral( 
"Created [reply:%1]" ).arg( 
reinterpret_cast< qint64 
>( reply ), 0, 16 ), 3 );
 
  400 void QgsNetworkAccessManager::unlockAfterSslErrorHandled()
 
  402   Q_ASSERT( QThread::currentThread() == QApplication::instance()->thread() );
 
  403   mSslErrorWaitCondition.wakeOne();
 
  407 void QgsNetworkAccessManager::abortRequest()
 
  409   QTimer *timer = qobject_cast<QTimer *>( sender() );
 
  412   QNetworkReply *reply = qobject_cast<QNetworkReply *>( timer->parent() );
 
  416   QgsDebugMsgLevel( QStringLiteral( 
"Abort [reply:%1] %2" ).arg( 
reinterpret_cast< qint64 
>( reply ), 0, 16 ).arg( reply->url().toString() ), 3 );
 
  423 void QgsNetworkAccessManager::onReplyFinished( QNetworkReply *reply )
 
  428 void QgsNetworkAccessManager::onReplyDownloadProgress( qint64 bytesReceived, qint64 bytesTotal )
 
  430   if ( QNetworkReply *reply = qobject_cast< QNetworkReply *>( sender() ) )
 
  437 void QgsNetworkAccessManager::onReplySslErrors( 
const QList<QSslError> &errors )
 
  439   QNetworkReply *reply = qobject_cast< QNetworkReply *>( sender() );
 
  441   Q_ASSERT( reply->manager() == 
this );
 
  443   QgsDebugMsg( QStringLiteral( 
"Stopping network reply timeout whilst SSL error is handled" ) );
 
  444   pauseTimeout( reply );
 
  450   emit sslErrorsOccurred( reply, errors );
 
  451   if ( 
this != sMainNAM )
 
  455     mSslErrorHandlerMutex.lock();
 
  456     mSslErrorWaitCondition.wait( &mSslErrorHandlerMutex );
 
  457     mSslErrorHandlerMutex.unlock();
 
  458     afterSslErrorHandled( reply );
 
  462 void QgsNetworkAccessManager::afterSslErrorHandled( QNetworkReply *reply )
 
  464   if ( reply->manager() == 
this )
 
  466     restartTimeout( reply );
 
  467     emit sslErrorsHandled( reply );
 
  469   else if ( 
this == sMainNAM )
 
  472     qobject_cast< QgsNetworkAccessManager *>( reply->manager() )->unlockAfterSslErrorHandled(); 
 
  476 void QgsNetworkAccessManager::afterAuthRequestHandled( QNetworkReply *reply )
 
  478   if ( reply->manager() == 
this )
 
  480     restartTimeout( reply );
 
  481     emit authRequestHandled( reply );
 
  485 void QgsNetworkAccessManager::pauseTimeout( QNetworkReply *reply )
 
  487   Q_ASSERT( reply->manager() == 
this );
 
  489   QTimer *timer = reply->findChild<QTimer *>( QStringLiteral( 
"timeoutTimer" ) );
 
  490   if ( timer && timer->isActive() )
 
  496 void QgsNetworkAccessManager::restartTimeout( QNetworkReply *reply )
 
  498   Q_ASSERT( reply->manager() == 
this );
 
  500   QTimer *timer = reply->findChild<QTimer *>( QStringLiteral( 
"timeoutTimer" ) );
 
  503     Q_ASSERT( !timer->isActive() );
 
  504     QgsDebugMsg( QStringLiteral( 
"Restarting network reply timeout" ) );
 
  505     timer->setSingleShot( 
true );
 
  510 int QgsNetworkAccessManager::getRequestId( QNetworkReply *reply )
 
  512   return reply->property( 
"requestId" ).toInt();
 
  515 void QgsNetworkAccessManager::handleSslErrors( QNetworkReply *reply, 
const QList<QSslError> &errors )
 
  517   mSslErrorHandler->handleSslErrors( reply, errors );
 
  518   afterSslErrorHandled( reply );
 
  523 void QgsNetworkAccessManager::onAuthRequired( QNetworkReply *reply, QAuthenticator *auth )
 
  526   Q_ASSERT( reply->manager() == 
this );
 
  528   QgsDebugMsg( QStringLiteral( 
"Stopping network reply timeout whilst auth request is handled" ) );
 
  529   pauseTimeout( reply );
 
  533   mAuthRequestHandlerSemaphore.acquire();
 
  536   emit authRequestOccurred( reply, auth );
 
  538   if ( 
this != sMainNAM )
 
  542     mAuthRequestHandlerSemaphore.acquire();
 
  543     mAuthRequestHandlerSemaphore.release();
 
  544     afterAuthRequestHandled( reply );
 
  550   if ( 
this != sMainNAM )
 
  556   mAuthHandler->handleAuthRequestOpenBrowser( url );
 
  561   if ( 
this != sMainNAM )
 
  567   mAuthHandler->handleAuthRequestCloseBrowser();
 
  572   if ( 
this != sMainNAM )
 
  579 void QgsNetworkAccessManager::handleAuthRequest( QNetworkReply *reply, QAuthenticator *auth )
 
  581   mAuthHandler->handleAuthRequest( reply, auth );
 
  585   afterAuthRequestHandled( reply );
 
  586   qobject_cast<QgsNetworkAccessManager *>( reply->manager() )->mAuthRequestHandlerSemaphore.release();
 
  593     case QNetworkRequest::AlwaysNetwork:
 
  594       return QStringLiteral( 
"AlwaysNetwork" );
 
  595     case QNetworkRequest::PreferNetwork:
 
  596       return QStringLiteral( 
"PreferNetwork" );
 
  597     case QNetworkRequest::PreferCache:
 
  598       return QStringLiteral( 
"PreferCache" );
 
  599     case QNetworkRequest::AlwaysCache:
 
  600       return QStringLiteral( 
"AlwaysCache" );
 
  602   return QStringLiteral( 
"PreferNetwork" );
 
  607   if ( name == QLatin1String( 
"AlwaysNetwork" ) )
 
  609     return QNetworkRequest::AlwaysNetwork;
 
  611   else if ( name == QLatin1String( 
"PreferNetwork" ) )
 
  613     return QNetworkRequest::PreferNetwork;
 
  615   else if ( name == QLatin1String( 
"PreferCache" ) )
 
  617     return QNetworkRequest::PreferCache;
 
  619   else if ( name == QLatin1String( 
"AlwaysCache" ) )
 
  621     return QNetworkRequest::AlwaysCache;
 
  623   return QNetworkRequest::PreferNetwork;
 
  629   mUseSystemProxy = 
false;
 
  631   Q_ASSERT( sMainNAM );
 
  633   if ( sMainNAM != 
this )
 
  635     connect( 
this, &QNetworkAccessManager::proxyAuthenticationRequired,
 
  636              sMainNAM, &QNetworkAccessManager::proxyAuthenticationRequired,
 
  654     connect( 
this, &QNetworkAccessManager::sslErrors,
 
  655              sMainNAM, &QNetworkAccessManager::sslErrors,
 
  670     setAuthHandler( std::make_unique< QgsNetworkAuthenticationHandler>() );
 
  673   connect( 
this, &QgsNetworkAccessManager::sslErrorsOccurred, sMainNAM, &QgsNetworkAccessManager::handleSslErrors );
 
  675   connect( 
this, &QNetworkAccessManager::authenticationRequired, 
this, &QgsNetworkAccessManager::onAuthRequired );
 
  676   connect( 
this, &QgsNetworkAccessManager::authRequestOccurred, sMainNAM, &QgsNetworkAccessManager::handleAuthRequest );
 
  678   connect( 
this, &QNetworkAccessManager::finished, 
this, &QgsNetworkAccessManager::onReplyFinished );
 
  683   QStringList excludes;
 
  684   QStringList noProxyURLs;
 
  686   const bool proxyEnabled = settings.
value( QStringLiteral( 
"proxy/proxyEnabled" ), 
false ).toBool();
 
  691     excludes = settings.
value( QStringLiteral( 
"proxy/proxyExcludedUrls" ), QStringList() ).toStringList();
 
  693     noProxyURLs = settings.
value( QStringLiteral( 
"proxy/noProxyUrls" ), QStringList() ).toStringList();
 
  696     const QString proxyHost = settings.
value( QStringLiteral( 
"proxy/proxyHost" ), 
"" ).toString();
 
  697     const int proxyPort = settings.
value( QStringLiteral( 
"proxy/proxyPort" ), 
"" ).toString().toInt();
 
  699     const QString proxyUser = settings.
value( QStringLiteral( 
"proxy/proxyUser" ), 
"" ).toString();
 
  700     const QString proxyPassword = settings.
value( QStringLiteral( 
"proxy/proxyPassword" ), 
"" ).toString();
 
  702     const QString proxyTypeString = settings.
value( QStringLiteral( 
"proxy/proxyType" ), 
"" ).toString();
 
  704     if ( proxyTypeString == QLatin1String( 
"DefaultProxy" ) )
 
  706       mUseSystemProxy = 
true;
 
  707       QNetworkProxyFactory::setUseSystemConfiguration( 
true );
 
  708       QList<QNetworkProxy> proxies = QNetworkProxyFactory::systemProxyForQuery();
 
  709       if ( !proxies.isEmpty() )
 
  711         proxy = proxies.first();
 
  717       QNetworkProxy::ProxyType proxyType = QNetworkProxy::DefaultProxy;
 
  718       if ( proxyTypeString == QLatin1String( 
"Socks5Proxy" ) )
 
  720         proxyType = QNetworkProxy::Socks5Proxy;
 
  722       else if ( proxyTypeString == QLatin1String( 
"HttpProxy" ) )
 
  724         proxyType = QNetworkProxy::HttpProxy;
 
  726       else if ( proxyTypeString == QLatin1String( 
"HttpCachingProxy" ) )
 
  728         proxyType = QNetworkProxy::HttpCachingProxy;
 
  730       else if ( proxyTypeString == QLatin1String( 
"FtpCachingProxy" ) )
 
  732         proxyType = QNetworkProxy::FtpCachingProxy;
 
  734       QgsDebugMsg( QStringLiteral( 
"setting proxy %1 %2:%3 %4/%5" )
 
  736                    .arg( proxyHost ).arg( proxyPort )
 
  737                    .arg( proxyUser, proxyPassword )
 
  739       proxy = QNetworkProxy( proxyType, proxyHost, proxyPort, proxyUser, proxyPassword );
 
  742     const QString authcfg = settings.
value( QStringLiteral( 
"proxy/authcfg" ), 
"" ).toString();
 
  743     if ( !authcfg.isEmpty( ) )
 
  745       QgsDebugMsg( QStringLiteral( 
"setting proxy from stored authentication configuration %1" ).arg( authcfg ) );
 
  758   QString cacheDirectory = settings.
value( QStringLiteral( 
"cache/directory" ) ).toString();
 
  759   if ( cacheDirectory.isEmpty() )
 
  760     cacheDirectory = QStandardPaths::writableLocation( QStandardPaths::CacheLocation );
 
  761   const qint64 cacheSize = settings.
value( QStringLiteral( 
"cache/size" ), 256 * 1024 * 1024 ).toLongLong();
 
  767   if ( cache() != newcache )
 
  768     setCache( newcache );
 
  770   if ( 
this != sMainNAM )
 
  772     static_cast<QgsNetworkCookieJar *
>( cookieJar() )->setAllCookies( 
static_cast<QgsNetworkCookieJar *
>( sMainNAM->cookieJar() )->allCookies() );
 
  776 void QgsNetworkAccessManager::syncCookies( 
const QList<QNetworkCookie> &cookies )
 
  778   if ( sender() != 
this )
 
  780     static_cast<QgsNetworkCookieJar *
>( cookieJar() )->setAllCookies( cookies );
 
  781     if ( 
this == sMainNAM )
 
  802   br.
get( request, forceRefresh, feedback );
 
  810   br.
post( request, data, forceRefresh, feedback );
 
  816   QString 
id = QUuid::createUuid().toString();
 
  817   sCustomPreprocessors.emplace_back( std::make_pair( 
id, processor ) );
 
  823   const size_t prevCount = sCustomPreprocessors.size();
 
  824   sCustomPreprocessors.erase( std::remove_if( sCustomPreprocessors.begin(), sCustomPreprocessors.end(), [
id]( std::pair< QString, std::function< 
void( QNetworkRequest * ) > > &a )
 
  826     return a.first == id;
 
  827   } ), sCustomPreprocessors.end() );
 
  828   return prevCount != sCustomPreprocessors.size();
 
  833   QString 
id = QUuid::createUuid().toString();
 
  834   sCustomReplyPreprocessors.emplace_back( std::make_pair( 
id, processor ) );
 
  840   const size_t prevCount = sCustomReplyPreprocessors.size();
 
  841   sCustomReplyPreprocessors.erase( std::remove_if( sCustomReplyPreprocessors.begin(), sCustomReplyPreprocessors.end(), [
id]( std::pair< QString, std::function< 
void( 
const QNetworkRequest &, QNetworkReply * ) > > &a )
 
  843     return a.first == id;
 
  844   } ), sCustomReplyPreprocessors.end() );
 
  845   return prevCount != sCustomReplyPreprocessors.size();
 
  850   for ( 
const auto &preprocessor :  sCustomPreprocessors )
 
  852     preprocessor.second( req );
 
  862   : mOperation( operation )
 
  863   , mRequest( request )
 
  864   , mOriginatingThreadId( QStringLiteral( 
"0x%2" ).arg( reinterpret_cast<quintptr>( QThread::currentThread() ), 2 * QT_POINTER_SIZE, 16, QLatin1Char( 
'0' ) ) )
 
  865   , mRequestId( requestId )
 
  866   , mContent( content )
 
  867   , mInitiatorClass( request.attribute( static_cast< QNetworkRequest::Attribute >( 
QgsNetworkRequestParameters::AttributeInitiatorClass ) ).toString() )
 
  868   , mInitiatorRequestId( request.attribute( static_cast< QNetworkRequest::Attribute >( 
QgsNetworkRequestParameters::AttributeInitiatorRequestId ) ) )
 
  880   QgsDebugMsg( QStringLiteral( 
"SSL errors occurred accessing URL:\n%1" ).arg( reply->request().url().toString() ) );
 
  890   QgsDebugMsg( QStringLiteral( 
"Network reply required authentication, but no handler was in place to provide this authentication request while accessing the URL:\n%1" ).arg( reply->request().url().toString() ) );
 
  896   QgsDebugMsg( QStringLiteral( 
"Network authentication required external browser to open URL %1, but no handler was in place" ).arg( url.toString() ) );
 
  901   QgsDebugMsg( QStringLiteral( 
"Network authentication required external browser closed, but no handler was in place" ) );
 
  905 #include "qgsnetworkaccessmanager.moc"