00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <QtGui>
00022 #include <QTimer>
00023 #include <vidalia.h>
00024 #include <file.h>
00025 #include <html.h>
00026 #include <stringutil.h>
00027 #include <net.h>
00028 #include <clientstatusevent.h>
00029 #include <dangerousversionevent.h>
00030 #include <vmessagebox.h>
00031 #include <procutil.h>
00032
00033 #include "procutil.h"
00034
00035 #include "mainwindow.h"
00036 #include "controlpasswordinputdialog.h"
00037
00038 #define IMG_BWGRAPH ":/images/16x16/utilities-system-monitor.png"
00039 #define IMG_CONTROL_PANEL ":/images/16x16/system-run.png"
00040 #define IMG_MESSAGELOG ":/images/16x16/format-justify-fill.png"
00041 #define IMG_CONFIG ":/images/16x16/preferences-system.png"
00042 #define IMG_IDENTITY ":/images/16x16/view-media-artist.png"
00043 #define IMG_HELP ":/images/16x16/system-help.png"
00044 #define IMG_ABOUT ":/images/16x16/help-about.png"
00045 #define IMG_EXIT ":/images/16x16/application-exit.png"
00046 #define IMG_NETWORK ":/images/16x16/applications-internet.png"
00047
00048 #define IMG_START_TOR_16 ":/images/16x16/media-playback-start.png"
00049 #define IMG_STOP_TOR_16 ":/images/16x16/media-playback-stop.png"
00050 #define IMG_START_TOR_48 ":/images/48x48/media-playback-start.png"
00051 #define IMG_STOP_TOR_48 ":/images/48x48/media-playback-stop.png"
00052 #define IMG_TOR_STOPPED_48 ":/images/48x48/tor-off.png"
00053 #define IMG_TOR_RUNNING_48 ":/images/48x48/tor-on.png"
00054 #define IMG_TOR_STARTING_48 ":/images/48x48/tor-starting.png"
00055 #define IMG_TOR_STOPPING_48 ":/images/48x48/tor-stopping.png"
00056
00057
00058 #if defined(Q_WS_WIN)
00059
00060 #define IMG_TOR_STOPPED ":/images/16x16/tor-off.png"
00061 #define IMG_TOR_RUNNING ":/images/16x16/tor-on.png"
00062 #define IMG_TOR_STARTING ":/images/16x16/tor-starting.png"
00063 #define IMG_TOR_STOPPING ":/images/16x16/tor-stopping.png"
00064 #elif defined(Q_WS_MAC)
00065
00066
00067 #define IMG_TOR_STOPPED "tor-off"
00068 #define IMG_TOR_RUNNING "tor-on"
00069 #define IMG_TOR_STARTING "tor-starting"
00070 #define IMG_TOR_STOPPING "tor-stopping"
00071 #else
00072
00073 #define IMG_TOR_STOPPED ":/images/22x22/tor-off.png"
00074 #define IMG_TOR_RUNNING ":/images/22x22/tor-on.png"
00075 #define IMG_TOR_STARTING ":/images/22x22/tor-starting.png"
00076 #define IMG_TOR_STOPPING ":/images/22x22/tor-stopping.png"
00077 #endif
00078
00079
00080 #define MIN_NEWIDENTITY_INTERVAL (10*1000)
00081
00082
00083 #define STARTUP_PROGRESS_STARTING 0
00084 #define STARTUP_PROGRESS_CONNECTING 10
00085 #define STARTUP_PROGRESS_AUTHENTICATING 20
00086 #define STARTUP_PROGRESS_BOOTSTRAPPING 30
00087 #define STARTUP_PROGRESS_CIRCUITBUILD 75
00088 #define STARTUP_PROGRESS_MAXIMUM (STARTUP_PROGRESS_BOOTSTRAPPING+100)
00089
00090
00091
00092
00093 MainWindow::MainWindow()
00094 : VidaliaWindow("MainWindow")
00095 {
00096 VidaliaSettings settings;
00097
00098 ui.setupUi(this);
00099
00100
00101 Vidalia::createShortcut("Ctrl+W", this, ui.btnHide, SLOT(click()));
00102 Vidalia::createShortcut("Esc", this, ui.btnHide, SLOT(click()));
00103
00104
00105 _messageLog = new MessageLog();
00106 _bandwidthGraph = new BandwidthGraph();
00107 _netViewer = new NetViewer();
00108 _configDialog = new ConfigDialog();
00109 connect(_messageLog, SIGNAL(helpRequested(QString)),
00110 this, SLOT(showHelpDialog(QString)));
00111 connect(_netViewer, SIGNAL(helpRequested(QString)),
00112 this, SLOT(showHelpDialog(QString)));
00113 connect(_configDialog, SIGNAL(helpRequested(QString)),
00114 this, SLOT(showHelpDialog(QString)));
00115
00116
00117 createActions();
00118
00119
00120 createTrayIcon();
00121
00122 _status = Unset;
00123 updateTorStatus(Stopped);
00124
00125
00126 _torControl = Vidalia::torControl();
00127 connect(_torControl, SIGNAL(started()), this, SLOT(started()));
00128 connect(_torControl, SIGNAL(startFailed(QString)),
00129 this, SLOT(startFailed(QString)));
00130 connect(_torControl, SIGNAL(stopped(int, QProcess::ExitStatus)),
00131 this, SLOT(stopped(int, QProcess::ExitStatus)));
00132 connect(_torControl, SIGNAL(connected()), this, SLOT(connected()));
00133 connect(_torControl, SIGNAL(disconnected()), this, SLOT(disconnected()));
00134 connect(_torControl, SIGNAL(connectFailed(QString)),
00135 this, SLOT(connectFailed(QString)));
00136 connect(_torControl, SIGNAL(authenticated()), this, SLOT(authenticated()));
00137 connect(_torControl, SIGNAL(authenticationFailed(QString)),
00138 this, SLOT(authenticationFailed(QString)));
00139 _torControl->setEvent(TorEvents::ClientStatus, this, true);
00140 _torControl->setEvent(TorEvents::GeneralStatus, this, true);
00141
00142
00143 _browserProcess = new HelperProcess(this);
00144 connect(_browserProcess, SIGNAL(finished(int, QProcess::ExitStatus)),
00145 this, SLOT(onSubprocessFinished(int, QProcess::ExitStatus)));
00146 connect(_browserProcess, SIGNAL(startFailed(QString)),
00147 this, SLOT(onBrowserFailed(QString)));
00148
00149
00150 _imProcess = new HelperProcess(this);
00151 connect(_imProcess, SIGNAL(finished(int, QProcess::ExitStatus)),
00152 this, SLOT(onSubprocessFinished(int, QProcess::ExitStatus)));
00153 connect(_imProcess, SIGNAL(startFailed(QString)),
00154 this, SLOT(onIMFailed(QString)));
00155
00156
00157 _proxyProcess = new HelperProcess(this);
00158 connect(_proxyProcess, SIGNAL(startFailed(QString)),
00159 this, SLOT(onProxyFailed(QString)));
00160
00161
00162 connect(vApp, SIGNAL(running()), this, SLOT(running()));
00163 connect(vApp, SIGNAL(shutdown()), this, SLOT(shutdown()));
00164
00165 #if defined(USE_MINIUPNPC)
00166
00167 connect(UPNPControl::instance(), SIGNAL(error(UPNPControl::UPNPError)),
00168 this, SLOT(upnpError(UPNPControl::UPNPError)));
00169 #endif
00170
00171 ui.chkShowOnStartup->setChecked(settings.showMainWindowAtStart());
00172 if (ui.chkShowOnStartup->isChecked())
00173 show();
00174
00175 _trayIcon.show();
00176 }
00177
00178
00179 MainWindow::~MainWindow()
00180 {
00181 _trayIcon.hide();
00182 delete _messageLog;
00183 delete _bandwidthGraph;
00184 delete _netViewer;
00185 delete _configDialog;
00186 }
00187
00188 void
00189 MainWindow::setVisible(bool visible)
00190 {
00191 if (visible) {
00192
00193 if (!TrayIcon::isTrayIconSupported()) {
00194
00195 ui.chkShowOnStartup->hide();
00196 ui.btnHide->hide();
00197
00198
00199
00200 }
00201 }
00202 VidaliaWindow::setVisible(visible);
00203 }
00204
00205
00206 void
00207 MainWindow::customEvent(QEvent *event)
00208 {
00209 if (event->type() == CustomEventType::ClientStatusEvent) {
00210 ClientStatusEvent *cse = dynamic_cast<ClientStatusEvent *>(event);
00211 if (!cse)
00212 return;
00213
00214 if (cse->status() == ClientStatusEvent::CircuitEstablished) {
00215 circuitEstablished();
00216 cse->accept();
00217 } else if (cse->status() == ClientStatusEvent::Bootstrap) {
00218 BootstrapStatusEvent *bse = dynamic_cast<BootstrapStatusEvent *>(cse);
00219 if (bse)
00220 bootstrapStatusChanged(bse->status());
00221 cse->accept();
00222 }
00223 } else if (event->type() == CustomEventType::GeneralStatusEvent) {
00224 GeneralStatusEvent *gse = dynamic_cast<GeneralStatusEvent *>(event);
00225 if (!gse)
00226 return;
00227
00228 if (gse->status() == GeneralStatusEvent::DangerousTorVersion) {
00229 DangerousVersionEvent *dve = dynamic_cast<DangerousVersionEvent *>(gse);
00230 if (dve && (dve->reason() == DangerousVersionEvent::ObsoleteVersion
00231 || dve->reason() == DangerousVersionEvent::UnrecommendedVersion)) {
00232 dangerousTorVersion();
00233 }
00234 gse->accept();
00235 }
00236 }
00237 }
00238
00239
00240
00241 void
00242 MainWindow::running()
00243 {
00244 VidaliaSettings settings;
00245
00246
00247
00248
00249
00250
00251 _useSavedPassword = true;
00252
00253 if (settings.runTorAtStart()) {
00254
00255 start();
00256 }
00257
00258
00259 if (settings.runProxyAtStart())
00260 startProxy();
00261 }
00262
00263
00264
00265 void
00266 MainWindow::shutdown()
00267 {
00268 if (_torControl->isVidaliaRunningTor()) {
00269
00270 _torControl->stop();
00271 }
00272
00273
00274 ServerSettings settings(_torControl);
00275 settings.cleanupPortForwarding();
00276
00277 if (_proxyProcess->state() != QProcess::NotRunning) {
00278
00279
00280 _proxyProcess->kill();
00281 }
00282
00283
00284 VidaliaSettings vidalia_settings;
00285
00286 if (! vidalia_settings.getBrowserDirectory().isEmpty()) {
00287
00288 QObject::disconnect(_browserProcess, SIGNAL(finished(int, QProcess::ExitStatus)), 0, 0);
00289 QObject::disconnect(_imProcess, SIGNAL(finished(int, QProcess::ExitStatus)), 0, 0);
00290
00291
00292 if (_browserProcess->state() == QProcess::Running)
00293 _browserProcess->terminate();
00294
00295 #if defined(Q_OS_WIN)
00296
00297 win32_end_process_by_filename(vidalia_settings.getBrowserExecutable());
00298 #endif
00299
00300 if (_imProcess->state() == QProcess::Running)
00301 _imProcess->terminate();
00302 }
00303
00304
00305 QObject::disconnect(_torControl, 0, 0, 0);
00306
00307
00308 QCoreApplication::quit();
00309 }
00310
00311
00312
00313
00314 void
00315 MainWindow::close()
00316 {
00317 if (_torControl->isVidaliaRunningTor()) {
00318
00319
00320
00321 ServerSettings settings(_torControl);
00322 if (_torControl->isConnected() && settings.isServerEnabled()) {
00323 connect(_torControl, SIGNAL(stopped()), this, SLOT(shutdown()));
00324 if (!stop())
00325 QObject::disconnect(_torControl, SIGNAL(stopped()), this, SLOT(shutdown()));
00326 return;
00327 }
00328 }
00329
00330 shutdown();
00331 }
00332
00333
00334
00335 void
00336 MainWindow::createActions()
00337 {
00338 _startStopAct = new QAction(tr("Start Tor"), this);
00339 connect(_startStopAct, SIGNAL(triggered()), this, SLOT(start()));
00340
00341 _exitAct = new QAction(tr("Exit"), this);
00342 connect(_exitAct, SIGNAL(triggered()), this, SLOT(close()));
00343
00344 _bandwidthAct = new QAction(tr("Bandwidth Graph"), this);
00345 connect(_bandwidthAct, SIGNAL(triggered()),
00346 _bandwidthGraph, SLOT(showWindow()));
00347 connect(ui.lblBandwidthGraph, SIGNAL(clicked()),
00348 _bandwidthGraph, SLOT(showWindow()));
00349
00350 _messageAct = new QAction(tr("Message Log"), this);
00351 connect(_messageAct, SIGNAL(triggered()),
00352 _messageLog, SLOT(showWindow()));
00353 connect(ui.lblMessageLog, SIGNAL(clicked()),
00354 _messageLog, SLOT(showWindow()));
00355
00356 _networkAct = new QAction(tr("Network Map"), this);
00357 connect(_networkAct, SIGNAL(triggered()),
00358 _netViewer, SLOT(showWindow()));
00359 connect(ui.lblViewNetwork, SIGNAL(clicked()),
00360 _netViewer, SLOT(showWindow()));
00361
00362 _controlPanelAct = new QAction(tr("Control Panel"), this);
00363 connect(_controlPanelAct, SIGNAL(triggered()), this, SLOT(show()));
00364
00365 _configAct = new QAction(tr("Settings"), this);
00366 connect(_configAct, SIGNAL(triggered()), this, SLOT(showConfigDialog()));
00367
00368 _aboutAct = new QAction(tr("About"), this);
00369 connect(_aboutAct, SIGNAL(triggered()), this, SLOT(showAboutDialog()));
00370
00371 _helpAct = new QAction(tr("Help"), this);
00372 connect(_helpAct, SIGNAL(triggered()), this, SLOT(showHelpDialog()));
00373 connect(ui.lblHelpBrowser, SIGNAL(clicked()), this, SLOT(showHelpDialog()));
00374
00375 _newIdentityAct = new QAction(tr("New Identity"), this);
00376 _newIdentityAct->setEnabled(false);
00377 connect(_newIdentityAct, SIGNAL(triggered()), this, SLOT(newIdentity()));
00378
00379 #if !defined(Q_WS_MAC)
00380
00381
00382
00383 _startStopAct->setIcon(QIcon(IMG_START_TOR_16));
00384 _exitAct->setIcon(QIcon(IMG_EXIT));
00385 _bandwidthAct->setIcon(QIcon(IMG_BWGRAPH));
00386 _messageAct->setIcon(QIcon(IMG_MESSAGELOG));
00387 _networkAct->setIcon(QIcon(IMG_NETWORK));
00388 _controlPanelAct->setIcon(QIcon(IMG_CONTROL_PANEL));
00389 _configAct->setIcon(QIcon(IMG_CONFIG));
00390 _aboutAct->setIcon(QIcon(IMG_ABOUT));
00391 _helpAct->setIcon(QIcon(IMG_HELP));
00392 _newIdentityAct->setIcon(QIcon(IMG_IDENTITY));
00393 #endif
00394 }
00395
00396
00397
00398 void
00399 MainWindow::createTrayIcon()
00400 {
00401
00402 createMenuBar();
00403
00404 _trayIcon.setContextMenu(createTrayMenu());
00405 connect(&_trayIcon, SIGNAL(doubleClicked()), this, SLOT(show()));
00406 }
00407
00408
00409
00410 QMenu*
00411 MainWindow::createTrayMenu()
00412 {
00413 QMenu *menu = new QMenu(this);
00414 menu->addAction(_startStopAct);
00415 menu->addSeparator();
00416 menu->addAction(_bandwidthAct);
00417 menu->addAction(_messageAct);
00418 menu->addAction(_networkAct);
00419 menu->addAction(_newIdentityAct);
00420 menu->addSeparator();
00421 menu->addAction(_controlPanelAct);
00422
00423 #if !defined(Q_WS_MAC)
00424
00425
00426 menu->addAction(_configAct);
00427 menu->addAction(_helpAct);
00428 menu->addAction(_aboutAct);
00429 menu->addSeparator();
00430 menu->addAction(_exitAct);
00431 #endif
00432 return menu;
00433 }
00434
00435
00436
00437
00438 void
00439 MainWindow::createMenuBar()
00440 {
00441 #if defined(Q_WS_MAC)
00442
00443
00444
00445 _startStopAct->setShortcut(tr("Ctrl+T"));
00446 _bandwidthAct->setShortcut(tr("Ctrl+B"));
00447 _messageAct->setShortcut(tr("Ctrl+L"));
00448 _networkAct->setShortcut(tr("Ctrl+N"));
00449 _helpAct->setShortcut(tr("Ctrl+?"));
00450 _newIdentityAct->setShortcut(tr("Ctrl+I"));
00451 _controlPanelAct->setShortcut(tr("Ctrl+P"));
00452
00453
00454
00455 _exitAct->setText("exit");
00456 _configAct->setText("config");
00457 _aboutAct->setText("about");
00458
00459
00460
00461 QMenuBar *menuBar = new QMenuBar(0);
00462 QMenu *fileMenu = menuBar->addMenu(tr("File"));
00463 fileMenu->addAction(_exitAct);
00464
00465 QMenu *torMenu = menuBar->addMenu(tr("Tor"));
00466 torMenu->addAction(_startStopAct);
00467 torMenu->addSeparator();
00468 torMenu->addAction(_newIdentityAct);
00469
00470 QMenu *viewMenu = menuBar->addMenu(tr("View"));
00471 viewMenu->addAction(_controlPanelAct);
00472 viewMenu->addSeparator();
00473 viewMenu->addAction(_bandwidthAct);
00474 viewMenu->addAction(_messageAct);
00475 viewMenu->addAction(_networkAct);
00476 viewMenu->addAction(_configAct);
00477
00478 QMenu *helpMenu = menuBar->addMenu(tr("Help"));
00479 _helpAct->setText(tr("Vidalia Help"));
00480 helpMenu->addAction(_helpAct);
00481 helpMenu->addAction(_aboutAct);
00482 #endif
00483 }
00484
00485
00486 void
00487 MainWindow::launchBrowserFromDirectory()
00488 {
00489 VidaliaSettings settings;
00490
00491 QString browserDirectory = settings.getBrowserDirectory();
00492 QString browserDirectoryFilename = settings.getBrowserExecutable();
00493
00494
00495
00496 QStringList env = QProcess::systemEnvironment();
00497 env << "TZ=UTC";
00498 env << "MOZ_NO_REMOTE=1";
00499 _browserProcess->setEnvironment(env);
00500
00501
00502 QString browserExecutable =
00503 QDir::toNativeSeparators(browserDirectory + "/App/Firefox/" + browserDirectoryFilename);
00504
00505 QString profileDir =
00506 QDir::toNativeSeparators(browserDirectory + "/Data/profile");
00507
00508
00509 QDir browserDirObj = QDir(browserDirectory);
00510
00511
00512 if (!browserDirObj.exists("Data/profile")) {
00513 browserDirObj.mkdir("Data/profile");
00514 copy_dir(browserDirectory + "/App/DefaultData/profile", browserDirectory + "/Data/profile");
00515 }
00516
00517
00518 if (!browserDirObj.exists("Data/plugins")) {
00519 browserDirObj.mkdir("Data/plugins");
00520 copy_dir(browserDirectory + "/App/DefaultData/plugins", browserDirectory + "/Data/plugins");
00521 }
00522
00523
00524 QStringList commandLine;
00525
00526
00527 commandLine << "-profile";
00528 commandLine << profileDir;
00529
00530
00531 _browserProcess->start(browserExecutable, commandLine);
00532 }
00533
00534
00535 void
00536 MainWindow::startSubprocesses()
00537 {
00538 VidaliaSettings settings;
00539 QString subprocess;
00540
00541
00542 if (!(subprocess = settings.getBrowserDirectory()).isEmpty()) {
00543
00544 launchBrowserFromDirectory();
00545 } else if (!(subprocess = settings.getBrowserExecutable()).isEmpty()) {
00546
00547 _browserProcess->setEnvironment(QProcess::systemEnvironment() << "TZ=UTC");
00548 _browserProcess->start(subprocess, QStringList());
00549 }
00550
00551
00552 subprocess = settings.getIMExecutable();
00553
00554 if (!subprocess.isEmpty())
00555 _imProcess->start(subprocess, QStringList());
00556
00557 }
00558
00559
00560 void
00561 MainWindow::onSubprocessFinished(int exitCode, QProcess::ExitStatus exitStatus)
00562 {
00563 Q_UNUSED(exitCode)
00564 Q_UNUSED(exitStatus)
00565
00566
00567 VidaliaSettings settings;
00568 QString browserExecutable = settings.getBrowserExecutable();
00569 QString browserDirectory = settings.getBrowserDirectory();
00570 QString imExecutable = settings.getIMExecutable();
00571
00572
00573 bool browserDone = (browserExecutable.isEmpty() && browserDirectory.isEmpty()) || _browserProcess->isDone();
00574 bool imDone = imExecutable.isEmpty() || _imProcess->isDone();
00575
00576
00577 if (browserDone && imDone) {
00578 if (browserDirectory.isEmpty()) {
00579
00580 shutdown();
00581 } else {
00582
00583 QTimer *browserWatcher = new QTimer(this);
00584 connect(browserWatcher, SIGNAL(timeout()), this, SLOT(onCheckForBrowser()));
00585 browserWatcher->start(2000);
00586 }
00587 }
00588 }
00589
00590
00591
00592 void
00593 MainWindow::onCheckForBrowser()
00594 {
00595
00596 #if defined(Q_OS_WIN)
00597
00598 VidaliaSettings settings;
00599 QString browserDirectoryFilename = settings.getBrowserExecutable();
00600
00601
00602 QHash<qint64, QString> procList = win32_process_list();
00603
00604
00605
00606 if (procList.isEmpty()) {
00607 return;
00608 }
00609
00610
00611 QHashIterator<qint64, QString> i(procList);
00612 while (i.hasNext()) {
00613 i.next();
00614 if (i.value().toLower() == browserDirectoryFilename) {
00615
00616 return;
00617 }
00618 }
00619
00620
00621 shutdown();
00622 #endif
00623 }
00624
00625
00626
00627 void
00628 MainWindow::onBrowserFailed(QString errmsg)
00629 {
00630 Q_UNUSED(errmsg);
00631
00632
00633 VMessageBox::warning(this, tr("Error starting web browser"),
00634 tr("Vidalia was unable to start the configured web browser"),
00635 VMessageBox::Ok|VMessageBox::Default|VMessageBox::Escape);
00636 }
00637
00638
00639
00640 void
00641 MainWindow::onIMFailed(QString errmsg)
00642 {
00643 Q_UNUSED(errmsg);
00644
00645
00646 VMessageBox::warning(this, tr("Error starting IM client"),
00647 tr("Vidalia was unable to start the configured IM client"),
00648 VMessageBox::Ok|VMessageBox::Default|VMessageBox::Escape);
00649 }
00650
00651
00652 void
00653 MainWindow::startProxy()
00654 {
00655 VidaliaSettings settings;
00656 QString executable = settings.getProxyExecutable();
00657 _proxyProcess->start(executable, settings.getProxyExecutableArguments());
00658 }
00659
00660
00661
00662 void
00663 MainWindow::onProxyFailed(QString errmsg)
00664 {
00665 Q_UNUSED(errmsg);
00666
00667
00668 VMessageBox::warning(this, tr("Error starting proxy server"),
00669 tr("Vidalia was unable to start the configured proxy server"),
00670 VMessageBox::Ok|VMessageBox::Default|VMessageBox::Escape);
00671 }
00672
00673
00674
00675 void
00676 MainWindow::bootstrapStatusChanged(const BootstrapStatus &bs)
00677 {
00678 int percentComplete = STARTUP_PROGRESS_BOOTSTRAPPING + bs.percentComplete();
00679 bool warn = (bs.severity() == tc::SeverityWarn &&
00680 bs.recommendedAction() != BootstrapStatus::RecommendIgnore);
00681
00682 QString description;
00683 switch (bs.status()) {
00684 case BootstrapStatus::ConnectingToDirMirror:
00685 description = tr("Connecting to a relay directory");
00686 break;
00687 case BootstrapStatus::HandshakingWithDirMirror:
00688 case BootstrapStatus::CreatingOneHopCircuit:
00689 description = tr("Establishing an encrypted directory connection");
00690 break;
00691 case BootstrapStatus::RequestingNetworkStatus:
00692 description = tr("Retrieving network status");
00693 break;
00694 case BootstrapStatus::LoadingNetworkStatus:
00695 description = tr("Loading network status");
00696 break;
00697 case BootstrapStatus::LoadingAuthorityCertificates:
00698 description = tr("Loading authority certificates");
00699 break;
00700 case BootstrapStatus::RequestingDescriptors:
00701 description = tr("Requesting relay information");
00702 break;
00703 case BootstrapStatus::LoadingDescriptors:
00704 description = tr("Loading relay information");
00705 break;
00706 case BootstrapStatus::ConnectingToEntryGuard:
00707 description = tr("Connecting to the Tor network");
00708 break;
00709 case BootstrapStatus::HandshakingWithEntryGuard:
00710 case BootstrapStatus::EstablishingCircuit:
00711 description = tr("Establishing a Tor circuit");
00712 break;
00713 case BootstrapStatus::BootstrappingDone:
00714 description = tr("Connected to the Tor network!");
00715 warn = false;
00716 break;
00717 default:
00718 description = tr("Unrecognized startup status");
00719 }
00720 if (warn) {
00721 QString reason;
00722
00723 switch (bs.reason()) {
00724 case tc::MiscellaneousReason:
00725 reason = tr("miscellaneous");
00726 break;
00727 case tc::IdentityMismatch:
00728 reason = tr("identity mismatch");
00729 break;
00730 case tc::ConnectionDone:
00731 reason = tr("done");
00732 break;
00733 case tc::ConnectionRefused:
00734 reason = tr("connection refused");
00735 break;
00736 case tc::ConnectionTimeout:
00737 reason = tr("connection timeout");
00738 break;
00739 case tc::ConnectionIoError:
00740 reason = tr("read/write error");
00741 break;
00742 case tc::NoRouteToHost:
00743 reason = tr("no route to host");
00744 break;
00745 case tc::ResourceLimitReached:
00746 reason = tr("insufficient resources");
00747 break;
00748 default:
00749 reason = tr("unknown");
00750 }
00751 description += tr(" failed (%1)").arg(reason);
00752 }
00753 setStartupProgress(percentComplete, description);
00754 }
00755
00756
00757
00758 MainWindow::TorStatus
00759 MainWindow::updateTorStatus(TorStatus status)
00760 {
00761 QString statusText, actionText;
00762 QString trayIconFile, statusIconFile;
00763 TorStatus prevStatus = _status;
00764
00765 vNotice("Tor status changed from '%1' to '%2'.")
00766 .arg(toString(prevStatus)).arg(toString(status));
00767 _status = status;
00768
00769 if (status == Stopped) {
00770 statusText = tr("Tor is not running");
00771 actionText = tr("Start Tor");
00772 trayIconFile = IMG_TOR_STOPPED;
00773 statusIconFile = IMG_TOR_STOPPED_48;
00774 _startStopAct->setEnabled(true);
00775 _startStopAct->setText(actionText);
00776 _startStopAct->setIcon(QIcon(IMG_START_TOR_16));
00777 ui.lblStartStopTor->setEnabled(true);
00778 ui.lblStartStopTor->setText(actionText);
00779 ui.lblStartStopTor->setPixmap(QPixmap(IMG_START_TOR_48));
00780 ui.lblStartStopTor->setStatusTip(actionText);
00781
00782
00783
00784 QObject::disconnect(_startStopAct, SIGNAL(triggered()), this, 0);
00785 QObject::disconnect(ui.lblStartStopTor, SIGNAL(clicked()), this, 0);
00786 connect(_startStopAct, SIGNAL(triggered()), this, SLOT(start()));
00787 connect(ui.lblStartStopTor, SIGNAL(clicked()), this, SLOT(start()));
00788 setStartupProgressVisible(false);
00789 } else if (status == Stopping) {
00790 if (_delayedShutdownStarted) {
00791 statusText = tr("Your relay is shutting down.\n"
00792 "Click 'Stop' again to stop your relay now.");
00793 } else {
00794 statusText = tr("Tor is shutting down");
00795 }
00796 trayIconFile = IMG_TOR_STOPPING;
00797 statusIconFile = IMG_TOR_STOPPING_48;
00798
00799 ui.lblStartStopTor->setStatusTip(tr("Stop Tor Now"));
00800 } else if (status == Started) {
00801 actionText = tr("Stop Tor");
00802 _startStopAct->setEnabled(true);
00803 _startStopAct->setText(actionText);
00804 _startStopAct->setIcon(QIcon(IMG_STOP_TOR_16));
00805 ui.lblStartStopTor->setEnabled(true);
00806 ui.lblStartStopTor->setText(actionText);
00807 ui.lblStartStopTor->setPixmap(QPixmap(IMG_STOP_TOR_48));
00808 ui.lblStartStopTor->setStatusTip(actionText);
00809
00810
00811
00812 QObject::disconnect(_startStopAct, SIGNAL(triggered()), this, 0);
00813 QObject::disconnect(ui.lblStartStopTor, SIGNAL(clicked()), this, 0);
00814 connect(_startStopAct, SIGNAL(triggered()), this, SLOT(stop()));
00815 connect(ui.lblStartStopTor, SIGNAL(clicked()), this, SLOT(stop()));
00816 } else if (status == Starting) {
00817 statusText = tr("Starting the Tor software");
00818 trayIconFile = IMG_TOR_STARTING;
00819 statusIconFile = IMG_TOR_STARTING_48;
00820 _startStopAct->setEnabled(false);
00821 ui.lblStartStopTor->setText(tr("Starting Tor"));
00822 ui.lblStartStopTor->setEnabled(false);
00823 ui.lblStartStopTor->setStatusTip(statusText);
00824 setStartupProgressVisible(true);
00825 setStartupProgress(STARTUP_PROGRESS_STARTING, statusText);
00826 } else if (status == CircuitEstablished) {
00827 statusText = tr("Connected to the Tor network!");
00828 trayIconFile = IMG_TOR_RUNNING;
00829 statusIconFile = IMG_TOR_RUNNING_48;
00830 setStartupProgressVisible(false);
00831 }
00832
00833
00834 if (!trayIconFile.isEmpty()) {
00835 _trayIcon.setIcon(trayIconFile);
00836 }
00837
00838 if (!statusIconFile.isEmpty())
00839 ui.lblTorStatusImg->setPixmap(QPixmap(statusIconFile));
00840 if (!statusText.isEmpty()) {
00841 _trayIcon.setToolTip(statusText);
00842 ui.lblTorStatus->setText(statusText);
00843 }
00844 return prevStatus;
00845 }
00846
00847
00848 void
00849 MainWindow::toggleShowOnStartup(bool checked)
00850 {
00851 VidaliaSettings settings;
00852 settings.setShowMainWindowAtStart(checked);
00853 }
00854
00855
00856
00857 void
00858 MainWindow::setStartupProgressVisible(bool visible)
00859 {
00860
00861
00862 if (visible) {
00863 ui.lblTorStatus->setVisible(false);
00864 ui.lblTorStatusImg->setVisible(false);
00865 repaint(ui.grpStatus->rect());
00866 ui.lblStartupProgress->setVisible(true);
00867 ui.progressBar->setVisible(true);
00868 } else {
00869 ui.lblStartupProgress->setVisible(false);
00870 ui.progressBar->setVisible(false);
00871 repaint(ui.grpStatus->rect());
00872 ui.lblTorStatus->setVisible(true);
00873 ui.lblTorStatusImg->setVisible(true);
00874 }
00875 }
00876
00877
00878
00879 void
00880 MainWindow::setStartupProgress(int progressValue,
00881 const QString &description)
00882 {
00883 ui.progressBar->setValue(progressValue);
00884 ui.lblStartupProgress->setText(description);
00885 _trayIcon.setToolTip(description);
00886 }
00887
00888
00889
00890 void
00891 MainWindow::start()
00892 {
00893 TorSettings settings;
00894 QStringList args;
00895
00896 updateTorStatus(Starting);
00897
00898
00899 if (net_test_connect(settings.getControlAddress(),
00900 settings.getControlPort())) {
00901 started();
00902 return;
00903 }
00904
00905
00906 QString torrc = settings.getTorrc();
00907 if (!torrc.isEmpty()) {
00908 if (!QFileInfo(torrc).exists())
00909 touch_file(torrc, true);
00910 args << "-f" << torrc;
00911 }
00912
00913
00914 QString dataDirectory = settings.getDataDirectory();
00915 if (!dataDirectory.isEmpty())
00916 args << "DataDirectory" << expand_filename(dataDirectory);
00917
00918
00919 quint16 controlPort = settings.getControlPort();
00920 if (controlPort)
00921 args << "ControlPort" << QString::number(controlPort);
00922
00923
00924 switch (settings.getAuthenticationMethod()) {
00925 case TorSettings::PasswordAuth:
00926 if (settings.useRandomPassword()) {
00927 _controlPassword = TorSettings::randomPassword();
00928 _useSavedPassword = false;
00929 } else {
00930 _controlPassword = settings.getControlPassword();
00931 _useSavedPassword = true;
00932 }
00933 args << "HashedControlPassword"
00934 << TorSettings::hashPassword(_controlPassword)
00935 << "CookieAuthentication" << "0";
00936 break;
00937 case TorSettings::CookieAuth:
00938 args << "CookieAuthentication" << "1"
00939 << "HashedControlPassword" << "";
00940 break;
00941 default:
00942 args << "CookieAuthentication" << "0"
00943 << "HashedControlPassword" << "";
00944 }
00945
00946
00947
00948
00949
00950 _isIntentionalExit = true;
00951
00952 _torControl->start(settings.getExecutable(), args);
00953 }
00954
00955
00956
00957 void
00958 MainWindow::startFailed(QString errmsg)
00959 {
00960
00961
00962
00963 Q_UNUSED(errmsg);
00964
00965 updateTorStatus(Stopped);
00966
00967
00968 int response = VMessageBox::warning(this, tr("Error Starting Tor"),
00969 tr("Vidalia was unable to start Tor. Check your settings "
00970 "to ensure the correct name and location of your Tor "
00971 "executable is specified."),
00972 VMessageBox::ShowSettings|VMessageBox::Default,
00973 VMessageBox::Cancel|VMessageBox::Escape,
00974 VMessageBox::Help);
00975
00976 if (response == VMessageBox::ShowSettings) {
00977
00978
00979 showConfigDialog();
00980 } else if (response == VMessageBox::Help) {
00981
00982 showHelpDialog("troubleshooting.start");
00983 }
00984 }
00985
00986
00987
00988 void
00989 MainWindow::started()
00990 {
00991 TorSettings settings;
00992
00993 updateTorStatus(Started);
00994
00995
00996
00997 _isIntentionalExit = false;
00998
00999 _delayedShutdownStarted = false;
01000
01001 _isVidaliaRunningTor = _torControl->isVidaliaRunningTor();
01002
01003 _torControl->connect(settings.getControlAddress(),
01004 settings.getControlPort());
01005 setStartupProgress(STARTUP_PROGRESS_CONNECTING, tr("Connecting to Tor"));
01006 }
01007
01008
01009
01010 void
01011 MainWindow::connectFailed(QString errmsg)
01012 {
01013
01014 int response = VMessageBox::warning(this,
01015 tr("Connection Error"), p(errmsg),
01016 VMessageBox::Ok|VMessageBox::Default|VMessageBox::Escape,
01017 VMessageBox::Retry, VMessageBox::Help);
01018
01019
01020 if (response == VMessageBox::Retry) {
01021
01022 TorSettings settings;
01023 _torControl->connect(settings.getControlAddress(),
01024 settings.getControlPort());
01025 } else {
01026
01027 if (response == VMessageBox::Help)
01028 showHelpDialog("troubleshooting.connect");
01029
01030 _torControl->stop();
01031 }
01032 }
01033
01034
01035 bool
01036 MainWindow::stop()
01037 {
01038 ServerSettings server(_torControl);
01039 QString errmsg;
01040 TorStatus prevStatus;
01041 bool rc;
01042
01043
01044
01045 if (server.isServerEnabled() && !_delayedShutdownStarted) {
01046
01047 int response = VMessageBox::question(this, tr("Relaying is Enabled"),
01048 tr("You are currently running a relay. "
01049 "Terminating your relay will interrupt any "
01050 "open connections from clients.\n\n"
01051 "Would you like to shutdown gracefully and "
01052 "give clients time to find a new relay?"),
01053 VMessageBox::Yes|VMessageBox::Default,
01054 VMessageBox::No,
01055 VMessageBox::Cancel|VMessageBox::Escape);
01056 if (response == VMessageBox::Yes)
01057 _delayedShutdownStarted = true;
01058 else if (response == VMessageBox::Cancel)
01059 return false;
01060 }
01061
01062 prevStatus = updateTorStatus(Stopping);
01063 if (_delayedShutdownStarted) {
01064
01065 rc = _torControl->signal(TorSignal::Shutdown, &errmsg);
01066 } else {
01067
01068 _isIntentionalExit = true;
01069 rc = _torControl->stop(&errmsg);
01070 }
01071
01072 if (!rc) {
01073
01074 int response = VMessageBox::warning(this, tr("Error Shutting Down"),
01075 p(tr("Vidalia was unable to stop the Tor software."))
01076 + p(errmsg),
01077 VMessageBox::Ok|VMessageBox::Default|VMessageBox::Escape,
01078 VMessageBox::Help);
01079
01080 if (response == VMessageBox::Help) {
01081
01082 showHelpDialog("troubleshooting.stop");
01083 }
01084
01085 _isIntentionalExit = false;
01086 _delayedShutdownStarted = false;
01087 updateTorStatus(prevStatus);
01088 }
01089 return rc;
01090 }
01091
01092
01093
01094 void
01095 MainWindow::stopped(int exitCode, QProcess::ExitStatus exitStatus)
01096 {
01097 updateTorStatus(Stopped);
01098
01099
01100
01101 if (!_isIntentionalExit) {
01102
01103
01104
01105 if (exitStatus == QProcess::CrashExit || exitCode != 0) {
01106 int ret = VMessageBox::warning(this, tr("Unexpected Error"),
01107 tr("Vidalia detected that the Tor software exited "
01108 "unexpectedly.\n\n"
01109 "Please check the message log for recent "
01110 "warning or error messages."),
01111 VMessageBox::Ok|VMessageBox::Escape,
01112 VMessageBox::ShowLog|VMessageBox::Default,
01113 VMessageBox::Help);
01114 if (ret == VMessageBox::ShowLog)
01115 _messageLog->showWindow();
01116 else if (ret == VMessageBox::Help)
01117 showHelpDialog("troubleshooting.torexited");
01118 }
01119 }
01120 }
01121
01122
01123 void
01124 MainWindow::connected()
01125 {
01126 authenticate();
01127 }
01128
01129
01130 void
01131 MainWindow::disconnect()
01132 {
01133 _torControl->disconnect();
01134 }
01135
01136
01137 void
01138 MainWindow::disconnected()
01139 {
01140 if (!_isVidaliaRunningTor) {
01141
01142
01143 updateTorStatus(Stopped);
01144 }
01145
01146
01147 _newIdentityAct->setEnabled(false);
01148 ui.lblNewIdentity->setEnabled(false);
01149 _isVidaliaRunningTor = false;
01150 }
01151
01152
01153
01154
01155 bool
01156 MainWindow::authenticate()
01157 {
01158 TorSettings::AuthenticationMethod authMethod;
01159 TorSettings settings;
01160 ProtocolInfo pi;
01161
01162 updateTorStatus(Authenticating);
01163 setStartupProgress(STARTUP_PROGRESS_AUTHENTICATING,
01164 tr("Authenticating to Tor"));
01165
01166 authMethod = settings.getAuthenticationMethod();
01167 pi = _torControl->protocolInfo();
01168 if (!pi.isEmpty()) {
01169 QStringList authMethods = pi.authMethods();
01170 if (authMethods.contains("COOKIE"))
01171 authMethod = TorSettings::CookieAuth;
01172 else if (authMethods.contains("HASHEDPASSWORD"))
01173 authMethod = TorSettings::PasswordAuth;
01174 else if (authMethods.contains("NULL"))
01175 authMethod = TorSettings::NullAuth;
01176 }
01177
01178 if (authMethod == TorSettings::CookieAuth) {
01179
01180 QByteArray cookie = loadControlCookie(pi.cookieAuthFile());
01181 while (cookie.isEmpty()) {
01182
01183 int ret = VMessageBox::question(this,
01184 tr("Cookie Authentication Required"),
01185 p(tr("The Tor software requires Vidalia to send the "
01186 "contents of an authentication cookie, but Vidalia "
01187 "was unable to find one."))
01188 + p(tr("Would you like to browse for the file "
01189 "'control_auth_cookie' yourself?")),
01190 VMessageBox::Browse|VMessageBox::Default,
01191 VMessageBox::Cancel|VMessageBox::Escape);
01192
01193 if (ret == VMessageBox::Cancel)
01194 goto cancel;
01195 QString cookieDir = QFileDialog::getOpenFileName(this,
01196 tr("Data Directory"),
01197 settings.getDataDirectory(),
01198 tr("Control Cookie (control_auth_cookie)"));
01199 if (cookieDir.isEmpty())
01200 goto cancel;
01201 cookieDir = QFileInfo(cookieDir).absolutePath();
01202 cookie = loadControlCookie(cookieDir);
01203 }
01204 vNotice("Authenticating using 'cookie' authentication.");
01205 return _torControl->authenticate(cookie);
01206 } else if (authMethod == TorSettings::PasswordAuth) {
01207
01208 vNotice("Authenticating using 'hashed password' authentication.");
01209 if (_useSavedPassword) {
01210 TorSettings settings;
01211 _controlPassword = settings.getControlPassword();
01212 }
01213 return _torControl->authenticate(_controlPassword);
01214 }
01215
01216 vNotice("Authenticating using 'null' authentication.");
01217 return _torControl->authenticate(QString(""));
01218
01219 cancel:
01220 vWarn("Cancelling control authentication attempt.");
01221 if (_isVidaliaRunningTor)
01222 stop();
01223 else
01224 disconnect();
01225 return false;
01226 }
01227
01228
01229 void
01230 MainWindow::authenticated()
01231 {
01232 ServerSettings serverSettings(_torControl);
01233 QString errmsg;
01234
01235 updateTorStatus(Authenticated);
01236
01237
01238
01239 if (_torControl->getTorVersion() < 0x020101) {
01240 setStartupProgress(STARTUP_PROGRESS_CIRCUITBUILD,
01241 tr("Connecting to the Tor network"));
01242 }
01243
01244
01245 _newIdentityAct->setEnabled(true);
01246 ui.lblNewIdentity->setEnabled(true);
01247
01248
01249 if (!_torControl->setEvents(&errmsg)) {
01250 VMessageBox::warning(this, tr("Error Registering for Events"),
01251 p(tr("Vidalia was unable to register for some events. "
01252 "Many of Vidalia's features may be unavailable."))
01253 + p(errmsg),
01254 VMessageBox::Ok);
01255 } else {
01256
01257
01258 _torControl->closeTorStdout();
01259 }
01260
01261
01262 serverSettings.configurePortForwarding();
01263
01264
01265 if (_torControl->circuitEstablished())
01266 circuitEstablished();
01267
01268 if (_torControl->getTorVersion() >= 0x020001)
01269 checkTorVersion();
01270 if (_torControl->getTorVersion() >= 0x020102) {
01271 BootstrapStatus status = _torControl->bootstrapStatus();
01272 if (status.isValid())
01273 bootstrapStatusChanged(status);
01274 }
01275 }
01276
01277
01278
01279 void
01280 MainWindow::authenticationFailed(QString errmsg)
01281 {
01282 bool retry = false;
01283
01284 vWarn("Authentication failed: %1").arg(errmsg);
01285
01286
01287 if (errmsg.contains("Password did not match")) {
01288 ControlPasswordInputDialog dlg;
01289 connect(&dlg, SIGNAL(helpRequested(QString)),
01290 this, SLOT(showHelpDialog(QString)));
01291
01292 qint64 torPid = 0;
01293
01294 #if defined(Q_OS_WIN32)
01295 QHash<qint64, QString> procs = process_list();
01296 foreach (qint64 pid, procs.keys()) {
01297 if (! procs.value(pid).compare("tor.exe", Qt::CaseInsensitive)) {
01298 torPid = pid;
01299 break;
01300 }
01301 }
01302 dlg.setResetEnabled(torPid > 0);
01303 #else
01304 dlg.setResetEnabled(false);
01305 #endif
01306
01307 int ret = dlg.exec();
01308 if (ret == QDialogButtonBox::Ok) {
01309 if (dlg.isSavePasswordChecked()) {
01310 TorSettings settings;
01311 settings.setAuthenticationMethod(TorSettings::PasswordAuth);
01312 settings.setUseRandomPassword(false);
01313 settings.setControlPassword(dlg.password());
01314 _useSavedPassword = true;
01315 } else {
01316 _controlPassword = dlg.password();
01317 _useSavedPassword = false;
01318 }
01319 retry = true;
01320 } else if (ret == QDialogButtonBox::Reset) {
01321 if (! process_kill(torPid)) {
01322 VMessageBox::warning(this,
01323 tr("Password Reset Failed"),
01324 p(tr("Vidalia tried to reset Tor's control password, but was not "
01325 "able to restart the Tor software. Please check your Task "
01326 "Manager to ensure there are no other Tor processes running.")),
01327 VMessageBox::Ok|VMessageBox::Default);
01328 } else {
01329 retry = true;
01330 }
01331 }
01332 } else {
01333
01334 int ret = VMessageBox::warning(this,
01335 tr("Authentication Error"),
01336 p(tr("Vidalia was unable to authenticate to the Tor software. "
01337 "(%1)").arg(errmsg)) +
01338 p(tr("Please check your control port authentication "
01339 "settings.")),
01340 VMessageBox::ShowSettings|VMessageBox::Default,
01341 VMessageBox::Cancel|VMessageBox::Escape);
01342
01343 if (ret == VMessageBox::ShowSettings)
01344 showConfigDialog(ConfigDialog::Advanced);
01345 }
01346
01347 if (_torControl->isRunning())
01348 if (_isVidaliaRunningTor)
01349 stop();
01350 else
01351 disconnect();
01352 if (retry)
01353 start();
01354 }
01355
01356
01357
01358
01359
01360
01361 QByteArray
01362 MainWindow::loadControlCookie(QString cookiePath)
01363 {
01364 QFile authCookie;
01365 QStringList pathList;
01366
01367 if (!cookiePath.isEmpty()) {
01368 pathList << cookiePath;
01369 } else {
01370
01371 TorSettings settings;
01372 QString dataDir = settings.getDataDirectory();
01373 if (!dataDir.isEmpty())
01374 pathList << dataDir;
01375
01376 #if defined(Q_WS_WIN)
01377 pathList << expand_filename("%APPDATA%\\Tor");
01378 #else
01379 pathList << expand_filename("~/.tor");
01380 #endif
01381 }
01382
01383
01384 foreach (QString path, pathList) {
01385 QString cookieFile = QFileInfo(path).isFile() ?
01386 path : path + "/control_auth_cookie";
01387 vDebug("Checking for authentication cookie in '%1'").arg(cookieFile);
01388 if (!QFileInfo(cookieFile).exists())
01389 continue;
01390
01391 authCookie.setFileName(cookieFile);
01392 if (authCookie.open(QIODevice::ReadOnly)) {
01393 vInfo("Reading authentication cookie from '%1'").arg(cookieFile);
01394 return authCookie.readAll();
01395 } else {
01396 vWarn("Couldn't open cookie file '%1': %2")
01397 .arg(cookieFile).arg(authCookie.errorString());
01398 }
01399 }
01400 vWarn("Couldn't find a readable authentication cookie.");
01401 return QByteArray();
01402 }
01403
01404
01405 void
01406 MainWindow::circuitEstablished()
01407 {
01408 updateTorStatus(CircuitEstablished);
01409 setStartupProgress(ui.progressBar->maximum(),
01410 tr("Connected to the Tor network!"));
01411 startSubprocesses();
01412 }
01413
01414
01415
01416 void
01417 MainWindow::checkTorVersion()
01418 {
01419 QString status;
01420 if (_torControl->getInfo("status/version/current", status)) {
01421 if (!status.compare("old", Qt::CaseInsensitive)
01422 || !status.compare("unrecommended", Qt::CaseInsensitive)
01423 || !status.compare("obsolete", Qt::CaseInsensitive)) {
01424 dangerousTorVersion();
01425 }
01426 }
01427 }
01428
01429
01430
01431 void
01432 MainWindow::dangerousTorVersion()
01433 {
01434 static bool alreadyWarned = false;
01435
01436 if (!alreadyWarned) {
01437 QString website = "https://www.torproject.org/";
01438 #if QT_VERSION >= 0x040200
01439 website = QString("<a href=\"%1\">%1</a>").arg(website);
01440 #endif
01441
01442 VMessageBox::information(this,
01443 tr("Tor Update Available"),
01444 p(tr("The currently installed version of Tor is out of date or no longer "
01445 "recommended. Please visit the Tor website to download the latest "
01446 "version.")) + p(tr("Tor website: %1").arg(website)),
01447 VMessageBox::Ok);
01448 alreadyWarned = true;
01449 }
01450 }
01451
01452
01453 void
01454 MainWindow::showAboutDialog()
01455 {
01456 static AboutDialog *aboutDialog = 0;
01457 if (!aboutDialog)
01458 aboutDialog = new AboutDialog(this);
01459 aboutDialog->showWindow();
01460 }
01461
01462
01463
01464 void
01465 MainWindow::showHelpDialog()
01466 {
01467 showHelpDialog(QString());
01468 }
01469
01470
01471 void
01472 MainWindow::showHelpDialog(const QString &topic)
01473 {
01474 static HelpBrowser *helpBrowser = 0;
01475 if (!helpBrowser)
01476 helpBrowser = new HelpBrowser(this);
01477 helpBrowser->showWindow(topic);
01478 }
01479
01480
01481
01482 void
01483 MainWindow::showConfigDialog(ConfigDialog::Page page)
01484 {
01485 _configDialog->showWindow(page);
01486 }
01487
01488
01489 void
01490 MainWindow::showServerConfigDialog()
01491 {
01492 showConfigDialog(ConfigDialog::Server);
01493 }
01494
01495
01496 void
01497 MainWindow::newIdentity()
01498 {
01499 QString errmsg;
01500
01501
01502
01503
01504 if (_torControl->signal(TorSignal::NewNym, &errmsg)) {
01505
01506 QString title = tr("New Identity");
01507 QString message = tr("All subsequent connections will "
01508 "appear to be different than your "
01509 "old connections.");
01510
01511
01512 _newIdentityAct->setEnabled(false);
01513 ui.lblNewIdentity->setEnabled(false);
01514 QTimer::singleShot(MIN_NEWIDENTITY_INTERVAL,
01515 this, SLOT(enableNewIdentity()));
01516
01517 if (TrayIcon::supportsBalloonMessages())
01518 _trayIcon.showBalloonMessage(title, message, TrayIcon::Information);
01519 else
01520 VMessageBox::information(this, title, message, VMessageBox::Ok);
01521 } else {
01522
01523 VMessageBox::warning(this,
01524 tr("Failed to Create New Identity"), errmsg, VMessageBox::Ok);
01525 }
01526 }
01527
01528
01529
01530 void
01531 MainWindow::enableNewIdentity()
01532 {
01533 if (_torControl->isConnected()) {
01534 _newIdentityAct->setEnabled(true);
01535 ui.lblNewIdentity->setEnabled(true);
01536 }
01537 }
01538
01539
01540 QString
01541 MainWindow::toString(TorStatus status)
01542 {
01543 switch (status) {
01544
01545
01546 case Unset: return "Unset";
01547 case Stopping: return "Stopping";
01548 case Stopped: return "Stopped";
01549 case Starting: return "Starting";
01550 case Started: return "Started";
01551 case Authenticating: return "Authenticating";
01552 case Authenticated: return "Authenticated";
01553 case CircuitEstablished: return "Circuit Established";
01554 default: break;
01555 }
01556 return "Unknown";
01557 }
01558
01559 #if defined(USE_MINIUPNPC)
01560
01561 void
01562 MainWindow::upnpError(UPNPControl::UPNPError error)
01563 {
01564 Q_UNUSED(error);
01565
01566 #if 0
01567
01568
01569
01570
01571
01572 VMessageBox::warning(this,
01573 tr("Port Forwarding Failed"),
01574 p(tr("Vidalia was unable to configure automatic port forwarding."))
01575 + p(UPNPControl::Instance()->errorString()),
01576 VMessageBox::Ok);
01577 #endif
01578 }
01579 #endif
01580