00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <fstream>
00023
00024 #include "qgshttptransaction.h"
00025 #include "qgslogger.h"
00026 #include "qgsconfig.h"
00027
00028 #include <QApplication>
00029 #include <QUrl>
00030 #include <QSettings>
00031 #include <QTimer>
00032 #include "qgslogger.h"
00033
00034 static int HTTP_PORT_DEFAULT = 80;
00035
00036
00037
00038
00039
00040 QgsHttpTransaction::QgsHttpTransaction( QString uri,
00041 QString proxyHost,
00042 int proxyPort,
00043 QString proxyUser,
00044 QString proxyPass,
00045 QNetworkProxy::ProxyType proxyType,
00046 QString userName,
00047 QString password )
00048 : httpresponsecontenttype( "" )
00049 , httpurl( uri )
00050 , httphost( proxyHost )
00051 , mError( "" )
00052 {
00053 QSettings s;
00054 mNetworkTimeoutMsec = s.value( "/qgis/networkAndProxy/networkTimeout", "20000" ).toInt();
00055 }
00056
00057 QgsHttpTransaction::QgsHttpTransaction()
00058 {
00059
00060 }
00061
00062 QgsHttpTransaction::~QgsHttpTransaction()
00063 {
00064 QgsDebugMsg( "deconstructing." );
00065 }
00066
00067
00068 void QgsHttpTransaction::setCredentials( const QString& username, const QString& password )
00069 {
00070 mUserName = username;
00071 mPassword = password;
00072 }
00073 void QgsHttpTransaction::getAsynchronously()
00074 {
00075
00076
00077
00078 }
00079
00080 bool QgsHttpTransaction::getSynchronously( QByteArray &respondedContent, int redirections, const QByteArray* postData )
00081 {
00082
00083 httpredirections = redirections;
00084
00085 QgsDebugMsg( "Entered." );
00086 QgsDebugMsg( "Using '" + httpurl + "'." );
00087 QgsDebugMsg( "Creds: " + mUserName + "/" + mPassword );
00088
00089 int httpport;
00090
00091 QUrl qurl( httpurl );
00092
00093 http = new QHttp( );
00094
00095 QHttpRequestHeader header( "GET", qurl.host() );
00096
00097 if ( qurl.port( HTTP_PORT_DEFAULT ) == HTTP_PORT_DEFAULT )
00098 {
00099 header.setValue( "Host", qurl.host() );
00100 }
00101 else
00102 {
00103 header.setValue( "Host", QString( "%1:%2" ).arg( qurl.host() ).arg( qurl.port() ) );
00104 }
00105
00106 header.setValue( "User-agent", QString( "Quantum GIS - " ) + VERSION );
00107
00108 http->setHost( qurl.host(), qurl.port( HTTP_PORT_DEFAULT ) );
00109
00110
00111 if ( !mUserName.isEmpty() && !mPassword.isEmpty() )
00112 {
00113 http->setUser( mUserName, mPassword );
00114 }
00115
00116 if ( !QgsHttpTransaction::applyProxySettings( *http, httpurl ) )
00117 {
00118 httphost = qurl.host();
00119 httpport = qurl.port( HTTP_PORT_DEFAULT );
00120 }
00121 else
00122 {
00123
00124 QSettings settings;
00125 httphost = settings.value( "proxy/proxyHost", "" ).toString();
00126 httpport = settings.value( "proxy/proxyPort", "" ).toString().toInt();
00127 }
00128
00129
00130
00131 mWatchdogTimer = new QTimer( this );
00132
00133 QgsDebugMsg( "qurl.host() is '" + qurl.host() + "'." );
00134
00135 httpresponse.truncate( 0 );
00136
00137
00138
00139
00140
00141
00142
00143 QString pathAndQuery = httpurl.remove( 0, httpurl.indexOf( qurl.host() ) );
00144 pathAndQuery = httpurl.remove( 0, pathAndQuery.indexOf( qurl.path() ) );
00145 if ( !postData )
00146 {
00147 header.setRequest( "GET", pathAndQuery );
00148
00149 httpid = http->request( header );
00150 }
00151 else
00152 {
00153 header.setRequest( "POST", pathAndQuery );
00154
00155 httpid = http->request( header, *postData );
00156 }
00157
00158 connect( http, SIGNAL( requestStarted( int ) ),
00159 this, SLOT( dataStarted( int ) ) );
00160
00161 connect( http, SIGNAL( responseHeaderReceived( const QHttpResponseHeader& ) ),
00162 this, SLOT( dataHeaderReceived( const QHttpResponseHeader& ) ) );
00163
00164 connect( http, SIGNAL( readyRead( const QHttpResponseHeader& ) ),
00165 this, SLOT( dataReceived( const QHttpResponseHeader& ) ) );
00166
00167 connect( http, SIGNAL( dataReadProgress( int, int ) ),
00168 this, SLOT( dataProgress( int, int ) ) );
00169
00170 connect( http, SIGNAL( requestFinished( int, bool ) ),
00171 this, SLOT( dataFinished( int, bool ) ) );
00172
00173 connect( http, SIGNAL( done( bool ) ),
00174 this, SLOT( transactionFinished( bool ) ) );
00175
00176 connect( http, SIGNAL( stateChanged( int ) ),
00177 this, SLOT( dataStateChanged( int ) ) );
00178
00179
00180 connect( mWatchdogTimer, SIGNAL( timeout() ),
00181 this, SLOT( networkTimedOut() ) );
00182
00183 mWatchdogTimer->setSingleShot( true );
00184 mWatchdogTimer->start( mNetworkTimeoutMsec );
00185
00186 QgsDebugMsg( "Starting get with id " + QString::number( httpid ) + "." );
00187 QgsDebugMsg( "Setting httpactive = true" );
00188
00189 httpactive = true;
00190
00191
00192 while ( httpactive )
00193 {
00194
00195 qApp->processEvents();
00196 }
00197
00198 QgsDebugMsg( "Response received." );
00199
00200 #ifdef QGISDEBUG
00201
00202
00203 #endif
00204
00205 delete http;
00206 http = 0;
00207
00208
00209 if ( !mError.isEmpty() )
00210 {
00211 QgsDebugMsg( "Processing an error '" + mError + "'." );
00212 return false;
00213 }
00214
00215
00216
00217
00218 if ( !httpredirecturl.isEmpty() )
00219 {
00220 QgsDebugMsg( "Starting get of '" + httpredirecturl + "'." );
00221
00222 QgsHttpTransaction httprecurse( httpredirecturl, httphost, httpport );
00223 httprecurse.setCredentials( mUserName, mPassword );
00224
00225
00226 connect(
00227 &httprecurse, SIGNAL( statusChanged( QString ) ),
00228 this, SIGNAL( statusChanged( QString ) )
00229 );
00230
00231 httprecurse.getSynchronously( respondedContent, ( redirections + 1 ) );
00232 return true;
00233
00234 }
00235
00236 respondedContent = httpresponse;
00237 return true;
00238
00239 }
00240
00241
00242 QString QgsHttpTransaction::responseContentType()
00243 {
00244 return httpresponsecontenttype;
00245 }
00246
00247
00248 void QgsHttpTransaction::dataStarted( int id )
00249 {
00250 QgsDebugMsg( "ID=" + QString::number( id ) + "." );
00251 }
00252
00253
00254 void QgsHttpTransaction::dataHeaderReceived( const QHttpResponseHeader& resp )
00255 {
00256 QgsDebugMsg( "statuscode " +
00257 QString::number( resp.statusCode() ) + ", reason '" + resp.reasonPhrase() + "', content type: '" +
00258 resp.value( "Content-Type" ) + "'." );
00259
00260
00261 mWatchdogTimer->start( mNetworkTimeoutMsec );
00262
00263 if ( resp.statusCode() == 302 )
00264 {
00265
00266
00267 httpredirecturl = resp.value( "Location" );
00268 }
00269 else if ( resp.statusCode() == 200 )
00270 {
00271
00272 }
00273 else
00274 {
00275 mError = tr( "WMS Server responded unexpectedly with HTTP Status Code %1 (%2)" )
00276 .arg( resp.statusCode() )
00277 .arg( resp.reasonPhrase() );
00278 }
00279
00280 httpresponsecontenttype = resp.value( "Content-Type" );
00281
00282 }
00283
00284
00285 void QgsHttpTransaction::dataReceived( const QHttpResponseHeader& resp )
00286 {
00287
00288
00289 #if 0
00290
00291 char* temp;
00292
00293 if ( 0 < http->readBlock( temp, http->bytesAvailable() ) )
00294 {
00295 httpresponse.append( temp );
00296 }
00297 #endif
00298
00299
00300 }
00301
00302
00303 void QgsHttpTransaction::dataProgress( int done, int total )
00304 {
00305
00306
00307
00308 mWatchdogTimer->start( mNetworkTimeoutMsec );
00309
00310 emit dataReadProgress( done );
00311 emit totalSteps( total );
00312
00313 QString status;
00314
00315 if ( total )
00316 {
00317 status = tr( "Received %1 of %2 bytes" ).arg( done ).arg( total );
00318 }
00319 else
00320 {
00321 status = tr( "Received %1 bytes (total unknown)" ).arg( done );
00322 }
00323
00324 emit statusChanged( status );
00325 }
00326
00327
00328 void QgsHttpTransaction::dataFinished( int id, bool error )
00329 {
00330
00331 #ifdef QGISDEBUG
00332 QgsDebugMsg( "ID=" + QString::number( id ) + "." );
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343 if ( !httpactive )
00344 {
00345 QgsDebugMsg( "http activity loop already false." );
00346 return;
00347 }
00348
00349 if ( error )
00350 {
00351 QgsDebugMsg( "however there was an error." );
00352 QgsDebugMsg( "error: " + http->errorString() );
00353
00354 mError = tr( "HTTP response completed, however there was an error: %1" ).arg( http->errorString() );
00355 }
00356 else
00357 {
00358 QgsDebugMsg( "no error." );
00359 }
00360 #endif
00361
00362
00363
00364
00365 #if 0
00366
00367 httpresponse = http->readAll();
00368
00369
00370 httpactive = false;
00371 #endif
00372 }
00373
00374
00375 void QgsHttpTransaction::transactionFinished( bool error )
00376 {
00377
00378 #ifdef QGISDEBUG
00379 QgsDebugMsg( "entered." );
00380
00381 #if 0
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391 if ( !httpactive )
00392 {
00393
00394 return;
00395 }
00396 #endif
00397
00398 if ( error )
00399 {
00400 QgsDebugMsg( "however there was an error." );
00401 QgsDebugMsg( "error: " + http->errorString() );
00402
00403 mError = tr( "HTTP transaction completed, however there was an error: %1" ).arg( http->errorString() );
00404 }
00405 else
00406 {
00407 QgsDebugMsg( "no error." );
00408 }
00409 #endif
00410
00411
00412 httpresponse = http->readAll();
00413
00414 QgsDebugMsg( "Setting httpactive = false" );
00415 httpactive = false;
00416 }
00417
00418
00419 void QgsHttpTransaction::dataStateChanged( int state )
00420 {
00421 QgsDebugMsg( "state " + QString::number( state ) + "." );
00422
00423
00424 mWatchdogTimer->start( mNetworkTimeoutMsec );
00425
00426 switch ( state )
00427 {
00428 case QHttp::Unconnected:
00429 QgsDebugMsg( "There is no connection to the host." );
00430 emit statusChanged( tr( "Not connected" ) );
00431 break;
00432
00433 case QHttp::HostLookup:
00434 QgsDebugMsg( "A host name lookup is in progress." );
00435
00436 emit statusChanged( tr( "Looking up '%1'" ).arg( httphost ) );
00437 break;
00438
00439 case QHttp::Connecting:
00440 QgsDebugMsg( "An attempt to connect to the host is in progress." );
00441
00442 emit statusChanged( tr( "Connecting to '%1'" ).arg( httphost ) );
00443 break;
00444
00445 case QHttp::Sending:
00446 QgsDebugMsg( "The client is sending its request to the server." );
00447
00448 emit statusChanged( tr( "Sending request '%1'" ).arg( httpurl ) );
00449 break;
00450
00451 case QHttp::Reading:
00452 QgsDebugMsg( "The client's request has been sent and the client is reading the server's response." );
00453
00454 emit statusChanged( tr( "Receiving reply" ) );
00455 break;
00456
00457 case QHttp::Connected:
00458 QgsDebugMsg( "The connection to the host is open, but the client is neither sending a request, nor waiting for a response." );
00459
00460 emit statusChanged( tr( "Response is complete" ) );
00461 break;
00462
00463 case QHttp::Closing:
00464 QgsDebugMsg( "The connection is closing down, but is not yet closed. (The state will be Unconnected when the connection is closed.)" );
00465
00466 emit statusChanged( tr( "Closing down connection" ) );
00467 break;
00468 }
00469 }
00470
00471
00472 void QgsHttpTransaction::networkTimedOut()
00473 {
00474 QgsDebugMsg( "entering." );
00475
00476 mError = tr( "Network timed out after %n second(s) of inactivity.\n"
00477 "This may be a problem in your network connection or at the WMS server.", "inactivity timeout", mNetworkTimeoutMsec / 1000 );
00478
00479 QgsDebugMsg( "Setting httpactive = false" );
00480 httpactive = false;
00481 QgsDebugMsg( "exiting." );
00482 }
00483
00484
00485 QString QgsHttpTransaction::errorString()
00486 {
00487 return mError;
00488 }
00489
00490 bool QgsHttpTransaction::applyProxySettings( QHttp& http, const QString& url )
00491 {
00492 QSettings settings;
00493
00494 bool proxyEnabled = settings.value( "proxy/proxyEnabled", false ).toBool();
00495 if ( !proxyEnabled )
00496 {
00497 return false;
00498 }
00499
00500
00501 QString proxyExcludedURLs = settings.value( "proxy/proxyExcludedUrls", "" ).toString();
00502 if ( !proxyExcludedURLs.isEmpty() )
00503 {
00504 QStringList excludedURLs = proxyExcludedURLs.split( "|" );
00505 QStringList::const_iterator exclIt = excludedURLs.constBegin();
00506 for ( ; exclIt != excludedURLs.constEnd(); ++exclIt )
00507 {
00508 if ( url.startsWith( *exclIt ) )
00509 {
00510 return false;
00511 }
00512 }
00513 }
00514
00515
00516 QString proxyHost = settings.value( "proxy/proxyHost", "" ).toString();
00517 int proxyPort = settings.value( "proxy/proxyPort", "" ).toString().toInt();
00518 QString proxyUser = settings.value( "proxy/proxyUser", "" ).toString();
00519 QString proxyPassword = settings.value( "proxy/proxyPassword", "" ).toString();
00520
00521 QString proxyTypeString = settings.value( "proxy/proxyType", "" ).toString();
00522 QNetworkProxy::ProxyType proxyType = QNetworkProxy::NoProxy;
00523 if ( proxyTypeString == "DefaultProxy" )
00524 {
00525 proxyType = QNetworkProxy::DefaultProxy;
00526 }
00527 else if ( proxyTypeString == "Socks5Proxy" )
00528 {
00529 proxyType = QNetworkProxy::Socks5Proxy;
00530 }
00531 else if ( proxyTypeString == "HttpProxy" )
00532 {
00533 proxyType = QNetworkProxy::HttpProxy;
00534 }
00535 else if ( proxyTypeString == "HttpCachingProxy" )
00536 {
00537 proxyType = QNetworkProxy::HttpCachingProxy;
00538 }
00539 else if ( proxyTypeString == "FtpCachingProxy" )
00540 {
00541 proxyType = QNetworkProxy::FtpCachingProxy;
00542 }
00543 http.setProxy( QNetworkProxy( proxyType, proxyHost, proxyPort, proxyUser, proxyPassword ) );
00544 return true;
00545 }
00546
00547 void QgsHttpTransaction::abort()
00548 {
00549 if ( http )
00550 {
00551 http->abort();
00552 }
00553 }
00554
00555