[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[vidalia-svn] r3729: Add support for automatically downloading a list of bridges (in vidalia/trunk: . src/vidalia src/vidalia/config)



Author: edmanm
Date: 2009-04-24 23:20:10 -0400 (Fri, 24 Apr 2009)
New Revision: 3729

Added:
   vidalia/trunk/src/vidalia/config/bridgedownloader.cpp
   vidalia/trunk/src/vidalia/config/bridgedownloader.h
   vidalia/trunk/src/vidalia/config/bridgedownloaderprogressdialog.cpp
   vidalia/trunk/src/vidalia/config/bridgedownloaderprogressdialog.h
   vidalia/trunk/src/vidalia/config/bridgedownloaderprogressdialog.ui
Modified:
   vidalia/trunk/CHANGELOG
   vidalia/trunk/src/vidalia/CMakeLists.txt
   vidalia/trunk/src/vidalia/config/networkpage.cpp
   vidalia/trunk/src/vidalia/config/networkpage.h
Log:

Add support for automatically downloading a list of bridges via HTTPS,
displaying the progress of the request, and adding any new bridge
addresses to the list in the Network settings page.


Modified: vidalia/trunk/CHANGELOG
===================================================================
--- vidalia/trunk/CHANGELOG	2009-04-20 09:29:17 UTC (rev 3728)
+++ vidalia/trunk/CHANGELOG	2009-04-25 03:20:10 UTC (rev 3729)
@@ -1,4 +1,7 @@
 0.2.1   xx-xxx-2009
+  o Add a "Find Bridges Now" button that will attempt to automatically
+    download a set of bridge addresses and add them to the list of bridges
+    in the Network settings page.
   o Tolerate bridge addresses that do not specify a port number, since Tor
     now defaults to using port 443 in such cases.
   o Renamed the 'make win32-installer' CMake target to 'make dist-win32'

Modified: vidalia/trunk/src/vidalia/CMakeLists.txt
===================================================================
--- vidalia/trunk/src/vidalia/CMakeLists.txt	2009-04-20 09:29:17 UTC (rev 3728)
+++ vidalia/trunk/src/vidalia/CMakeLists.txt	2009-04-25 03:20:10 UTC (rev 3729)
@@ -72,6 +72,8 @@
   config/abstracttorsettings.cpp
   config/advancedpage.cpp
   config/appearancepage.cpp
+  config/bridgedownloader.cpp
+  config/bridgedownloaderprogressdialog.cpp
   config/bridgeusagedialog.cpp
   config/configdialog.cpp
   config/configpagestack.cpp
@@ -98,6 +100,8 @@
   config/abstracttorsettings.h
   config/advancedpage.h
   config/appearancepage.h
+  config/bridgedownloader.h
+  config/bridgedownloaderprogressdialog.h
   config/bridgeusagedialog.h
   config/configdialog.h
   config/configpage.h
@@ -245,6 +249,7 @@
   bwgraph/bwgraph.ui
   config/advancedpage.ui
   config/appearancepage.ui
+  config/bridgedownloaderprogressdialog.ui
   config/bridgeusagedialog.ui
   config/configdialog.ui
   config/generalpage.ui

Added: vidalia/trunk/src/vidalia/config/bridgedownloader.cpp
===================================================================
--- vidalia/trunk/src/vidalia/config/bridgedownloader.cpp	                        (rev 0)
+++ vidalia/trunk/src/vidalia/config/bridgedownloader.cpp	2009-04-25 03:20:10 UTC (rev 3729)
@@ -0,0 +1,154 @@
+/*
+**  This file is part of Vidalia, and is subject to the license terms in the
+**  LICENSE file, found in the top level directory of this distribution. If you
+**  did not receive the LICENSE file with this file, you may obtain it from the
+**  Vidalia source package distributed by the Vidalia Project at
+**  http://www.vidalia-project.net/. No part of Vidalia, including this file,
+**  may be copied, modified, propagated, or distributed except according to the
+**  terms described in the LICENSE file.
+*/
+
+/*
+** \file bridgedownloader.cpp
+** \version $Id$
+** \brief Downloads a list of new bridge addresses via HTTPS
+*/
+
+#include <QSslSocket>
+#include <vidalia.h>
+#include <bridgedownloader.h>
+
+#define BRIDGEDB_HOST  "bridges.torproject.org"
+#define BRIDGEDB_PORT  443
+
+
+BridgeDownloader::BridgeDownloader(QObject *parent)
+  : QObject(parent),
+    _requestId(0)
+{
+  _https = new QHttp(BRIDGEDB_HOST,  QHttp::ConnectionModeHttps,
+                     BRIDGEDB_PORT, this);
+
+  connect(_https, SIGNAL(stateChanged(int)),
+          this, SLOT(httpsStateChanged(int)));
+  connect(_https, SIGNAL(requestFinished(int, bool)),
+          this, SLOT(httpsRequestFinished(int, bool)));
+  connect(_https, SIGNAL(dataReadProgress(int, int)),
+          this, SIGNAL(downloadProgress(int, int)));
+  connect(_https, SIGNAL(sslErrors(QList<QSslError>)),
+          this, SLOT(sslErrors(QList<QSslError>)));  
+}
+
+bool
+BridgeDownloader::downloadBridges(BridgeDownloadMethod method)
+{
+  if (! isMethodSupported(method))
+    return false;
+
+  switch (method) {
+    case DownloadMethodHttps:
+      startHttpsDownload();
+      break;
+ 
+    default:
+      break;
+  }
+  return true;
+}
+
+bool
+BridgeDownloader::isMethodSupported(BridgeDownloadMethod method)
+{
+  switch (method) {
+    case DownloadMethodHttps:
+      return QSslSocket::supportsSsl();
+
+    default:
+      break;
+  }
+  return false;
+}
+
+void
+BridgeDownloader::startHttpsDownload()
+{  
+  emit statusChanged(tr("Starting HTTPS bridge request..."));
+  emit downloadProgress(0, 0);
+
+  _requestId = _https->get("/?format=plain");
+  vInfo("Sending an HTTPS bridge request to %1:%2 (id %3).").arg(BRIDGEDB_HOST)
+                                                            .arg(BRIDGEDB_PORT)
+                                                            .arg(_requestId);
+}
+
+void
+BridgeDownloader::cancelBridgeRequest()
+{
+  _https->abort();
+}
+
+void
+BridgeDownloader::httpsStateChanged(int state)
+{
+  switch (state) {
+    case QHttp::Connecting:
+      emit statusChanged(tr("Connecting to %1:%2...").arg(BRIDGEDB_HOST)
+                                                     .arg(BRIDGEDB_PORT));
+      break;
+
+    case QHttp::Sending:
+      emit statusChanged(tr("Sending an HTTPS request for bridges..."));
+      break;
+
+    case QHttp::Reading:
+      emit statusChanged(tr("Downloading a list of bridges..."));
+      break;
+
+    default:
+      break;
+  }
+}
+
+void
+BridgeDownloader::httpsRequestFinished(int id, bool error)
+{
+  if (id != _requestId)
+    return;
+
+  if (error) {
+    QString errorString = _https->errorString();
+    vWarn("Bridge request failed (id %1): %2").arg(id).arg(errorString);
+  
+    emit bridgeRequestFailed(errorString);
+  } else {
+    QByteArray response = _https->readAll();
+    vInfo("Bridge request complete (id %1): received %2 bytes.").arg(id)
+                                                   .arg(response.size());
+
+    QStringList bridges, lines = QString(response).split("\n");
+    foreach (QString line, lines) {
+      line = line.trimmed();
+      if (line.startsWith("bridge ", Qt::CaseInsensitive))
+        bridges << line;
+    }
+    emit bridgeRequestFinished(bridges);
+  }
+  _https->close();
+}
+
+void
+BridgeDownloader::sslErrors(const QList<QSslError> &sslErrors)
+{
+  QString errorString;
+  QStringList errorStrings;
+
+  vWarn("%1 SSL error(s) when requesting bridge information (id %2):")
+                                                      .arg(sslErrors.size())
+                                                      .arg(_requestId);
+  foreach (QSslError sslError, sslErrors) {
+    errorString = sslError.errorString();
+    errorStrings << errorString;
+    vWarn("  SSL Error: %1").arg(errorString);
+  }
+}
+


Property changes on: vidalia/trunk/src/vidalia/config/bridgedownloader.cpp
___________________________________________________________________
Added: svn:keywords
   + Id
Added: svn:eol-style
   + native

Added: vidalia/trunk/src/vidalia/config/bridgedownloader.h
===================================================================
--- vidalia/trunk/src/vidalia/config/bridgedownloader.h	                        (rev 0)
+++ vidalia/trunk/src/vidalia/config/bridgedownloader.h	2009-04-25 03:20:10 UTC (rev 3729)
@@ -0,0 +1,118 @@
+/*
+**  This file is part of Vidalia, and is subject to the license terms in the
+**  LICENSE file, found in the top level directory of this distribution. If you
+**  did not receive the LICENSE file with this file, you may obtain it from the
+**  Vidalia source package distributed by the Vidalia Project at
+**  http://www.vidalia-project.net/. No part of Vidalia, including this file,
+**  may be copied, modified, propagated, or distributed except according to the
+**  terms described in the LICENSE file.
+*/
+
+/*
+** \file bridgedownloader.h
+** \version $Id$
+** \brief Downloads a list of new bridge addresses via HTTPS
+*/
+
+#ifndef _BRIDGEDOWNLOADER_H
+#define _BRIDGEDOWNLOADER_H
+
+#include <QHttp>
+#include <QSslError>
+#include <QStringList>
+
+
+class BridgeDownloader : public QObject
+{
+  Q_OBJECT
+
+public:
+  /** Available bridge download methods. */
+  enum BridgeDownloadMethod {
+    DownloadMethodHttps, /** Download via an HTTPS connection. */
+  };
+
+  /** Default constructor.
+   */
+  BridgeDownloader(QObject *parent = 0);
+
+  /** Initiates a request for a set of bridges using the specified
+   * download <b>method</b>. Returns true if the request was initiated
+   * successfully, or false on error.
+   */
+  bool downloadBridges(BridgeDownloadMethod method);
+
+  /** Returns true if <b>method</b> is supported by the currently
+   * available Qt libraries.
+   */
+  static bool isMethodSupported(BridgeDownloadMethod method);
+
+public slots:
+  /** Cancels any pending bridge download requests.
+   */
+  void cancelBridgeRequest();
+
+signals:
+  /** Emitted when the underlying QHttp object reads data from an HTTPS
+   * response. <b>done</b> indicates how many bytes out of <b>total</b>
+   * have been read so far. Note that <b>total</b> may be 0 if the expected
+   * total size of the response is not known.
+   */
+  void downloadProgress(int done, int total);
+
+  /** Emitted when the status of the bridge request changes. <b>status</b>
+   * describes the new current state of the request.
+   */
+  void statusChanged(const QString &status);
+
+  /** Emitted when the previous request for bridge addresses completes
+   * successfully. The QStringList <b>bridges</b> contains a (possibly empty)
+   * list of bridge addresses parsed from the received response.
+   */
+  void bridgeRequestFinished(const QStringList &bridges);
+
+  /** Emitted when the previous request for bridge addresses fails. The
+   * QString <b>error</b> is a human-readable string describing the error
+   * encountered.
+   */
+  void bridgeRequestFailed(const QString &error);
+
+private slots:
+  /** Called when the state of the underlying QHttp object changes. A
+   * statusChanged() signal is emitted with the appropriate text
+   * describing the new state of the request.
+   */
+  void httpsStateChanged(int state); 
+
+  /** Called when the underlying QHttp object used to make the bridge
+   * request completes. <b>error</b> is set to false if the request was
+   * successful, or true if the request failed. If <b>id</b> does not
+   * match the request ID previously returned by QHttp::get(), then the
+   * signal is ignored since it is the result of a close() or abort()
+   * request.
+   */
+  void httpsRequestFinished(int id, bool error);
+
+  /** Called when the HTTPS connection encounters one or more
+   * <b>sslErrors</b>. Currently the errors are just logged and
+   * bridgeRequestFailed() is <i>not</i> emitted, since QHttp will also
+   * emit 
+   */
+  void sslErrors(const QList<QSslError> &sslErrors);
+
+private:
+  /** Initiates an HTTPS connection to bridges.torproject.org to start
+   * downloading a set of bridges.
+   */
+  void startHttpsDownload();
+
+  /** Used to connect to the bridge database, send an HTTPS request for
+   * new bridge addresses and then read the response. */
+  QHttp* _https;
+  
+  /** Unique numeric identifier of the current bridge request. */
+  int _requestId;
+};
+
+#endif
+


Property changes on: vidalia/trunk/src/vidalia/config/bridgedownloader.h
___________________________________________________________________
Added: svn:keywords
   + Id
Added: svn:eol-style
   + native

Added: vidalia/trunk/src/vidalia/config/bridgedownloaderprogressdialog.cpp
===================================================================
--- vidalia/trunk/src/vidalia/config/bridgedownloaderprogressdialog.cpp	                        (rev 0)
+++ vidalia/trunk/src/vidalia/config/bridgedownloaderprogressdialog.cpp	2009-04-25 03:20:10 UTC (rev 3729)
@@ -0,0 +1,91 @@
+/*
+**  This file is part of Vidalia, and is subject to the license terms in the
+**  LICENSE file, found in the top level directory of this distribution. If you
+**  did not receive the LICENSE file with this file, you may obtain it from the
+**  Vidalia source package distributed by the Vidalia Project at
+**  http://www.vidalia-project.net/. No part of Vidalia, including this file,
+**  may be copied, modified, propagated, or distributed except according to the
+**  terms described in the LICENSE file.
+*/
+
+/*
+** \file bridgedownloaderprogressdialog.cpp
+** \version $Id$
+** \brief Displays the progress of a request for bridge addresses
+*/
+
+#include <QTimer>
+
+#include "bridgedownloaderprogressdialog.h"
+
+
+BridgeDownloaderProgressDialog::BridgeDownloaderProgressDialog(QWidget *parent)
+  : QDialog(parent)
+{
+  ui.setupUi(this);
+ 
+  connect(ui.buttonBox, SIGNAL(clicked(QAbstractButton *)),
+          this, SLOT(buttonClicked(QAbstractButton *)));
+
+  setModal(true);
+}
+
+void
+BridgeDownloaderProgressDialog::setVisible(bool visible)
+{
+  if (visible) {
+    ui.progressBar->setRange(0, 0);
+    ui.buttonBox->setStandardButtons(QDialogButtonBox::Cancel);
+  }
+  QDialog::setVisible(visible);
+}
+
+void
+BridgeDownloaderProgressDialog::setStatus(const QString &status)
+{
+  ui.lblStatus->setText(status);
+}
+
+void
+BridgeDownloaderProgressDialog::setDownloadProgress(int done, int total)
+{
+  ui.progressBar->setRange(0, total);
+  ui.progressBar->setValue(done);
+}
+
+void
+BridgeDownloaderProgressDialog::bridgeRequestFinished(const QStringList &bridges)
+{
+  Q_UNUSED(bridges);
+  
+  accept();
+}
+
+void
+BridgeDownloaderProgressDialog::bridgeRequestFailed(const QString &error)
+{
+  ui.lblStatus->setText(tr("Unable to download bridges: %1").arg(error));
+
+  ui.progressBar->setRange(0, 1);
+  ui.progressBar->setValue(1);
+
+  ui.buttonBox->setStandardButtons(QDialogButtonBox::Cancel
+                                     | QDialogButtonBox::Retry
+                                     | QDialogButtonBox::Help);
+}
+
+void
+BridgeDownloaderProgressDialog::buttonClicked(QAbstractButton *button)
+{
+  int standardButton = ui.buttonBox->standardButton(button);
+  if (standardButton == QDialogButtonBox::Retry) {
+    setStatus(tr("Retrying bridge request..."));
+    setDownloadProgress(0, 0);
+    ui.buttonBox->setStandardButtons(QDialogButtonBox::Cancel);
+  
+    QTimer::singleShot(1000, this, SIGNAL(retry()));
+  } else {
+    done(standardButton);
+  }
+}
+


Property changes on: vidalia/trunk/src/vidalia/config/bridgedownloaderprogressdialog.cpp
___________________________________________________________________
Added: svn:keywords
   + Id
Added: svn:eol-style
   + native

Added: vidalia/trunk/src/vidalia/config/bridgedownloaderprogressdialog.h
===================================================================
--- vidalia/trunk/src/vidalia/config/bridgedownloaderprogressdialog.h	                        (rev 0)
+++ vidalia/trunk/src/vidalia/config/bridgedownloaderprogressdialog.h	2009-04-25 03:20:10 UTC (rev 3729)
@@ -0,0 +1,84 @@
+/*
+**  This file is part of Vidalia, and is subject to the license terms in the
+**  LICENSE file, found in the top level directory of this distribution. If you
+**  did not receive the LICENSE file with this file, you may obtain it from the
+**  Vidalia source package distributed by the Vidalia Project at
+**  http://www.vidalia-project.net/. No part of Vidalia, including this file,
+**  may be copied, modified, propagated, or distributed except according to the
+**  terms described in the LICENSE file.
+*/
+
+/*
+** \file bridgedownloaderprogressdialog.h
+** \version $Id$
+** \brief Displays the progress of a request for bridge addresses
+*/
+
+#ifndef _BRIDGEDOWNLOADERPROGRESSDIALOG_H
+#define _BRIDGEDOWNLOADERPROGRESSDIALOG_H
+
+#include <QDialog>
+
+#include "ui_bridgedownloaderprogressdialog.h"
+
+
+class BridgeDownloaderProgressDialog : public QDialog
+{
+  Q_OBJECT
+
+public:
+  /** Default constructor.
+   */
+  BridgeDownloaderProgressDialog(QWidget *parent = 0);
+
+public slots:
+   /** Sets the status message text in the dialog to <b>status</b>.
+   */
+  void setStatus(const QString &status);
+
+  /** Updates the bridge download progress bar to <b>value</b> out of
+   * <b>maximum</b> steps. If <b>value</b> and <b>maximum</b> are both 0,
+   * then a "busy" progress bar is displayed.
+   */
+  void setDownloadProgress(int value, int maximum);
+
+  /** Called when the bridge download completes successfully and discards 
+   * the progress dialog with an Accept result code. <b>bridges</b>
+   * contains the list of bridges downloaded, but is currently ignored.
+   */
+  void bridgeRequestFinished(const QStringList &bridges);
+
+  /** Called when the bridge download fails. The string <b>error</b>
+   * provides a human-readable description of the reason the download
+   * failed, which is displayed for the user.
+   */
+  void bridgeRequestFailed(const QString &error);
+
+signals:
+  /** Emitted when the user clicks the "Retry" button after a previous
+   * bridge request has failed.
+   */
+  void retry();
+
+protected:
+  /** Overloaded method called when the progress dialog is first shown in
+   * order to initialize the progress bar, status text and dialog button
+   * box.
+   */
+  virtual void setVisible(bool visible);
+
+private slots:
+  /** Called when <b>button</b> is clicked in the progress dialog's
+   * QDialogButtonBox. Dismisses the dialog and sets the result code to
+   * the QDialogButtonBox::StandardButton enum value indicated by
+   * <b>button</b>.
+   */
+  void buttonClicked(QAbstractButton *button);
+
+private:
+  /**< Qt Designer generated object. */
+  Ui::BridgeDownloaderProgressDialog ui;
+};
+
+#endif
+


Property changes on: vidalia/trunk/src/vidalia/config/bridgedownloaderprogressdialog.h
___________________________________________________________________
Added: svn:keywords
   + Id
Added: svn:eol-style
   + native

Added: vidalia/trunk/src/vidalia/config/bridgedownloaderprogressdialog.ui
===================================================================
--- vidalia/trunk/src/vidalia/config/bridgedownloaderprogressdialog.ui	                        (rev 0)
+++ vidalia/trunk/src/vidalia/config/bridgedownloaderprogressdialog.ui	2009-04-25 03:20:10 UTC (rev 3729)
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>BridgeDownloaderProgressDialog</class>
+ <widget class="QDialog" name="BridgeDownloaderProgressDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>366</width>
+    <height>105</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Downloading Bridges</string>
+  </property>
+  <property name="windowIcon">
+   <iconset resource="../res/vidalia.qrc">
+    <normaloff>:/images/32x32/network-workgroup.png</normaloff>:/images/32x32/network-workgroup.png</iconset>
+  </property>
+  <property name="modal">
+   <bool>true</bool>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="0" column="0" rowspan="2">
+    <widget class="QLabel" name="lblPixmap">
+     <property name="text">
+      <string/>
+     </property>
+     <property name="pixmap">
+      <pixmap resource="../res/vidalia.qrc">:/images/48x48/network-workgroup.png</pixmap>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="1">
+    <widget class="QLabel" name="lblStatus">
+     <property name="text">
+      <string/>
+     </property>
+     <property name="wordWrap">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="1">
+    <widget class="QProgressBar" name="progressBar">
+     <property name="value">
+      <number>0</number>
+     </property>
+     <property name="textVisible">
+      <bool>false</bool>
+     </property>
+     <property name="format">
+      <string/>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="0" colspan="2">
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources>
+  <include location="../res/vidalia.qrc"/>
+ </resources>
+ <connections/>
+</ui>


Property changes on: vidalia/trunk/src/vidalia/config/bridgedownloaderprogressdialog.ui
___________________________________________________________________
Added: svn:eol-style
   + native

Modified: vidalia/trunk/src/vidalia/config/networkpage.cpp
===================================================================
--- vidalia/trunk/src/vidalia/config/networkpage.cpp	2009-04-20 09:29:17 UTC (rev 3728)
+++ vidalia/trunk/src/vidalia/config/networkpage.cpp	2009-04-25 03:20:10 UTC (rev 3729)
@@ -19,10 +19,12 @@
 #include <QClipboard>
 #include <QHostAddress>
 #include <QRegExp>
+#include <QMessageBox>
 #include <networksettings.h>
 #include <vmessagebox.h>
 #include <vidalia.h>
 #include <stringutil.h>
+#include <bridgedownloaderprogressdialog.h>
 
 #include "networkpage.h"
 #include "domainvalidator.h"
@@ -36,7 +38,7 @@
 {
   /* Invoke the Qt Designer generated object setup routine */
   ui.setupUi(this);
- 
+
   connect(ui.btnAddBridge, SIGNAL(clicked()), this, SLOT(addBridge()));
   connect(ui.btnRemoveBridge, SIGNAL(clicked()), this, SLOT(removeBridge()));
   connect(ui.btnCopyBridge, SIGNAL(clicked()), 
@@ -57,6 +59,17 @@
                        ui.listBridges, this,
                        SLOT(copySelectedBridgesToClipboard()));
 
+  if (! BridgeDownloader::isMethodSupported(BridgeDownloader::DownloadMethodHttps)) {
+    ui.btnFindBridges->setVisible(false);
+    ui.lblHelpFindBridges->setText(
+      tr("<a href=\"bridges.finding\">How can I find bridges?</a>"));
+    _bridgeDownloader = 0;
+  } else {
+    _bridgeDownloader = new BridgeDownloader(this);
+    connect(_bridgeDownloader, SIGNAL(bridgeRequestFinished(QStringList)),
+            this, SLOT(bridgeRequestFinished(QStringList)));
+  }
+
 #if defined(Q_WS_MAC)
   /* On OS X, the network page looks better without frame titles. Everywhere
    * else needs titles or else there's a break in the frame border. */
@@ -64,9 +77,6 @@
   ui.grpFirewallSettings->setTitle("");
   ui.grpBridgeSettings->setTitle("");
 #endif
-#if !defined(USE_QSSLSOCKET) || 1
-  ui.btnFindBridges->setVisible(false);
-#endif
 }
 
 /** Called when the user changes the UI translation. */
@@ -152,10 +162,7 @@
       temp += " " + fp.toUpper();
     }
   } else {
-    QString fp = parts.join("");
-    if (fp.length() != 40 || !string_is_hex(fp))
-      return false;
-    temp = fp.toUpper();
+    return false;
   }
   *out = temp;
   return true;
@@ -345,11 +352,76 @@
 }
 
 /** Called when the user clicks the "Find Bridges Now" button.
- * Attempts to establish an HTTP connection to bridges.torproject.org
+ * Attempts to establish an HTTPS connection to bridges.torproject.org
  * and download one or more bridge addresses. */
 void
 NetworkPage::findBridges()
 {
+  BridgeDownloaderProgressDialog *dlg = new BridgeDownloaderProgressDialog(this);
 
+  connect(_bridgeDownloader, SIGNAL(statusChanged(QString)),
+          dlg, SLOT(setStatus(QString)));
+  connect(_bridgeDownloader, SIGNAL(downloadProgress(int, int)),
+          dlg, SLOT(setDownloadProgress(int, int)));
+  connect(_bridgeDownloader, SIGNAL(bridgeRequestFailed(QString)),
+          dlg, SLOT(bridgeRequestFailed(QString)));
+  connect(_bridgeDownloader, SIGNAL(bridgeRequestFinished(QStringList)),
+          dlg, SLOT(bridgeRequestFinished(QStringList)));
+  connect(dlg, SIGNAL(retry()), this, SLOT(startBridgeRequest()));
+
+  startBridgeRequest();
+  switch (dlg->exec()) {
+    case QDialogButtonBox::Cancel:
+      _bridgeDownloader->cancelBridgeRequest();
+      break;
+
+    case QDialogButtonBox::Help:
+      emit helpRequested("bridges.finding");
+      break;
+  }
+
+  delete dlg;
 }
 
+/** Starts a new request for additional bridge addresses. */
+void
+NetworkPage::startBridgeRequest()
+{
+  _bridgeDownloader->downloadBridges(BridgeDownloader::DownloadMethodHttps);
+}
+
+/** Called when a previous bridge request initiated by the findBridges()
+ * method has completed. <b>bridges</b> contains a list of all bridges
+ * received. */
+void
+NetworkPage::bridgeRequestFinished(const QStringList &bridges)
+{
+  bool foundNewBridges = false;
+  QString normalized;
+
+  foreach (QString bridge, bridges) {
+    if (! validateBridge(bridge, &normalized))
+      continue;
+
+    QString address = normalized.split(" ").at(0);
+    if (ui.listBridges->findItems(address, Qt::MatchContains).isEmpty()) {
+      ui.listBridges->addItem(normalized);
+      foundNewBridges = true;
+    }
+  }
+
+  if (! foundNewBridges) {
+    QMessageBox dlg(this);
+    dlg.setIcon(QMessageBox::Information);
+    dlg.setText(tr("No new bridges are currently available. You can either "
+                   "wait a while and try again, or try another method of "
+                   "finding new bridges."));
+    dlg.setInformativeText(tr("Click Help to see other methods of finding "
+                              "new bridges."));
+    dlg.setStandardButtons(QMessageBox::Ok | QMessageBox::Help);
+ 
+    if (dlg.exec() == QMessageBox::Help)
+      emit helpRequested("bridges.finding");      
+  }
+}
+

Modified: vidalia/trunk/src/vidalia/config/networkpage.h
===================================================================
--- vidalia/trunk/src/vidalia/config/networkpage.h	2009-04-20 09:29:17 UTC (rev 3728)
+++ vidalia/trunk/src/vidalia/config/networkpage.h	2009-04-25 03:20:10 UTC (rev 3729)
@@ -19,6 +19,7 @@
 
 #include <QPoint>
 #include <vidalia.h>
+#include <bridgedownloader.h>
 
 #include "configpage.h"
 #include "ui_networkpage.h"
@@ -65,10 +66,16 @@
   /** Called when a link in a label is clicked. <b>url</b> is the target of
    * the clicked link.*/
   void onLinkActivated(const QString &url);
-  /** Called when the user clicks the "Find Bridges Now" button.
-   * Attempts to establish an HTTP connection to bridges.torproject.org
-   * and download one or more bridge addresses. */
+  /** Called when the user clicks the "Find Bridges Now" button. Calls
+   * startBridgeRequest() to start a new request for additional bridge
+   * addresses, and displays a progress dialog for the user. */
   void findBridges();
+  /** Starts a new request for additional bridge addresses. */
+  void startBridgeRequest();
+  /** Called when a previous bridge request initiated by the findBridges()
+   * method has completed. <b>bridges</b> contains a list of all bridges
+   * received. */
+  void bridgeRequestFinished(const QStringList &bridges);
 
 private:
   /** Verifies that <b>bridge</b> is a valid bridge identifier and places a 
@@ -78,6 +85,10 @@
    * <b>bridge</b> is a valid bridge identifier, false otherwise. */
   bool validateBridge(const QString &bridge, QString *out);
 
+  /** Helper class used to facilitate downloading one or more bridge
+   * addresses. */
+  BridgeDownloader* _bridgeDownloader;
+
   /** Qt Designer generated object */
   Ui::NetworkPage ui;
 };