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