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