Vidalia 0.2.10

BridgeDownloader.cpp

Go to the documentation of this file.
00001 /*
00002 **  This file is part of Vidalia, and is subject to the license terms in the
00003 **  LICENSE file, found in the top level directory of this distribution. If you
00004 **  did not receive the LICENSE file with this file, you may obtain it from the
00005 **  Vidalia source package distributed by the Vidalia Project at
00006 **  http://www.vidalia-project.net/. No part of Vidalia, including this file,
00007 **  may be copied, modified, propagated, or distributed except according to the
00008 **  terms described in the LICENSE file.
00009 */
00010 
00011 /*
00012 ** \file BridgeDownloader.cpp
00013 ** \version $Id: BridgeDownloader.cpp 3735 2009-04-28 20:28:01Z edmanm $
00014 ** \brief Downloads a list of new bridge addresses via HTTPS
00015 */
00016 
00017 #include "BridgeDownloader.h"
00018 #include "Vidalia.h"
00019 
00020 #include <QSslSocket>
00021 
00022 #define BRIDGEDB_HOST  "bridges.torproject.org"
00023 #define BRIDGEDB_PORT  443
00024 
00025 
00026 BridgeDownloader::BridgeDownloader(QObject *parent)
00027   : QObject(parent),
00028     _requestId(0)
00029 {
00030   _https = new QHttp(BRIDGEDB_HOST,  QHttp::ConnectionModeHttps,
00031                      BRIDGEDB_PORT, this);
00032 
00033   connect(_https, SIGNAL(stateChanged(int)),
00034           this, SLOT(httpsStateChanged(int)));
00035   connect(_https, SIGNAL(requestFinished(int, bool)),
00036           this, SLOT(httpsRequestFinished(int, bool)));
00037   connect(_https, SIGNAL(dataReadProgress(int, int)),
00038           this, SIGNAL(downloadProgress(int, int)));
00039   connect(_https, SIGNAL(sslErrors(QList<QSslError>)),
00040           this, SLOT(sslErrors(QList<QSslError>)));  
00041 }
00042 
00043 void
00044 BridgeDownloader::setProxy(const QString &host, int port,
00045                            const QString &username, const QString &password)
00046 {
00047   _https->setProxy(host, port, username, password);
00048 }
00049 
00050 bool
00051 BridgeDownloader::downloadBridges(BridgeDownloadMethod method)
00052 {
00053   if (! isMethodSupported(method))
00054     return false;
00055 
00056   switch (method) {
00057     case DownloadMethodHttps:
00058       startHttpsDownload();
00059       break;
00060  
00061     default:
00062       break;
00063   }
00064   return true;
00065 }
00066 
00067 bool
00068 BridgeDownloader::isMethodSupported(BridgeDownloadMethod method)
00069 {
00070   switch (method) {
00071     case DownloadMethodHttps:
00072       return QSslSocket::supportsSsl();
00073 
00074     default:
00075       break;
00076   }
00077   return false;
00078 }
00079 
00080 void
00081 BridgeDownloader::startHttpsDownload()
00082 {  
00083   emit statusChanged(tr("Starting HTTPS bridge request..."));
00084   emit downloadProgress(0, 0);
00085 
00086   _requestId = _https->get("/?format=plain");
00087   vInfo("Sending an HTTPS bridge request to %1:%2 (id %3).").arg(BRIDGEDB_HOST)
00088                                                             .arg(BRIDGEDB_PORT)
00089                                                             .arg(_requestId);
00090 }
00091 
00092 void
00093 BridgeDownloader::cancelBridgeRequest()
00094 {
00095   _https->abort();
00096 }
00097 
00098 void
00099 BridgeDownloader::httpsStateChanged(int state)
00100 {
00101   switch (state) {
00102     case QHttp::Connecting:
00103       emit statusChanged(tr("Connecting to %1:%2...").arg(BRIDGEDB_HOST)
00104                                                      .arg(BRIDGEDB_PORT));
00105       break;
00106 
00107     case QHttp::Sending:
00108       emit statusChanged(tr("Sending an HTTPS request for bridges..."));
00109       break;
00110 
00111     case QHttp::Reading:
00112       emit statusChanged(tr("Downloading a list of bridges..."));
00113       break;
00114 
00115     default:
00116       break;
00117   }
00118 }
00119 
00120 void
00121 BridgeDownloader::httpsRequestFinished(int id, bool error)
00122 {
00123   if (id != _requestId)
00124     return;
00125 
00126   if (error) {
00127     QString errorString = _https->errorString();
00128     vWarn("Bridge request failed (id %1): %2").arg(id).arg(errorString);
00129   
00130     emit bridgeRequestFailed(errorString);
00131   } else {
00132     QByteArray response = _https->readAll();
00133     vInfo("Bridge request complete (id %1): received %2 bytes.").arg(id)
00134                                                    .arg(response.size());
00135 
00136     QStringList bridges, lines = QString(response).split("\n");
00137     foreach (QString line, lines) {
00138       line = line.trimmed();
00139       if (line.startsWith("bridge ", Qt::CaseInsensitive))
00140         bridges << line;
00141     }
00142     emit bridgeRequestFinished(bridges);
00143   }
00144   _https->close();
00145 }
00146 
00147 void
00148 BridgeDownloader::sslErrors(const QList<QSslError> &sslErrors)
00149 {
00150   QString errorString;
00151   QStringList errorStrings;
00152 
00153   vWarn("%1 SSL error(s) when requesting bridge information (id %2):")
00154                                                       .arg(sslErrors.size())
00155                                                       .arg(_requestId);
00156   foreach (QSslError sslError, sslErrors) {
00157     errorString = sslError.errorString();
00158     errorStrings << errorString;
00159     vWarn("  SSL Error: %1").arg(errorString);
00160   }
00161 }
00162