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