Vidalia 0.2.12

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 ** \brief Downloads a list of new bridge addresses via HTTPS
00014 */
00015 
00016 #include "BridgeDownloader.h"
00017 #include "Vidalia.h"
00018 
00019 #include <QSslSocket>
00020 
00021 #define BRIDGEDB_HOST  "bridges.torproject.org"
00022 #define BRIDGEDB_PORT  443
00023 
00024 
00025 BridgeDownloader::BridgeDownloader(QObject *parent)
00026   : QObject(parent),
00027     _requestId(0)
00028 {
00029   _https = new QHttp(BRIDGEDB_HOST,  QHttp::ConnectionModeHttps,
00030                      BRIDGEDB_PORT, this);
00031 
00032   connect(_https, SIGNAL(stateChanged(int)),
00033           this, SLOT(httpsStateChanged(int)));
00034   connect(_https, SIGNAL(requestFinished(int, bool)),
00035           this, SLOT(httpsRequestFinished(int, bool)));
00036   connect(_https, SIGNAL(dataReadProgress(int, int)),
00037           this, SIGNAL(downloadProgress(int, int)));
00038   connect(_https, SIGNAL(sslErrors(QList<QSslError>)),
00039           this, SLOT(sslErrors(QList<QSslError>)));  
00040 }
00041 
00042 void
00043 BridgeDownloader::setProxy(const QString &host, int port,
00044                            const QString &username, const QString &password)
00045 {
00046   _https->setProxy(host, port, username, password);
00047 }
00048 
00049 bool
00050 BridgeDownloader::downloadBridges(BridgeDownloadMethod method)
00051 {
00052   if (! isMethodSupported(method))
00053     return false;
00054 
00055   switch (method) {
00056     case DownloadMethodHttps:
00057       startHttpsDownload();
00058       break;
00059  
00060     default:
00061       break;
00062   }
00063   return true;
00064 }
00065 
00066 bool
00067 BridgeDownloader::isMethodSupported(BridgeDownloadMethod method)
00068 {
00069   switch (method) {
00070     case DownloadMethodHttps:
00071       return QSslSocket::supportsSsl();
00072 
00073     default:
00074       break;
00075   }
00076   return false;
00077 }
00078 
00079 void
00080 BridgeDownloader::startHttpsDownload()
00081 {  
00082   emit statusChanged(tr("Starting HTTPS bridge request..."));
00083   emit downloadProgress(0, 0);
00084 
00085   _requestId = _https->get("/?format=plain");
00086   vInfo("Sending an HTTPS bridge request to %1:%2 (id %3).").arg(BRIDGEDB_HOST)
00087                                                             .arg(BRIDGEDB_PORT)
00088                                                             .arg(_requestId);
00089 }
00090 
00091 void
00092 BridgeDownloader::cancelBridgeRequest()
00093 {
00094   _https->abort();
00095 }
00096 
00097 void
00098 BridgeDownloader::httpsStateChanged(int state)
00099 {
00100   switch (state) {
00101     case QHttp::Connecting:
00102       emit statusChanged(tr("Connecting to %1:%2...").arg(BRIDGEDB_HOST)
00103                                                      .arg(BRIDGEDB_PORT));
00104       break;
00105 
00106     case QHttp::Sending:
00107       emit statusChanged(tr("Sending an HTTPS request for bridges..."));
00108       break;
00109 
00110     case QHttp::Reading:
00111       emit statusChanged(tr("Downloading a list of bridges..."));
00112       break;
00113 
00114     default:
00115       break;
00116   }
00117 }
00118 
00119 void
00120 BridgeDownloader::httpsRequestFinished(int id, bool error)
00121 {
00122   if (id != _requestId)
00123     return;
00124 
00125   if (error) {
00126     QString errorString = _https->errorString();
00127     vWarn("Bridge request failed (id %1): %2").arg(id).arg(errorString);
00128   
00129     emit bridgeRequestFailed(errorString);
00130   } else {
00131     QByteArray response = _https->readAll();
00132     vInfo("Bridge request complete (id %1): received %2 bytes.").arg(id)
00133                                                    .arg(response.size());
00134 
00135     QStringList bridges, lines = QString(response).split("\n");
00136     foreach (QString line, lines) {
00137       line = line.trimmed();
00138       if (line.startsWith("bridge ", Qt::CaseInsensitive))
00139         bridges << line;
00140     }
00141     emit bridgeRequestFinished(bridges);
00142   }
00143   _https->close();
00144 }
00145 
00146 void
00147 BridgeDownloader::sslErrors(const QList<QSslError> &sslErrors)
00148 {
00149   QString errorString;
00150   QStringList errorStrings;
00151 
00152   vWarn("%1 SSL error(s) when requesting bridge information (id %2):")
00153                                                       .arg(sslErrors.size())
00154                                                       .arg(_requestId);
00155   foreach (QSslError sslError, sslErrors) {
00156     errorString = sslError.errorString();
00157     errorStrings << errorString;
00158     vWarn("  SSL Error: %1").arg(errorString);
00159   }
00160 }
00161