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