Vidalia 0.3.1
MainWindow.cpp
Go to the documentation of this file.
1/*
2** This file is part of Vidalia, and is subject to the license terms in the
3** LICENSE file, found in the top level directory of this distribution. If you
4** did not receive the LICENSE file with this file, you may obtain it from the
5** Vidalia source package distributed by the Vidalia Project at
6** http://www.torproject.org/projects/vidalia.html. No part of Vidalia,
7** including this file, may be copied, modified, propagated, or distributed
8** except according to the terms described in the LICENSE file.
9*/
10
11/*
12** \file MainWindow.cpp
13** \brief Main (hidden) window. Creates tray menu and child windows
14**
15** Implements the main window. The main window is a hidden window that serves
16** as the parent of the tray icon and popup menu, as well as other application
17** dialogs.
18*/
19
20#include "MainWindow.h"
21#include "Vidalia.h"
23#include "VMessageBox.h"
24#include "TorSettings.h"
25#include "ServerSettings.h"
26#include "AboutDialog.h"
27#include "HelpBrowser.h"
28#include "VAttachButton.h"
29#ifdef USE_AUTOUPDATE
31#endif
32
33#include "ProtocolInfo.h"
34
35#include "net.h"
36#include "file.h"
37#include "html.h"
38#include "stringutil.h"
39#include "procutil.h"
40
41#include "PluginWrapper.h"
42#include "DebugDialog.h"
43
44#include <QtGui>
45
46#ifdef Q_WS_MAC
47#include <Carbon/Carbon.h>
48#endif
49
50#define IMG_BWGRAPH ":/images/16x16/utilities-system-monitor.png"
51#define IMG_CONTROL_PANEL ":/images/16x16/system-run.png"
52#define IMG_MESSAGELOG ":/images/16x16/format-justify-fill.png"
53#define IMG_CONFIG ":/images/16x16/preferences-system.png"
54#define IMG_IDENTITY ":/images/16x16/view-media-artist.png"
55#define IMG_HELP ":/images/16x16/system-help.png"
56#define IMG_ABOUT ":/images/16x16/help-about.png"
57#define IMG_EXIT ":/images/16x16/application-exit.png"
58#define IMG_NETWORK ":/images/16x16/applications-internet.png"
59
60#define IMG_START_TOR_16 ":/images/16x16/media-playback-start.png"
61#define IMG_STOP_TOR_16 ":/images/16x16/media-playback-stop.png"
62#define IMG_START_TOR_48 ":/images/48x48/media-playback-start.png"
63#define IMG_STOP_TOR_48 ":/images/48x48/media-playback-stop.png"
64#define IMG_TOR_STOPPED_48 ":/images/48x48/tor-off.png"
65#define IMG_TOR_RUNNING_48 ":/images/48x48/tor-on.png"
66#define IMG_TOR_STARTING_48 ":/images/48x48/tor-starting.png"
67#define IMG_TOR_STOPPING_48 ":/images/48x48/tor-stopping.png"
68
69/* Decide which of our four sets of tray icons to use. */
70#if defined(Q_WS_WIN)
71/* QSystemTrayIcon on Windows wants 16x16 .png files */
72#define IMG_TOR_STOPPED ":/images/16x16/tor-off.png"
73#define IMG_TOR_RUNNING ":/images/16x16/tor-on.png"
74#define IMG_TOR_STARTING ":/images/16x16/tor-starting.png"
75#define IMG_TOR_STOPPING ":/images/16x16/tor-stopping.png"
76#elif defined(Q_WS_MAC)
77/* On Mac, the dock icons look best at 128x128, otherwise they get blurry
78 * if resized from a smaller image */
79#define IMG_TOR_STOPPED ":/images/128x128/tor-off.png"
80#define IMG_TOR_RUNNING ":/images/128x128/tor-on.png"
81#define IMG_TOR_STARTING ":/images/128x128/tor-starting.png"
82#define IMG_TOR_STOPPING ":/images/128x128/tor-stopping.png"
83void qt_mac_set_dock_menu(QMenu *menu);
84#else
85/* On X11, we just use always the 22x22 .png files */
86#define IMG_TOR_STOPPED ":/images/22x22/tor-off.png"
87#define IMG_TOR_RUNNING ":/images/22x22/tor-on.png"
88#define IMG_TOR_STARTING ":/images/22x22/tor-starting.png"
89#define IMG_TOR_STOPPING ":/images/22x22/tor-stopping.png"
90#endif
91
92/** Only allow 'New Identity' to be clicked once every 10 seconds. */
93#define MIN_NEWIDENTITY_INTERVAL (10*1000)
94
95/* Startup progress milestones */
96#define STARTUP_PROGRESS_STARTING 0
97#define STARTUP_PROGRESS_CONNECTING 10
98#define STARTUP_PROGRESS_AUTHENTICATING 20
99#define STARTUP_PROGRESS_BOOTSTRAPPING 30
100#define STARTUP_PROGRESS_CIRCUITBUILD 75
101#define STARTUP_PROGRESS_MAXIMUM (STARTUP_PROGRESS_BOOTSTRAPPING+100)
102
103/** Default constructor. It installs an icon in the system tray area and
104 * creates the popup menu associated with that icon. */
106: VidaliaWindow("MainWindow")
107{
108 _startedWithPrevious = false;
109
110 /* Create a new TorControl object, used to communicate with Tor */
112
113 _engine = new PluginEngine();
114
115 _dummy = new QAction(tr("No dettached tabs"), this);
116
117 createGUI();
119
120 /* Start with Tor initially stopped */
121 _status = Unset;
122 _isVidaliaRunningTor = false;
124
125#if defined(Q_WS_MAC)
126 VidaliaSettings settings;
127 /* Display OSX dock icon if icon preference is not set to "Tray Only" */
128 if (settings.getIconPref() != VidaliaSettings::Tray) {
129 ProcessSerialNumber psn = { 0, kCurrentProcess };
130 TransformProcessType(&psn, kProcessTransformToForegroundApplication);
131 }
132 /* Vidalia launched in background (LSUIElement=true). Bring to foreground. */
134#endif
135}
136
137/** Destructor */
139{
140 delete _engine;
141}
142
143/** Calls the different methods that will handle the GUI "creation".
144 * It's called once at the MainWindow creation. */
145void
147{
148 ui.setupUi(this);
153
154 // We need to create this tab at the beggining
155 // and we must specify the statusBar
156 _messageLog = new MessageLog(this->statusBar());
157 _graph = new BandwidthGraph(this->statusBar());
158
160 ui.tabWidget->pinTab(0);
161}
162
163/** Creates the actions used in toolbars and menu */
164void
166{
167 _actionShowControlPanel = new QAction(QIcon(IMG_CONTROL_PANEL), tr("Control Panel"), this);
168 _actionRestartTor = new QAction(tr("Restart"), this);
169 _actionReloadConfig = new QAction(tr("Reload Tor's config"), this);
170 _actionNewIdentity = new QAction(QIcon(IMG_IDENTITY), tr("New Identity"), this);
171 _actionStatus = new QAction(QIcon(IMG_CONTROL_PANEL), tr("Status"), this);
172 _actionNetworkMap = new QAction(QIcon(IMG_NETWORK), tr("Network Map"), this);
173 _actionMessageLog= new QAction(QIcon(IMG_MESSAGELOG), tr("Message Log"), this);
174 _actionBandwidthGraph = new QAction(QIcon(IMG_BWGRAPH), tr("Bandwidth Graph"), this);
175 _actionConfigure = new QAction(QIcon(IMG_CONFIG), tr("Settings"), this);
176 _actionVidaliaHelp = new QAction(QIcon(IMG_HELP), tr("Help"), this);
177 _actionAbout = new QAction(QIcon(IMG_ABOUT), tr("About"), this);
178 _actionStartStopTor = new QAction(QIcon(IMG_START_TOR_16), tr("Start Tor"), this);
179 _actionExit = new QAction(QIcon(IMG_EXIT), tr("Exit"), this);
180 _actionDebugDialog = new QAction(tr("Debug output"), this);
181}
182
183/** Creates the menu bar */
184void
186{
187 _reattachMenu.setTitle(tr("Reattach tabs"));
188
189 QMenuBar *menu = menuBar();
190 menu->clear();
191
192 QMenu *torMenu = menu->addMenu(tr("Tor"));
193 torMenu->addAction(_actionStartStopTor);
194 torMenu->addAction(_actionRestartTor);
195#if !defined(Q_WS_WIN)
196 torMenu->addAction(_actionReloadConfig);
197#endif
198 torMenu->addSeparator();
199 torMenu->addAction(_actionExit);
200
201 QMenu *actionsMenu = menu->addMenu(tr("Actions"));
202 actionsMenu->addAction(_actionNewIdentity);
203
204 QMenu *viewMenu = menu->addMenu(tr("View"));
205 viewMenu->addAction(_actionStatus);
206 viewMenu->addAction(_actionNetworkMap);
207 viewMenu->addAction(_actionMessageLog);
208 viewMenu->addAction(_actionBandwidthGraph);
209 viewMenu->addSeparator();
210 viewMenu->addAction(_actionConfigure);
211
212 QMenu *pluginsMenu = menu->addMenu(tr("Plugins"));
213 foreach(QAction *action, _engine->getAllActions()) {
214 pluginsMenu->addAction(action);
215 }
216 pluginsMenu->addSeparator();
217 pluginsMenu->addAction(_actionDebugDialog);
218
219 menu->addMenu(&_reattachMenu);
220 _reattachMenu.addAction(_dummy);
221 _dummy->setEnabled(false);
222
223 QMenu *helpMenu = menu->addMenu(tr("Help"));
224 helpMenu->addAction(_actionVidaliaHelp);
225 helpMenu->addSeparator();
226 helpMenu->addAction(_actionAbout);
227}
228
229/** Creates the main toolbar */
230void
232{
233 QToolBar *tool = ui.toolBar;
234
235 tool->addAction(_actionStartStopTor);
236 tool->addAction(_actionNewIdentity);
237 tool->addAction(_actionConfigure);
238
239 tool->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
240}
241
242/** Creates a QMenu object that contains QActions which compose the system
243 * tray menu. */
244QMenu*
246{
247 QMenu *menu = new QMenu(this);
248 menu->addAction(_actionStartStopTor);
249 menu->addSeparator();
250 menu->addAction(_actionBandwidthGraph);
251 menu->addAction(_actionMessageLog);
252 menu->addAction(_actionNetworkMap);
253 menu->addAction(_actionNewIdentity);
254 menu->addSeparator();
255 menu->addAction(_actionShowControlPanel);
256
257 menu->addMenu(&_reattachMenu);
258
259#if !defined(Q_WS_MAC)
260 /* These aren't added to the dock menu on Mac, since they are in the
261 * standard Mac locations in the menu bar. */
262 menu->addAction(_actionConfigure);
263 menu->addAction(_actionVidaliaHelp);
264 menu->addAction(_actionAbout);
265 menu->addSeparator();
266 menu->addAction(_actionExit);
267#endif
268 return menu;
269}
270
271/** Called when tor detects a problem with the system clock */
272void
273MainWindow::clockSkewed(int skew, const QString &source)
274{
275 if (source.startsWith("OR:", Qt::CaseInsensitive)) {
276 // Tor versions 0.2.1.19 and earlier, and 0.2.2.1 and earlier, throw
277 // this message a little too liberally in this case.
278 quint32 torVersion = Vidalia::torControl()->getTorVersion();
279 if (torVersion <= 0x00020113)
280 return;
281 QString str = Vidalia::torControl()->getTorVersionString();
282 if (str.startsWith("0.2.2.") && torVersion <= 0x00020201)
283 return;
284 }
285
286 _trayIcon.showMessage(tr("Your clock is wrong"),
287 tr("Your computer's clock is wrong, tor may not work as "
288 "expected. Please check the Message Log for more information."));
289}
290
291
292/** Creates a tray icon with a context menu and adds it to the system
293 * notification area. On Mac, we also set up an application menubar. */
294void
296{
297 QMenu *menu = createTrayMenu();
298
299 /* Add the menu it to the tray icon */
300 _trayIcon.setContextMenu(menu);
301
302 connect(&_trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
303 this, SLOT(trayIconActivated(QSystemTrayIcon::ActivationReason)));
304
305#if defined(Q_WS_MAC)
306 qt_mac_set_dock_menu(menu);
307#endif
308
309 VidaliaSettings settings;
310
313 show();
314 _trayIcon.show();
315}
316
317void
319{
320 if (visible) {
321 /* In Gnome, will hide buttons if Vidalia is run on startup. */
322 if (!QSystemTrayIcon::isSystemTrayAvailable()) {
323 /* Don't let people hide the main window, since that's all they have. */
325 /* Causes window to not appear in Enlightenment. */
326 //setMinimumHeight(height()-ui.btnHide->height());
327 //setMaximumHeight(height()-ui.btnHide->height());
328 }
329 }
331}
332
333/** Respond to a double-click on the tray icon by opening the Control Panel
334 * window. */
335void
336MainWindow::trayIconActivated(QSystemTrayIcon::ActivationReason reason)
337{
338 if (reason == QSystemTrayIcon::DoubleClick)
339 setVisible(!isVisible());
340}
341
342void
344{
346
347 _actionShowControlPanel->setText(tr("Control Panel"));
348 _actionRestartTor->setText(tr("Restart"));
349 _actionReloadConfig->setText(tr("Reload Tor's config"));
350 _actionConfigure->setText(tr("Settings"));
351
352 if (_status == Stopped) {
353 _actionStartStopTor->setText(tr("Start Tor"));
354 } else if (_status == Starting) {
355 _actionStartStopTor->setText(tr("Starting Tor"));
356 } else {
357 _actionStartStopTor->setText(tr("Stop Tor"));
358 }
359
360 _actionBandwidthGraph->setText(tr("Bandwidth Graph"));
361 _actionMessageLog->setText(tr("Message Log"));
362 _actionNetworkMap->setText(tr("Network Map"));
363 _actionStatus->setText(tr("Status"));
364 _actionVidaliaHelp->setText(tr("Help"));
365 _actionNewIdentity->setText(tr("New Identity"));
366
367#if !defined(Q_WS_MAC)
368 _actionAbout->setText(tr("About"));
369 _actionConfigure->setText(tr("Settings"));
370 _actionExit->setText(tr("Exit"));
371#endif
372
374 ui.retranslateUi(this);
375}
376
377void
379{
380 connect(_actionExit, SIGNAL(triggered()), this, SLOT(close()));
381 connect(_actionStartStopTor, SIGNAL(triggered()), this, SLOT(start()));
382 connect(_actionRestartTor, SIGNAL(triggered()), this, SLOT(restart()));
383 connect(_actionReloadConfig, SIGNAL(triggered()), this, SLOT(sighup()));
384 connect(_actionShowControlPanel, SIGNAL(triggered()), this, SLOT(show()));
385 connect(_actionNewIdentity, SIGNAL(triggered()), this, SLOT(newIdentity()));
386
387 connect(_actionMessageLog, SIGNAL(triggered()), this, SLOT(showMessageLogTab()));
388 connect(_actionConfigure, SIGNAL(triggered()), this, SLOT(showConfigDialog()));
389 connect(_actionBandwidthGraph, SIGNAL(triggered()), this, SLOT(showBandwidthTab()));
390 connect(_actionAbout, SIGNAL(triggered()), this, SLOT(showAboutDialog()));
391 connect(_actionVidaliaHelp, SIGNAL(triggered()), this, SLOT(showHelpDialog()));
392 connect(_actionStatus, SIGNAL(triggered()), this, SLOT(showStatusTab()));
393 connect(_actionNetworkMap, SIGNAL(triggered()), this, SLOT(showNetViewerTab()));
394
395 connect(_actionDebugDialog, SIGNAL(triggered()), this, SLOT(showDebugDialog()));
396
397 /* Catch signals when the application is running or shutting down */
398 connect(vApp, SIGNAL(running()), this, SLOT(running()));
399 connect(vApp, SIGNAL(aboutToQuit()), this, SLOT(aboutToQuit()));
400
401 connect(_torControl, SIGNAL(started()), this, SLOT(started()));
402 connect(_torControl, SIGNAL(startFailed(QString)),
403 this, SLOT(startFailed(QString)));
404 connect(_torControl, SIGNAL(stopped(int, QProcess::ExitStatus)),
405 this, SLOT(stopped(int, QProcess::ExitStatus)));
406 connect(_torControl, SIGNAL(connected()), this, SLOT(connected()));
407 connect(_torControl, SIGNAL(disconnected()), this, SLOT(disconnected()));
408 connect(_torControl, SIGNAL(connectFailed(QString)),
409 this, SLOT(connectFailed(QString)));
410 connect(_torControl, SIGNAL(authenticated()), this, SLOT(authenticated()));
411 connect(_torControl, SIGNAL(authenticationFailed(QString)),
412 this, SLOT(authenticationFailed(QString)));
413 connect(_torControl, SIGNAL(clockSkewed(int, QString)),
414 this, SLOT(clockSkewed(int, QString)));
415
418 QString, QStringList)),
420 QString, QStringList)));
421
426 this, SLOT(circuitEstablished()));
427 connect(_torControl, SIGNAL(dangerousPort(quint16, bool)),
428 this, SLOT(warnDangerousPort(quint16, bool)));
429
430 connect(ui.tabWidget, SIGNAL(tabCloseRequested(int)),
431 this, SLOT(handleCloseTab(int)));
432
433#if defined(USE_AUTOUPDATE)
434 /* Create a timer used to remind us to check for software updates */
435 connect(&_updateTimer, SIGNAL(timeout()), this, SLOT(checkForUpdates()));
436
437 /* Also check for updates in the foreground when the user clicks the
438 * "Check Now" button in the config dialog. */
439 connect(_configDialog, SIGNAL(checkForUpdates()),
440 this, SLOT(checkForUpdatesWithUi()));
441
442 /* The rest of these slots are called as the update process executes. */
443 connect(&_updateProcess, SIGNAL(downloadProgress(QString,int,int)),
444 &_updateProgressDialog, SLOT(setDownloadProgress(QString,int,int)));
445 connect(&_updateProcess, SIGNAL(updatesAvailable(UpdateProcess::BundleInfo,PackageList)),
446 this, SLOT(updatesAvailable(UpdateProcess::BundleInfo,PackageList)));
447 connect(&_updateProcess, SIGNAL(updatesInstalled(int)),
448 this, SLOT(updatesInstalled(int)));
449 connect(&_updateProcess, SIGNAL(installUpdatesFailed(QString)),
450 this, SLOT(installUpdatesFailed(QString)));
451 connect(&_updateProgressDialog, SIGNAL(cancelUpdate()),
452 &_updateProcess, SLOT(cancel()));
453#endif
454
455#if defined(USE_MINIUPNPC)
456 /* Catch UPnP-related signals */
458 this, SLOT(upnpError(UPNPControl::UPNPError)));
459#endif
460
461 connect(_engine, SIGNAL(pluginTab(VidaliaTab *)),
462 this, SLOT(addTab(VidaliaTab *)));
463}
464
465/** Called when the application is closing, by selecting "Exit" from the tray
466 * menu. If we're running a Tor server, then ask if we want to kill Tor now,
467 * or do a delayed shutdown. */
468void
470{
472 /* If we're running a server currently, ask if we want to do a delayed
473 * shutdown. If we do, then close Vidalia only when Tor stops. Otherwise,
474 * kill Tor and bail now. */
475 ServerSettings settings(_torControl);
476 if (_torControl->isConnected() && settings.isServerEnabled()) {
477 connect(_torControl, SIGNAL(stopped()), vApp, SLOT(quit()));
478 if (!stop())
479 QObject::disconnect(_torControl, SIGNAL(stopped()), vApp, SLOT(quit()));
480 return;
481 }
482 }
483 vApp->quit();
484}
485
486/** Called when the application has started and the main event loop is
487 * running. */
488void
490{
491 VidaliaSettings settings;
492
493 if (vApp->readPasswordFromStdin()) {
494 QTextStream in(stdin);
495 in >> _controlPassword;
496 _useSavedPassword = false;
497 } else {
498 /* Initialize _useSavedPassword to true. If Tor is already running when
499 * Vidalia starts, then there is no point in generating a random password.
500 * If Tor is not already running, then this will be set according to the
501 * current configuration in the start() method.
502 */
503 _useSavedPassword = true;
504 }
505
506 if (settings.runTorAtStart()) {
507 /* If we're supposed to start Tor when Vidalia starts, then do it now */
508 start();
509 }
510
511#if defined(USE_AUTOUPDATE)
512 if (settings.isAutoUpdateEnabled()) {
513 QDateTime lastCheckedAt = settings.lastCheckedForUpdates();
514 if (UpdateProcess::shouldCheckForUpdates(lastCheckedAt)) {
515 if (settings.runTorAtStart() && ! _torControl->isCircuitEstablished()) {
516 /* We started Tor but it hasn't bootstrapped yet, so give it a bit
517 * before we decide to check for updates. If Tor manages to build a
518 * circuit before this timer times out, we will stop the timer and
519 * launch a check for updates immediately. (see circuitEstablished()).
520 */
521 _updateTimer.start(5*60*1000);
522 } else {
523 /* Initiate a background check for updates now */
524 checkForUpdates();
525 }
526 } else {
527 /* Schedule the next time to check for updates */
528 QDateTime nextCheckAt = UpdateProcess::nextCheckForUpdates(lastCheckedAt);
529 QDateTime now = QDateTime::currentDateTime().toUTC();
530
531 vInfo("Last checked for software updates at %1. Will check again at %2.")
532 .arg(lastCheckedAt.toLocalTime().toString("dd-MM-yyyy hh:mm:ss"))
533 .arg(nextCheckAt.toLocalTime().toString("dd-MM-yyyy hh:mm:ss"));
534 _updateTimer.start((nextCheckAt.toTime_t() - now.toTime_t()) * 1000);
535 }
536 }
537#endif
538}
539
540/** Terminate the Tor process if it is being run under Vidalia, disconnect all
541 * TorControl signals, and exit Vidalia. */
542void
544{
545 vNotice("Cleaning up before exiting.");
546
548 /* Kill our Tor process now */
549 _torControl->stop();
550 }
551
552 /* Disable port forwarding */
553 ServerSettings settings(_torControl);
554 settings.cleanupPortForwarding();
555
556 /* Disconnect all of the TorControl object's signals */
558}
559
560
561/** Attempts to start Tor. If Tor fails to start, then startFailed() will be
562 * called with an error message containing the reason. */
563void
565{
566 TorSettings settings;
567 QStringList args;
568
570
571 // Disable autoconfiguration if there are missing config data
572 if(settings.autoControlPort()) {
573 if(settings.getDataDirectory().isEmpty()) {
574 vWarn("Disabling ControlPort autoconfiguration. DataDirectory is empty!");
575 settings.setAutoControlPort(false);
576 }
577 }
578
579
580 /* Check if Tor is already running separately */
581 if(settings.getControlMethod() == ControlMethod::Port) {
582 if(!settings.autoControlPort() && net_test_connect(settings.getControlAddress(),
583 settings.getControlPort())) {
584 started();
585 return;
586 }
587 } else {
588 if (socket_test_connect(settings.getSocketPath())) {
589 started();
590 return;
591 }
592 }
593
594 QString torrc = settings.getTorrc();
595
596 if(settings.bootstrap()) {
597 QString boottorrc = settings.bootstrapFrom();
598 vNotice(tr("Bootstrapping torrc from %1 to %2")
599 .arg(boottorrc).arg(torrc));
600 if(QFileInfo(boottorrc).exists()) {
601 if(QFile::copy(boottorrc, torrc)) {
602 settings.setBootstrap(false);
603 }
604 }
605 }
606
607 /* Make sure the torrc we want to use really exists. */
608 if (!torrc.isEmpty()) {
609 if (!QFileInfo(torrc).exists())
610 touch_file(torrc, true);
611 args << "-f" << torrc;
612 }
613
614 /* Specify Tor's data directory, if different from the default */
615 QString dataDirectory = settings.getDataDirectory();
616 QString expDataDirectory = expand_filename(dataDirectory);
617 if (!dataDirectory.isEmpty())
618 args << "DataDirectory" << expDataDirectory;
619
620 if(settings.getControlMethod() == ControlMethod::Port) {
621 if(settings.autoControlPort()) {
622 QString portconf = QString("%1/port.conf").arg(expDataDirectory);
623 if(!QFile::remove(portconf))
624 vWarn(QString("Unable to remove %1, may be it didn't existed.").arg(portconf));
625
626 QString control_str = "auto";
627 QString socks_str = "auto";
628
629 if(!_previousControlPort.isEmpty()) {
630 control_str = _previousControlPort;
632 }
633 if(!_previousSocksPort.isEmpty()) {
634 socks_str = _previousSocksPort;
636 }
637
638 args << "ControlPort" << control_str;
639 args << "SocksPort" << socks_str;
640 args << "ControlPortWriteToFile" << QString("%1/port.conf").arg(expDataDirectory);
641 } else {
642 /* Add the intended control port value */
643 quint16 controlPort = settings.getControlPort();
644 if (controlPort)
645 args << "ControlPort" << QString::number(controlPort);
646 }
647 } else {
648 QString path = settings.getSocketPath();
649 args << "ControlSocket" << path;
650 }
651
652 args << "__OwningControllerProcess" << QString::number(QCoreApplication::applicationPid());
653
654 /* Add the control port authentication arguments */
655 switch (settings.getAuthenticationMethod()) {
657 if (! vApp->readPasswordFromStdin()) {
658 if (settings.useRandomPassword()) {
660 _useSavedPassword = false;
661 } else {
663 _useSavedPassword = true;
664 }
665 }
666 args << "HashedControlPassword"
668
669 break;
671 args << "CookieAuthentication" << "1";
672 break;
673 default:
674 args << "CookieAuthentication" << "0";
675 }
676
677 /* This doesn't get set to false until Tor is actually up and running, so we
678 * don't yell at users twice if their Tor doesn't even start, due to the fact
679 * that QProcess::stopped() is emitted even if the process didn't even
680 * start. */
681 _isIntentionalExit = true;
682 /* Kick off the Tor process */
683 _torControl->start(settings.getExecutable(), args);
684}
685
686/** Slot: Called when the Tor process is started. It will connect the control
687 * socket and set the icons and tooltips accordingly. */
688void
690{
691 TorSettings settings;
692
694
695 /* Now that Tor is running, we want to know if it dies when we didn't want
696 * it to. */
697 _isIntentionalExit = false;
698 /* We haven't started a delayed shutdown yet. */
700 /* Remember whether we started Tor or not */
702
703 if(settings.autoControlPort()) {
704 QString dataDirectory = settings.getDataDirectory();
705 QFile file(QString("%1/port.conf").arg(expand_filename(dataDirectory)));
706 int tries = 0, maxtries = 5;
707 while((!file.open(QIODevice::ReadOnly | QIODevice::Text)) and
708 (tries++ < maxtries)) {
709 vWarn(QString("This is try number: %1.").arg(tries));
710#if defined(Q_WS_WIN)
711 Sleep(1000);
712#else
713 sleep(1);
714#endif
715 }
716
717 if(tries >= maxtries) {
718 vWarn("Couldn't read port.conf file");
719 if(_torControl->isRunning()) {
720 connectFailed(tr("Vidalia can't find out how to talk to Tor because it can't access this file: %1\n\nHere's the last error message:\n %2")
721 .arg(file.fileName())
722 .arg(file.errorString()));
723 } else {
724 vWarn("Tor isn't running!");
725 connectFailed(tr("It seems Tor has stopped running since Vidalia started it.\n\nSee the Advanced Message Log for more information."));
726 }
727 return;
728 }
729
730 QTextStream in(&file);
731 if(!in.atEnd()) {
732 QString line = in.readLine();
733 QStringList parts = line.split("=");
734 if(parts.size() != 2) return;
735 if(parts[0].trimmed() != "PORT") return;
736
737 QStringList addrPort = parts[1].split(":");
738 if(addrPort.size() != 2) return;
739
740 QHostAddress addr(addrPort.at(0));
741 quint16 port = addrPort.at(1).toInt();
742 _torControl->connect(addr, port);
743 }
744
745 file.close();
746 } else {
747 /* Try to connect to Tor's control port */
748 if(settings.getControlMethod() == ControlMethod::Port)
750 settings.getControlPort());
751 else
752 _torControl->connect(settings.getSocketPath());
753 }
754 setStartupProgress(STARTUP_PROGRESS_CONNECTING, tr("Connecting to Tor"));
755}
756
757/** Disconnects the control socket and stops the Tor process. */
758bool
760{
762 QString errmsg;
763 TorStatus prevStatus;
764 bool rc;
765 VidaliaSettings settings;
766
767 /* If we're running a server, give users the option of terminating
768 * gracefully so clients have time to find new servers. */
769 if (server.isServerEnabled() && !_delayedShutdownStarted) {
770 /* Ask the user if they want to shutdown nicely. */
771 int response = VMessageBox::Yes;
772 if(!settings.rememberShutdown()) {
773 response = VMessageBox::question(this, tr("Relaying is Enabled"),
774 tr("You are currently running a relay. "
775 "Terminating your relay will interrupt any "
776 "open connections from clients.\n\n"
777 "Would you like to shutdown gracefully and "
778 "give clients time to find a new relay?"),
779 VMessageBox::Yes|VMessageBox::Default,
781 VMessageBox::Cancel|VMessageBox::Escape,
782 "Remember this answer", &settings, SETTING_REMEMBER_SHUTDOWN);
783 }
784 if (response == VMessageBox::Yes)
786 else if (response == VMessageBox::Cancel)
787 return false;
788 }
789
790 prevStatus = updateTorStatus(Stopping);
792 /* Start a delayed shutdown */
793 rc = _torControl->signal(TorSignal::Shutdown, &errmsg);
794 } else {
795 /* We want Tor to stop now, regardless of whether we're a server. */
796 _isIntentionalExit = true;
797 rc = _torControl->stop(&errmsg);
798 }
799
800 if (!rc) {
801 /* We couldn't tell Tor to stop, for some reason. */
802 int response = VMessageBox::warning(this, tr("Error Shutting Down"),
803 p(tr("Vidalia was unable to stop the Tor software."))
804 + p(errmsg),
805 VMessageBox::Ok|VMessageBox::Default|VMessageBox::Escape,
807
808 if (response == VMessageBox::Help) {
809 /* Show some troubleshooting help */
810 showHelpDialog("troubleshooting.stop");
811 }
812 /* Tor is still running since stopping failed */
813 _isIntentionalExit = false;
815 updateTorStatus(prevStatus);
816 }
817 return rc;
818}
819
820/** Slot: Called when the Tor process has exited. It will adjust the tray
821 * icons and tooltips accordingly. */
822void
823MainWindow::stopped(int exitCode, QProcess::ExitStatus exitStatus)
824{
826
827 /* If we didn't intentionally close Tor, then check to see if it crashed or
828 * if it closed itself and returned an error code. */
829 if (!_isIntentionalExit) {
830 /* A quick overview of Tor's code tells me that if it catches a SIGTERM or
831 * SIGINT, Tor will exit(0). We might need to change this warning message
832 * if this turns out to not be the case. */
833 if (exitStatus == QProcess::CrashExit || exitCode != 0) {
834 int ret = VMessageBox::warning(this, tr("Unexpected Error"),
835 tr("Vidalia detected that the Tor software exited "
836 "unexpectedly.\n\n"
837 "Please check the message log for recent "
838 "warning or error messages."),
839 VMessageBox::Ok|VMessageBox::Escape,
840 VMessageBox::ShowLog|VMessageBox::Default,
842 if (ret == VMessageBox::ShowLog)
844 else if (ret == VMessageBox::Help)
845 showHelpDialog("troubleshooting.torexited");
846 }
847 }
848}
849
850/** Called when the Tor process fails to start, for example, because the path
851 * specified to the Tor executable didn't lead to an executable. */
852void
854{
855 /* We don't display the error message for now, because the error message
856 * that Qt gives us in this instance is almost always "Unknown Error". That
857 * will make users sad. */
858 Q_UNUSED(errmsg);
859
861 _startedWithPrevious = false;
864 vWarn("Retrying with new ports");
865 start();
866 return;
867 }
868
870
871 /* Display an error message and see if the user wants some help */
872 int response = VMessageBox::warning(this, tr("Error Starting Tor"),
873 tr("Vidalia was unable to start Tor. Check your settings "
874 "to ensure the correct name and location of your Tor "
875 "executable is specified."),
876 VMessageBox::ShowSettings|VMessageBox::Default,
877 VMessageBox::Cancel|VMessageBox::Escape,
879
880 if (response == VMessageBox::ShowSettings) {
881 /* Show the settings dialog so the user can make sure they're pointing to
882 * the correct Tor. */
884 } else if (response == VMessageBox::Help) {
885 /* Show troubleshooting information about starting Tor */
886 showHelpDialog("troubleshooting.start");
887 }
888}
889
890/** Called when the control socket has successfully connected to Tor. */
891void
893{
894 authenticate();
896 QString err;
898 vWarn(err);
899 }
900
901 TorSettings settings;
902 if(settings.autoControlPort()) {
903 // We want to remember the ports if it's on auto
904 QString control_str = "", socks_str = "";
905 if(_torControl->getInfo("net/listeners/control", control_str)) {
906 QStringList control_parts = control_str.split(":");
907 if(control_parts.size() > 1)
908 control_str = control_parts[1];
909 }
910 if(_torControl->getInfo("net/listeners/socks", socks_str)) {
911 QStringList socks_parts = socks_str.split(":");
912 if(socks_parts.size() > 1)
913 socks_str = socks_parts[1];
914 }
915
916 _previousControlPort = control_str;
917 _previousSocksPort = socks_str;
918 } else {
919 // Otherwise we want to clear the remembered ports
922 }
923}
924
925/** Called when the connection to the control socket fails. The reason will be
926 * given in the errmsg parameter. */
927void
929{
930 /* Ok, ok. It really isn't going to connect. I give up. */
931 int response = VMessageBox::warning(this,
932 tr("Connection Error"), p(errmsg),
933 VMessageBox::Ok|VMessageBox::Default|VMessageBox::Escape,
935
936
937 if (response == VMessageBox::Retry) {
938 /* Let's give it another try. */
939 TorSettings settings;
941 settings.getControlPort());
942 } else {
943 /* Show the help browser (if requested) */
944 if (response == VMessageBox::Help)
945 showHelpDialog("troubleshooting.connect");
946 /* Since Vidalia can't connect, we can't really do much, so stop Tor. */
947 _torControl->stop();
948 }
949}
950
951/** Called when Vidalia has successfully authenticated to Tor. */
952void
954{
955 ServerSettings serverSettings(_torControl);
956 QString errmsg;
957
959
960 /* If Tor doesn't have bootstrapping events, then update the current
961 * status string and bump the progress bar along a bit. */
962 if (_torControl->getTorVersion() < 0x020101) {
964 tr("Connecting to the Tor network"));
965 }
966
967 /* Let people click on their beloved "New Identity" button */
968 _actionNewIdentity->setEnabled(true);
969
970 /* Register for any pertinent asynchronous events. */
971 if (!_torControl->setEvents(&errmsg)) {
972 VMessageBox::warning(this, tr("Error Registering for Events"),
973 p(tr("Vidalia was unable to register for some events. "
974 "Many of Vidalia's features may be unavailable."))
975 + p(errmsg),
977 } else {
978 /* Stop reading from Tor's stdout immediately, since we successfully
979 * registered for Tor events, including any desired log events. */
981 }
982
983 /* Configure UPnP port forwarding if needed */
984 serverSettings.configurePortForwarding();
985
986 /* Check if Tor has a circuit established */
989 }
990 /* Check the status of Tor's version */
991 if (_torControl->getTorVersion() >= 0x020001)
993 if (_torControl->getTorVersion() >= 0x020102) {
995 if (status.isValid())
997 }
998}
999
1000/** Called when Vidalia fails to authenticate to Tor. The failure reason is
1001 * specified in <b>errmsg</b>. */
1002void
1004{
1005 bool retry = false;
1006
1007 vWarn("Authentication failed: %1").arg(errmsg);
1008
1009 /* Parsing log messages is evil, but we're left with little option */
1010 if (errmsg.contains("Password did not match")) {
1012 connect(&dlg, SIGNAL(helpRequested(QString)),
1013 this, SLOT(showHelpDialog(QString)));
1014
1015 qint64 torPid = 0;
1016
1017 TorSettings settings;
1018 QHash<qint64, QString> procs = process_list(settings.getControlPort());
1019 foreach (qint64 pid, procs.keys()) {
1020 if (! procs.value(pid).compare("tor", Qt::CaseInsensitive)) {
1021 torPid = pid;
1022 break;
1023 }
1024 }
1025
1026 dlg.setResetEnabled(torPid > 0);
1027
1028 int ret = dlg.exec();
1029 if (ret == QDialogButtonBox::Reset) {
1030 if (! process_kill(torPid)) {
1032 tr("Password Reset Failed"),
1033 p(tr("Vidalia tried to restart Tor, but was not "
1034 "able to. Please check your Task Manager to "
1035 "ensure there are no other Tor processes running.")),
1036 VMessageBox::Ok|VMessageBox::Default);
1037 } else {
1038 retry = true;
1039 }
1040 }
1041 }
1042
1043 if (_torControl->isRunning())
1045 stop();
1046 else
1047 disconnect();
1048 if (retry)
1049 start();
1050}
1051
1052/** Called when Tor thinks its version is old or unrecommended, and displays
1053 * a message notifying the user. */
1054void
1056 const QString &current,
1057 const QStringList &recommended)
1058{
1059 Q_UNUSED(current);
1060 Q_UNUSED(recommended);
1061
1062 if (reason == tc::ObsoleteTorVersion
1063 || reason == tc::UnrecommendedTorVersion)
1065}
1066
1067/** Called when Tor thinks its version is old or unrecommended, and displays a
1068 * message notifying the user. */
1069void
1071{
1072 static bool alreadyWarned = false;
1073
1074 if (!alreadyWarned) {
1075#if !defined(USE_AUTOUPDATE)
1076 QString website = "https://www.torproject.org/";
1077# if QT_VERSION >= 0x040200
1078 website = QString("<a href=\"%1\">%1</a>").arg(website);
1079# endif
1080
1081 VMessageBox::information(this, tr("Tor Update Available"),
1082 p(tr("The currently installed version of Tor is out of date or no longer "
1083 "recommended. Please visit the Tor website to download the latest "
1084 "version.")) + p(tr("Tor website: %1").arg(website)),
1086#else
1087 int ret = VMessageBox::information(this,
1088 tr("Tor Update Available"),
1089 p(tr("The currently installed version of Tor is out of date "
1090 "or no longer recommended."))
1091 + p(tr("Would you like to check if a newer package is "
1092 "available for installation?")),
1093 VMessageBox::Yes|VMessageBox::Default,
1094 VMessageBox::No|VMessageBox::Escape);
1095
1096 if (ret == VMessageBox::Yes)
1097 checkForUpdatesWithUi();
1098#endif
1099 alreadyWarned = true;
1100 }
1101}
1102
1103/** Called when Tor's bootstrapping status changes. <b>bse</b> represents
1104 * Tor's current estimate of its bootstrapping progress. */
1105void
1107{
1108 int percentComplete = STARTUP_PROGRESS_BOOTSTRAPPING + bs.percentComplete();
1109 bool warn = (bs.severity() == tc::WarnSeverity &&
1111
1112 QString description;
1113 switch (bs.status()) {
1115 description = tr("Connecting to a relay directory");
1116 break;
1119 description = tr("Establishing an encrypted directory connection");
1120 break;
1122 description = tr("Retrieving network status");
1123 break;
1125 description = tr("Loading network status");
1126 break;
1128 description = tr("Loading authority certificates");
1129 break;
1131 description = tr("Requesting relay information");
1132 break;
1134 description = tr("Loading relay information");
1135 break;
1137 description = tr("Connecting to the Tor network");
1138 break;
1141 description = tr("Establishing a Tor circuit");
1142 break;
1144 description = tr("Connected to the Tor network!");
1145 warn = false; /* probably false anyway */
1146 break;
1147 default:
1148 description = tr("Unrecognized startup status");
1149 }
1150 if (warn) {
1151 QString reason;
1152 /* Is it really a good idea to translate these? */
1153 switch (bs.reason()) {
1155 reason = tr("miscellaneous");
1156 break;
1158 reason = tr("identity mismatch");
1159 break;
1160 case tc::ConnectionDone:
1161 reason = tr("done");
1162 break;
1164 reason = tr("connection refused");
1165 break;
1167 reason = tr("connection timeout");
1168 break;
1170 reason = tr("read/write error");
1171 break;
1172 case tc::NoRouteToHost:
1173 reason = tr("no route to host");
1174 break;
1176 reason = tr("insufficient resources");
1177 break;
1178 default:
1179 reason = tr("unknown");
1180 }
1181 description += tr(" failed (%1)").arg(reason);
1182 }
1183 setStartupProgress(percentComplete, description);
1184}
1185
1186/** Called when Tor has successfully established a circuit. */
1187void
1189{
1191 // TODO: fix hardcoded total length
1193 tr("Connected to the Tor network!"));
1194
1195#if defined(USE_AUTOUPDATE)
1196 VidaliaSettings settings;
1197 if (settings.isAutoUpdateEnabled()) {
1198 QDateTime lastCheckedAt = settings.lastCheckedForUpdates();
1199 if (UpdateProcess::shouldCheckForUpdates(lastCheckedAt)) {
1200 /* Initiate a background check for updates now */
1201 _updateTimer.stop();
1202 checkForUpdates();
1203 }
1204 }
1205#endif
1206}
1207
1208/** Called when Tor thinks the user has tried to connect to a port that
1209 * typically is used for unencrypted applications. Warns the user and allows
1210 * them to ignore future warnings on <b>port</b>. It is possible that Tor
1211 * will produce multiple asynchronous status events warning of dangerous ports
1212 * while the message box is displayed (for example, while the user is away
1213 * from the keyboard), so subsequent messages will be discarded until the
1214 * first message box is dismissed. */
1215void
1216MainWindow::warnDangerousPort(quint16 port, bool rejected)
1217{
1218 static QMessageBox *dlg = 0;
1219
1220 /* Don't display another message box until the first one is dismissed */
1221 if (dlg)
1222 return;
1223
1224 QString application;
1225 switch (port) {
1226 case 23:
1227 application = tr("(probably Telnet)");
1228 break;
1229
1230 case 109:
1231 case 110:
1232 case 143:
1233 application = tr("(probably an email client)");
1234 break;
1235
1236 default:
1237 application = "";
1238 }
1239
1240 QString text = tr("One of your applications %1 appears to be making a "
1241 "potentially unencrypted and unsafe connection to port %2.")
1242 .arg(application).arg(port);
1243
1244 QString extraText = p(tr("Anything sent over this connection could be "
1245 "monitored. Please check your application's "
1246 "configuration and use only encrypted protocols, "
1247 "such as SSL, if possible."));
1248 if (rejected) {
1249 extraText.append(p(tr("Tor has automatically closed your connection in "
1250 "order to protect your anonymity.")));
1251 }
1252
1253 dlg = new QMessageBox(QMessageBox::Warning,
1254 tr("Potentially Unsafe Connection"), text,
1255 QMessageBox::Ok | QMessageBox::Ignore);
1256 dlg->setInformativeText(extraText);
1257 dlg->setDefaultButton(QMessageBox::Ok);
1258 dlg->setEscapeButton(QMessageBox::Ok);
1259
1260 int ret = dlg->exec();
1261 if (ret == QMessageBox::Ignore) {
1263 TorSettings settings;
1264 QStringList portList;
1265 QList<quint16> ports;
1266 int idx;
1267
1268 ports = settings.getWarnPlaintextPorts();
1269 idx = ports.indexOf(port);
1270 if (idx >= 0) {
1271 ports.removeAt(idx);
1272 settings.setWarnPlaintextPorts(ports);
1273
1274 foreach (quint16 port, ports) {
1275 portList << QString::number(port);
1276 }
1277 tc->setConf("WarnPlaintextPorts", portList.join(","));
1278 portList.clear();
1279 }
1280
1281 ports = settings.getRejectPlaintextPorts();
1282 idx = ports.indexOf(port);
1283 if (idx >= 0) {
1284 ports.removeAt(idx);
1285 settings.setRejectPlaintextPorts(ports);
1286
1287 foreach (quint16 port, ports) {
1288 portList << QString::number(port);
1289 }
1290 tc->setConf("RejectPlaintextPorts", portList.join(","));
1291 }
1292 }
1293 delete dlg;
1294 dlg = 0;
1295}
1296
1297/** Attempts to authenticate to Tor's control port, depending on the
1298 * authentication method specified in TorSettings::getAuthenticationMethod().
1299 */
1300bool
1302{
1304 TorSettings settings;
1305 ProtocolInfo pi;
1306
1309 tr("Authenticating to Tor"));
1310
1311 authMethod = settings.getAuthenticationMethod();
1312 pi = _torControl->protocolInfo();
1313 QStringList authMethods;
1314 if (!pi.isEmpty()) {
1315 authMethods = pi.authMethods();
1316 if (authMethods.contains("COOKIE"))
1317 authMethod = TorSettings::CookieAuth;
1318 else if (authMethods.contains("HASHEDPASSWORD"))
1319 authMethod = TorSettings::PasswordAuth;
1320 else if (authMethods.contains("NULL"))
1321 authMethod = TorSettings::NullAuth;
1322 }
1323
1324 if (authMethod == TorSettings::CookieAuth) {
1325 if(!tryCookie(pi)) {
1326 if(authMethods.contains("HASHEDPASSWORD") and !tryHashed()) {
1327 goto cancel;
1328 } else {
1329 return true;
1330 }
1331 } else {
1332 return true;
1333 }
1334 } else if (authMethod == TorSettings::PasswordAuth) {
1335 return tryHashed();
1336 }
1337 /* No authentication. Send an empty password. */
1338 vNotice("Authenticating using 'null' authentication.");
1339 return _torControl->authenticate(QString(""));
1340
1341cancel:
1342 vWarn("Cancelling control authentication attempt.");
1344 stop();
1345 else
1346 disconnect();
1347 return false;
1348}
1349
1350bool
1352{
1353 TorSettings settings;
1354 /* Try to load an auth cookie and send it to Tor */
1355 QByteArray cookie = loadControlCookie(pi.cookieAuthFile());
1356 while (cookie.isEmpty()) {
1357 /* Prompt the user to find their control_auth_cookie */
1358 int ret = VMessageBox::question(this,
1359 tr("Cookie Authentication Required"),
1360 p(tr("The Tor software requires Vidalia to send the "
1361 "contents of an authentication cookie, but Vidalia "
1362 "was unable to find one."))
1363 + p(tr("Would you like to browse for the file "
1364 "'control_auth_cookie' yourself?")),
1365 VMessageBox::Browse|VMessageBox::Default,
1366 VMessageBox::Cancel|VMessageBox::Escape);
1367
1368 if (ret == VMessageBox::Cancel)
1369 return false;
1370 QString cookieDir = QFileDialog::getOpenFileName(this,
1371 tr("Data Directory"),
1372 settings.getDataDirectory(),
1373 tr("Control Cookie (control_auth_cookie)"));
1374 if (cookieDir.isEmpty())
1375 return false;
1376 cookieDir = QFileInfo(cookieDir).absolutePath();
1377 cookie = loadControlCookie(cookieDir);
1378 }
1379 if(cookie.size() != 32) {
1380 vWarn(QString("Cookie length has to be exactly 32 bytes long. Found %1 bytes")
1381 .arg(cookie.size()));
1382 return false;
1383 }
1384 vNotice("Authenticating using 'cookie' authentication.");
1385 return _torControl->authenticate(cookie);
1386}
1387
1388bool
1390{
1391 /* Get the control password and send it to Tor */
1392 vNotice("Authenticating using 'hashed password' authentication.");
1393 if (_useSavedPassword) {
1394 TorSettings settings;
1396 }
1397
1398 qputenv("TOR_CONTROL_PASSWD",
1399 _controlPassword.toAscii().toHex());
1400
1402}
1403
1404/** Checks the status of the current version of Tor to see if it's old,
1405 * unrecommended, or obsolete. */
1406void
1408{
1409 VidaliaSettings settings;
1410 if(settings.skipVersionCheck())
1411 return;
1412 QString status;
1413 if (_torControl->getInfo("status/version/current", status)) {
1414 if (!status.compare("old", Qt::CaseInsensitive)
1415 || !status.compare("unrecommended", Qt::CaseInsensitive)
1416 || !status.compare("obsolete", Qt::CaseInsensitive)) {
1418 }
1419 }
1420}
1421
1422/** Searches for and attempts to load the control authentication cookie. This
1423 * assumes the cookie is named 'control_auth_cookie'. If <b>cookiePath</b> is
1424 * empty, this method will search some default locations depending on the
1425 * current platform. <b>cookiePath</b> can point to either a cookie file or a
1426 * directory containing the cookie file. */
1427QByteArray
1429{
1430 QFile authCookie;
1431 QStringList pathList;
1432
1433 if (!cookiePath.isEmpty()) {
1434 pathList << cookiePath;
1435 } else {
1436 /* Try some default locations */
1437 TorSettings settings;
1438 QString dataDir = settings.getDataDirectory();
1439 if (!dataDir.isEmpty())
1440 pathList << dataDir;
1441
1442#if defined(Q_WS_WIN)
1443 pathList << expand_filename("%APPDATA%\\Tor");
1444#else
1445 pathList << expand_filename("~/.tor");
1446#endif
1447 }
1448
1449 /* Search for the cookie file */
1450 foreach (QString path, pathList) {
1451 QString cookieFile = QFileInfo(path).isFile() ?
1452 path : path + "/control_auth_cookie";
1453 vDebug("Checking for authentication cookie in '%1'").arg(cookieFile);
1454 if (!QFileInfo(cookieFile).exists())
1455 continue;
1456
1457 authCookie.setFileName(cookieFile);
1458 if (authCookie.open(QIODevice::ReadOnly)) {
1459 vInfo("Reading authentication cookie from '%1'").arg(cookieFile);
1460 return authCookie.readAll();
1461 } else {
1462 vWarn("Couldn't open cookie file '%1': %2")
1463 .arg(cookieFile).arg(authCookie.errorString());
1464 }
1465 }
1466 vWarn("Couldn't find a readable authentication cookie.");
1467 return QByteArray();
1468}
1469
1470/** Updates the UI to reflect Tor's current <b>status</b>. Returns the
1471 * previously set TorStatus value.*/
1474{
1475 QString statusText, actionText;
1476 QString trayIconFile, statusIconFile;
1477 TorStatus prevStatus = _status;
1478
1479 vNotice("Tor status changed from '%1' to '%2'.")
1480 .arg(toString(prevStatus)).arg(toString(status));
1481 _status = status;
1482
1483 if (status == Stopped) {
1484 statusText = tr("Tor is not running");
1485 actionText = tr("Start Tor");
1486 trayIconFile = IMG_TOR_STOPPED;
1487 statusIconFile = IMG_TOR_STOPPED_48;
1488 _actionRestartTor->setEnabled(false);
1489 _actionReloadConfig->setEnabled(false);
1490 _actionStartStopTor->setEnabled(true);
1491 _actionStartStopTor->setEnabled(true);
1492 _actionStartStopTor->setIcon(QIcon(IMG_START_TOR_16));
1493 _actionStartStopTor->setText(actionText);
1494
1495 /* XXX: This might need to be smarter if we ever start connecting other
1496 * slots to these triggered() and clicked() signals. */
1497 QObject::disconnect(_actionStartStopTor, SIGNAL(triggered()), this, 0);
1498 connect(_actionStartStopTor, SIGNAL(triggered()), this, SLOT(start()));
1500 } else if (status == Stopping) {
1501 _actionRestartTor->setEnabled(false);
1502 _actionReloadConfig->setEnabled(false);
1504 statusText = tr("Your relay is shutting down.\n"
1505 "Click 'Stop' again to stop your relay now.");
1506 } else {
1507 statusText = tr("Tor is shutting down");
1508 }
1509 trayIconFile = IMG_TOR_STOPPING;
1510 statusIconFile = IMG_TOR_STOPPING_48;
1511
1512 } else if (status == Started) {
1513 actionText = tr("Stop Tor");
1514 _actionRestartTor->setEnabled(true);
1515 _actionReloadConfig->setEnabled(true);
1516 _actionStartStopTor->setEnabled(true);
1517 _actionStartStopTor->setIcon(QIcon(IMG_STOP_TOR_16));
1518 _actionStartStopTor->setText(actionText);
1519
1520 /* XXX: This might need to be smarter if we ever start connecting other
1521 * slots to these triggered() and clicked() signals. */
1522 QObject::disconnect(_actionStartStopTor, SIGNAL(triggered()), this, 0);
1523 connect(_actionStartStopTor, SIGNAL(triggered()), this, SLOT(stop()));
1524 } else if (status == Starting) {
1525 statusText = tr("Starting the Tor software");
1526 trayIconFile = IMG_TOR_STARTING;
1527 statusIconFile = IMG_TOR_STARTING_48;
1528 _actionStartStopTor->setEnabled(false);
1529 _actionRestartTor->setEnabled(false);
1530 _actionReloadConfig->setEnabled(false);
1533 } else if (status == CircuitEstablished) {
1534 statusText = tr("Connected to the Tor network!");
1535 trayIconFile = IMG_TOR_RUNNING;
1536 statusIconFile = IMG_TOR_RUNNING_48;
1538 }
1539
1540 /* Update the tray icon */
1541 if (!trayIconFile.isEmpty()) {
1542 setTrayIcon(trayIconFile);
1543 }
1544 /* Update the status banner on the control panel */
1545 if (!statusIconFile.isEmpty())
1546 _statusTab.setTorStatus(QPixmap(statusIconFile));
1547 if (!statusText.isEmpty()) {
1548 _trayIcon.setToolTip(statusText);
1549 _statusTab.setTorStatus(statusText);
1550 }
1551 return prevStatus;
1552}
1553
1554/** Sets the current tray or dock icon image to <b>iconFile</b>. */
1555void
1556MainWindow::setTrayIcon(const QString &iconFile)
1557{
1558#if defined(Q_WS_MAC)
1559 VidaliaSettings settings;
1560 QApplication::setWindowIcon(QPixmap(iconFile));
1561
1562 /* only display tray icon if icon preference is not set to "Dock Only" */
1563 if (settings.getIconPref() != VidaliaSettings::Dock)
1564 _trayIcon.setIcon(QIcon(iconFile));
1565#else
1566 /* always display tray icon for other platforms */
1567 _trayIcon.setIcon(QIcon(iconFile));
1568#endif
1569}
1570
1571/** Converts a TorStatus enum value to a string for debug logging purposes. */
1572QString
1574{
1575 switch (status) {
1576 /* These strings only appear in debug logs, so they should not be
1577 * translated. */
1578 case Unset: return "Unset";
1579 case Stopping: return "Stopping";
1580 case Stopped: return "Stopped";
1581 case Starting: return "Starting";
1582 case Started: return "Started";
1583 case Authenticating: return "Authenticating";
1584 case Authenticated: return "Authenticated";
1585 case CircuitEstablished: return "Circuit Established";
1586 default: break;
1587 }
1588 return "Unknown";
1589}
1590
1591/** Called when the user changes a setting that needs Tor restarting */
1592void
1594{
1595 if(stop()) {
1596 start();
1597 }
1598}
1599
1600/** Sends a sighup signal to Tor on platforms other than Windows */
1601void
1603{
1604 bool rc;
1605 QString errmsg;
1606 rc = _torControl->signal(TorSignal::Reload, &errmsg);
1607
1608 if (!rc) {
1609 int response = VMessageBox::warning(this, tr("Error reloading configuration"),
1610 p(tr("Vidalia was unable to reload Tor's configuration."))
1611 + p(errmsg),
1613 }
1614}
1615
1616/** Sets the visibility of the startup status description and progress bar to
1617 * <b>visible</b>. */
1618void
1620{
1623}
1624
1625/** Sets the progress bar completion value to <b>progressValue</b> and sets
1626 * the status text to <b>description</b>. */
1627void
1629 const QString &description)
1630{
1631 _statusTab.setProgress(progressValue, description);
1632 _trayIcon.setToolTip(description);
1633}
1634
1635/** Called when Vidalia wants to disconnect from a Tor it did not start. */
1636void
1638{
1640}
1641
1642/** Called when the control socket has been disconnected. */
1643void
1645{
1646 if (!_isVidaliaRunningTor) {
1647 /* If we didn't start our own Tor process, interpret losing the control
1648 * connection as "Tor is stopped". */
1650 }
1651
1652 /*XXX We should warn here if we get disconnected when we didn't intend to */
1653 _actionNewIdentity->setEnabled(false);
1654 _isVidaliaRunningTor = false;
1655}
1656
1657void
1659{
1660 ConfigDialog *configDialog = new ConfigDialog();
1661 connect(configDialog, SIGNAL(helpRequested(QString)),
1662 this, SLOT(showHelpDialog(QString)));
1663 configDialog->showWindow(page);
1664}
1665
1666/** Called when the user selects the "New Identity" action from the menu. */
1667void
1669{
1670 QString errmsg;
1671
1672 /* Send the NEWNYM signal. If message balloons are supported and the NEWNYM
1673 * is successful, we will show the result as a balloon. Otherwise, we'll
1674 * just use a message box. */
1675 if (_torControl->signal(TorSignal::NewNym, &errmsg)) {
1676 /* NEWNYM signal was successful */
1677 QString title = tr("New Identity");
1678 QString message = tr("All subsequent connections will "
1679 "appear to be different than your "
1680 "old connections.");
1681
1682 /* Disable the New Identity button for MIN_NEWIDENTITY_INTERVAL */
1683 _actionNewIdentity->setEnabled(false);
1684 QTimer::singleShot(MIN_NEWIDENTITY_INTERVAL,
1685 this, SLOT(enableNewIdentity()));
1686
1687 if (QSystemTrayIcon::supportsMessages())
1688 _trayIcon.showMessage(title, message, QSystemTrayIcon::Information);
1689 else
1690 VMessageBox::information(this, title, message, VMessageBox::Ok);
1691 } else {
1692 /* NEWNYM signal failed */
1694 tr("Failed to Create New Identity"), errmsg, VMessageBox::Ok);
1695 }
1696}
1697
1698/** Re-enables the 'New Identity' button after a delay from the previous time
1699 * 'New Identity' was used. */
1700void
1702{
1703 if (_torControl->isConnected()) {
1704 _actionNewIdentity->setEnabled(true);
1705 }
1706}
1707
1708void
1710{
1711 /* If the tab that's going to be closed is the status one
1712 * don't do it */
1713 if(index == 0)
1714 return;
1715
1716 delTab(index);
1717}
1718
1719void
1721{
1722 QAction *act = qobject_cast<QAction *>(sender());
1723 VidaliaTab *tab = qobject_cast<VidaliaTab *>(act->parent());
1724 _detachedTabMap.removeAll(tab->getTitle());
1725 tab->setParent(ui.tabWidget);
1726 addTab(tab);
1727 _reattachMenu.removeAction(act);
1728 if(_reattachMenu.actions().size() < 1) {
1729 _reattachMenu.addAction(_dummy);
1730 _dummy->setEnabled(false);
1731 }
1732}
1733
1734void
1736{
1737 VAttachButton *but = qobject_cast<VAttachButton *>(sender());
1738 VidaliaTab *tab = but->getTab();
1739 int index = ui.tabWidget->indexOf(tab);
1740
1741 ui.tabWidget->removeTab(index);
1742 tab->setParent(0);
1743 tab->show();
1744
1745 QString key = _tabMap.at(index);
1746 _tabMap.removeAll(key);
1747 _detachedTabMap << key;
1748
1749 QAction *act = new QAction(tab->getTitle(), tab);
1750 connect(act, SIGNAL(triggered()), this, SLOT(attachTab()));
1751 _reattachMenu.addAction(act);
1752 _reattachMenu.removeAction(_dummy);
1753}
1754
1755void
1757{
1758 VidaliaTab *tab = qobject_cast<VidaliaTab *>(sender());
1759 int index = ui.tabWidget->indexOf(tab);
1760 if(index < 0) {
1761 QAction *act = 0;
1762 foreach(QAction *tmpAct, _reattachMenu.actions()) {
1763 if(tmpAct->parent() == tab) {
1764 act = tmpAct;
1765 break;
1766 }
1767 }
1768
1769 if(act != 0)
1770 _reattachMenu.removeAction(act);
1771
1772 _detachedTabMap.removeAll(tab->getTitle());
1773
1774 tab->setParent(ui.tabWidget);
1775 addTab(tab);
1776
1777 if(_reattachMenu.actions().size() < 1) {
1778 _reattachMenu.addAction(_dummy);
1779 _dummy->setEnabled(false);
1780 }
1781
1782 delTab(ui.tabWidget->currentIndex());
1783 }
1784}
1785
1786void
1788{
1789 /** If the tab's already open, display it and delete the
1790 * instanse passed */
1791 if(_tabMap.contains(tab->getTitle())) {
1792 ui.tabWidget->setCurrentIndex(_tabMap.indexOf(tab->getTitle()));
1793
1794 /** If we are trying to open the exact same tab twice
1795 * don't do anything */
1796 if(tab == ui.tabWidget->widget(_tabMap.indexOf(tab->getTitle())))
1797 return;
1798
1799 /** Exception for tabs that need to be always created */
1800 if (tab != _messageLog &&
1801 tab != &_statusTab &&
1802 tab != &_netViewer &&
1803 tab != _graph)
1804 tab->deleteLater();
1805 return;
1806 }
1807
1808 VAttachButton *atb = new VAttachButton();
1809
1810 ui.tabWidget->addTab(tab, tab->getTitle());
1811 int pos = ui.tabWidget->count() - 1;
1812 ui.tabWidget->setCurrentIndex(pos);
1813
1814 atb->setTab(tab);
1815#if defined(Q_WS_MAC)
1816 ui.tabWidget->setTabButton(pos, QTabBar::RightSide, atb);
1817#else
1818 ui.tabWidget->setTabButton(pos, QTabBar::LeftSide, atb);
1819#endif
1820
1821 connect(tab, SIGNAL(closeTab()),
1822 this, SLOT(handleAttachedClose()));
1823
1824 connect(atb, SIGNAL(attachTab()),
1825 this, SLOT(attachTab()));
1826 connect(atb, SIGNAL(detachTab()),
1827 this, SLOT(detachTab()));
1828 /** The new tab is added to the last position */
1829 _tabMap << tab->getTitle();
1830 connect(tab, SIGNAL(helpRequested(QString)),
1831 this, SLOT(showHelpDialog(QString)));
1832 if(!isVisible())
1833 setVisible(true);
1834}
1835
1836void
1838{
1839 if(index == -1)
1840 index = ui.tabWidget->currentIndex();
1841
1842 VidaliaTab *tab = qobject_cast<VidaliaTab*>(ui.tabWidget->widget(index));
1843 // if it isn't one of the tabs that's supposed to be open at every moment
1844 if (tab != _messageLog &&
1845 tab != &_statusTab &&
1846 tab != &_netViewer &&
1847 tab != _graph) {
1848 QObject::disconnect(ui.tabWidget->widget(index), 0, 0, 0);
1849 tab->deleteLater();
1850 }
1851 ui.tabWidget->removeTab(index);
1852 QString key = _tabMap.at(index);
1853 _tabMap.removeAll(key);
1854}
1855
1856void
1858{
1860}
1861
1862void
1864{
1866}
1867
1868void
1870{
1871 addTab(_graph);
1872}
1873
1874/** Creates and displays Vidalia's About dialog. */
1875void
1877{
1878 AboutDialog dlg(this);
1879 dlg.exec();
1880}
1881
1882/** Displays the help browser and displays the most recently viewed help
1883 * topic. */
1884void
1886{
1887 showHelpDialog(QString());
1888}
1889
1890/**< Shows the help browser and displays the given help <b>topic</b>. */
1891void
1892MainWindow::showHelpDialog(const QString &topic)
1893{
1894 static HelpBrowser *helpBrowser = 0;
1895 if (!helpBrowser)
1896 helpBrowser = new HelpBrowser(this);
1897 helpBrowser->showWindow(topic);
1898}
1899
1900void
1902{
1904}
1905
1906void
1908{
1909 DebugDialog dlg;
1910 dlg.exec();
1911}
1912
1913#if defined(USE_MINIUPNPC)
1914/** Called when a UPnP error occurs. */
1915void
1916MainWindow::upnpError(UPNPControl::UPNPError error)
1917{
1918 Q_UNUSED(error);
1919
1920#if 0
1921 /* XXX: Is there a better way to do this? Currently, this could get called
1922 * if there is an error when testing UPnP support, and again when attempting
1923 * to reset the UPnP state when the test dialog is closed. The user would
1924 * not be amused with all the warning dialogs. */
1925
1927 tr("Port Forwarding Failed"),
1928 p(tr("Vidalia was unable to configure automatic port forwarding."))
1929 + p(UPNPControl::Instance()->errorString()),
1931#endif
1932}
1933#endif
1934
1935#if defined(USE_AUTOUPDATE)
1936/** Called when the user clicks the 'Check Now' button in the General
1937 * settings page. */
1938void
1939MainWindow::checkForUpdatesWithUi()
1940{
1941 checkForUpdates(true);
1942}
1943
1944/** Called when the update interval timer expires, notifying Vidalia that
1945 * we should check for updates again. */
1946void
1947MainWindow::checkForUpdates(bool showProgress)
1948{
1949 VidaliaSettings settings;
1950
1951 if (_updateProcess.isRunning()) {
1952 if (showProgress) {
1953 /* A check for updates is already in progress, so just bring the update
1954 * progress dialog into focus.
1955 */
1956 _updateProgressDialog.show();
1957 }
1958 } else {
1959 /* If Tor is running and bootstrapped, then use Tor to check for updates */
1961 _updateProcess.setSocksPort(_torControl->getSocksPort());
1962 else
1963 _updateProcess.setSocksPort(0);
1964
1965 /* Initialize the UpdateProgressDialog and display it, if necessary. */
1966 _updateProgressDialog.setStatus(UpdateProgressDialog::CheckingForUpdates);
1967 if (showProgress)
1968 _updateProgressDialog.show();
1969
1970 /* Initiate a check for available software updates. This check will
1971 * be done in the background, notifying the user only if there are
1972 * updates to be installed.
1973 */
1974 _updateProcess.checkForUpdates(UpdateProcess::TorBundleInfo);
1975
1976 /* Remember when we last checked for software updates */
1977 settings.setLastCheckedForUpdates(QDateTime::currentDateTime().toUTC());
1978
1979 /* Restart the "Check for Updates" timer */
1980 _updateTimer.start(UpdateProcess::checkForUpdatesInterval() * 1000);
1981 }
1982}
1983
1984/** Called when the check for software updates fails. */
1985void
1986MainWindow::checkForUpdatesFailed(const QString &errmsg)
1987{
1988 if (_updateProgressDialog.isVisible()) {
1989 _updateProgressDialog.hide();
1990 VMessageBox::warning(this, tr("Update Failed"), errmsg,
1992 }
1993}
1994
1995/** Called when there is an update available for installation. */
1996void
1997MainWindow::updatesAvailable(UpdateProcess::BundleInfo bi,
1998 const PackageList &packageList)
1999{
2000 vInfo("%1 software update(s) available").arg(packageList.size());
2001 if (packageList.size() > 0) {
2002 UpdatesAvailableDialog dlg(packageList, &_updateProgressDialog);
2003
2004 switch (dlg.exec()) {
2006 installUpdates(bi);
2007 break;
2008
2009 default:
2010 _updateProgressDialog.hide();
2011 break;
2012 }
2013 } else {
2014 if (_updateProgressDialog.isVisible()) {
2015 _updateProgressDialog.hide();
2016 VMessageBox::information(this, tr("Your software is up to date"),
2017 tr("There are no new Tor software packages "
2018 "available for your computer at this time."),
2020 }
2021 }
2022}
2023
2024/** Stops Tor (if necessary), installs any available for <b>bi</b>, and
2025 * restarts Tor (if necessary). */
2026void
2027MainWindow::installUpdates(UpdateProcess::BundleInfo bi)
2028{
2029 _updateProgressDialog.setStatus(UpdateProgressDialog::InstallingUpdates);
2030 _updateProgressDialog.show();
2031
2033 _restartTorAfterUpgrade = true;
2034 _isIntentionalExit = true;
2035 _torControl->stop();
2036 } else {
2037 _restartTorAfterUpgrade = false;
2038 }
2039 _updateProcess.installUpdates(bi);
2040}
2041
2042/** Called when all <b>numUpdates</b> software updates have been installed
2043 * successfully. */
2044void
2045MainWindow::updatesInstalled(int numUpdates)
2046{
2047 _updateProgressDialog.setStatus(UpdateProgressDialog::UpdatesInstalled);
2048 _updateProgressDialog.show();
2049
2050 if (_restartTorAfterUpgrade)
2051 start();
2052}
2053
2054/** Called when an update fails to install. <b>errmsg</b> contains details
2055 * about the failure. */
2056void
2057MainWindow::installUpdatesFailed(const QString &errmsg)
2058{
2059 _updateProgressDialog.hide();
2060
2061 VMessageBox::warning(this, tr("Installation Failed"),
2062 p(tr("Vidalia was unable to install your software updates."))
2063 + p(tr("The following error occurred:"))
2064 + p(errmsg),
2066
2067 if (_restartTorAfterUpgrade)
2068 start();
2069}
2070
2071#endif
2072
#define STARTUP_PROGRESS_CONNECTING
Definition: MainWindow.cpp:97
#define IMG_TOR_STOPPED_48
Definition: MainWindow.cpp:64
#define IMG_BWGRAPH
Definition: MainWindow.cpp:50
#define STARTUP_PROGRESS_AUTHENTICATING
Definition: MainWindow.cpp:98
#define IMG_NETWORK
Definition: MainWindow.cpp:58
#define STARTUP_PROGRESS_STARTING
Definition: MainWindow.cpp:96
#define IMG_TOR_STOPPED
Definition: MainWindow.cpp:86
#define IMG_TOR_STARTING
Definition: MainWindow.cpp:88
#define IMG_TOR_RUNNING
Definition: MainWindow.cpp:87
#define IMG_ABOUT
Definition: MainWindow.cpp:56
#define IMG_HELP
Definition: MainWindow.cpp:55
#define STARTUP_PROGRESS_BOOTSTRAPPING
Definition: MainWindow.cpp:99
#define IMG_TOR_RUNNING_48
Definition: MainWindow.cpp:65
#define IMG_START_TOR_16
Definition: MainWindow.cpp:60
#define IMG_CONFIG
Definition: MainWindow.cpp:53
#define IMG_CONTROL_PANEL
Definition: MainWindow.cpp:51
#define MIN_NEWIDENTITY_INTERVAL
Definition: MainWindow.cpp:93
#define IMG_TOR_STOPPING_48
Definition: MainWindow.cpp:67
#define IMG_MESSAGELOG
Definition: MainWindow.cpp:52
#define IMG_STOP_TOR_16
Definition: MainWindow.cpp:61
#define IMG_TOR_STOPPING
Definition: MainWindow.cpp:89
#define STARTUP_PROGRESS_CIRCUITBUILD
Definition: MainWindow.cpp:100
#define IMG_TOR_STARTING_48
Definition: MainWindow.cpp:66
#define IMG_IDENTITY
Definition: MainWindow.cpp:54
#define IMG_EXIT
Definition: MainWindow.cpp:57
QList< PackageInfo > PackageList
Definition: PackageInfo.h:93
stop errmsg connect(const QHostAddress &address, quint16 port)
stop errmsg disconnect()
#define vNotice(fmt)
Definition: Vidalia.h:41
#define vWarn(fmt)
Definition: Vidalia.h:42
#define vInfo(fmt)
Definition: Vidalia.h:40
#define vDebug(fmt)
Definition: Vidalia.h:39
#define vApp
Definition: Vidalia.h:37
#define SETTING_REMEMBER_SHUTDOWN
bool isValid() const
int percentComplete() const
tc::Severity severity() const
tc::ConnectionStatusReason reason() const
Status status() const
Recommendation recommendedAction() const
void showWindow(Page page=General)
void showWindow(QString topic=QString())
void sighup()
void enableNewIdentity()
QStringList _tabMap
Definition: MainWindow.h:306
void authenticated()
Definition: MainWindow.cpp:953
void restart()
NetViewer _netViewer
Definition: MainWindow.h:302
void started()
Definition: MainWindow.cpp:689
bool _isIntentionalExit
Definition: MainWindow.h:251
void createMenuBar()
Definition: MainWindow.cpp:185
QAction * _actionReloadConfig
Definition: MainWindow.h:283
void showHelpDialog()
virtual void retranslateUi()
Definition: MainWindow.cpp:343
void clockSkewed(int skew, const QString &source)
Definition: MainWindow.cpp:273
QAction * _actionExit
Definition: MainWindow.h:292
void bootstrapStatusChanged(const BootstrapStatus &bs)
bool stop()
Definition: MainWindow.cpp:759
BandwidthGraph * _graph
Definition: MainWindow.h:303
QMenu _reattachMenu
Definition: MainWindow.h:295
void showNetViewerTab()
QString toString(TorStatus status)
void aboutToQuit()
Definition: MainWindow.cpp:543
void running()
Definition: MainWindow.cpp:489
void showDebugDialog()
void handleCloseTab(int index)
@ Authenticating
Definition: MainWindow.h:201
@ CircuitEstablished
Definition: MainWindow.h:203
void connectFailed(QString errmsg)
Definition: MainWindow.cpp:928
void start()
Definition: MainWindow.cpp:564
void showBandwidthTab()
void stopped(int errorCode, QProcess::ExitStatus exitStatus)
Definition: MainWindow.cpp:823
void createActions()
Definition: MainWindow.cpp:165
void showAboutDialog()
void trayIconActivated(QSystemTrayIcon::ActivationReason reason)
Definition: MainWindow.cpp:336
void close()
Definition: MainWindow.cpp:469
QAction * _actionShowControlPanel
Definition: MainWindow.h:280
QString _previousSocksPort
Definition: MainWindow.h:311
bool _startedWithPrevious
Definition: MainWindow.h:309
void checkTorVersion()
QString _controlPassword
Definition: MainWindow.h:260
void setStartupProgress(int percentComplete, const QString &description)
bool tryCookie(const ProtocolInfo &pi)
QMenu * createTrayMenu()
Definition: MainWindow.cpp:245
void startFailed(QString errmsg)
Definition: MainWindow.cpp:853
QAction * _actionDebugDialog
Definition: MainWindow.h:293
TorControl * _torControl
Definition: MainWindow.h:257
void attachTab()
QByteArray loadControlCookie(QString cookiePath=QString())
QAction * _actionBandwidthGraph
Definition: MainWindow.h:288
bool _useSavedPassword
Definition: MainWindow.h:263
void dangerousTorVersion(tc::TorVersionStatus reason, const QString &version, const QStringList &recommended)
bool _delayedShutdownStarted
Definition: MainWindow.h:253
QAction * _actionStatus
Definition: MainWindow.h:285
QAction * _actionVidaliaHelp
Definition: MainWindow.h:290
bool authenticate()
virtual void setVisible(bool visible)
Definition: MainWindow.cpp:318
void disconnected()
void circuitEstablished()
QStringList _detachedTabMap
Definition: MainWindow.h:307
QAction * _actionNewIdentity
Definition: MainWindow.h:284
QAction * _actionAbout
Definition: MainWindow.h:291
QAction * _actionConfigure
Definition: MainWindow.h:289
void warnDangerousPort(quint16 port, bool rejected)
void createTrayIcon()
Definition: MainWindow.cpp:295
QAction * _actionMessageLog
Definition: MainWindow.h:287
void connected()
Definition: MainWindow.cpp:892
void displayTorVersionWarning()
QAction * _actionStartStopTor
Definition: MainWindow.h:281
StatusTab _statusTab
Definition: MainWindow.h:300
void disconnect()
QString _previousControlPort
Definition: MainWindow.h:310
TorStatus updateTorStatus(TorStatus status)
void showMessageLogTab()
void createGUI()
Definition: MainWindow.cpp:146
void newIdentity()
QAction * _actionNetworkMap
Definition: MainWindow.h:286
void showConfigDialog(ConfigDialog::Page page=ConfigDialog::General)
void setStartupProgressVisible(bool visible)
PluginEngine * _engine
Definition: MainWindow.h:305
bool tryHashed()
QAction * _actionRestartTor
Definition: MainWindow.h:282
void detachTab()
void addTab(VidaliaTab *tab)
TorStatus _status
Definition: MainWindow.h:249
void showStatusTab()
void createToolBar()
Definition: MainWindow.cpp:231
void authenticationFailed(QString errmsg)
QSystemTrayIcon _trayIcon
Definition: MainWindow.h:265
void setTrayIcon(const QString &iconFile)
QAction * _dummy
Definition: MainWindow.h:296
void handleAttachedClose()
void delTab(int index=-1)
void createConnections()
Definition: MainWindow.cpp:378
Ui::MainWindow ui
Definition: MainWindow.h:298
bool _isVidaliaRunningTor
Definition: MainWindow.h:255
MessageLog * _messageLog
Definition: MainWindow.h:301
QList< QAction * > getAllActions()
QStringList authMethods() const
Definition: ProtocolInfo.h:35
QString cookieAuthFile() const
Definition: ProtocolInfo.h:41
bool isEmpty() const
void configurePortForwarding()
void cleanupPortForwarding()
void setProgressVisible(bool visible)
Definition: StatusTab.cpp:56
void checkShowOnStartup(bool check)
Definition: StatusTab.cpp:69
void setTorStatus(const QPixmap &icon)
Definition: StatusTab.cpp:29
void setTorStatusVisible(bool visible)
Definition: StatusTab.cpp:42
bool isCheckedShowOnStartup()
Definition: StatusTab.cpp:63
void setProgress(int progress, const QString &description)
Definition: StatusTab.cpp:49
void hideCheckShowOnStartup()
Definition: StatusTab.cpp:75
BootstrapStatus bootstrapStatus(QString *errmsg=0)
Definition: TorControl.cpp:403
void circuitEstablished()
bool authenticate(const QByteArray cookie, QString *errmsg=0)
Definition: TorControl.cpp:298
bool isCircuitEstablished()
Definition: TorControl.cpp:424
bool takeOwnership(QString *errmsg)
bool setEvents(QString *errmsg=0)
Definition: TorControl.cpp:707
bool signal(TorSignal::Signal sig, QString *errmsg=0)
Definition: TorControl.cpp:555
bool isVidaliaRunningTor()
Definition: TorControl.cpp:163
void start(const QString &tor, const QStringList &args)
Definition: TorControl.cpp:110
void connect(const QHostAddress &address, quint16 port)
Definition: TorControl.cpp:195
bool isConnected()
Definition: TorControl.cpp:262
void disconnect()
Definition: TorControl.cpp:210
bool getInfo(QHash< QString, QString > &map, QString *errmsg=0)
Definition: TorControl.cpp:450
bool setEvent(TorEvents::Event e, bool add=true, bool set=true, QString *errmsg=0)
Definition: TorControl.cpp:697
bool isRunning()
Definition: TorControl.cpp:170
quint16 getSocksPort(QString *errmsg=0)
Definition: TorControl.cpp:608
quint32 getTorVersion()
Definition: TorControl.cpp:667
bool stop(QString *errmsg=0)
Definition: TorControl.cpp:131
ProtocolInfo protocolInfo(QString *errmsg=0)
Definition: TorControl.cpp:350
QString getTorVersionString()
Definition: TorControl.cpp:659
void closeTorStdout()
Definition: TorControl.cpp:179
@ GeneralStatus
Definition: TorEvents.h:56
@ ClientStatus
Definition: TorEvents.h:57
void setBootstrap(bool enabled)
QString getExecutable() const
QList< quint16 > getWarnPlaintextPorts() const
bool useRandomPassword() const
static QString randomPassword()
QString getControlPassword() const
quint16 getControlPort() const
bool bootstrap() const
QHostAddress getControlAddress() const
QList< quint16 > getRejectPlaintextPorts() const
QString getDataDirectory() const
QString getTorrc() const
QString bootstrapFrom() const
QString getSocketPath() const
void setRejectPlaintextPorts(const QList< quint16 > &ports)
void setWarnPlaintextPorts(const QList< quint16 > &ports)
ControlMethod::Method getControlMethod() const
bool autoControlPort() const
void setAutoControlPort(const bool autoControl)
AuthenticationMethod getAuthenticationMethod() const
static QString hashPassword(const QString &password)
@ Shutdown
Definition: TorSignal.h:28
static UPNPControl * instance()
Definition: UPNPControl.cpp:31
static int checkForUpdatesInterval()
static QDateTime nextCheckForUpdates(const QDateTime &lastCheckedAt)
static bool shouldCheckForUpdates(const QDateTime &lastCheckedAt)
void setTab(VidaliaTab *tab)
VidaliaTab * getTab()
static int information(QWidget *parent, QString caption, QString text, int button0, int button1=NoButton, int button2=NoButton)
static int warning(QWidget *parent, QString caption, QString text, int button0, int button1=NoButton, int button2=NoButton)
static int question(QWidget *parent, QString caption, QString text, int button0, int button1=NoButton, int button2=NoButton, QString remember=QString(), VSettings *settings=0, QString key=QString())
static TorControl * torControl()
Definition: Vidalia.h:76
bool skipVersionCheck() const
void setLastCheckedForUpdates(const QDateTime &checkedAt)
IconPosition getIconPref()
QDateTime lastCheckedForUpdates() const
bool isAutoUpdateEnabled() const
QString getTitle() const
Definition: VidaliaTab.h:34
virtual void setVisible(bool visible)
void helpRequested(const QString &topic)
bool touch_file(const QString &filename, bool createdir, QString *errmsg)
Definition: file.cpp:31
QString expand_filename(const QString &filename)
Definition: file.cpp:108
QString p(QString str)
Definition: html.cpp:22
Definition: tcglobal.cpp:19
DebugMessage warn(const QString &fmt)
Definition: tcglobal.cpp:32
TorVersionStatus
Definition: tcglobal.h:86
@ UnrecommendedTorVersion
Definition: tcglobal.h:88
@ ObsoleteTorVersion
Definition: tcglobal.h:87
DebugMessage error(const QString &fmt)
Definition: tcglobal.cpp:40
@ NoRouteToHost
Definition: tcglobal.h:65
@ ResourceLimitReached
Definition: tcglobal.h:66
@ ConnectionTimeout
Definition: tcglobal.h:63
@ ConnectionRefused
Definition: tcglobal.h:61
@ MiscellaneousReason
Definition: tcglobal.h:58
@ ConnectionIoError
Definition: tcglobal.h:64
@ IdentityMismatch
Definition: tcglobal.h:59
@ ConnectionDone
Definition: tcglobal.h:60
@ WarnSeverity
Definition: tcglobal.h:74
bool socket_test_connect(QString server, int timeout)
Definition: net.cpp:37
bool net_test_connect(QHostAddress host, quint16 port, int timeout)
Definition: net.cpp:25
QHash< qint64, QString > process_list(quint16 port)
Definition: procutil.cpp:112
bool process_kill(qint64 pid)
Definition: procutil.cpp:118
bool err(QString *str, const QString &errmsg)
Definition: stringutil.cpp:37