47 #include <Carbon/Carbon.h>
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"
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"
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)
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);
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"
93 #define MIN_NEWIDENTITY_INTERVAL (10*1000)
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)
115 _dummy =
new QAction(tr(
"No dettached tabs"),
this);
125 #if defined(Q_WS_MAC)
129 ProcessSerialNumber psn = { 0, kCurrentProcess };
130 TransformProcessType(&psn, kProcessTransformToForegroundApplication);
160 ui.tabWidget->pinTab(0);
189 QMenuBar *menu = menuBar();
192 QMenu *torMenu = menu->addMenu(tr(
"Tor"));
195 #if !defined(Q_WS_WIN)
198 torMenu->addSeparator();
201 QMenu *actionsMenu = menu->addMenu(tr(
"Actions"));
204 QMenu *viewMenu = menu->addMenu(tr(
"View"));
209 viewMenu->addSeparator();
212 QMenu *pluginsMenu = menu->addMenu(tr(
"Plugins"));
214 pluginsMenu->addAction(action);
216 pluginsMenu->addSeparator();
221 _dummy->setEnabled(
false);
223 QMenu *helpMenu = menu->addMenu(tr(
"Help"));
225 helpMenu->addSeparator();
233 QToolBar *tool =
ui.toolBar;
239 tool->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
247 QMenu *menu =
new QMenu(
this);
249 menu->addSeparator();
254 menu->addSeparator();
259 #if !defined(Q_WS_MAC)
265 menu->addSeparator();
275 if (source.startsWith(
"OR:", Qt::CaseInsensitive)) {
279 if (torVersion <= 0x00020113)
282 if (str.startsWith(
"0.2.2.") && torVersion <= 0x00020201)
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."));
305 #if defined(Q_WS_MAC)
306 qt_mac_set_dock_menu(menu);
322 if (!QSystemTrayIcon::isSystemTrayAvailable()) {
338 if (reason == QSystemTrayIcon::DoubleClick)
367 #if !defined(Q_WS_MAC)
374 ui.retranslateUi(
this);
405 this, SLOT(
stopped(
int, QProcess::ExitStatus)));
418 QString, QStringList)),
420 QString, QStringList)));
430 connect(
ui.tabWidget, SIGNAL(tabCloseRequested(
int)),
433 #if defined(USE_AUTOUPDATE)
435 connect(&_updateTimer, SIGNAL(timeout()),
this, SLOT(checkForUpdates()));
439 connect(_configDialog, SIGNAL(checkForUpdates()),
440 this, SLOT(checkForUpdatesWithUi()));
443 connect(&_updateProcess, SIGNAL(downloadProgress(QString,
int,
int)),
444 &_updateProgressDialog, SLOT(setDownloadProgress(QString,
int,
int)));
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()));
455 #if defined(USE_MINIUPNPC)
493 if (
vApp->readPasswordFromStdin()) {
494 QTextStream in(stdin);
511 #if defined(USE_AUTOUPDATE)
521 _updateTimer.start(5*60*1000);
529 QDateTime now = QDateTime::currentDateTime().toUTC();
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);
545 vNotice(
"Cleaning up before exiting.");
574 vWarn(
"Disabling ControlPort autoconfiguration. DataDirectory is empty!");
594 QString torrc = settings.
getTorrc();
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)) {
608 if (!torrc.isEmpty()) {
609 if (!QFileInfo(torrc).exists())
611 args <<
"-f" << torrc;
617 if (!dataDirectory.isEmpty())
618 args <<
"DataDirectory" << expDataDirectory;
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));
626 QString control_str =
"auto";
627 QString socks_str =
"auto";
638 args <<
"ControlPort" << control_str;
639 args <<
"SocksPort" << socks_str;
640 args <<
"ControlPortWriteToFile" << QString(
"%1/port.conf").arg(expDataDirectory);
645 args <<
"ControlPort" << QString::number(controlPort);
649 args <<
"ControlSocket" << path;
652 args <<
"__OwningControllerProcess" << QString::number(QCoreApplication::applicationPid());
657 if (!
vApp->readPasswordFromStdin()) {
666 args <<
"HashedControlPassword"
671 args <<
"CookieAuthentication" <<
"1";
674 args <<
"CookieAuthentication" <<
"0";
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)
717 if(tries >= maxtries) {
718 vWarn(
"Couldn't read port.conf file");
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()));
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."));
730 QTextStream in(&file);
732 QString line = in.readLine();
733 QStringList parts = line.split(
"=");
734 if(parts.size() != 2)
return;
735 if(parts[0].trimmed() !=
"PORT")
return;
737 QStringList addrPort = parts[1].split(
":");
738 if(addrPort.size() != 2)
return;
740 QHostAddress addr(addrPort.at(0));
741 quint16 port = addrPort.at(1).toInt();
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?"),
803 p(tr(
"Vidalia was unable to stop the Tor software."))
833 if (exitStatus == QProcess::CrashExit || exitCode != 0) {
835 tr(
"Vidalia detected that the Tor software exited "
837 "Please check the message log for recent "
838 "warning or error messages."),
864 vWarn(
"Retrying with new ports");
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."),
904 QString control_str =
"", socks_str =
"";
906 QStringList control_parts = control_str.split(
":");
907 if(control_parts.size() > 1)
908 control_str = control_parts[1];
911 QStringList socks_parts = socks_str.split(
":");
912 if(socks_parts.size() > 1)
913 socks_str = socks_parts[1];
932 tr(
"Connection Error"),
p(errmsg),
964 tr(
"Connecting to the Tor network"));
973 p(tr(
"Vidalia was unable to register for some events. "
974 "Many of Vidalia's features may be unavailable."))
1007 vWarn(
"Authentication failed: %1").arg(errmsg);
1010 if (errmsg.contains(
"Password did not match")) {
1019 foreach (qint64 pid, procs.keys()) {
1020 if (! procs.value(pid).compare(
"tor", Qt::CaseInsensitive)) {
1028 int ret = dlg.exec();
1029 if (ret == QDialogButtonBox::Reset) {
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.")),
1056 const QString ¤t,
1057 const QStringList &recommended)
1060 Q_UNUSED(recommended);
1072 static bool alreadyWarned =
false;
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);
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)),
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?")),
1097 checkForUpdatesWithUi();
1099 alreadyWarned =
true;
1112 QString description;
1115 description = tr(
"Connecting to a relay directory");
1119 description = tr(
"Establishing an encrypted directory connection");
1122 description = tr(
"Retrieving network status");
1125 description = tr(
"Loading network status");
1128 description = tr(
"Loading authority certificates");
1131 description = tr(
"Requesting relay information");
1134 description = tr(
"Loading relay information");
1137 description = tr(
"Connecting to the Tor network");
1141 description = tr(
"Establishing a Tor circuit");
1144 description = tr(
"Connected to the Tor network!");
1148 description = tr(
"Unrecognized startup status");
1155 reason = tr(
"miscellaneous");
1158 reason = tr(
"identity mismatch");
1161 reason = tr(
"done");
1164 reason = tr(
"connection refused");
1167 reason = tr(
"connection timeout");
1170 reason = tr(
"read/write error");
1173 reason = tr(
"no route to host");
1176 reason = tr(
"insufficient resources");
1179 reason = tr(
"unknown");
1181 description += tr(
" failed (%1)").arg(reason);
1193 tr(
"Connected to the Tor network!"));
1195 #if defined(USE_AUTOUPDATE)
1201 _updateTimer.stop();
1218 static QMessageBox *dlg = 0;
1224 QString application;
1227 application = tr(
"(probably Telnet)");
1233 application = tr(
"(probably an email client)");
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);
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."));
1249 extraText.append(
p(tr(
"Tor has automatically closed your connection in "
1250 "order to protect your anonymity.")));
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);
1260 int ret = dlg->exec();
1261 if (ret == QMessageBox::Ignore) {
1264 QStringList portList;
1265 QList<quint16> ports;
1269 idx = ports.indexOf(port);
1271 ports.removeAt(idx);
1274 foreach (quint16 port, ports) {
1275 portList << QString::number(port);
1277 tc->
setConf(
"WarnPlaintextPorts", portList.join(
","));
1282 idx = ports.indexOf(port);
1284 ports.removeAt(idx);
1287 foreach (quint16 port, ports) {
1288 portList << QString::number(port);
1290 tc->
setConf(
"RejectPlaintextPorts", portList.join(
","));
1309 tr(
"Authenticating to Tor"));
1313 QStringList authMethods;
1316 if (authMethods.contains(
"COOKIE"))
1318 else if (authMethods.contains(
"HASHEDPASSWORD"))
1320 else if (authMethods.contains(
"NULL"))
1326 if(authMethods.contains(
"HASHEDPASSWORD") and !
tryHashed()) {
1338 vNotice(
"Authenticating using 'null' authentication.");
1342 vWarn(
"Cancelling control authentication attempt.");
1356 while (cookie.isEmpty()) {
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?")),
1370 QString cookieDir = QFileDialog::getOpenFileName(
this,
1371 tr(
"Data Directory"),
1373 tr(
"Control Cookie (control_auth_cookie)"));
1374 if (cookieDir.isEmpty())
1376 cookieDir = QFileInfo(cookieDir).absolutePath();
1379 if(cookie.size() != 32) {
1380 vWarn(QString(
"Cookie length has to be exactly 32 bytes long. Found %1 bytes")
1381 .arg(cookie.size()));
1384 vNotice(
"Authenticating using 'cookie' authentication.");
1392 vNotice(
"Authenticating using 'hashed password' authentication.");
1398 qputenv(
"TOR_CONTROL_PASSWD",
1414 if (!status.compare(
"old", Qt::CaseInsensitive)
1415 || !status.compare(
"unrecommended", Qt::CaseInsensitive)
1416 || !status.compare(
"obsolete", Qt::CaseInsensitive)) {
1431 QStringList pathList;
1433 if (!cookiePath.isEmpty()) {
1434 pathList << cookiePath;
1439 if (!dataDir.isEmpty())
1440 pathList << dataDir;
1442 #if defined(Q_WS_WIN)
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())
1457 authCookie.setFileName(cookieFile);
1458 if (authCookie.open(QIODevice::ReadOnly)) {
1459 vInfo(
"Reading authentication cookie from '%1'").arg(cookieFile);
1460 return authCookie.readAll();
1462 vWarn(
"Couldn't open cookie file '%1': %2")
1463 .arg(cookieFile).arg(authCookie.errorString());
1466 vWarn(
"Couldn't find a readable authentication cookie.");
1467 return QByteArray();
1475 QString statusText, actionText;
1476 QString trayIconFile, statusIconFile;
1479 vNotice(
"Tor status changed from '%1' to '%2'.")
1484 statusText = tr(
"Tor is not running");
1485 actionText = tr(
"Start Tor");
1504 statusText = tr(
"Your relay is shutting down.\n"
1505 "Click 'Stop' again to stop your relay now.");
1507 statusText = tr(
"Tor is shutting down");
1512 }
else if (status ==
Started) {
1513 actionText = tr(
"Stop Tor");
1525 statusText = tr(
"Starting the Tor software");
1534 statusText = tr(
"Connected to the Tor network!");
1541 if (!trayIconFile.isEmpty()) {
1545 if (!statusIconFile.isEmpty())
1547 if (!statusText.isEmpty()) {
1558 #if defined(Q_WS_MAC)
1560 QApplication::setWindowIcon(QPixmap(iconFile));
1578 case Unset:
return "Unset";
1580 case Stopped:
return "Stopped";
1582 case Started:
return "Started";
1610 p(tr(
"Vidalia was unable to reload Tor's configuration."))
1629 const QString &description)
1677 QString title = tr(
"New Identity");
1678 QString message = tr(
"All subsequent connections will "
1679 "appear to be different than your "
1680 "old connections.");
1687 if (QSystemTrayIcon::supportsMessages())
1688 _trayIcon.showMessage(title, message, QSystemTrayIcon::Information);
1722 QAction *act = qobject_cast<QAction *>(sender());
1725 tab->setParent(
ui.tabWidget);
1730 _dummy->setEnabled(
false);
1739 int index =
ui.tabWidget->indexOf(tab);
1741 ui.tabWidget->removeTab(index);
1745 QString key =
_tabMap.at(index);
1749 QAction *act =
new QAction(tab->getTitle(), tab);
1759 int index =
ui.tabWidget->indexOf(tab);
1763 if(tmpAct->parent() == tab) {
1774 tab->setParent(
ui.tabWidget);
1779 _dummy->setEnabled(
false);
1782 delTab(
ui.tabWidget->currentIndex());
1811 int pos =
ui.tabWidget->count() - 1;
1812 ui.tabWidget->setCurrentIndex(pos);
1815 #if defined(Q_WS_MAC)
1816 ui.tabWidget->setTabButton(pos, QTabBar::RightSide, atb);
1818 ui.tabWidget->setTabButton(pos, QTabBar::LeftSide, atb);
1821 connect(tab, SIGNAL(closeTab()),
1840 index =
ui.tabWidget->currentIndex();
1851 ui.tabWidget->removeTab(index);
1852 QString key =
_tabMap.at(index);
1913 #if defined(USE_MINIUPNPC)
1927 tr(
"Port Forwarding Failed"),
1928 p(tr(
"Vidalia was unable to configure automatic port forwarding."))
1929 +
p(UPNPControl::Instance()->errorString()),
1935 #if defined(USE_AUTOUPDATE)
1939 MainWindow::checkForUpdatesWithUi()
1941 checkForUpdates(
true);
1947 MainWindow::checkForUpdates(
bool showProgress)
1951 if (_updateProcess.isRunning()) {
1956 _updateProgressDialog.show();
1963 _updateProcess.setSocksPort(0);
1968 _updateProgressDialog.show();
1986 MainWindow::checkForUpdatesFailed(
const QString &errmsg)
1988 if (_updateProgressDialog.isVisible()) {
1989 _updateProgressDialog.hide();
2000 vInfo(
"%1 software update(s) available").arg(packageList.size());
2001 if (packageList.size() > 0) {
2004 switch (dlg.exec()) {
2010 _updateProgressDialog.hide();
2014 if (_updateProgressDialog.isVisible()) {
2015 _updateProgressDialog.hide();
2017 tr(
"There are no new Tor software packages "
2018 "available for your computer at this time."),
2030 _updateProgressDialog.show();
2033 _restartTorAfterUpgrade =
true;
2037 _restartTorAfterUpgrade =
false;
2039 _updateProcess.installUpdates(bi);
2045 MainWindow::updatesInstalled(
int numUpdates)
2048 _updateProgressDialog.show();
2050 if (_restartTorAfterUpgrade)
2057 MainWindow::installUpdatesFailed(
const QString &errmsg)
2059 _updateProgressDialog.hide();
2062 p(tr(
"Vidalia was unable to install your software updates."))
2063 +
p(tr(
"The following error occurred:"))
2067 if (_restartTorAfterUpgrade)