00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <QtGui>
00033 #include <QTimer>
00034 #include <vidalia.h>
00035 #include <util/file.h>
00036 #include <util/html.h>
00037 #include <util/string.h>
00038 #include <QSysInfo>
00039
00040 #include "common/vmessagebox.h"
00041 #include "common/animatedpixmap.h"
00042 #include "mainwindow.h"
00043
00044
00045 #define IMG_APP_ICON ":/images/16x16/tor-logo.png"
00046 #define IMG_BWGRAPH ":/images/16x16/utilities-system-monitor.png"
00047 #define IMG_CONTROL_PANEL ":/images/16x16/preferences-desktop.png"
00048 #define IMG_MESSAGELOG ":/images/16x16/format-justify-fill.png"
00049 #define IMG_CONFIG ":/images/16x16/preferences-system.png"
00050 #define IMG_IDENTITY ":/images/16x16/system-users.png"
00051 #define IMG_HELP ":/images/16x16/help-browser.png"
00052 #define IMG_ABOUT ":/images/16x16/tor-logo.png"
00053 #define IMG_EXIT ":/images/16x16/emblem-unreadable.png"
00054 #define IMG_NETWORK ":/images/16x16/applications-internet.png"
00055
00056 #define IMG_START_TOR_16 ":/images/16x16/start-tor.png"
00057 #define IMG_STOP_TOR_16 ":/images/16x16/stop-tor.png"
00058 #define IMG_START_TOR_48 ":/images/48x48/start-tor.png"
00059 #define IMG_STOP_TOR_48 ":/images/48x48/stop-tor.png"
00060 #define IMG_TOR_STOPPED_48 ":/images/48x48/tor-off.png"
00061 #define IMG_TOR_RUNNING_48 ":/images/48x48/tor-on.png"
00062 #define IMG_TOR_STARTING_48 ":/images/48x48/tor-starting.png"
00063 #define IMG_TOR_STOPPING_48 ":/images/48x48/tor-stopping.png"
00064
00065 #define ANIM_PROCESS_WORKING ":/images/32x32/process-working.png"
00066
00067
00068 #if defined(USE_QSYSTEMTRAYICON)
00069
00070 #if defined(Q_WS_WIN)
00071
00072 #define IMG_TOR_STOPPED ":/images/16x16/tor-off.png"
00073 #define IMG_TOR_RUNNING ":/images/16x16/tor-on.png"
00074 #define IMG_TOR_STARTING ":/images/16x16/tor-starting.png"
00075 #define IMG_TOR_STOPPING ":/images/16x16/tor-stopping.png"
00076 #endif
00077 #else
00078
00079 #if defined(Q_WS_WIN)
00080
00081 #include "res/vidalia_win.rc.h"
00082 #define IMG_TOR_STOPPED QString::number(IDI_TOR_OFF)
00083 #define IMG_TOR_RUNNING QString::number(IDI_TOR_ON)
00084 #define IMG_TOR_STARTING QString::number(IDI_TOR_STARTING)
00085 #define IMG_TOR_STOPPING QString::number(IDI_TOR_STOPPING)
00086 #endif
00087 #endif
00088 #if defined(Q_WS_MAC)
00089
00090
00091 #define IMG_TOR_STOPPED "tor-off"
00092 #define IMG_TOR_RUNNING "tor-on"
00093 #define IMG_TOR_STARTING "tor-starting"
00094 #define IMG_TOR_STOPPING "tor-stopping"
00095 #elif defined(Q_WS_X11)
00096
00097 #define IMG_TOR_STOPPED ":/images/22x22/tor-off.png"
00098 #define IMG_TOR_RUNNING ":/images/22x22/tor-on.png"
00099 #define IMG_TOR_STARTING ":/images/22x22/tor-starting.png"
00100 #define IMG_TOR_STOPPING ":/images/22x22/tor-stopping.png"
00101 #endif
00102
00103
00104 #define MIN_NEWIDENTITY_INTERVAL (10*1000)
00105
00106
00107
00108
00109 MainWindow::MainWindow()
00110 : VidaliaWindow("MainWindow")
00111 {
00112 VidaliaSettings settings;
00113
00114 ui.setupUi(this);
00115
00116
00117 _messageLog = new MessageLog();
00118 _bandwidthGraph = new BandwidthGraph();
00119 _netViewer = new NetViewer();
00120
00121
00122 createActions();
00123
00124
00125 createTrayIcon();
00126
00127 _status = Unset;
00128 updateTorStatus(Stopped);
00129
00130
00131 _torControl = Vidalia::torControl();
00132 connect(_torControl, SIGNAL(started()), this, SLOT(started()));
00133 connect(_torControl, SIGNAL(startFailed(QString)),
00134 this, SLOT(startFailed(QString)));
00135 connect(_torControl, SIGNAL(stopped(int, QProcess::ExitStatus)),
00136 this, SLOT(stopped(int, QProcess::ExitStatus)));
00137 connect(_torControl, SIGNAL(connected()), this, SLOT(connected()));
00138 connect(_torControl, SIGNAL(disconnected()), this, SLOT(disconnected()));
00139 connect(_torControl, SIGNAL(connectFailed(QString)),
00140 this, SLOT(connectFailed(QString)));
00141 connect(_torControl, SIGNAL(authenticated()), this, SLOT(authenticated()));
00142 connect(_torControl, SIGNAL(authenticationFailed(QString)),
00143 this, SLOT(authenticationFailed(QString)));
00144
00145
00146 connect(vApp, SIGNAL(shutdown()), this, SLOT(shutdown()));
00147
00148 if (_torControl->isRunning()) {
00149
00150
00151 updateTorStatus(Starting);
00152
00153 started();
00154 } else if (settings.runTorAtStart()) {
00155
00156 start();
00157 }
00158
00159 if (isTrayIconSupported()) {
00160
00161 _trayIcon.show();
00162
00163 ui.chkShowOnStartup->setChecked(settings.showMainWindowAtStart());
00164 if (ui.chkShowOnStartup->isChecked())
00165 show();
00166 } else {
00167
00168 ui.chkShowOnStartup->hide();
00169 ui.btnHide->hide();
00170 setMinimumHeight(height()-ui.btnHide->height());
00171 setMaximumHeight(height()-ui.btnHide->height());
00172 show();
00173 }
00174 }
00175
00176
00177 MainWindow::~MainWindow()
00178 {
00179 _trayIcon.hide();
00180 delete _messageLog;
00181 delete _netViewer;
00182 delete _bandwidthGraph;
00183 }
00184
00185
00186 bool
00187 MainWindow::isTrayIconSupported()
00188 {
00189 #if defined(Q_WS_WIN) || defined(Q_WS_MAC)
00190
00191 return true;
00192 #elif defined(USE_QSYSTEMTRAYICON)
00193
00194 return QSystemTrayIcon::isSystemTrayAvailable();
00195 #else
00196
00197
00198 return true;
00199 #endif
00200 }
00201
00202
00203
00204 void
00205 MainWindow::shutdown()
00206 {
00207 if (_torControl->isVidaliaRunningTor()) {
00208
00209 _torControl->stop();
00210 }
00211
00212
00213 QObject::disconnect(_torControl, 0, 0, 0);
00214
00215
00216 QCoreApplication::quit();
00217 }
00218
00219
00220
00221
00222 void
00223 MainWindow::close()
00224 {
00225 if (_torControl->isVidaliaRunningTor()) {
00226
00227
00228
00229 ServerSettings settings(_torControl);
00230 if (_torControl->isConnected() && settings.isServerEnabled()) {
00231 connect(_torControl, SIGNAL(stopped()), this, SLOT(shutdown()));
00232 if (!stop())
00233 QObject::disconnect(_torControl, SIGNAL(stopped()), this, SLOT(shutdown()));
00234 return;
00235 }
00236 }
00237
00238 shutdown();
00239 }
00240
00241
00242
00243 void
00244 MainWindow::createActions()
00245 {
00246 _startStopAct = new QAction(QIcon(IMG_START_TOR_16), tr("Start Tor"), this);
00247 connect(_startStopAct, SIGNAL(triggered()), this, SLOT(start()));
00248
00249 _exitAct = new QAction(QIcon(IMG_EXIT), tr("Exit"), this);
00250 connect(_exitAct, SIGNAL(triggered()), this, SLOT(close()));
00251
00252 _bandwidthAct = new QAction(QIcon(IMG_BWGRAPH), tr("Bandwidth Graph"), this);
00253 connect(_bandwidthAct, SIGNAL(triggered()),
00254 _bandwidthGraph, SLOT(showWindow()));
00255 connect(ui.lblBandwidthGraph, SIGNAL(clicked()),
00256 _bandwidthGraph, SLOT(showWindow()));
00257
00258 _messageAct = new QAction(QIcon(IMG_MESSAGELOG), tr("Message Log"), this);
00259 connect(_messageAct, SIGNAL(triggered()),
00260 _messageLog, SLOT(showWindow()));
00261 connect(ui.lblMessageLog, SIGNAL(clicked()),
00262 _messageLog, SLOT(showWindow()));
00263
00264 _networkAct = new QAction(QIcon(IMG_NETWORK), tr("Network Map"), this);
00265 connect(_networkAct, SIGNAL(triggered()),
00266 _netViewer, SLOT(showWindow()));
00267 connect(ui.lblViewNetwork, SIGNAL(clicked()),
00268 _netViewer, SLOT(showWindow()));
00269
00270 _controlPanelAct = new QAction(QIcon(IMG_CONTROL_PANEL),
00271 tr("Control Panel"), this);
00272 connect(_controlPanelAct, SIGNAL(triggered()), this, SLOT(show()));
00273
00274 _configAct = new QAction(QIcon(IMG_CONFIG), tr("Settings"), this);
00275 connect(_configAct, SIGNAL(triggered()), this, SLOT(showConfigDialog()));
00276
00277 _aboutAct = new QAction(QIcon(IMG_ABOUT), tr("About"), this);
00278 connect(_aboutAct, SIGNAL(triggered()), this, SLOT(showAboutDialog()));
00279
00280 _helpAct = new QAction(QIcon(IMG_HELP), tr("Help"), this);
00281 connect(_helpAct, SIGNAL(triggered()), vApp, SLOT(help()));
00282 connect(ui.lblHelpBrowser, SIGNAL(clicked()), vApp, SLOT(help()));
00283
00284 _newIdentityAct = new QAction(QIcon(IMG_IDENTITY), tr("New Identity"), this);
00285 _newIdentityAct->setEnabled(false);
00286 connect(_newIdentityAct, SIGNAL(triggered()), this, SLOT(newIdentity()));
00287 }
00288
00289
00290
00291 void
00292 MainWindow::createTrayIcon()
00293 {
00294
00295 createMenuBar();
00296
00297 _trayIcon.setContextMenu(createTrayMenu());
00298
00299 #if defined(USE_QSYSTEMTRAYICON)
00300 connect(&_trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
00301 this, SLOT(trayActivated(QSystemTrayIcon::ActivationReason)));
00302 #else
00303 connect(&_trayIcon, SIGNAL(doubleClicked()), this, SLOT(show()));
00304 #endif
00305 }
00306
00307
00308
00309 QMenu*
00310 MainWindow::createTrayMenu()
00311 {
00312 QMenu *menu = new QMenu(this);
00313 menu->addAction(_startStopAct);
00314 menu->addSeparator();
00315 menu->addAction(_bandwidthAct);
00316 menu->addAction(_messageAct);
00317 menu->addAction(_networkAct);
00318 menu->addAction(_newIdentityAct);
00319 menu->addSeparator();
00320 menu->addAction(_controlPanelAct);
00321
00322 #if !defined(Q_WS_MAC)
00323
00324
00325 menu->addAction(_configAct);
00326 menu->addAction(_helpAct);
00327 menu->addAction(_aboutAct);
00328 menu->addSeparator();
00329 menu->addAction(_exitAct);
00330 #endif
00331 return menu;
00332 }
00333
00334
00335
00336
00337 void
00338 MainWindow::createMenuBar()
00339 {
00340 #if defined(Q_WS_MAC)
00341
00342
00343
00344 _startStopAct->setShortcut(tr("Ctrl+T"));
00345 _bandwidthAct->setShortcut(tr("Ctrl+B"));
00346 _messageAct->setShortcut(tr("Ctrl+L"));
00347 _networkAct->setShortcut(tr("Ctrl+N"));
00348 _helpAct->setShortcut(tr("Ctrl+?"));
00349 _newIdentityAct->setShortcut(tr("Ctrl+I"));
00350 _controlPanelAct->setShortcut(tr("Ctrl+P"));
00351
00352
00353
00354 _exitAct->setText("exit");
00355 _configAct->setText("config");
00356 _aboutAct->setText("about");
00357
00358
00359
00360 QMenuBar *menuBar = new QMenuBar();
00361 QMenu *fileMenu = menuBar->addMenu(tr("File"));
00362 fileMenu->addAction(_exitAct);
00363
00364 QMenu *torMenu = menuBar->addMenu(tr("Tor"));
00365 torMenu->addAction(_startStopAct);
00366 torMenu->addSeparator();
00367 torMenu->addAction(_newIdentityAct);
00368
00369 QMenu *viewMenu = menuBar->addMenu(tr("View"));
00370 viewMenu->addAction(_controlPanelAct);
00371 viewMenu->addSeparator();
00372 viewMenu->addAction(_bandwidthAct);
00373 viewMenu->addAction(_messageAct);
00374 viewMenu->addAction(_networkAct);
00375 viewMenu->addAction(_configAct);
00376
00377 QMenu *helpMenu = menuBar->addMenu(tr("Help"));
00378 _helpAct->setText(tr("Vidalia Help"));
00379 helpMenu->addAction(_helpAct);
00380 helpMenu->addAction(_aboutAct);
00381
00382 setMenuBar(menuBar);
00383 #endif
00384 }
00385
00386
00387
00388 MainWindow::TorStatus
00389 MainWindow::updateTorStatus(TorStatus status)
00390 {
00391 QString statusText, actionText;
00392 QString trayIconFile, statusIconFile;
00393 TorStatus prevStatus = _status;
00394
00395 vNotice("Tor status changed from '%1' to '%2'.")
00396 .arg(toString(prevStatus)).arg(toString(status));
00397 _status = status;
00398
00399 if (status == Stopped) {
00400 statusText = tr("Tor is not running");
00401 actionText = tr("Start Tor");
00402 trayIconFile = IMG_TOR_STOPPED;
00403 statusIconFile = IMG_TOR_STOPPED_48;
00404 _startStopAct->setEnabled(true);
00405 _startStopAct->setText(actionText);
00406 _startStopAct->setIcon(QIcon(IMG_START_TOR_16));
00407 ui.lblStartStopTor->setEnabled(true);
00408 ui.lblStartStopTor->setText(actionText);
00409 ui.lblStartStopTor->setPixmap(QPixmap(IMG_START_TOR_48));
00410 ui.lblStartStopTor->setStatusTip(actionText);
00411
00412
00413
00414 QObject::disconnect(_startStopAct, SIGNAL(triggered()), this, 0);
00415 QObject::disconnect(ui.lblStartStopTor, SIGNAL(clicked()), this, 0);
00416 connect(_startStopAct, SIGNAL(triggered()), this, SLOT(start()));
00417 connect(ui.lblStartStopTor, SIGNAL(clicked()), this, SLOT(start()));
00418 } else if (status == Stopping) {
00419 if (_delayedShutdownStarted) {
00420 statusText = tr("Your Tor server is shutting down.\r\n"
00421 "Click 'Stop Tor' again to force Tor to stop now.");
00422 } else {
00423 statusText = tr("Tor is shutting down");
00424 }
00425 trayIconFile = IMG_TOR_STOPPING;
00426 statusIconFile = IMG_TOR_STOPPING_48;
00427
00428 ui.lblStartStopTor->setStatusTip(tr("Stop Tor Now"));
00429 } else if (status == Started) {
00430 statusText = tr("Tor is running");
00431 actionText = tr("Stop Tor");
00432 _startStopAct->setEnabled(true);
00433 _startStopAct->setText(actionText);
00434 _startStopAct->setIcon(QIcon(IMG_STOP_TOR_16));
00435 ui.lblStartStopTor->setEnabled(true);
00436 ui.lblStartStopTor->setText(actionText);
00437 ui.lblStartStopTor->setPixmap(QPixmap(IMG_STOP_TOR_48));
00438 ui.lblStartStopTor->setStatusTip(actionText);
00439
00440
00441
00442 QObject::disconnect(_startStopAct, SIGNAL(triggered()), this, 0);
00443 QObject::disconnect(ui.lblStartStopTor, SIGNAL(clicked()), this, 0);
00444 connect(_startStopAct, SIGNAL(triggered()), this, SLOT(stop()));
00445 connect(ui.lblStartStopTor, SIGNAL(clicked()), this, SLOT(stop()));
00446 } else if (status == Starting) {
00447 statusText = tr("Tor is starting up");
00448 trayIconFile = IMG_TOR_STARTING;
00449 statusIconFile = IMG_TOR_STARTING_48;
00450 _startStopAct->setEnabled(false);
00451 ui.lblStartStopTor->setText(tr("Starting Tor"));
00452 ui.lblStartStopTor->setEnabled(false);
00453 ui.lblStartStopTor->setStatusTip(statusText);
00454 ui.lblStartStopTor->setAnimation(QPixmap(ANIM_PROCESS_WORKING));
00455 } else if (status == Authenticated) {
00456 trayIconFile = IMG_TOR_RUNNING;
00457 statusIconFile = IMG_TOR_RUNNING_48;
00458 }
00459
00460
00461 if (!trayIconFile.isEmpty()) {
00462 #if defined(USE_QSYSTEMTRAYICON)
00463 _trayIcon.setIcon(QIcon(trayIconFile));
00464 #else
00465 _trayIcon.setIcon(trayIconFile);
00466 #endif
00467 }
00468
00469 if (!statusIconFile.isEmpty())
00470 ui.lblTorStatusImg->setPixmap(QPixmap(statusIconFile));
00471 if (!statusText.isEmpty()) {
00472 _trayIcon.setToolTip(statusText);
00473 ui.lblTorStatus->setText(statusText);
00474 }
00475 return prevStatus;
00476 }
00477
00478 #if defined(USE_QSYSTEMTRAYICON)
00479
00480 void
00481 MainWindow::trayActivated(QSystemTrayIcon::ActivationReason reason)
00482 {
00483 if (reason == QSystemTrayIcon::DoubleClick)
00484 show();
00485 }
00486 #endif
00487
00488
00489 void
00490 MainWindow::toggleShowOnStartup(bool checked)
00491 {
00492 VidaliaSettings settings;
00493 settings.setShowMainWindowAtStart(checked);
00494 }
00495
00496
00497
00498 void
00499 MainWindow::start()
00500 {
00501 updateTorStatus(Starting);
00502
00503
00504
00505
00506 _isIntentionalExit = true;
00507
00508 _torControl->start();
00509 }
00510
00511
00512
00513 void
00514 MainWindow::startFailed(QString errmsg)
00515 {
00516
00517
00518
00519 Q_UNUSED(errmsg);
00520
00521 updateTorStatus(Stopped);
00522
00523
00524 int response = VMessageBox::warning(this, tr("Error Starting Tor"),
00525 tr("Vidalia was unable to start Tor. Check your settings "
00526 "to ensure the correct name and location of your Tor "
00527 "executable is specified."),
00528 VMessageBox::ShowSettings|VMessageBox::Default,
00529 VMessageBox::Cancel|VMessageBox::Escape,
00530 VMessageBox::Help);
00531
00532 if (response == VMessageBox::ShowSettings) {
00533
00534
00535 showConfigDialog();
00536 } else if (response == VMessageBox::Help) {
00537
00538 Vidalia::help("troubleshooting.start");
00539 }
00540 }
00541
00542
00543
00544 void
00545 MainWindow::started()
00546 {
00547 updateTorStatus(Started);
00548
00549
00550
00551 _isIntentionalExit = false;
00552
00553 _delayedShutdownStarted = false;
00554
00555 _isVidaliaRunningTor = _torControl->isVidaliaRunningTor();
00556
00557 _torControl->connect();
00558 }
00559
00560
00561
00562 void
00563 MainWindow::connectFailed(QString errmsg)
00564 {
00565 updateTorStatus(Disconnected);
00566
00567
00568 int response = VMessageBox::warning(this,
00569 tr("Error Connecting to Tor"), p(errmsg),
00570 VMessageBox::Ok|VMessageBox::Default|VMessageBox::Escape,
00571 VMessageBox::Retry, VMessageBox::Help);
00572
00573
00574 if (response == VMessageBox::Retry) {
00575
00576 _torControl->connect();
00577 } else {
00578
00579 if (response == VMessageBox::Help)
00580 Vidalia::help("troubleshooting.connect");
00581
00582 _torControl->stop();
00583 }
00584 }
00585
00586
00587 bool
00588 MainWindow::stop()
00589 {
00590 ServerSettings server(_torControl);
00591 QString errmsg;
00592 TorStatus prevStatus;
00593 bool rc;
00594
00595
00596
00597 if (server.isServerEnabled() && !_delayedShutdownStarted) {
00598
00599 int response = VMessageBox::question(this, tr("Server is Enabled"),
00600 tr("You are currently running a Tor server. "
00601 "Terminating your server will interrupt any "
00602 "open connections from clients.\n\n"
00603 "Would you like to shutdown gracefully and "
00604 "give clients time to find a new server?"),
00605 VMessageBox::Yes|VMessageBox::Default,
00606 VMessageBox::No,
00607 VMessageBox::Cancel|VMessageBox::Escape);
00608 if (response == VMessageBox::Yes)
00609 _delayedShutdownStarted = true;
00610 else if (response == VMessageBox::Cancel)
00611 return false;
00612 }
00613
00614 prevStatus = updateTorStatus(Stopping);
00615 if (_delayedShutdownStarted) {
00616
00617 rc = _torControl->signal(TorSignal::Shutdown, &errmsg);
00618 } else {
00619
00620 _isIntentionalExit = true;
00621 rc = _torControl->stop(&errmsg);
00622 }
00623
00624 if (!rc) {
00625
00626 int response = VMessageBox::warning(this, tr("Error Stopping Tor"),
00627 p(tr("Vidalia was unable to stop Tor.")) + p(errmsg),
00628 VMessageBox::Ok|VMessageBox::Default|VMessageBox::Escape,
00629 VMessageBox::Help);
00630
00631 if (response == VMessageBox::Help) {
00632
00633 Vidalia::help("troubleshooting.stop");
00634 }
00635
00636 _isIntentionalExit = false;
00637 _delayedShutdownStarted = false;
00638 updateTorStatus(prevStatus);
00639 }
00640 return rc;
00641 }
00642
00643
00644
00645 void
00646 MainWindow::stopped(int exitCode, QProcess::ExitStatus exitStatus)
00647 {
00648 updateTorStatus(Stopped);
00649
00650
00651
00652 if (!_isIntentionalExit) {
00653
00654
00655
00656 if (exitStatus == QProcess::CrashExit || exitCode != 0) {
00657 int ret = VMessageBox::warning(this, tr("Tor Exited"),
00658 tr("Vidalia detected that Tor exited unexpectedly.\n\n"
00659 "Please check the message log for indicators "
00660 "about what happened to Tor before it exited."),
00661 VMessageBox::Ok|VMessageBox::Escape,
00662 VMessageBox::ShowLog|VMessageBox::Default,
00663 VMessageBox::Help);
00664 if (ret == VMessageBox::ShowLog)
00665 _messageLog->showWindow();
00666 else if (ret == VMessageBox::Help)
00667 Vidalia::help("troubleshooting.torexited");
00668 }
00669 }
00670 }
00671
00672
00673 void
00674 MainWindow::connected()
00675 {
00676 updateTorStatus(Connected);
00677 authenticate();
00678 }
00679
00680
00681 void
00682 MainWindow::disconnect()
00683 {
00684 updateTorStatus(Disconnecting);
00685 _torControl->disconnect();
00686 }
00687
00688
00689 void
00690 MainWindow::disconnected()
00691 {
00692 updateTorStatus(Disconnected);
00693 if (!_isVidaliaRunningTor) {
00694
00695
00696 updateTorStatus(Stopped);
00697 }
00698
00699
00700 _newIdentityAct->setEnabled(false);
00701 ui.lblNewIdentity->setEnabled(false);
00702 _isVidaliaRunningTor = false;
00703 }
00704
00705
00706
00707
00708 bool
00709 MainWindow::authenticate()
00710 {
00711 TorSettings::AuthenticationMethod authMethod;
00712 TorSettings settings;
00713 ProtocolInfo pi;
00714
00715 updateTorStatus(Authenticating);
00716
00717 authMethod = settings.getAuthenticationMethod();
00718 pi = _torControl->protocolInfo();
00719 if (!pi.isEmpty()) {
00720 QStringList authMethods = pi.authMethods();
00721 if (authMethods.contains("COOKIE"))
00722 authMethod = TorSettings::CookieAuth;
00723 else if (authMethods.contains("HASHEDPASSWORD"))
00724 authMethod = TorSettings::PasswordAuth;
00725 else if (authMethods.contains("NULL"))
00726 authMethod = TorSettings::NullAuth;
00727 }
00728
00729 if (authMethod == TorSettings::CookieAuth) {
00730
00731 QByteArray cookie = loadControlCookie(pi.cookieAuthFile());
00732 while (cookie.isEmpty()) {
00733
00734 int ret = VMessageBox::question(this,
00735 tr("Cookie Authentication Required"),
00736 p(tr("Tor requires Vidalia to send the contents of an "
00737 "authentication cookie, but Vidalia was unable to "
00738 "find one."))
00739 + p(tr("Would you like to browse for the file "
00740 "'control_auth_cookie' yourself?")),
00741 VMessageBox::Browse|VMessageBox::Default,
00742 VMessageBox::Cancel|VMessageBox::Escape);
00743
00744 if (ret == VMessageBox::Cancel)
00745 goto cancel;
00746 QString cookieDir = QFileDialog::getOpenFileName(this,
00747 tr("Tor Data Directory"),
00748 settings.getDataDirectory(),
00749 tr("Tor Control Cookie (control_auth_cookie)"));
00750 if (cookieDir.isEmpty())
00751 goto cancel;
00752 cookieDir = QFileInfo(cookieDir).absolutePath();
00753 cookie = loadControlCookie(cookieDir);
00754 }
00755 vNotice("Authenticating using 'cookie' authentication.");
00756 return _torControl->authenticate(cookie);
00757 } else if (authMethod == TorSettings::PasswordAuth) {
00758
00759 vNotice("Authenticating using 'hashed password' authentication.");
00760 QString password = settings.getControlPassword();
00761 return _torControl->authenticate(password);
00762 }
00763
00764 vNotice("Authenticating using 'null' authentication.");
00765 return _torControl->authenticate(QString(""));
00766
00767 cancel:
00768 vWarn("Cancelling control authentication attempt.");
00769 if (_isVidaliaRunningTor)
00770 stop();
00771 else
00772 disconnect();
00773 return false;
00774 }
00775
00776
00777 void
00778 MainWindow::authenticated()
00779 {
00780 ServerSettings serverSettings(_torControl);
00781 QString errmsg;
00782
00783 updateTorStatus(Authenticated);
00784
00785
00786 _newIdentityAct->setEnabled(true);
00787 ui.lblNewIdentity->setEnabled(true);
00788
00789
00790 if (!_torControl->setEvents(&errmsg))
00791 VMessageBox::warning(this, tr("Error Registering for Events"),
00792 p(tr("Vidalia was unable to register for Tor events. "
00793 "Many of Vidalia's features may be unavailable."))
00794 + p(errmsg),
00795 VMessageBox::Ok);
00796
00797
00798
00799 if (serverSettings.changedSinceLastApply()) {
00800 if (!serverSettings.apply(&errmsg)) {
00801 int ret = VMessageBox::warning(this,
00802 tr("Error Applying Server Settings"),
00803 p(tr("Vidalia was unable to apply your server's settings."))
00804 + p(errmsg),
00805 VMessageBox::Ok|VMessageBox::Escape,
00806 VMessageBox::ShowSettings|VMessageBox::Default,
00807 VMessageBox::ShowLog);
00808
00809 if (ret == VMessageBox::ShowSettings) {
00810
00811 showConfigDialog(ConfigDialog::Server);
00812 } else if (ret == VMessageBox::ShowLog) {
00813
00814 _messageLog->showWindow();
00815 }
00816 }
00817 }
00818 }
00819
00820
00821
00822 void
00823 MainWindow::authenticationFailed(QString errmsg)
00824 {
00825 bool retry = false;
00826
00827 vWarn("Authentication failed: %1").arg(errmsg);
00828
00829
00830 if (errmsg.contains("Password did not match")) {
00831
00832 QString password = QInputDialog::getText(this,
00833 tr("Password Authentication Required"),
00834 tr("Please enter your control password:"),
00835 QLineEdit::Password);
00836 if (!password.isEmpty()) {
00837 TorSettings settings;
00838 settings.setAuthenticationMethod(TorSettings::PasswordAuth);
00839 settings.setControlPassword(password);
00840 retry = true;
00841 }
00842 } else {
00843
00844 int ret = VMessageBox::warning(this,
00845 tr("Error Authenticating to Tor"),
00846 p(tr("Vidalia was unable to authenticate to Tor. "
00847 "(%1)").arg(errmsg)) +
00848 p(tr("Please check your control port authentication "
00849 "settings.")),
00850 VMessageBox::ShowSettings|VMessageBox::Default,
00851 VMessageBox::Cancel|VMessageBox::Escape);
00852
00853 if (ret == VMessageBox::ShowSettings)
00854 showConfigDialog(ConfigDialog::Advanced);
00855 }
00856
00857 if (_torControl->isRunning() && _isVidaliaRunningTor)
00858 stop();
00859 else if (_torControl->isConnected())
00860 disconnect();
00861 if (retry)
00862 start();
00863 }
00864
00865
00866
00867
00868
00869
00870 QByteArray
00871 MainWindow::loadControlCookie(QString cookiePath)
00872 {
00873 QFile authCookie;
00874 QStringList pathList;
00875
00876 if (!cookiePath.isEmpty()) {
00877 pathList << cookiePath;
00878 } else {
00879
00880 TorSettings settings;
00881 QString dataDir = settings.getDataDirectory();
00882 if (!dataDir.isEmpty())
00883 pathList << dataDir;
00884
00885 #if defined(Q_WS_WIN)
00886 pathList << expand_filename("%APPDATA%\\Tor");
00887 #else
00888 pathList << expand_filename("~/.tor");
00889 #endif
00890 }
00891
00892
00893 foreach (QString path, pathList) {
00894 QString cookieFile = QFileInfo(path).isFile() ?
00895 path : path + "/control_auth_cookie";
00896 vDebug("Checking for authentication cookie in '%1'").arg(cookieFile);
00897 if (!QFileInfo(cookieFile).exists())
00898 continue;
00899
00900 authCookie.setFileName(cookieFile);
00901 if (authCookie.open(QIODevice::ReadOnly)) {
00902 vInfo("Reading authentication cookie from '%1'").arg(cookieFile);
00903 return authCookie.readAll();
00904 } else {
00905 vWarn("Couldn't open cookie file '%1': %2")
00906 .arg(cookieFile).arg(authCookie.errorString());
00907 }
00908 }
00909 vWarn("Couldn't find a readable authentication cookie.");
00910 return QByteArray();
00911 }
00912
00913
00914 void
00915 MainWindow::showAboutDialog()
00916 {
00917 static AboutDialog *aboutDialog = 0;
00918 if (!aboutDialog)
00919 aboutDialog = new AboutDialog(this);
00920 aboutDialog->showWindow();
00921 }
00922
00923
00924
00925 void
00926 MainWindow::showConfigDialog(ConfigDialog::Page page)
00927 {
00928 static ConfigDialog *configDialog = 0;
00929 if (!configDialog)
00930 configDialog = new ConfigDialog(this);
00931 configDialog->showWindow(page);
00932 }
00933
00934
00935 void
00936 MainWindow::showServerConfigDialog()
00937 {
00938 showConfigDialog(ConfigDialog::Server);
00939 }
00940
00941
00942 void
00943 MainWindow::newIdentity()
00944 {
00945 QString errmsg;
00946
00947
00948
00949
00950 if (_torControl->signal(TorSignal::NewNym, &errmsg)) {
00951
00952 QString title = tr("New Identity");
00953 QString message = tr("All subsequent connections will "
00954 "appear to be different than your "
00955 "old connections.");
00956
00957
00958 _newIdentityAct->setEnabled(false);
00959 ui.lblNewIdentity->setEnabled(false);
00960 QTimer::singleShot(MIN_NEWIDENTITY_INTERVAL,
00961 this, SLOT(enableNewIdentity()));
00962
00963 #if defined(USE_QSYSTEMTRAYICON)
00964
00965
00966
00967 # if defined(Q_WS_WIN)
00968 if (QSystemTrayIcon::supportsMessages() &&
00969 QSysInfo::WindowsVersion > QSysInfo::WV_2000)
00970 # else
00971 if (QSystemTrayIcon::supportsMessages())
00972 # endif
00973 _trayIcon.showMessage(title, message, QSystemTrayIcon::Information);
00974 else
00975 VMessageBox::information(this, title, message, VMessageBox::Ok);
00976 #else
00977
00978 VMessageBox::information(this, title, message, VMessageBox::Ok);
00979 #endif
00980 } else {
00981
00982 VMessageBox::warning(this,
00983 tr("Failed to Create New Identity"), errmsg, VMessageBox::Ok);
00984 }
00985 }
00986
00987
00988
00989 void
00990 MainWindow::enableNewIdentity()
00991 {
00992 if (_torControl->isConnected()) {
00993 _newIdentityAct->setEnabled(true);
00994 ui.lblNewIdentity->setEnabled(true);
00995 }
00996 }
00997
00998
00999 QString
01000 MainWindow::toString(TorStatus status)
01001 {
01002 switch (status) {
01003
01004
01005 case Unset: return "Unset";
01006 case Stopping: return "Stopping";
01007 case Stopped: return "Stopped";
01008 case Starting: return "Starting";
01009 case Started: return "Started";
01010 case Connecting: return "Connecting";
01011 case Connected: return "Connected";
01012 case Disconnecting: return "Disconnecting";
01013 case Disconnected: return "Disconnected";
01014 case Authenticating: return "Authenticating";
01015 case Authenticated: return "Authenticated";
01016 default: break;
01017 }
01018 return "Unknown";
01019 }
01020