ServerPage.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 ServerPage.cpp
00013 ** \version $Id: ServerPage.cpp 4143 2009-10-12 00:59:22Z edmanm $
00014 ** \brief Tor server configuration options
00015 */
00016 
00017 #include "config.h"
00018 #include "ServerPage.h"
00019 #include "Vidalia.h"
00020 #include "VMessageBox.h"
00021 #include "ConfigDialog.h"
00022 #include "IpValidator.h"
00023 #include "PortValidator.h"
00024 #include "DomainValidator.h"
00025 #include "NicknameValidator.h"
00026 #include "BridgeUsageDialog.h"
00027 
00028 #include "html.h"
00029 #include "stringutil.h"
00030 
00031 #if defined(USE_MINIUPNPC)
00032 #include "UPNPTestDialog.h"
00033 #endif
00034 
00035 
00036 #include <QClipboard>
00037 #include <QMessageBox>
00038 
00039 /* These are completely made up values (in bytes/sec). */
00040 #define CABLE256_AVG_RATE       (32*1024)
00041 #define CABLE256_MAX_RATE       (64*1024)
00042 #define CABLE512_AVG_RATE       (64*1024)
00043 #define CABLE512_MAX_RATE       (128*1024)
00044 #define CABLE768_AVG_RATE       (96*1024)
00045 #define CABLE768_MAX_RATE       (192*1024)
00046 #define T1_AVG_RATE             (192*1024)
00047 #define T1_MAX_RATE             (384*1024)
00048 #define HIGHBW_AVG_RATE         (5120*1024)
00049 #define HIGHBW_MAX_RATE         (10240*1024)
00050 /** Minimum allowed bandwidth rate (20KB) */
00051 #define MIN_BANDWIDTH_RATE      20
00052 /** Maximum bandwidth rate. This is limited to 2147483646 bytes, 
00053  * or 2097151 kilobytes. (2147483646/1024) */ 
00054 #define MAX_BANDWIDTH_RATE      2097151
00055 
00056 /** Ports represented by the "Websites" checkbox. (80) */
00057 #define PORTS_HTTP   (QStringList() << "80")
00058 /** Ports represented by the "Secure Websites" checkbox. (443) */
00059 #define PORTS_HTTPS  (QStringList() << "443")
00060 /** Ports represented by the "Retrieve Mail" checkbox. (110,143,993,995) */
00061 #define PORTS_MAIL   (QStringList() << "110" << "143" << "993" << "995")
00062 /** Ports represented by the "Instant Messaging" checkbox.
00063  * (703,1863,5050,5190,5222,8300,8888) */
00064 #define PORTS_IM     (QStringList() << "706" << "1863" << "5050" << "5190" \
00065                                     << "5222" << "5223" << "8300" << "8888")
00066 /** Ports represented by the "Internet Relay Chat" checkbox. 
00067  * (6660-6669,6697,7000-7001) */
00068 #define PORTS_IRC    (QStringList() << "6660-6669" << "6697" << "7000-7001")
00069 
00070 
00071 /** Constructor */
00072 ServerPage::ServerPage(QWidget *parent)
00073 : ConfigPage(parent, "Server")
00074 {
00075   /* Invoke the Qt Designer generated object setup routine */
00076   ui.setupUi(this);
00077   
00078   /* Create ServerSettings object */
00079   _settings = new ServerSettings(Vidalia::torControl());
00080 
00081   /* Bind events to actions */
00082   connect(ui.btnRateHelp, SIGNAL(clicked()), this, SLOT(bandwidthHelp()));
00083   connect(ui.btnExitHelp, SIGNAL(clicked()), this, SLOT(exitPolicyHelp()));
00084   connect(ui.btnUpnpHelp, SIGNAL(clicked()), this, SLOT(upnpHelp()));
00085   connect(ui.cmboRate, SIGNAL(currentIndexChanged(int)),
00086                  this, SLOT(rateChanged(int)));
00087   connect(ui.lineAvgRateLimit, SIGNAL(editingFinished()), 
00088                          this, SLOT(customRateChanged()));
00089   connect(ui.lineMaxRateLimit, SIGNAL(editingFinished()), 
00090                          this, SLOT(customRateChanged()));
00091   connect(ui.rdoClientMode, SIGNAL(toggled(bool)),
00092                       this, SLOT(serverModeChanged(bool)));
00093   connect(ui.rdoServerMode, SIGNAL(toggled(bool)),
00094                       this, SLOT(serverModeChanged(bool)));
00095   connect(ui.rdoBridgeMode, SIGNAL(toggled(bool)),
00096                       this, SLOT(serverModeChanged(bool)));
00097   connect(Vidalia::torControl(), SIGNAL(authenticated()),
00098                            this, SLOT(onAuthenticated()));
00099   connect(Vidalia::torControl(), SIGNAL(disconnected()),
00100                            this, SLOT(onDisconnected()));
00101   connect(ui.btnCopyBridgeIdentity, SIGNAL(clicked()),
00102                               this, SLOT(copyBridgeIdentity()));
00103   connect(ui.lblBridgeUsage, SIGNAL(linkActivated(QString)),
00104                        this, SLOT(linkActivated(QString)));
00105 
00106   /* Set validators for address, mask and various port number fields */
00107   ui.lineServerNickname->setValidator(new NicknameValidator(this));
00108   ui.lineServerPort->setValidator(new QIntValidator(1, 65535, this));
00109   ui.lineDirPort->setValidator(new QIntValidator(1, 65535, this));
00110   ui.lineAvgRateLimit->setValidator(
00111     new QIntValidator(MIN_BANDWIDTH_RATE, MAX_BANDWIDTH_RATE, this));
00112   ui.lineMaxRateLimit->setValidator(
00113     new QIntValidator(MIN_BANDWIDTH_RATE, MAX_BANDWIDTH_RATE, this));
00114 
00115 #if defined(USE_MINIUPNPC)
00116   connect(ui.btnTestUpnp, SIGNAL(clicked()), this, SLOT(testUpnp()));
00117 #else
00118   ui.chkEnableUpnp->setVisible(false);
00119   ui.btnTestUpnp->setVisible(false);
00120 #endif
00121 }
00122 
00123 /** Destructor */
00124 ServerPage::~ServerPage()
00125 {
00126   delete _settings;
00127 }
00128 
00129 /** Called when the user changes the UI translation. */
00130 void
00131 ServerPage::retranslateUi()
00132 {
00133   ui.retranslateUi(this);
00134 }
00135 
00136 /** Called when Vidalia has authenticated to Tor. If the user's Tor is not
00137  * recent enough, this disables the bridge server option and displays a
00138  * warning if the user had previously configured Tor as a bridge. */
00139 void
00140 ServerPage::onAuthenticated()
00141 {
00142   quint32 torVersion = Vidalia::torControl()->getTorVersion();
00143   if (torVersion < 0x020008) {
00144     ui.rdoBridgeMode->setEnabled(false);
00145     if (ui.rdoBridgeMode->isChecked()) {
00146       int ret = VMessageBox::warning(this,
00147                   tr("Bridge Support Unavailable"),
00148                   p(tr("You have configured Tor to act as a bridge relay "
00149                        "for censored users, but your version of Tor does not "
00150                        "support bridges.")) +
00151                   p(tr("Please upgrade your Tor software or configure Tor to "
00152                        "act as a normal Tor relay.")),
00153                   VMessageBox::ShowSettings|VMessageBox::Default,
00154                   VMessageBox::Cancel);
00155       if (ret == VMessageBox::ShowSettings) {
00156         ConfigDialog *dialog = dynamic_cast<ConfigDialog *>(window());
00157         if (dialog)
00158           dialog->showWindow(ConfigDialog::Server);
00159       }
00160     }
00161   }
00162 }
00163 
00164 /** Called when Vidalia disconnects from Tor. This method reenables the bridge
00165  * server option. */
00166 void
00167 ServerPage::onDisconnected()
00168 {
00169   ui.rdoBridgeMode->setEnabled(true);
00170 }
00171 
00172 /** Copies the user's bridge relay identity to the clipboard. */
00173 void
00174 ServerPage::copyBridgeIdentity()
00175 {
00176   QString bridge = ui.lblBridgeIdentity->text();
00177   if (!bridge.isEmpty())
00178     vApp->clipboard()->setText(bridge);
00179 }
00180 
00181 /** Loads the user's bridge relay identity into the appropriate widgets. If
00182  * the user's bridge is not running, then "Not Running" will be displayed.
00183  * Otherwise, either the bridge's "address:port", "fingerprint", or
00184  * "address:port fingerprint" will be displayed, depending on whether our
00185  * GETCONF and GETINFO commands are successful. */
00186 void
00187 ServerPage::loadBridgeIdentity()
00188 {
00189   TorControl *tc = Vidalia::torControl();
00190   QString bridge, address, orPort, fingerprint;
00191 
00192   if (tc->isConnected()) {
00193     tc->getInfo("address", address);
00194     tc->getInfo("fingerprint", fingerprint);
00195     tc->getConf("ORPort", orPort);
00196   
00197     if (!address.isEmpty() && !orPort.isEmpty() && orPort != "0")
00198       bridge = address + ":" + orPort + " ";
00199     if (!fingerprint.isEmpty())
00200       bridge += fingerprint;
00201     bridge = bridge.trimmed();
00202   }
00203 
00204   ui.lblBridgeIdentity->setText(bridge.isEmpty()
00205                                   ? tr("Your bridge relay is not running.")
00206                                   : bridge);
00207   ui.lblYourBridgeRelayIs->setEnabled(!bridge.isEmpty());
00208   ui.lblBridgeIdentity->setEnabled(!bridge.isEmpty());
00209   ui.btnCopyBridgeIdentity->setEnabled(!bridge.isEmpty());
00210 }
00211 
00212 /** Called when the user toggles any one of the server mode radio buttons
00213  * and hides or displays the server configuration tabs appropriately. */
00214 void
00215 ServerPage::serverModeChanged(bool enabled)
00216 {
00217   Q_UNUSED(enabled);
00218   bool bridgeEnabled = ui.rdoBridgeMode->isChecked();
00219   
00220   /* Show the tab menu only if the user is running a normal relay or a bridge
00221    * relay. */
00222   ui.tabsMenu->setVisible(ui.rdoServerMode->isChecked() || bridgeEnabled);
00223   
00224   /* Disable the Exit Policies tab when bridge relay mode is selected */
00225   ui.tabsMenu->setTabEnabled(2, !bridgeEnabled);
00226   
00227   /* Display the widgets that show the user their bridge identity if bridge
00228    * relay mode is selected. */
00229   ui.lblYourBridgeRelayIs->setVisible(bridgeEnabled);
00230   ui.lblBridgeIdentity->setVisible(bridgeEnabled);
00231   ui.btnCopyBridgeIdentity->setVisible(bridgeEnabled);
00232   ui.chkPublishBridgeAddress->setVisible(bridgeEnabled);
00233   ui.lblBridgeUsage->setVisible(bridgeEnabled
00234                                   && Vidalia::torControl()->isConnected());
00235 }
00236 
00237 /** Returns true if the user has changed their server settings since the
00238  * last time they were applied to Tor. */
00239 bool
00240 ServerPage::changedSinceLastApply()
00241 {
00242   return _settings->changedSinceLastApply();
00243 }
00244 
00245 /** Applies the server configuration settings to Tor. Returns true if the
00246  * settings were applied successfully. Otherwise, <b>errmsg</b> is
00247  * set and false is returned. */
00248 bool
00249 ServerPage::apply(QString &errmsg)
00250 {
00251   return _settings->apply(&errmsg);
00252 }
00253 
00254 /** Returns true if the user has changed their server settings since the
00255  * last time they were applied to Tor. */
00256 void
00257 ServerPage::revert()
00258 {
00259   _settings->revert();
00260 }
00261 
00262 /** Saves changes made to settings on the Server settings page. */
00263 bool
00264 ServerPage::save(QString &errmsg)
00265 {
00266   /* Force the bandwidth rate limits to validate */
00267   customRateChanged();
00268   
00269   if (ui.rdoServerMode->isChecked() || ui.rdoBridgeMode->isChecked()) {
00270     /* A server must have an ORPort and a nickname */
00271     if (ui.lineServerPort->text().isEmpty() ||
00272         ui.lineServerNickname->text().isEmpty()) {
00273       errmsg = tr("You must specify at least a relay nickname and port.");
00274       return false;
00275     }
00276     /* If the bandwidth rates aren't set, use some defaults before saving */
00277     if (ui.lineAvgRateLimit->text().isEmpty()) {
00278       ui.lineAvgRateLimit->setText(QString::number(2097152/1024) /* 2MB */);
00279     }
00280     if (ui.lineMaxRateLimit->text().isEmpty()) {
00281       ui.lineMaxRateLimit->setText(QString::number(5242880/1024) /* 5MB */);
00282     }
00283   }
00284   
00285   /* "Server" is enabled whether we're a bridge or normal relay. "Bridge" is
00286    * only enabled if we're a bridge (obviously). */
00287   _settings->setServerEnabled(ui.rdoServerMode->isChecked()
00288                                 || ui.rdoBridgeMode->isChecked());
00289   _settings->setBridgeEnabled(ui.rdoBridgeMode->isChecked());
00290   if (ui.rdoBridgeMode->isChecked())
00291     _settings->setPublishServerDescriptor(ui.chkPublishBridgeAddress->isChecked());
00292 
00293   /* Save the rest of the server settings. */
00294   _settings->setDirectoryMirror(ui.chkMirrorDirectory->isChecked());
00295   _settings->setNickname(ui.lineServerNickname->text());
00296   _settings->setORPort(ui.lineServerPort->text().toUInt());
00297   _settings->setDirPort(ui.lineDirPort->text().toUInt());
00298   _settings->setContactInfo(ui.lineServerContact->text());
00299   saveBandwidthLimits();
00300   saveExitPolicies();
00301 
00302 #if defined(USE_MINIUPNPC)
00303   _settings->setUpnpEnabled(ui.chkEnableUpnp->isChecked());
00304 #endif
00305 
00306   return true;
00307 }
00308 
00309 /** Loads previously saved settings */
00310 void
00311 ServerPage::load()
00312 {
00313   if (_settings->isBridgeEnabled())
00314     ui.rdoBridgeMode->setChecked(true);
00315   else if (_settings->isServerEnabled())
00316     ui.rdoServerMode->setChecked(true);
00317   else
00318     ui.rdoClientMode->setChecked(true);
00319 
00320   ui.lineServerNickname->setText(_settings->getNickname());
00321   ui.lineServerPort->setText(QString::number(_settings->getORPort()));
00322   ui.lineDirPort->setText(QString::number(_settings->getDirPort()));
00323   ui.lineServerContact->setText(_settings->getContactInfo());
00324   ui.chkMirrorDirectory->setChecked(_settings->isDirectoryMirror());
00325   ui.lblBridgeUsage->setVisible(_settings->isBridgeEnabled()
00326                                   && Vidalia::torControl()->isConnected());
00327   ui.chkPublishBridgeAddress->setChecked(_settings->publishServerDescriptor());
00328 
00329   loadBandwidthLimits();
00330   loadExitPolicies();
00331   loadBridgeIdentity();
00332 
00333 #if defined(USE_MINIUPNPC)
00334   ui.chkEnableUpnp->setChecked(_settings->isUpnpEnabled());
00335 #endif
00336 }
00337 
00338 /** Shows exit policy related help information */
00339 void
00340 ServerPage::exitPolicyHelp()
00341 {
00342   emit helpRequested("server.exitpolicy");
00343 }
00344 
00345 /** Shows the bandwidth rate limiting help information */
00346 void
00347 ServerPage::bandwidthHelp()
00348 {
00349   emit helpRequested("server.bandwidth");
00350 }
00351 
00352 /** Loads the server's bandwidth average and burst limits. */
00353 void
00354 ServerPage::loadBandwidthLimits()
00355 {
00356   quint32 avgRate = _settings->getBandwidthAvgRate();
00357   quint32 maxRate = _settings->getBandwidthBurstRate();
00358 
00359   if (avgRate == CABLE256_AVG_RATE && 
00360       maxRate == CABLE256_MAX_RATE) {
00361     /* Cable/DSL 256 Kbps */
00362     ui.cmboRate->setCurrentIndex(CableDsl256); 
00363   } else if (avgRate == CABLE512_AVG_RATE && 
00364              maxRate == CABLE512_MAX_RATE) {
00365     /* Cable/DSL 512 Kbps */
00366     ui.cmboRate->setCurrentIndex(CableDsl512);
00367   } else if (avgRate == CABLE768_AVG_RATE && 
00368              maxRate == CABLE768_MAX_RATE) {
00369     /* Cable/DSL 768 Kbps */
00370     ui.cmboRate->setCurrentIndex(CableDsl768);
00371   } else if (avgRate == T1_AVG_RATE && 
00372              maxRate == T1_MAX_RATE) {
00373     /* T1/Cable/DSL 1.5 Mbps */
00374     ui.cmboRate->setCurrentIndex(T1CableDsl1500);
00375   } else if (avgRate == HIGHBW_AVG_RATE && 
00376              maxRate == HIGHBW_MAX_RATE) {
00377     /* > 1.5 Mbps */
00378     ui.cmboRate->setCurrentIndex(GreaterThan1500);
00379   } else {
00380     /* Custom bandwidth limits */
00381     ui.cmboRate->setCurrentIndex(CustomBwLimits);
00382   }
00383   /* Fill in the custom bandwidth limit boxes */
00384   ui.lineAvgRateLimit->setText(QString::number(avgRate/1024));
00385   ui.lineMaxRateLimit->setText(QString::number(maxRate/1024));
00386 }
00387 
00388 /** Saves the server's bandwidth average and burst limits. */
00389 void
00390 ServerPage::saveBandwidthLimits()
00391 {
00392   quint32 avgRate, maxRate;
00393 
00394   switch (ui.cmboRate->currentIndex()) {
00395     case CableDsl256: /* Cable/DSL 256 Kbps */
00396       avgRate = CABLE256_AVG_RATE;
00397       maxRate = CABLE256_MAX_RATE;
00398       break;
00399     case CableDsl512: /* Cable/DSL 512 Kbps */
00400       avgRate = CABLE512_AVG_RATE;
00401       maxRate = CABLE512_MAX_RATE;
00402       break;
00403     case CableDsl768: /* Cable/DSL 768 Kbps */
00404       avgRate = CABLE768_AVG_RATE;
00405       maxRate = CABLE768_MAX_RATE;
00406       break;
00407     case T1CableDsl1500: /* T1/Cable/DSL 1.5 Mbps */
00408       avgRate = T1_AVG_RATE;
00409       maxRate = T1_MAX_RATE;
00410       break;
00411     case GreaterThan1500: /* > 1.5 Mbps */
00412       avgRate = HIGHBW_AVG_RATE;
00413       maxRate = HIGHBW_MAX_RATE;
00414       break;
00415     default: /* Custom bandwidth limits */
00416       avgRate = (quint32)(ui.lineAvgRateLimit->text().toUInt()*1024);
00417       maxRate = (quint32)(ui.lineMaxRateLimit->text().toUInt()*1024);
00418       break;
00419   }
00420   _settings->setBandwidthAvgRate(avgRate);
00421   _settings->setBandwidthBurstRate(maxRate);
00422 }
00423 
00424 /** */
00425 void
00426 ServerPage::loadExitPolicies()
00427 {
00428   ExitPolicy exitPolicy = _settings->getExitPolicy();
00429   
00430   if (exitPolicy.contains(Policy(Policy::RejectAll))) {
00431     /* If the policy ends with reject *:*, check if the policy explicitly
00432      * accepts these ports */
00433     ui.chkWebsites->setChecked(exitPolicy.acceptsPorts(PORTS_HTTP));
00434     ui.chkSecWebsites->setChecked(exitPolicy.acceptsPorts(PORTS_HTTPS));
00435     ui.chkMail->setChecked(exitPolicy.acceptsPorts(PORTS_MAIL));
00436     ui.chkIRC->setChecked(exitPolicy.acceptsPorts(PORTS_IRC));
00437     ui.chkIM->setChecked(exitPolicy.acceptsPorts(PORTS_IM));
00438     ui.chkMisc->setChecked(false);
00439   } else {
00440     /* If the exit policy ends with accept *:*, check if the policy explicitly
00441      * rejects these ports */
00442     ui.chkWebsites->setChecked(!exitPolicy.rejectsPorts(PORTS_HTTP));
00443     ui.chkSecWebsites->setChecked(!exitPolicy.rejectsPorts(PORTS_HTTPS));
00444     ui.chkMail->setChecked(!exitPolicy.rejectsPorts(PORTS_MAIL));
00445     ui.chkIRC->setChecked(!exitPolicy.rejectsPorts(PORTS_IRC));
00446     ui.chkIM->setChecked(!exitPolicy.rejectsPorts(PORTS_IM));
00447     ui.chkMisc->setChecked(true);
00448   }
00449 }
00450 
00451 /** */
00452 void
00453 ServerPage::saveExitPolicies()
00454 {
00455   ExitPolicy exitPolicy;
00456   bool rejectUnchecked = ui.chkMisc->isChecked();
00457   
00458   /* If misc is checked, then reject unchecked items and leave the default exit
00459    * policy alone. Else, accept only checked items and end with reject *:*,
00460    * replacing the default exit policy. */
00461   if (ui.chkWebsites->isChecked() && !rejectUnchecked) {
00462     exitPolicy.addAcceptedPorts(PORTS_HTTP);
00463   } else if (!ui.chkWebsites->isChecked() && rejectUnchecked) {
00464     exitPolicy.addRejectedPorts(PORTS_HTTP);
00465   }
00466   if (ui.chkSecWebsites->isChecked() && !rejectUnchecked) {
00467     exitPolicy.addAcceptedPorts(PORTS_HTTPS);
00468   } else if (!ui.chkSecWebsites->isChecked() && rejectUnchecked) {
00469     exitPolicy.addRejectedPorts(PORTS_HTTPS);
00470   }
00471   if (ui.chkMail->isChecked() && !rejectUnchecked) {
00472     exitPolicy.addAcceptedPorts(PORTS_MAIL);
00473   } else if (!ui.chkMail->isChecked() && rejectUnchecked) {
00474     exitPolicy.addRejectedPorts(PORTS_MAIL);
00475   }
00476   if (ui.chkIRC->isChecked() && !rejectUnchecked) {
00477     exitPolicy.addAcceptedPorts(PORTS_IRC);
00478   } else if (!ui.chkIRC->isChecked() && rejectUnchecked) {
00479     exitPolicy.addRejectedPorts(PORTS_IRC);
00480   }
00481   if (ui.chkIM->isChecked() && !rejectUnchecked) {
00482     exitPolicy.addAcceptedPorts(PORTS_IM);
00483   } else if (!ui.chkIM->isChecked() && rejectUnchecked) {
00484     exitPolicy.addRejectedPorts(PORTS_IM);
00485   }
00486   if (!ui.chkMisc->isChecked()) {
00487     exitPolicy.addPolicy(Policy(Policy::RejectAll));
00488   }
00489   _settings->setExitPolicy(exitPolicy);
00490 }
00491 
00492 /** Called when the user selects a new value from the rate combo box. */
00493 void
00494 ServerPage::rateChanged(int index)
00495 {
00496   /* If the "Custom" option is selected, show the custom bandwidth 
00497    * limits form. */
00498   ui.frmCustomRate->setVisible(index == CustomBwLimits);
00499 }
00500 
00501 /** Called when the user edits the long-term average or maximum bandwidth limit. 
00502  * This ensures that the average bandwidth rate is greater than MIN_RATE
00503  * (20KB/s) and that the max rate is greater than the average rate. */
00504 void
00505 ServerPage::customRateChanged()
00506 {
00507   /* Make sure the average rate isn't too low or too high */
00508   quint32 avgRate = (quint32)ui.lineAvgRateLimit->text().toUInt();
00509   if (avgRate < MIN_BANDWIDTH_RATE) {
00510     ui.lineAvgRateLimit->setText(QString::number(MIN_BANDWIDTH_RATE));    
00511   }
00512   if (avgRate > MAX_BANDWIDTH_RATE) {
00513     ui.lineAvgRateLimit->setText(QString::number(MAX_BANDWIDTH_RATE));
00514   }
00515   /* Ensure the max burst rate is greater than the average rate but less than
00516    * the maximum allowed rate. */
00517   quint32 burstRate = (quint32)ui.lineMaxRateLimit->text().toUInt();
00518   if (avgRate > burstRate) {
00519     ui.lineMaxRateLimit->setText(QString::number(avgRate));
00520   }
00521   if (burstRate > MAX_BANDWIDTH_RATE) {
00522     ui.lineMaxRateLimit->setText(QString::number(MAX_BANDWIDTH_RATE));
00523   }
00524 }
00525 
00526 /** Tests automatic port forwarding using UPnP. */
00527 void
00528 ServerPage::testUpnp()
00529 {
00530 #if defined(USE_MINIUPNPC)
00531   UPNPTestDialog dlg(ui.lineServerPort->text().toUInt(),
00532                      ui.lineDirPort->text().toUInt(), this);
00533   
00534   connect(&dlg, SIGNAL(help()), this, SLOT(upnpHelp()));
00535 
00536   dlg.exec();
00537 #endif
00538 }
00539 
00540 /** Called when the user clicks the UPnP test dialog's help button. */
00541 void
00542 ServerPage::upnpHelp()
00543 {
00544   emit helpRequested("server.upnp");
00545 }
00546 
00547 /** Called when the user clicks on a QLabel containing a hyperlink. */
00548 void
00549 ServerPage::linkActivated(const QString &url)
00550 {
00551   if (!url.compare("#bridgeUsage"))
00552     displayBridgeUsage();
00553 }
00554 
00555 /** Retrieves bridge usage history from Tor, parses and validates it, and
00556  * then displays it in a new dialog. */
00557 void
00558 ServerPage::displayBridgeUsage()
00559 {
00560   QString info;
00561 
00562   info = Vidalia::torControl()->getInfo("status/clients-seen").toString();
00563   if (info.isEmpty()) {
00564     QMessageBox dlg(QMessageBox::Information, tr("No Recent Usage"),
00565                     tr("No clients have used your relay recently."), 
00566                     QMessageBox::Ok, this);
00567     dlg.setInformativeText(tr("Leave your relay running so clients have "
00568                               "a better chance of finding and using it."));
00569     dlg.exec();
00570   } else {
00571     QDateTime timeStarted;
00572     QHash<QString,int> countrySummary;
00573     QHash<QString,QString> keyvals;
00574     BridgeUsageDialog dlg(this);
00575     bool ok;
00576 
00577     keyvals = string_parse_keyvals(info, &ok);
00578     if (!ok || !keyvals.contains("TimeStarted") 
00579             || !keyvals.contains("CountrySummary"))
00580       goto err;
00581 
00582     timeStarted = QDateTime::fromString(keyvals.value("TimeStarted"), 
00583                                         "yyyy-MM-dd HH:mm:ss");
00584     if (!timeStarted.isValid())
00585       goto err;
00586 
00587     foreach (QString pair, keyvals.value("CountrySummary").split(",")) {
00588       QStringList parts = pair.split("=");
00589       if (parts.size() != 2)
00590         goto err;
00591 
00592       countrySummary.insert(parts.at(0).toUpper(), parts.at(1).toInt(&ok));
00593       if (!ok)
00594         goto err;
00595     }
00596 
00597     dlg.update(timeStarted, countrySummary);
00598     dlg.exec();
00599   }
00600   return;
00601 
00602 err:
00603   QMessageBox dlg(QMessageBox::Warning, tr("Bridge History"),
00604                   tr("Vidalia was unable to retrieve your bridge's usage "
00605                      "history."), QMessageBox::Ok, this);
00606   dlg.setInformativeText(tr("Tor returned an improperly formatted "
00607                             "response when Vidalia requested your "
00608                             "bridge's usage history."));
00609   dlg.setDetailedText(tr("The returned response was: %1").arg(info));
00610   dlg.exec();
00611 }
00612 

Generated on 31 Mar 2010 for Vidalia by  doxygen 1.6.1