00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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
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
00051 #define MIN_BANDWIDTH_RATE 20
00052
00053
00054 #define MAX_BANDWIDTH_RATE 2097151
00055
00056
00057 #define PORTS_HTTP (QStringList() << "80")
00058
00059 #define PORTS_HTTPS (QStringList() << "443")
00060
00061 #define PORTS_MAIL (QStringList() << "110" << "143" << "993" << "995")
00062
00063
00064 #define PORTS_IM (QStringList() << "706" << "1863" << "5050" << "5190" \
00065 << "5222" << "5223" << "8300" << "8888")
00066
00067
00068 #define PORTS_IRC (QStringList() << "6660-6669" << "6697" << "7000-7001")
00069
00070
00071
00072 ServerPage::ServerPage(QWidget *parent)
00073 : ConfigPage(parent, "Server")
00074 {
00075
00076 ui.setupUi(this);
00077
00078
00079 _settings = new ServerSettings(Vidalia::torControl());
00080
00081
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
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
00124 ServerPage::~ServerPage()
00125 {
00126 delete _settings;
00127 }
00128
00129
00130 void
00131 ServerPage::retranslateUi()
00132 {
00133 ui.retranslateUi(this);
00134 }
00135
00136
00137
00138
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
00165
00166 void
00167 ServerPage::onDisconnected()
00168 {
00169 ui.rdoBridgeMode->setEnabled(true);
00170 }
00171
00172
00173 void
00174 ServerPage::copyBridgeIdentity()
00175 {
00176 QString bridge = ui.lblBridgeIdentity->text();
00177 if (!bridge.isEmpty())
00178 vApp->clipboard()->setText(bridge);
00179 }
00180
00181
00182
00183
00184
00185
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
00213
00214 void
00215 ServerPage::serverModeChanged(bool enabled)
00216 {
00217 Q_UNUSED(enabled);
00218 bool bridgeEnabled = ui.rdoBridgeMode->isChecked();
00219
00220
00221
00222 ui.tabsMenu->setVisible(ui.rdoServerMode->isChecked() || bridgeEnabled);
00223
00224
00225 ui.tabsMenu->setTabEnabled(2, !bridgeEnabled);
00226
00227
00228
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
00238
00239 bool
00240 ServerPage::changedSinceLastApply()
00241 {
00242 return _settings->changedSinceLastApply();
00243 }
00244
00245
00246
00247
00248 bool
00249 ServerPage::apply(QString &errmsg)
00250 {
00251 return _settings->apply(&errmsg);
00252 }
00253
00254
00255
00256 void
00257 ServerPage::revert()
00258 {
00259 _settings->revert();
00260 }
00261
00262
00263 bool
00264 ServerPage::save(QString &errmsg)
00265 {
00266
00267 customRateChanged();
00268
00269 if (ui.rdoServerMode->isChecked() || ui.rdoBridgeMode->isChecked()) {
00270
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
00277 if (ui.lineAvgRateLimit->text().isEmpty()) {
00278 ui.lineAvgRateLimit->setText(QString::number(2097152/1024) );
00279 }
00280 if (ui.lineMaxRateLimit->text().isEmpty()) {
00281 ui.lineMaxRateLimit->setText(QString::number(5242880/1024) );
00282 }
00283 }
00284
00285
00286
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
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
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
00339 void
00340 ServerPage::exitPolicyHelp()
00341 {
00342 emit helpRequested("server.exitpolicy");
00343 }
00344
00345
00346 void
00347 ServerPage::bandwidthHelp()
00348 {
00349 emit helpRequested("server.bandwidth");
00350 }
00351
00352
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
00362 ui.cmboRate->setCurrentIndex(CableDsl256);
00363 } else if (avgRate == CABLE512_AVG_RATE &&
00364 maxRate == CABLE512_MAX_RATE) {
00365
00366 ui.cmboRate->setCurrentIndex(CableDsl512);
00367 } else if (avgRate == CABLE768_AVG_RATE &&
00368 maxRate == CABLE768_MAX_RATE) {
00369
00370 ui.cmboRate->setCurrentIndex(CableDsl768);
00371 } else if (avgRate == T1_AVG_RATE &&
00372 maxRate == T1_MAX_RATE) {
00373
00374 ui.cmboRate->setCurrentIndex(T1CableDsl1500);
00375 } else if (avgRate == HIGHBW_AVG_RATE &&
00376 maxRate == HIGHBW_MAX_RATE) {
00377
00378 ui.cmboRate->setCurrentIndex(GreaterThan1500);
00379 } else {
00380
00381 ui.cmboRate->setCurrentIndex(CustomBwLimits);
00382 }
00383
00384 ui.lineAvgRateLimit->setText(QString::number(avgRate/1024));
00385 ui.lineMaxRateLimit->setText(QString::number(maxRate/1024));
00386 }
00387
00388
00389 void
00390 ServerPage::saveBandwidthLimits()
00391 {
00392 quint32 avgRate, maxRate;
00393
00394 switch (ui.cmboRate->currentIndex()) {
00395 case CableDsl256:
00396 avgRate = CABLE256_AVG_RATE;
00397 maxRate = CABLE256_MAX_RATE;
00398 break;
00399 case CableDsl512:
00400 avgRate = CABLE512_AVG_RATE;
00401 maxRate = CABLE512_MAX_RATE;
00402 break;
00403 case CableDsl768:
00404 avgRate = CABLE768_AVG_RATE;
00405 maxRate = CABLE768_MAX_RATE;
00406 break;
00407 case T1CableDsl1500:
00408 avgRate = T1_AVG_RATE;
00409 maxRate = T1_MAX_RATE;
00410 break;
00411 case GreaterThan1500:
00412 avgRate = HIGHBW_AVG_RATE;
00413 maxRate = HIGHBW_MAX_RATE;
00414 break;
00415 default:
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
00432
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
00441
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
00459
00460
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
00493 void
00494 ServerPage::rateChanged(int index)
00495 {
00496
00497
00498 ui.frmCustomRate->setVisible(index == CustomBwLimits);
00499 }
00500
00501
00502
00503
00504 void
00505 ServerPage::customRateChanged()
00506 {
00507
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
00516
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
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
00541 void
00542 ServerPage::upnpHelp()
00543 {
00544 emit helpRequested("server.upnp");
00545 }
00546
00547
00548 void
00549 ServerPage::linkActivated(const QString &url)
00550 {
00551 if (!url.compare("#bridgeUsage"))
00552 displayBridgeUsage();
00553 }
00554
00555
00556
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