Vidalia 0.2.12
|
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