QGIS API Documentation  2.2.0-Valmiera
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qgsnetworkaccessmanager.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsnetworkaccessmanager.cpp
3  This class implements a QNetworkManager with the ability to chain in
4  own proxy factories.
5 
6  -------------------
7  begin : 2010-05-08
8  copyright : (C) 2010 by Juergen E. Fischer
9  email : jef at norbit dot de
10 
11 ***************************************************************************/
12 
13 /***************************************************************************
14  * *
15  * This program is free software; you can redistribute it and/or modify *
16  * it under the terms of the GNU General Public License as published by *
17  * the Free Software Foundation; either version 2 of the License, or *
18  * (at your option) any later version. *
19  * *
20  ***************************************************************************/
21 
23 #include <qgsmessagelog.h>
24 #include <qgslogger.h>
25 #include <qgis.h>
26 
27 #include <QUrl>
28 #include <QSettings>
29 #include <QTimer>
30 #include <QNetworkReply>
31 
32 class QgsNetworkProxyFactory : public QNetworkProxyFactory
33 {
34  public:
37 
38  virtual QList<QNetworkProxy> queryProxy( const QNetworkProxyQuery & query = QNetworkProxyQuery() )
39  {
41 
42  // iterate proxies factories and take first non empty list
43  foreach ( QNetworkProxyFactory *f, nam->proxyFactories() )
44  {
45  QList<QNetworkProxy> systemproxies = f->systemProxyForQuery( query );
46  if ( systemproxies.size() > 0 )
47  return systemproxies;
48 
49  QList<QNetworkProxy> proxies = f->queryProxy( query );
50  if ( proxies.size() > 0 )
51  return proxies;
52  }
53 
54  // no proxies from the proxy factor list check for excludes
55  if ( query.queryType() != QNetworkProxyQuery::UrlRequest )
56  return QList<QNetworkProxy>() << nam->fallbackProxy();
57 
58  QString url = query.url().toString();
59 
60  foreach ( QString exclude, nam->excludeList() )
61  {
62  if ( url.startsWith( exclude ) )
63  {
64  QgsDebugMsg( QString( "using default proxy for %1 [exclude %2]" ).arg( url ).arg( exclude ) );
65  return QList<QNetworkProxy>() << QNetworkProxy();
66  }
67  }
68 
69  QgsDebugMsg( QString( "using user proxy for %1" ).arg( url ) );
70  return QList<QNetworkProxy>() << nam->fallbackProxy();
71  }
72 };
73 
75 {
76  static QgsNetworkAccessManager sInstance;
77 
78  return &sInstance;
79 }
80 
82  : QNetworkAccessManager( parent )
83 {
84  setProxyFactory( new QgsNetworkProxyFactory() );
85 }
86 
88 {
89 }
90 
91 void QgsNetworkAccessManager::insertProxyFactory( QNetworkProxyFactory *factory )
92 {
93  mProxyFactories.insert( 0, factory );
94 }
95 
96 void QgsNetworkAccessManager::removeProxyFactory( QNetworkProxyFactory *factory )
97 {
98  mProxyFactories.removeAll( factory );
99 }
100 
101 const QList<QNetworkProxyFactory *> QgsNetworkAccessManager::proxyFactories() const
102 {
103  return mProxyFactories;
104 }
105 
106 const QStringList &QgsNetworkAccessManager::excludeList() const
107 {
108  return mExcludedURLs;
109 }
110 
111 const QNetworkProxy &QgsNetworkAccessManager::fallbackProxy() const
112 {
113  return mFallbackProxy;
114 }
115 
116 void QgsNetworkAccessManager::setFallbackProxyAndExcludes( const QNetworkProxy &proxy, const QStringList &excludes )
117 {
118  QgsDebugMsg( QString( "proxy settings: (type:%1 host: %2:%3, user:%4, password:%5" )
119  .arg( proxy.type() == QNetworkProxy::DefaultProxy ? "DefaultProxy" :
120  proxy.type() == QNetworkProxy::Socks5Proxy ? "Socks5Proxy" :
121  proxy.type() == QNetworkProxy::NoProxy ? "NoProxy" :
122  proxy.type() == QNetworkProxy::HttpProxy ? "HttpProxy" :
123  proxy.type() == QNetworkProxy::HttpCachingProxy ? "HttpCachingProxy" :
124  proxy.type() == QNetworkProxy::FtpCachingProxy ? "FtpCachingProxy" :
125  "Undefined" )
126  .arg( proxy.hostName() )
127  .arg( proxy.port() )
128  .arg( proxy.user() )
129  .arg( proxy.password().isEmpty() ? "not set" : "set" ) );
130 
131  mFallbackProxy = proxy;
132  mExcludedURLs = excludes;
133 }
134 
135 QNetworkReply *QgsNetworkAccessManager::createRequest( QNetworkAccessManager::Operation op, const QNetworkRequest &req, QIODevice *outgoingData )
136 {
137  QSettings s;
138 
139  QNetworkRequest *pReq(( QNetworkRequest * ) &req ); // hack user agent
140 
141  QString userAgent = s.value( "/qgis/networkAndProxy/userAgent", "Mozilla/5.0" ).toString();
142  if ( !userAgent.isEmpty() )
143  userAgent += " ";
144  userAgent += QString( "QGIS/%1" ).arg( QGis::QGIS_VERSION );
145  pReq->setRawHeader( "User-Agent", userAgent.toUtf8() );
146 
147  emit requestAboutToBeCreated( op, req, outgoingData );
148  QNetworkReply *reply = QNetworkAccessManager::createRequest( op, req, outgoingData );
149 
150  connect( reply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( connectionProgress() ) );
151  connect( reply, SIGNAL( uploadProgress( qint64, qint64 ) ), this, SLOT( connectionProgress() ) );
152  connect( reply, SIGNAL( destroyed( QObject* ) ), this, SLOT( connectionDestroyed( QObject* ) ) );
153  emit requestCreated( reply );
154 
155  // abort request, when network timeout happens
156  QTimer *timer = new QTimer( reply );
157  connect( timer, SIGNAL( timeout() ), this, SLOT( abortRequest() ) );
158  timer->setSingleShot( true );
159  timer->start( s.value( "/qgis/networkAndProxy/networkTimeout", "20000" ).toInt() );
160 
161  mActiveRequests.insert( reply, timer );
162  return reply;
163 }
164 
166 {
167  QNetworkReply *reply = qobject_cast<QNetworkReply *>( sender() );
168  Q_ASSERT( reply );
169 
170  QTimer* timer = mActiveRequests.find( reply ).value();
171  Q_ASSERT( timer );
172 
173  QSettings s;
174  timer->start( s.value( "/qgis/networkAndProxy/networkTimeout", "20000" ).toInt() );
175 }
176 
178 {
179  mActiveRequests.remove( qobject_cast<QNetworkReply*>( reply ) );
180 }
181 
183 {
184  QTimer *timer = qobject_cast<QTimer *>( sender() );
185  Q_ASSERT( timer );
186 
187  QNetworkReply *reply = qobject_cast<QNetworkReply *>( timer->parent() );
188  Q_ASSERT( reply );
189 
190  QgsMessageLog::logMessage( tr( "Network request %1 timed out" ).arg( reply->url().toString() ), tr( "Network" ) );
191 
192  if ( reply->isRunning() )
193  reply->close();
194 }
195 
196 QString QgsNetworkAccessManager::cacheLoadControlName( QNetworkRequest::CacheLoadControl theControl )
197 {
198  switch ( theControl )
199  {
200  case QNetworkRequest::AlwaysNetwork:
201  return "AlwaysNetwork";
202  break;
203  case QNetworkRequest::PreferNetwork:
204  return "PreferNetwork";
205  break;
206  case QNetworkRequest::PreferCache:
207  return "PreferCache";
208  break;
209  case QNetworkRequest::AlwaysCache:
210  return "AlwaysCache";
211  break;
212  default:
213  break;
214  }
215  return "PreferNetwork";
216 }
217 
218 QNetworkRequest::CacheLoadControl QgsNetworkAccessManager::cacheLoadControlFromName( const QString &theName )
219 {
220  if ( theName == "AlwaysNetwork" )
221  {
222  return QNetworkRequest::AlwaysNetwork;
223  }
224  else if ( theName == "PreferNetwork" )
225  {
226  return QNetworkRequest::PreferNetwork;
227  }
228  else if ( theName == "PreferCache" )
229  {
230  return QNetworkRequest::PreferCache;
231  }
232  else if ( theName == "AlwaysCache" )
233  {
234  return QNetworkRequest::AlwaysCache;
235  }
236  return QNetworkRequest::PreferNetwork;
237 }