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
30 #include "UpdatesAvailableDialog.h"
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"
83 void 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. */
145 void
147 {
148  ui.setupUi(this);
149  createActions();
150  createMenuBar();
151  createToolBar();
152  createTrayIcon();
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 
159  addTab(&_statusTab);
160  ui.tabWidget->pinTab(0);
161 }
162 
163 /** Creates the actions used in toolbars and menu */
164 void
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 */
184 void
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 */
230 void
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. */
244 QMenu*
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 */
272 void
273 MainWindow::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. */
294 void
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 
317 void
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  }
330  VidaliaWindow::setVisible(visible);
331 }
332 
333 /** Respond to a double-click on the tray icon by opening the Control Panel
334  * window. */
335 void
336 MainWindow::trayIconActivated(QSystemTrayIcon::ActivationReason reason)
337 {
338  if (reason == QSystemTrayIcon::DoubleClick)
339  setVisible(!isVisible());
340 }
341 
342 void
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 
373  createMenuBar();
374  ui.retranslateUi(this);
375 }
376 
377 void
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. */
468 void
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. */
488 void
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. */
542 void
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. */
563 void
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;
631  _startedWithPrevious = true;
632  }
633  if(!_previousSocksPort.isEmpty()) {
634  socks_str = _previousSocksPort;
635  _startedWithPrevious = true;
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. */
688 void
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. */
699  _delayedShutdownStarted = false;
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. */
758 bool
760 {
761  ServerSettings server(_torControl);
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;
814  _delayedShutdownStarted = 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. */
822 void
823 MainWindow::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. */
852 void
853 MainWindow::startFailed(QString errmsg)
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;
863  _previousSocksPort = "";
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. */
891 void
893 {
894  authenticate();
896  QString err;
897  if(!_torControl->takeOwnership(&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
921  _previousSocksPort = "";
922  }
923 }
924 
925 /** Called when the connection to the control socket fails. The reason will be
926  * given in the errmsg parameter. */
927 void
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. */
952 void
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)
992  checkTorVersion();
993  if (_torControl->getTorVersion() >= 0x020102) {
995  if (status.isValid())
996  bootstrapStatusChanged(status);
997  }
998 }
999 
1000 /** Called when Vidalia fails to authenticate to Tor. The failure reason is
1001  * specified in <b>errmsg</b>. */
1002 void
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)) {
1031  VMessageBox::warning(this,
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())
1044  if (_isVidaliaRunningTor)
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. */
1054 void
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. */
1069 void
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)),
1085  VMessageBox::Ok);
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. */
1105 void
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;
1157  case tc::IdentityMismatch:
1158  reason = tr("identity mismatch");
1159  break;
1160  case tc::ConnectionDone:
1161  reason = tr("done");
1162  break;
1163  case tc::ConnectionRefused:
1164  reason = tr("connection refused");
1165  break;
1166  case tc::ConnectionTimeout:
1167  reason = tr("connection timeout");
1168  break;
1169  case tc::ConnectionIoError:
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. */
1187 void
1189 {
1191  // TODO: fix hardcoded total length
1192  setStartupProgress(130,
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. */
1215 void
1216 MainWindow::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  */
1300 bool
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 
1341 cancel:
1342  vWarn("Cancelling control authentication attempt.");
1344  stop();
1345  else
1346  disconnect();
1347  return false;
1348 }
1349 
1350 bool
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 
1388 bool
1390 {
1391  /* Get the control password and send it to Tor */
1392  vNotice("Authenticating using 'hashed password' authentication.");
1393  if (_useSavedPassword) {
1394  TorSettings settings;
1395  _controlPassword = settings.getControlPassword();
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. */
1406 void
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. */
1427 QByteArray
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>. */
1555 void
1556 MainWindow::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. */
1572 QString
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 */
1592 void
1594 {
1595  if(stop()) {
1596  start();
1597  }
1598 }
1599 
1600 /** Sends a sighup signal to Tor on platforms other than Windows */
1601 void
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),
1612  VMessageBox::Ok);
1613  }
1614 }
1615 
1616 /** Sets the visibility of the startup status description and progress bar to
1617  * <b>visible</b>. */
1618 void
1620 {
1621  _statusTab.setTorStatusVisible(!visible);
1622  _statusTab.setProgressVisible(visible);
1623 }
1624 
1625 /** Sets the progress bar completion value to <b>progressValue</b> and sets
1626  * the status text to <b>description</b>. */
1627 void
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. */
1636 void
1638 {
1640 }
1641 
1642 /** Called when the control socket has been disconnected. */
1643 void
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 
1657 void
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. */
1667 void
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 */
1693  VMessageBox::warning(this,
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. */
1700 void
1702 {
1703  if (_torControl->isConnected()) {
1704  _actionNewIdentity->setEnabled(true);
1705  }
1706 }
1707 
1708 void
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 
1719 void
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 
1734 void
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 
1755 void
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 
1786 void
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 
1836 void
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 
1856 void
1858 {
1859  addTab(&_statusTab);
1860 }
1861 
1862 void
1864 {
1866 }
1867 
1868 void
1870 {
1871  addTab(_graph);
1872 }
1873 
1874 /** Creates and displays Vidalia's About dialog. */
1875 void
1877 {
1878  AboutDialog dlg(this);
1879  dlg.exec();
1880 }
1881 
1882 /** Displays the help browser and displays the most recently viewed help
1883  * topic. */
1884 void
1886 {
1887  showHelpDialog(QString());
1888 }
1889 
1890 /**< Shows the help browser and displays the given help <b>topic</b>. */
1891 void
1892 MainWindow::showHelpDialog(const QString &topic)
1893 {
1894  static HelpBrowser *helpBrowser = 0;
1895  if (!helpBrowser)
1896  helpBrowser = new HelpBrowser(this);
1897  helpBrowser->showWindow(topic);
1898 }
1899 
1900 void
1902 {
1903  addTab(&_netViewer);
1904 }
1905 
1906 void
1908 {
1909  DebugDialog dlg;
1910  dlg.exec();
1911 }
1912 
1913 #if defined(USE_MINIUPNPC)
1914 /** Called when a UPnP error occurs. */
1915 void
1916 MainWindow::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 
1926  VMessageBox::warning(this,
1927  tr("Port Forwarding Failed"),
1928  p(tr("Vidalia was unable to configure automatic port forwarding."))
1929  + p(UPNPControl::Instance()->errorString()),
1930  VMessageBox::Ok);
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. */
1938 void
1939 MainWindow::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. */
1946 void
1947 MainWindow::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. */
1985 void
1986 MainWindow::checkForUpdatesFailed(const QString &errmsg)
1987 {
1988  if (_updateProgressDialog.isVisible()) {
1989  _updateProgressDialog.hide();
1990  VMessageBox::warning(this, tr("Update Failed"), errmsg,
1991  VMessageBox::Ok);
1992  }
1993 }
1994 
1995 /** Called when there is an update available for installation. */
1996 void
1997 MainWindow::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."),
2019  VMessageBox::Ok);
2020  }
2021  }
2022 }
2023 
2024 /** Stops Tor (if necessary), installs any available for <b>bi</b>, and
2025  * restarts Tor (if necessary). */
2026 void
2027 MainWindow::installUpdates(UpdateProcess::BundleInfo bi)
2028 {
2029  _updateProgressDialog.setStatus(UpdateProgressDialog::InstallingUpdates);
2030  _updateProgressDialog.show();
2031 
2032  if (_isVidaliaRunningTor) {
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. */
2044 void
2045 MainWindow::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. */
2056 void
2057 MainWindow::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),
2065  VMessageBox::Ok);
2066 
2067  if (_restartTorAfterUpgrade)
2068  start();
2069 }
2070 
2071 #endif
2072 
bool touch_file(const QString &filename, bool createdir, QString *errmsg)
Definition: file.cpp:31
QString p(QString str)
Definition: html.cpp:22
bool _isIntentionalExit
Definition: MainWindow.h:251
DebugMessage error(const QString &fmt)
Definition: tcglobal.cpp:40
#define IMG_START_TOR_16
Definition: MainWindow.cpp:60
bool signal(TorSignal::Signal sig, QString *errmsg=0)
Definition: TorControl.cpp:555
TorStatus updateTorStatus(TorStatus status)
BandwidthGraph * _graph
Definition: MainWindow.h:303
bool stop(QString *errmsg=0)
Definition: TorControl.cpp:131
bool stop()
Definition: MainWindow.cpp:759
void setProgressVisible(bool visible)
Definition: StatusTab.cpp:56
bool _useSavedPassword
Definition: MainWindow.h:263
static int checkForUpdatesInterval()
QAction * _actionMessageLog
Definition: MainWindow.h:287
void closeTorStdout()
Definition: TorControl.cpp:179
void showStatusTab()
QAction * _dummy
Definition: MainWindow.h:296
tc::Severity severity() const
void newIdentity()
#define IMG_EXIT
Definition: MainWindow.cpp:57
Definition: tcglobal.cpp:19
QAction * _actionVidaliaHelp
Definition: MainWindow.h:290
QString expand_filename(const QString &filename)
Definition: file.cpp:108
bool useRandomPassword() const
Recommendation recommendedAction() const
bool err(QString *str, const QString &errmsg)
Definition: stringutil.cpp:37
void disconnect()
Definition: TorControl.cpp:210
void connected()
Definition: MainWindow.cpp:892
bool _startedWithPrevious
Definition: MainWindow.h:309
static UPNPControl * instance()
Definition: UPNPControl.cpp:31
bool isAutoUpdateEnabled() const
quint32 getTorVersion()
Definition: TorControl.cpp:667
QSystemTrayIcon _trayIcon
Definition: MainWindow.h:265
void trayIconActivated(QSystemTrayIcon::ActivationReason reason)
Definition: MainWindow.cpp:336
void setProgress(int progress, const QString &description)
Definition: StatusTab.cpp:49
QStringList _tabMap
Definition: MainWindow.h:306
void delTab(int index=-1)
#define IMG_TOR_RUNNING
Definition: MainWindow.cpp:87
void checkTorVersion()
#define STARTUP_PROGRESS_BOOTSTRAPPING
Definition: MainWindow.cpp:99
virtual void setVisible(bool visible)
Definition: MainWindow.cpp:318
void configurePortForwarding()
bool authenticate(const QByteArray cookie, QString *errmsg=0)
Definition: TorControl.cpp:298
bool tryHashed()
NetViewer _netViewer
Definition: MainWindow.h:302
#define vInfo(fmt)
Definition: Vidalia.h:40
QStringList _detachedTabMap
Definition: MainWindow.h:307
QString _previousSocksPort
Definition: MainWindow.h:311
void running()
Definition: MainWindow.cpp:489
void createMenuBar()
Definition: MainWindow.cpp:185
void authenticationFailed(QString errmsg)
QAction * _actionNewIdentity
Definition: MainWindow.h:284
bool bootstrap() const
VidaliaTab * getTab()
QList< quint16 > getRejectPlaintextPorts() const
void bootstrapStatusChanged(const BootstrapStatus &bs)
bool setConf(QHash< QString, QString > map, QString *errmsg=0)
Definition: TorControl.cpp:722
void showDebugDialog()
void createActions()
Definition: MainWindow.cpp:165
QString _previousControlPort
Definition: MainWindow.h:310
QString _controlPassword
Definition: MainWindow.h:260
quint16 getSocksPort(QString *errmsg=0)
Definition: TorControl.cpp:608
QMenu * createTrayMenu()
Definition: MainWindow.cpp:245
bool setEvent(TorEvents::Event e, bool add=true, bool set=true, QString *errmsg=0)
Definition: TorControl.cpp:697
bool isEmpty() const
void handleCloseTab(int index)
bool setEvents(QString *errmsg=0)
Definition: TorControl.cpp:707
bool _isVidaliaRunningTor
Definition: MainWindow.h:255
bool getInfo(QHash< QString, QString > &map, QString *errmsg=0)
Definition: TorControl.cpp:450
void setTab(VidaliaTab *tab)
Status status() const
QMenu _reattachMenu
Definition: MainWindow.h:295
TorControl * _torControl
Definition: MainWindow.h:257
AuthenticationMethod getAuthenticationMethod() const
void circuitEstablished()
#define IMG_TOR_STOPPED
Definition: MainWindow.cpp:86
void detachTab()
void hideCheckShowOnStartup()
Definition: StatusTab.cpp:75
void helpRequested(const QString &topic)
#define IMG_TOR_STOPPING_48
Definition: MainWindow.cpp:67
Ui::MainWindow ui
Definition: MainWindow.h:298
QList< QAction * > getAllActions()
QHash< qint64, QString > process_list(quint16 port)
Definition: procutil.cpp:112
void sighup()
void disconnected()
void started()
Definition: MainWindow.cpp:689
void showWindow(Page page=General)
bool isValid() const
tc::ConnectionStatusReason reason() const
#define IMG_TOR_STOPPING
Definition: MainWindow.cpp:89
QString toString(TorStatus status)
TorStatus _status
Definition: MainWindow.h:249
static int information(QWidget *parent, QString caption, QString text, int button0, int button1=NoButton, int button2=NoButton)
bool isRunning()
Definition: TorControl.cpp:170
bool skipVersionCheck() const
void setWarnPlaintextPorts(const QList< quint16 > &ports)
#define vDebug(fmt)
Definition: Vidalia.h:39
void checkShowOnStartup(bool check)
Definition: StatusTab.cpp:69
bool tryCookie(const ProtocolInfo &pi)
void clockSkewed(int skew, const QString &source)
Definition: MainWindow.cpp:273
StatusTab _statusTab
Definition: MainWindow.h:300
void setTorStatusVisible(bool visible)
Definition: StatusTab.cpp:42
#define IMG_IDENTITY
Definition: MainWindow.cpp:54
QList< PackageInfo > PackageList
Definition: PackageInfo.h:93
#define IMG_TOR_STARTING_48
Definition: MainWindow.cpp:66
void circuitEstablished()
void createConnections()
Definition: MainWindow.cpp:378
#define STARTUP_PROGRESS_CIRCUITBUILD
Definition: MainWindow.cpp:100
#define vNotice(fmt)
Definition: Vidalia.h:41
static TorControl * torControl()
Definition: Vidalia.h:76
QList< quint16 > getWarnPlaintextPorts() const
static QString randomPassword()
void connectFailed(QString errmsg)
Definition: MainWindow.cpp:928
void start()
Definition: MainWindow.cpp:564
#define IMG_CONTROL_PANEL
Definition: MainWindow.cpp:51
bool net_test_connect(QHostAddress host, quint16 port, int timeout)
Definition: net.cpp:25
QStringList authMethods() const
Definition: ProtocolInfo.h:35
stop errmsg connect(const QHostAddress &address, quint16 port)
void setTrayIcon(const QString &iconFile)
#define IMG_MESSAGELOG
Definition: MainWindow.cpp:52
void setBootstrap(bool enabled)
PluginEngine * _engine
Definition: MainWindow.h:305
void setTorStatus(const QPixmap &icon)
Definition: StatusTab.cpp:29
void showBandwidthTab()
void showHelpDialog()
virtual void retranslateUi()
Definition: MainWindow.cpp:343
QAction * _actionBandwidthGraph
Definition: MainWindow.h:288
#define IMG_TOR_RUNNING_48
Definition: MainWindow.cpp:65
ControlMethod::Method getControlMethod() const
#define IMG_TOR_STOPPED_48
Definition: MainWindow.cpp:64
#define IMG_BWGRAPH
Definition: MainWindow.cpp:50
#define STARTUP_PROGRESS_CONNECTING
Definition: MainWindow.cpp:97
QDateTime lastCheckedForUpdates() const
TorVersionStatus
Definition: tcglobal.h:86
void setStartupProgressVisible(bool visible)
QString cookieAuthFile() const
Definition: ProtocolInfo.h:41
bool socket_test_connect(QString server, int timeout)
Definition: net.cpp:37
QString getTorVersionString()
Definition: TorControl.cpp:659
void restart()
#define vWarn(fmt)
Definition: Vidalia.h:42
#define MIN_NEWIDENTITY_INTERVAL
Definition: MainWindow.cpp:93
QString getDataDirectory() const
int percentComplete() const
bool isCheckedShowOnStartup()
Definition: StatusTab.cpp:63
bool isCircuitEstablished()
Definition: TorControl.cpp:424
bool autoControlPort() const
stop errmsg disconnect()
void aboutToQuit()
Definition: MainWindow.cpp:543
QString getTorrc() const
IconPosition getIconPref()
ProtocolInfo protocolInfo(QString *errmsg=0)
Definition: TorControl.cpp:350
static int warning(QWidget *parent, QString caption, QString text, int button0, int button1=NoButton, int button2=NoButton)
void cleanupPortForwarding()
void showConfigDialog(ConfigDialog::Page page=ConfigDialog::General)
void createGUI()
Definition: MainWindow.cpp:146
void setAutoControlPort(const bool auto)
bool process_kill(qint64 pid)
Definition: procutil.cpp:118
#define IMG_CONFIG
Definition: MainWindow.cpp:53
QAction * _actionReloadConfig
Definition: MainWindow.h:283
QString bootstrapFrom() const
void warnDangerousPort(quint16 port, bool rejected)
bool isConnected()
Definition: TorControl.cpp:262
void close()
Definition: MainWindow.cpp:469
void showWindow(QString topic=QString())
void setRejectPlaintextPorts(const QList< quint16 > &ports)
#define IMG_NETWORK
Definition: MainWindow.cpp:58
bool takeOwnership(QString *errmsg)
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())
MessageLog * _messageLog
Definition: MainWindow.h:301
bool isVidaliaRunningTor()
Definition: TorControl.cpp:163
QString getSocketPath() const
void displayTorVersionWarning()
static QString hashPassword(const QString &password)
#define IMG_STOP_TOR_16
Definition: MainWindow.cpp:61
void showAboutDialog()
void authenticated()
Definition: MainWindow.cpp:953
void connect(const QHostAddress &address, quint16 port)
Definition: TorControl.cpp:195
void stopped(int errorCode, QProcess::ExitStatus exitStatus)
Definition: MainWindow.cpp:823
void createTrayIcon()
Definition: MainWindow.cpp:295
static bool shouldCheckForUpdates(const QDateTime &lastCheckedAt)
#define IMG_ABOUT
Definition: MainWindow.cpp:56
void startFailed(QString errmsg)
Definition: MainWindow.cpp:853
#define vApp
Definition: Vidalia.h:37
static QDateTime nextCheckForUpdates(const QDateTime &lastCheckedAt)
void setLastCheckedForUpdates(const QDateTime &checkedAt)
void dangerousTorVersion(tc::TorVersionStatus reason, const QString &version, const QStringList &recommended)
#define IMG_TOR_STARTING
Definition: MainWindow.cpp:88
QAction * _actionRestartTor
Definition: MainWindow.h:282
void enableNewIdentity()
void showMessageLogTab()
QAction * _actionStartStopTor
Definition: MainWindow.h:281
QAction * _actionConfigure
Definition: MainWindow.h:289
BootstrapStatus bootstrapStatus(QString *errmsg=0)
Definition: TorControl.cpp:403
void handleAttachedClose()
void addTab(VidaliaTab *tab)
QAction * _actionShowControlPanel
Definition: MainWindow.h:280
void disconnect()
QString getTitle() const
Definition: VidaliaTab.h:34
#define STARTUP_PROGRESS_AUTHENTICATING
Definition: MainWindow.cpp:98
void attachTab()
QAction * _actionStatus
Definition: MainWindow.h:285
QString getExecutable() const
#define IMG_HELP
Definition: MainWindow.cpp:55
QString getControlPassword() const
void createToolBar()
Definition: MainWindow.cpp:231
QByteArray loadControlCookie(QString cookiePath=QString())
DebugMessage warn(const QString &fmt)
Definition: tcglobal.cpp:32
void showNetViewerTab()
bool authenticate()
void setStartupProgress(int percentComplete, const QString &description)
virtual void setVisible(bool visible)
QAction * _actionExit
Definition: MainWindow.h:292
quint16 getControlPort() const
QHostAddress getControlAddress() const
QAction * _actionNetworkMap
Definition: MainWindow.h:286
#define SETTING_REMEMBER_SHUTDOWN
bool _delayedShutdownStarted
Definition: MainWindow.h:253
QAction * _actionDebugDialog
Definition: MainWindow.h:293
void start(const QString &tor, const QStringList &args)
Definition: TorControl.cpp:110
QAction * _actionAbout
Definition: MainWindow.h:291
#define STARTUP_PROGRESS_STARTING
Definition: MainWindow.cpp:96