You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3596 lines
154 KiB
Java

/*
* Copyright (C) 2009-2017 Alistair Neil <info@dazzleships.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package client;
import java.awt.Color;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ItemEvent;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JFileChooser;
import javax.swing.JPopupMenu;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.event.TableModelEvent;
import javax.swing.table.TableRowSorter;
import lib.AboutDialog;
import lib.DesktopNotify;
import lib.ExtensionFileFilter;
import lib.GTKFixes;
import lib.InfoDialog;
import lib.TextResourceDialog;
import lib.Localisation;
import lib.NetFunctions;
import lib.OSFunction;
import lib.SimpleFile;
import lib.SimpleProps;
import lib.SwingTrayIcon;
import lib.TrayPopupMenu;
import lib.Utilities;
/**
*
* @author Alistair Neil <info@dazzleships.net>
*/
public class SelekTOR extends javax.swing.JFrame {
private static final Localisation LOCAL = new Localisation("resources/MessagesBundle");
private static final String EMPTYSTR = "";
private static final String PREFSVER = "1.01";
private static final String APPNAME = "SelekTOR";
private static final String APPVER = "3.13.73";
private static final String APPSERIES = "3xx";
private static final String WEBDOMAIN = "www.dazzleships.net";
private static final String FILEDOMAIN = "http://dazzle.000webhostapp.com";
private static final String HOMEPAGE = "http://" + WEBDOMAIN;
private static final String HOMEPAGE_SSL = "https://" + WEBDOMAIN;
private static final String CONTACT = HOMEPAGE_SSL + "/?page_id=247";
private static final String APPUPDATE = FILEDOMAIN + "/anapps/linux/selektor/";
private static final String TESTURL = "http://google.com";
private static final String TORPROJECT = "https://torproject.org/";
private static final String TORCHECK = "https://check.torproject.org/";
private static final String ATLAS = "https://atlas.torproject.org/";
private static final String PATREON = "https://www.patreon.com/SelekTOR";
private static final String DOCSPATH = "/usr/share/doc/selektor/";
private static final String EXITFAVOURITES = "favourites.txt";
private static final String GUARDWHITELIST = "guardwhitelist.txt";
private static final String GEOIPZIP = "geoip.zip";
private static final String GEOIPSHA = "geoip.sha";
private static final String ICONFILE = "selektor.png";
private static final int TESTING_DISABLED = 0;
private static final int TESTING_ACTIVE = -1;
private static final long MAXTHRESHOLD = 5000;
private String torExe;
private String dataDirectory;
private String clientLocation;
private String settingsPath;
private String cachePath;
private String defaultGeoipPath;
private String geoipPath;
private String geoip6Path;
private String iconPath = EMPTYSTR;
private TorController tcMain;
private NodeList nodeList;
private PacFactory pacFactory;
private String strExitISOCode = "GB";
private String strRequestedExit = EMPTYSTR;
private NodeItem niActiveGuard;
private NodeItem niActiveMiddle;
private NodeItem niActiveExit;
private int intRowSelected = -1;
private ExitNodeTableModel entm;
private SimpleProps sp;
private final ArrayList<TorController> alTestThreads = new ArrayList<>();
private int intActiveNodeTests = 0;
private int intBestNodeIndex = 0;
private String[] strArrBestNodes;
private long lngThreshold = MAXTHRESHOLD;
private int intThresholdExceeded = 0;
private NetFunctions nf;
private boolean boolNetEnabled = true;
private String strSecret;
private String strRawSecret;
private String strHash;
private String strDNSHost = "127.0.0.1";
private String strDNSPort = "9053";
private String strHTTPHost = "127.0.0.1";
private String strHTTPPort;
private String strSocksHost = "127.0.0.1";
private String strSocksPort = "9050";
private String strExitNodes = "{FI}";
private String strExcludeNodes;
private final ArrayList<String> alTestQueue = new ArrayList<>();
private Timer tmr;
private int intBeginTesting;
private int intLatencyCheck = 0;
private int intAutoSelectCheck;
private long lngHibernateTimeStamp;
private volatile boolean boolFirstRun;
private ArrayList<String> alArgs;
private TorMonFrame tmf;
private long startupDelay;
private DesktopNotify dn;
private SwingTrayIcon sti;
private String desktopname = EMPTYSTR;
private String compositor = EMPTYSTR;
private boolean updateCheckDisabled;
private int intTimeoutSocketMsec = 8000;
private int intTimeoutStartupDelayMsec = 2000;
private int iLatencyCheck = 0; // 4950
/**
* Initialises SelekTOR UI Frame
*
* @param args
*/
public SelekTOR(String[] args) {
boolFirstRun = true;
// Initialises UI theme to system default
Utilities.loadUIStyle("System");
// Check for multiple instances of this app
if (false && OSFunction.isMultipleInstance(APPNAME)) {
openInstanceDialog();
cleanupExit();
return;
}
// Initialise some essentialvariables
// I know this looks a bit odd but trust me this allows us to install and run from anywhere
String runPath = OSFunction.getUsersCurrentFolder() + OSFunction.getFileSeparator();
if (runPath.startsWith("/usr/share")) {
runPath = "/usr/share/";
}
iconPath = runPath + "icons" + OSFunction.getFileSeparator();
settingsPath = OSFunction.getAppSettingsPath(APPNAME, APPSERIES);
cachePath = settingsPath + "cache" + OSFunction.getFileSeparator();
// Initialise property settings
initProperties();
// Initialise pac factory
initPacFactory();
// Get the desktop
desktopname = OSFunction.getActiveDesktop();
compositor = OSFunction.getCompositor();
// Process any supplied cli arguments
if (processCLIArgs(args)) {
cleanupExit();
return;
}
// Ensure any old proxy settings are cleaned up
pacCleanup();
// Verify Tor client is installed
if (torExe != null) {
clientLocation = torExe;
} else if (OSFunction.isWindows()) {
clientLocation = OSFunction.findFile("tor.exe", "Tor/");
} else {
clientLocation = OSFunction.findFile("tor", "/usr/sbin/", "/usr/bin/");
}
if (clientLocation == null) {
Logger.getGlobal().log(Level.SEVERE, "Tor executable not found.");
openTorClientDialog();
cleanupExit();
return;
}
// Verify if geoip data is installed
defaultGeoipPath = "/usr/share/tor/";
geoipPath = OSFunction.findFile("geoip", settingsPath, defaultGeoipPath);
geoip6Path = OSFunction.findFile("geoip6", settingsPath, defaultGeoipPath);
if (geoipPath == null || geoip6Path == null) {
Logger.getGlobal().log(Level.SEVERE, "Geoip not found.");
openTorClientDialog();
cleanupExit();
return;
}
// Verify if gsettings is installed
if (OSFunction.getGsettingsPath() == null) {
Logger.getGlobal().log(Level.SEVERE, "Gsettings not found.");
openGsettingsDialog();
cleanupExit();
return;
}
// Netbeans components init
initComponents();
Utilities.preloadFileChooser();
updateProgramStatus(LOCAL.getString("progstatus_initial"));
// Process any startup delay
try {
Thread.sleep(startupDelay);
} catch (InterruptedException ex) {
}
startupDelay = -1;
// Backup proxy preferences
pacFactory.backupProxyPrefs();
pacFactory.setProxyAutoConfigURL(null);
// Initialise node table
initNodeTables();
// Initialise tor main and test threads
initTorMain();
// Do a Tor version check
float torversion = tcMain.getVersion();
Logger.getGlobal().logp(Level.INFO, this.getClass().getName(), "", "Tor version = " + torversion);
if (torversion < 0.2420) {
openToOldDialog();
cleanupExit();
return;
}
// Create testing threads
initTestThreads(sp.getInt("PREF_TOR_TESTHREADS"));
// Final Initialisation of other components which need to be done last
initFinalComponents();
// System tray
initSystemTray();
// Main program timer
initTimer();
// Do tor main start
applyMainTorSettings();
tcMain.setStartupDelay(1000);
tcMain.start();
initGUIVisibility();
Logger.getGlobal().log(Level.INFO, "Environment = {0}", System.getenv().toString());
Logger.getGlobal().log(Level.INFO, "Active desktop = {0}", desktopname);
Logger.getGlobal().log(Level.INFO, "Compositor = {0}", compositor);
if (Logger.getGlobal().isLoggable(Level.FINE)) {
for (String s : OSFunction.getCachedProcesses()) {
Logger.getGlobal().log(Level.FINE, "Process = {0}", s);
}
}
}
/**
* Initialise properties
*/
private void initProperties() {
// Initialise application title
setTitle(APPNAME);
// Application icon
setIconImage(new javax.swing.ImageIcon(iconPath + ICONFILE).getImage());
// Initial logging settings
Logger.getGlobal().setLevel(Level.SEVERE);
addLoggingFile(settingsPath + "status.log", false);
// Init properties
sp = new SimpleProps(settingsPath + APPNAME + ".xml", APPNAME + " Settings");
// Set up our defaults
sp.setDefaultModeEnabled(true);
sp.setString("PREF_ISOCOUNTRY", "DK");
//? int
sp.setInt("PREF_LISTENPORT", Integer.parseInt(strSocksPort));
sp.setInt("PREF_TOR_TESTHREADS", 2);
sp.setInt("PREF_TORLOGLEV", 2);
sp.setInt("PREF_PROXY_MODE", 2);
sp.setLong("PREF_GEODATE", 0);
sp.setBool("PREF_GEOCHECK", true);
sp.setBool("PREF_AUTOSTART", false);
sp.setBool("PREF_NOSYSTRAY", false);
sp.setBool("PREF_HIDETOTRAY", false);
sp.setBool("PREF_MINONCLOSE", false);
sp.setBool("PREF_HIDE_MIN", false);
sp.setBool("PREF_UPDATECHECK", true);
sp.setBool("PREF_SAFESOCKS", false);
sp.setBool("PREF_TESTSOCKS", false);
sp.setBool("PREF_AVOIDDISK", true);
sp.setBool("PREF_SAFELOG", false);
sp.setBool("PREF_CACHEDELETE", false);
sp.setBool("PREF_DISABLE_NOTIFY", false);
sp.setString("PREF_HTTP_PROXY", EMPTYSTR);
sp.setString("PREF_DONOT_PROXY", "localhost,127.0.0.1");
sp.setString("PREF_TORBRIDGE", EMPTYSTR);
sp.setString("PREF_TORARGS", EMPTYSTR);
sp.setDefaultModeEnabled(false);
sp.resetToDefaults();
sp.load();
// This will reset the preferences file to its default if we dont get a preferences version match
if (!sp.getString("prefsver").contentEquals(PREFSVER)) {
sp.resetToDefaults();
sp.setString("prefsver", PREFSVER);
sp.delete();
sp.save();
} else {
sp.save();
}
// Dont allow listen ports below 9050, prevents any conflicts with the Tor default service.
// Which can be used along side SelekTOR
/*
if (sp.getInt("PREF_LISTENPORT") < 9050) {
sp.setInt("PREF_LISTENPORT", 9050);
sp.save();
}
*/
strExitISOCode = sp.getString("PREF_ISOCOUNTRY");
}
/**
* Initialise logging facilities
*
* @param logpath
* @param append
*/
private void addLoggingFile(String logpath, boolean append) {
try {
if (logpath != null) {
FileHandler fh = new FileHandler(logpath, 10000000, 1, append);
fh.setFormatter(new SimpleFormatter());
Logger.getGlobal().addHandler(fh);
}
} catch (SecurityException | IOException ex) {
}
}
/**
* Processes any supplied arguments post UI component build
*
* @param args Startup arguments
*/
private boolean processCLIArgs(String... args) {
alArgs = new ArrayList<>();
alArgs.addAll(Arrays.asList(args));
for (String s : args) {
if (s.contentEquals("--tor-exe")) {
alArgs.remove(s);
if (alArgs.size() > 0) {
torExe = alArgs.get(0);
alArgs.remove(0);
}
}
if (s.contentEquals("--data-directory")) {
alArgs.remove(s);
if (alArgs.size() > 0) {
dataDirectory = alArgs.get(0);
alArgs.remove(0);
}
}
if (s.contentEquals("--raw-secret")) {
alArgs.remove(s);
if (alArgs.size() > 0) {
strRawSecret = alArgs.get(0);
alArgs.remove(0);
}
}
if (s.contentEquals("--socks-port")) {
alArgs.remove(s);
if (alArgs.size() > 0) {
strSocksPort = alArgs.get(0);
alArgs.remove(0);
}
}
if (s.contentEquals("--socks-host")) {
alArgs.remove(s);
if (alArgs.size() > 0) {
strSocksHost = alArgs.get(0);
alArgs.remove(0);
}
}
if (s.contentEquals("--dns-port")) {
alArgs.remove(s);
if (alArgs.size() > 0) {
strDNSPort = alArgs.get(0);
alArgs.remove(0);
}
}
if (s.contentEquals("--dns-host")) {
alArgs.remove(s);
if (alArgs.size() > 0) {
strDNSHost = alArgs.get(0);
alArgs.remove(0);
}
}
if (s.contentEquals("--http-port")) {
alArgs.remove(s);
if (alArgs.size() > 0) {
strHTTPPort = alArgs.get(0);
alArgs.remove(0);
}
}
if (s.contentEquals("--http-host")) {
alArgs.remove(s);
if (alArgs.size() > 0) {
strHTTPHost = alArgs.get(0);
alArgs.remove(0);
}
}
if (s.contentEquals("--exclude-nodes")) {
alArgs.remove(s);
if (alArgs.size() > 0) {
strExcludeNodes = alArgs.get(0);
alArgs.remove(0);
}
}
if (s.contentEquals("--exit-nodes")) {
alArgs.remove(s);
if (alArgs.size() > 0) {
strExitNodes = alArgs.get(0);
alArgs.remove(0);
}
}
if (s.contentEquals("--start-delay")) {
alArgs.remove(s);
if (alArgs.size() > 0) {
String strDelay = alArgs.get(0);
try {
startupDelay = Long.valueOf(strDelay) * 1000;
alArgs.remove(0);
} catch (NumberFormatException ex) {
}
}
}
if (s.contentEquals("--debug-all")) {
alArgs.remove(s);
if (!alArgs.isEmpty()) {
addLoggingFile(alArgs.get(0), false);
alArgs.remove(0);
}
Logger.getGlobal().setLevel(Level.ALL);
}
if (s.contentEquals("--debug-warn")) {
alArgs.remove(s);
if (!alArgs.isEmpty()) {
addLoggingFile(alArgs.get(0), false);
alArgs.remove(0);
}
Logger.getGlobal().setLevel(Level.WARNING);
}
if (s.contentEquals("--debug-info")) {
alArgs.remove(s);
if (!alArgs.isEmpty()) {
addLoggingFile(alArgs.get(0), false);
}
Logger.getGlobal().setLevel(Level.INFO);
}
if (s.contentEquals("--debug-fine")) {
alArgs.remove(s);
if (!alArgs.isEmpty()) {
addLoggingFile(alArgs.get(0), false);
alArgs.remove(0);
}
Logger.getGlobal().setLevel(Level.FINE);
}
if (s.contentEquals("--debug-finer")) {
alArgs.remove(s);
if (!alArgs.isEmpty()) {
addLoggingFile(alArgs.get(0), false);
alArgs.remove(0);
}
Logger.getGlobal().setLevel(Level.FINER);
}
if (s.contentEquals("--debug-finest")) {
alArgs.remove(s);
if (!alArgs.isEmpty()) {
addLoggingFile(alArgs.get(0), false);
alArgs.remove(0);
}
Logger.getGlobal().setLevel(Level.FINEST);
}
if (s.contentEquals("--reset-defaults")) {
alArgs.remove(s);
sp.resetToDefaults();
sp.save();
sp.load();
return true;
}
if (s.contentEquals("--clear-cache")) {
alArgs.remove(s);
SimpleFile.deleteFolder(cachePath);
}
if (s.contentEquals("--help")) {
alArgs.remove(s);
outputHelp();
// Disable proxy restore on exit
pacFactory = null;
return true;
}
if (s.contentEquals("--cleanup")) {
alArgs.remove(s);
if (!sp.getBool("PREF_AUTOSTART")) {
return true;
}
}
if (s.contentEquals("--default-proxy-quiet")) {
alArgs.remove(s);
pacFactory.setProxyAutoConfigURL(null);
pacFactory.deleteProxyPrefs();
// Disable proxy restore on exit
pacFactory = null;
return true;
}
if (s.contentEquals("--restore-proxy-quiet")) {
alArgs.remove(s);
return true;
}
if (s.contentEquals("--update-disable")) {
alArgs.remove(s);
updateCheckDisabled = true;
}
if (s.contentEquals("--restore-proxy")) {
alArgs.remove(s);
InfoDialog id = createInfoDialog();
id.createWarn(LOCAL.getString("dlg_restoreproxy_title"),
LOCAL.getString("dlg_restoreproxy_body"));
id.pack();
id.setVisible(true);
if (id.getReturnStatus() == InfoDialog.OK) {
return true;
}
// Disable proxy restore on exit
pacFactory = null;
return true;
}
if (s.contentEquals("--default-proxy")) {
alArgs.remove(s);
InfoDialog id = createInfoDialog();
id.createWarn(LOCAL.getString("dlg_resetproxy_title"),
LOCAL.getString("dlg_resetproxy_body"));
id.pack();
id.setVisible(true);
if (id.getReturnStatus() == InfoDialog.OK) {
pacFactory.setProxyAutoConfigURL(null);
pacFactory.deleteProxyPrefs();
}
// Disable proxy restore on exit
pacFactory = null;
return true;
}
if (s.contentEquals("--ignore-desktop")) {
alArgs.remove(s);
desktopname = EMPTYSTR;
}
}
if (alArgs.size() > 0) {
outputHelp();
// Disable proxy restore on exit
pacFactory = null;
return true;
}
return false;
}
/**
* Output on standard out command line help info
*/
private void outputHelp() {
System.out.println(APPNAME + " " + APPVER + " valid command line arguments.");
System.out.println();
System.out.println("--help : This help information");
System.out.println("--tor-exe : full path of the tor executable");
//d
System.out.println("--raw-secret: raw secret for ocntroller");
System.out.println("--dns-port : DNSPort e.g. 9053");
System.out.println("--socks-port : SocksPort e.g. 9054");
System.out.println("--http-port : HTTPPort e.g. 9128");
System.out.println("--dns-host : DNSHost e.g. 9053");
System.out.println("--socks-host : SocksHost e.g. 9054");
System.out.println("--http-host : HTTPHost e.g. 9128");
System.out.println("--debug-all [filename] : All debug output.");
System.out.println("--debug-warn [filename] : Warnings level debug output.");
System.out.println("--debug-info [filename] : Information level debug output.");
System.out.println("--debug-fine [filename] : Fine level debug output.");
System.out.println("--debug-finer [filename] : Finer level debug output.");
System.out.println("--debug-finest [filename] : Finest level debug output.");
System.out.println("--reset-defaults : Return user settings to their safe defaults.");
System.out.println("--clear-cache : Clears the Tor cache on startup.");
System.out.println("--ignore-desktop : Ignore desktop detection information.");
System.out.println("--start-delay : Delay startup in seconds, eg. --start-delay 5");
System.out.println("--cleanup : Cleans up after a bad shutdown which may have left system proxy in an unknown state.");
System.out.println("--default-proxy-quiet : Set system proxy back to its defaults quietly, without GUI dialog.");
System.out.println("--restore-proxy-quiet : Attempt to restore proxy to its last known settings using a previously saved backup, "
+ "without GUI dialog.");
System.out.println("--default-proxy : Set system proxy back to its defaults accepts verification input via a GUI dialog..");
System.out.println("--restore-proxy : Attempt to restore proxy to its last known settings using a previously saved backup, "
+ "with input verification via a GUI dialog.");
System.out.println("--update-disable : Disables the version update checking at startup and removes "
+ "the option from preferences.");
System.out.println();
}
/**
* Sets the enabled status of various GUI objects
*
* @param enabled
*/
private void setComponentsEnabled(boolean enabled) {
jButtonExitNodeDetails.setEnabled(enabled);
jButtonMiddleNodeDetails.setEnabled(enabled);
jButtonGuardNodeDetails.setEnabled(enabled);
jButtonSetGuards.setEnabled(enabled);
jMenuItemPatternEdit.setEnabled(enabled);
jMenuItemAddPattern.setEnabled(enabled);
jTableExitNodes.setEnabled(enabled);
jComboCountry.setEnabled(enabled);
jMenuItemTorCheck.setEnabled(enabled);
jCheckProxyDisable.setEnabled(enabled);
jCheckProxyByPattern.setEnabled(enabled);
jCheckProxyAll.setEnabled(enabled);
jCheckTrayProxyDisable.setEnabled(enabled);
jCheckTrayProxyByPattern.setEnabled(enabled);
jCheckTrayProxyAll.setEnabled(enabled);
jButtonClearFavs.setEnabled(enabled);
if (!enabled) {
jMenuItemGeoip.setEnabled(enabled);
}
}
/**
* Final initialisation of objects that need to be done near the end of
* startup
*
*/
private void initFinalComponents() {
// Apply fixes for linux gtk issues in java
GTKFixes.fixMenubarHeight(jMenuBar, jMenuItemGUI);
GTKFixes.fixMenuSelectionColor(jMenuMenu, jMenuProxy, jMenuHelp);
GTKFixes.fixJMenuPopupBorder(jMenuMenu, jMenuProxy, jMenuHelp);
GTKFixes.fixMenuItemFgColor(jCheckProxyDisable, jCheckProxyByPattern, jCheckProxyAll);
GTKFixes.fixMenuItemFgColor(jCheckTrayProxyDisable, jCheckTrayProxyByPattern, jCheckTrayProxyAll);
// Disable certain components until first node is activated
setComponentsEnabled(false);
// Add proxy buttons to proxy button groups
buttonGroupProxy.add(jCheckProxyDisable);
buttonGroupProxy.add(jCheckProxyByPattern);
buttonGroupProxy.add(jCheckProxyAll);
buttonGroupProxyTray.add(jCheckTrayProxyDisable);
buttonGroupProxyTray.add(jCheckTrayProxyByPattern);
buttonGroupProxyTray.add(jCheckTrayProxyAll);
// Update initial proxy selection
switch (sp.getInt("PREF_PROXY_MODE")) {
case 0:
jCheckProxyDisable.setSelected(true);
break;
case 1:
jCheckProxyByPattern.setSelected(true);
break;
case 2:
jCheckProxyAll.setSelected(true);
break;
}
// Make debug log menu item visible if required
jMenuItemDebugLog.setVisible(Logger.getGlobal().getLevel() != Level.SEVERE);
}
/**
* Initialise our internal 1 second timer tick
*
*/
private void initTimer() {
tmr = new Timer(1000, new java.awt.event.ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
// Do a hibernate check, check to see if computer has been asleep for more than 60 secs
if ((System.currentTimeMillis() - lngHibernateTimeStamp) > 60000) {
Logger.getGlobal().logp(Level.INFO, SelekTOR.class.getName(),
"initTimer()", "Hibernate Recovery");
lngHibernateTimeStamp = System.currentTimeMillis();
setComponentsEnabled(false);
stopAllTorThreads();
boolFirstRun = true;
tcMain.start();
}
lngHibernateTimeStamp = System.currentTimeMillis();
if (!boolNetEnabled) {
return;
}
// Do Latency checking
if (intLatencyCheck > 0 && iLatencyCheck > 0) {
intLatencyCheck--;
if (intLatencyCheck == 0) {
intLatencyCheck = 5;
getFreshNodeInfo();
// Tor latency check, only when node active
if (niActiveExit != null) {
// Do latency check
tcMain.doLatencyCheck(iLatencyCheck);
}
}
}
// Activate a node selection check
if (intAutoSelectCheck > 0) {
intAutoSelectCheck--;
if (intAutoSelectCheck == 0) {
autoSelectNode();
}
}
// Activate a testing cycle
if (intBeginTesting > 0) {
intBeginTesting--;
if (intBeginTesting == 0) {
runTestingCycle();
}
}
} catch (Exception ex) {
Logger.getGlobal().logp(Level.WARNING, this.getClass().getName(), "initTimer() actionPerformed", EMPTYSTR, ex);
}
}
});
lngHibernateTimeStamp = System.currentTimeMillis();
tmr.setInitialDelay(0);
tmr.setRepeats(true);
tmr.start();
}
/**
* Initialise our pacfactory object
*
*/
private void initPacFactory() {
pacFactory = new PacFactory();
pacFactory.setTempFolder(cachePath);
pacFactory.setBackupFolder(settingsPath + "backup");
pacFactory.setPatternsFolder(settingsPath + "patterns");
pacFactory.setPACFolder(settingsPath);
pacFactory.setDefaultProxy(sp.getString("PREF_HTTP_PROXY"));
pacFactory.setDoNotProxy(sp.getString("PREF_DONOT_PROXY"));
}
/**
* Open the preferences dialog
*/
private void openPreferencesDialog() {
// open dialog
PrefsDialog pd;
String disableditems = EMPTYSTR;
if (!sti.isSupported()) {
sp.setBool("PREF_NOSYSTRAY", true);
disableditems += "jCheckDisableTray";
}
if (updateCheckDisabled) {
disableditems += ",jCheckAppUpdate";
}
pd = new PrefsDialog(this, sp, disableditems);
pd.setTitle(LOCAL.getString("wintitle_prefs").replace("$appname", APPNAME));
pd.pack();
pd.setLocationRelativeTo(this);
pd.setVisible(true);
// Check for changes
String changed = sp.getChangedProperties();
if (pd.getReturnStatus() == PrefsDialog.APPLY) {
sp.save();
}
if (changed.contains("PREF_HTTP_PROXY")) {
pacFactory.setDefaultProxy(sp.getString("PREF_HTTP_PROXY"));
rebuildPatternPac();
}
if (changed.contains("PREF_NOSYSTRAY")) {
if (sp.getBool("PREF_NOSYSTRAY")) {
sti.unload();
} else {
sti.load();
}
}
if (changed.contains("PREF_DISABLE_NOTIFY")) {
dn.setEnabled(!sp.getBool("PREF_DISABLE_NOTIFY"));
if (dn.isEnabled() && !dn.isSupported()) {
openLibnotifyDialog();
}
}
if (!boolNetEnabled) {
return;
}
// Check to see if bridges entry was changed
if (changed.contains("TORBRIDGE")) {
// Update status message
updateProgramStatus(LOCAL.getString("progstatus_applychanges"));
// Validate bridge entry
if (!tcMain.validateBridges(sp.getString("PREF_TORBRIDGE"))) {
// Validation failed
sp.setString("PREF_TORBRIDGE", EMPTYSTR);
sp.save();
// Apply default bridge settings by doing hard Tor restart
stopAllTorThreads();
applyMainTorSettings();
tcMain.start();
// Indicate validation failure to user
openBridgeErrorDialog();
} else {
// Apply default bridge settings by doing hard Tor restart
stopAllTorThreads();
applyMainTorSettings();
tcMain.start();
}
return;
}
// Check for any parameters that have changed that require full restart
if (changed.contains("LISTENPORT") || changed.contains("SAFE")
|| changed.contains("AVOID")
|| changed.contains("LOGLEV") || changed.contains("TORARGS")
|| changed.contains("TESTSOCKS")) {
// Update status message
updateProgramStatus(LOCAL.getString("progstatus_applychanges"));
// Apply default bridge settings by doing hard Tor restart
stopAllTorThreads();
applyMainTorSettings();
tcMain.start();
}
}
private void applyMainTorSettings() {
// Check to see if bridges are active
String bridge = sp.getString("PREF_TORBRIDGE");
if (!tcMain.validateBridges(bridge)) {
bridge = EMPTYSTR;
sp.setString("PREF_TORBRIDGE", bridge);
sp.save();
}
// Update entry node label on UI
if (bridge.isEmpty()) {
jLabelGuard.setText(LOCAL.getString("label_guardnode"));
} else {
jLabelGuard.setText(LOCAL.getString("label_bridgenode"));
}
tcMain.setBridges(bridge);
tcMain.setTestingURL(TESTURL);
tcMain.setListenPort(sp.getInt("PREF_LISTENPORT"));
tcMain.setEntryNodes(nodeList.getGuardFavouritesAsCSV());
tcMain.setBoolTorOption("SafeSocks", sp.getBool("PREF_SAFESOCKS"));
tcMain.setBoolTorOption("TestSocks", sp.getBool("PREF_TESTSOCKS"));
tcMain.setBoolTorOption("AvoidDiskWrites", sp.getBool("PREF_AVOIDDISK"));
tcMain.setBoolTorOption("SafeLogging", sp.getBool("PREF_SAFELOG"));
tcMain.setExternalArgs(sp.getString("PREF_TORARGS"));
tcMain.setLogLevel(sp.getInt("PREF_TORLOGLEV"));
tcMain.setGeoIP4(geoipPath);
tcMain.setGeoIP6(geoip6Path);
tmf.setLaunchString("# Via commandline\n"
+ tcMain.getCLIOptionsAsString() + "\n\n"
+ "# Via torrc configuration file\n"
+ tcMain.getTorrcOptionsAsString()
);
}
/**
* Abort actions on all tor client threads
*/
private void abortAllTorThreads() {
if (niActiveExit != null) {
niActiveExit.setCircuitHops(null);
}
if (tcMain != null) {
tcMain.abortActions();
}
abortTesting();
}
/**
* Bring all tor threads to a stop
*/
private void stopAllTorThreads() {
abortTesting();
stopTestClients();
if (nodeList != null) {
nodeList.terminate();
}
if (tcMain != null) {
tcMain.stop();
tcMain.clearStdout();
tcMain.setStartupDelay(intTimeoutStartupDelayMsec);
}
}
/**
* Do nodelist refresh
*/
private void regenNodelist() {
Thread t = new Thread(new java.lang.Runnable() {
@Override
public void run() {
if (boolFirstRun) {
updateProgramStatus(LOCAL.getString("progstatus_generate"));
nodeList.refreshNodelist(tcMain);
// App update check
checkForAppUpdates();
}
switch (nodeList.getCurrentStatus()) {
case NodeList.NODELIST_BUILT:
SwingUtilities.invokeLater(new java.lang.Runnable() {
@Override
public void run() {
if (boolFirstRun) {
dn.setNotificationBody(LOCAL.getString("traymenu_proxymode" + (sp.getInt("PREF_PROXY_MODE") + 1)));
applyProxyChanges(sp.getInt("PREF_PROXY_MODE"));
}
// Update countries combo box
String[] countries = nodeList.getValidatedCountries();
DefaultComboBoxModel<String> dcbm = new DefaultComboBoxModel<>(countries);
jComboCountry.setModel(dcbm);
jComboCountry.setSelectedIndex(-1);
String strSelection = strExitISOCode + "," + LOCAL.getDisplayCountry(strExitISOCode);
// Check selection exists
if (dcbm.getIndexOf(strSelection) < 0) {
// Does not exist so default to the first country entry
jComboCountry.setSelectedIndex(0);
} else {
jComboCountry.setSelectedItem(strSelection);
}
// Check to make shure we have enough guard nodes
int activeguards = nodeList.saveGuardWhitelist();
if (activeguards < 3 && activeguards > 0) {
openNotEnoughGuardsDialog();
}
}
});
break;
case NodeList.NODELIST_FAILED:
SwingUtilities.invokeLater(new java.lang.Runnable() {
@Override
public void run() {
Logger.getGlobal().logp(Level.WARNING, SelekTOR.class
.getName(), "fetchRemoteData()", "Nodelist Failed");
openFatalErrorDialog(LOCAL.getString("dlg_nodelistfail_body"));
cleanupExit();
}
});
break;
}
}
});
t.start();
}
/**
* Check remoteversion to determine if their is a newer application
* available
*
*/
private void checkForAppUpdates() {
// App update
if (!sp.getBool("PREF_UPDATECHECK") || updateCheckDisabled) {
Logger.getGlobal().log(Level.WARNING, "Update check is disabled.");
return;
}
TorCircuit tc = tcMain.getLatestCircuit();
if (tc != null) {
String finger = tc.getExit(TorCircuit.FINGER);
NodeItem ni = nodeList.getNode(finger);
if (ni != null) {
Logger.getGlobal().log(Level.INFO, "Active Exit is {0}({1}) in {2}",
new Object[]{ni.getNickName(), finger, ni.getCountryName()});
}
}
String url = APPUPDATE + "version.html";
Socket s = tcMain.createTorSocketToURL(url, false);
nf.setSocketTimeout(intTimeoutSocketMsec);
String version = nf.getURLContentAsString(url, s);
if (version == null) {
Logger.getGlobal().log(Level.WARNING, "Failed to retrieve version info.");
return;
}
Logger.getGlobal().log(Level.INFO, "Sucessfully retrieved version info.");
final String remoteversion = version.trim();
SwingUtilities.invokeLater(new java.lang.Runnable() {
@Override
public void run() {
if (Utilities.isNewerVersion(APPVER, remoteversion)) {
InfoDialog id = createInfoDialog();
id.createInfo(LOCAL.getString("dlg_update_title"),
LOCAL.getString("dlg_update_body").replace("$version", remoteversion));
id.setAutoClose(30000);
id.pack();
id.setVisible(true);
}
}
});
}
/**
* Check to see if we need to update geoip
*
*/
private void updateGeoipCheck() {
jMenuItemGeoip.setEnabled(true);
if (!sp.getBool("PREF_GEOCHECK")) {
return;
}
long lngDate = sp.getLong("PREF_GEODATE");
if (System.currentTimeMillis() > lngDate) {
updateGeoip();
}
}
/**
* Pops up the GEOIP update dialog
*/
private void updateGeoip() {
InfoDialog id = new InfoDialog(this) {
private final InfoDialog id = this;
@Override
public void progressTask(int retstatus, final JProgressBar jpb) {
Thread t = new Thread(new java.lang.Runnable() {
@Override
public void run() {
String url = APPUPDATE + GEOIPSHA;
String destfile = OSFunction.getTempFolder(EMPTYSTR) + APPNAME
+ "_" + GEOIPZIP;
try {
setAckEnabled(false);
jpb.setString(LOCAL.getString("dload_status_contact"));
Socket s;
// Grab checksum file from dazzleships
if (isCheckBoxSelected()) {
if (niActiveExit == null) {
// Indicate download failure
Logger.getGlobal().log(Level.INFO, "Invalid exit node");
throw new IOException();
}
if (niActiveExit.getLatency() > 4000) {
// Indicate download failure
Logger.getGlobal().log(Level.INFO, "Poor exit node");
throw new IOException();
}
s = tcMain.createTorSocketToURL(url, false);
} else {
s = new Socket(FILEDOMAIN, 80);
}
nf.setSocketTimeout(intTimeoutSocketMsec);
nf.setProgressBar(jpb);
jpb.setStringPainted(true);
if (!id.isVisible()) {
throw new IOException();
}
Logger.getGlobal().log(Level.INFO, "Starting geoip.sha download");
String chksum = nf.getURLContentAsString(url, s);
if (chksum == null || chksum.isEmpty()) {
// Indicate download failure
Logger.getGlobal().log(Level.INFO, "geoip.sha download failed");
throw new IOException();
}
// Grab geodata zip file from dazzleships
if (!id.isVisible()) {
throw new IOException();
}
Logger.getGlobal().log(Level.INFO, "Starting geoip.zip download");
url = APPUPDATE + GEOIPZIP;
if (isCheckBoxSelected()) {
s = tcMain.createTorSocketToURL(url, false);
} else {
s = new Socket(FILEDOMAIN, 80);
}
final SimpleFile sf = new SimpleFile(destfile);
// Delete old/previous file
if (sf.exists()) {
sf.delete();
}
// Ensure zip file downloaded
nf.saveURLContentToFile(destfile, url, s, true);
if (!sf.exists()) {
// Indicate download failure
Logger.getGlobal().log(Level.INFO, "geoip.zip download failed");
throw new IOException();
}
// Do checksum verification
String fchk = Utilities.getSha1Sum(destfile);
if (!fchk.contentEquals(chksum.trim())) {
// Delete corrupt zip file
sf.delete();
// Indicate download failure
Logger.getGlobal().log(Level.INFO, "geoip.zip checksum does not match");
throw new IOException();
}
if (!id.isVisible()) {
throw new IOException();
}
if (sf.extractZipTo(settingsPath)) {
SwingUtilities.invokeLater(new java.lang.Runnable() {
@Override
public void run() {
// Set new check time
updateGeoipCheckDate();
// Update geoip paths
geoipPath = OSFunction.findFile("geoip", settingsPath, defaultGeoipPath);
geoip6Path = OSFunction.findFile("geoip6", settingsPath, defaultGeoipPath);
// Restart Tor client, to take advantage of new geoip
jComboCountry.setEnabled(false);
setComponentsEnabled(false);
boolFirstRun = true;
stopAllTorThreads();
applyMainTorSettings();
tcMain.start();
setVisible(false);
dispose();
}
});
}
} catch (final Exception ex) {
// Exits here in case of download fail
SwingUtilities.invokeLater(new java.lang.Runnable() {
@Override
public void run() {
Logger.getGlobal().log(Level.WARNING, ex.getMessage());
jpb.setString(LOCAL.getString("dload_status_failed"));
setAckEnabled(true);
}
});
}
}
});
if (retstatus == InfoDialog.OK) {
t.start();
} else {
updateGeoipCheckDate();
setVisible(false);
dispose();
}
}
};
id.setTitle(APPNAME);
id.setCancelButtonText(LOCAL.getString("button_cancel"));
id.setContinueButtonText(LOCAL.getString("button_continue"));
id.setCloseButtonText(LOCAL.getString("button_close"));
id.setCheckBoxText(LOCAL.getString("chkbox_viator"));
id.setCheckBoxVisible(true);
id.setCheckBoxEnabled(true);
id.pack();
id.createProgress(LOCAL.getString("dlg_geo_title"),
LOCAL.getString("dlg_geo_body"));
id.pack();
id.setVisible(true);
}
private void updateGeoipCheckDate() {
// Set new check time
sp.setLong("PREF_GEODATE", System.currentTimeMillis() + ((long) 60000 * 60 * 24 * 90));
if (strRawSecret == null ) { strRawSecret = Utilities.generateSecretKey(16); }
sp.setString("PREF_SECRET", strRawSecret);
sp.save();
}
/**
* System tray initialisation
*/
private void initSystemTray() {
// Initialise tray utility
sti = new SwingTrayIcon(this.getGraphicsConfiguration(), "resources/trayicon.png");
if (desktopname.contentEquals("gnome3")
|| desktopname.contentEquals("enlightenment")
|| desktopname.contentEquals("kde5")) {
sti.disable();
}
// Initialise desktop notification
dn = new DesktopNotify(sti, iconPath + ICONFILE);
dn.setNotificationTitle(APPNAME);
dn.setEnabled(!sp.getBool("PREF_DISABLE_NOTIFY"));
if (dn.isEnabled() && !dn.isSupported()) {
openLibnotifyDialog();
}
// If trayIcon valid add mouse listener
TrayPopupMenu tpm = new TrayPopupMenu();
GTKFixes.fixTrayMenuPopupBorder(tpm);
tpm.add(jCheckTrayProxyDisable);
tpm.add(jCheckTrayProxyByPattern);
tpm.add(jCheckTrayProxyAll);
tpm.add(new JPopupMenu.Separator());
tpm.add(jMenuItemGUI);
tpm.add(jMenuItemQuitx);
sti.addMouseListener(new javax.swing.event.MouseInputListener() {
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1) {
toggleGUIVisibility();
}
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mouseDragged(MouseEvent e) {
}
@Override
public void mouseMoved(MouseEvent e) {
}
});
sti.setTrayPopupMenu(tpm);
if (!sp.getBool("PREF_NOSYSTRAY")) {
sti.load();
}
}
private InfoDialog createInfoDialog() {
InfoDialog id = new InfoDialog(this);
id.setTitle(APPNAME);
id.setCancelButtonText(LOCAL.getString("button_cancel"));
id.setContinueButtonText(LOCAL.getString("button_continue"));
id.setCloseButtonText(LOCAL.getString("button_close"));
return id;
}
private void openInstanceDialog() {
InfoDialog id = createInfoDialog();
id.createError(LOCAL.getString("dlg_instancefail_title"),
LOCAL.getString("dlg_instancefail_body").replace("$appname", APPNAME));
id.pack();
id.setVisible(true);
}
private void openNotEnoughGuardsDialog() {
InfoDialog id = createInfoDialog();
id.createWarn(LOCAL.getString("dlg_guardwarn_title"),
LOCAL.getString("dlg_notenoughguards_body").replace("$appname", APPNAME));
id.setCancelVisible(false);
id.setContinueButtonText(LOCAL.getString("button_setguards"));
id.pack();
id.setVisible(true);
if (id.getReturnStatus() == InfoDialog.OK) {
openGuardsSettingDialog();
}
}
private void openGsettingsDialog() {
InfoDialog id = createInfoDialog();
id.createError(LOCAL.getString("dlg_gsetting_title"),
LOCAL.getString("dlg_gsetting_body").replace("$appname", APPNAME));
id.pack();
id.setVisible(true);
}
private void openTorClientDialog() {
InfoDialog id = createInfoDialog();
id.createError(LOCAL.getString("dlg_torclient_title"),
LOCAL.getString("dlg_torclient_body").replace("$appname", APPNAME));
id.pack();
id.setVisible(true);
}
private void openLibnotifyDialog() {
InfoDialog id = createInfoDialog();
id.createError(LOCAL.getString("dlg_libnotify_title"),
LOCAL.getString("dlg_libnotify_body").replace("$appname", APPNAME));
id.setModal(false);
id.setAutoClose(10000);
id.pack();
id.setVisible(true);
}
private void openBridgeErrorDialog() {
InfoDialog id = createInfoDialog();
id.createError(LOCAL.getString("dlg_bridgerr_title"),
LOCAL.getString("dlg_bridgerr_body").replace("$appname", APPNAME));
id.pack();
id.setVisible(true);
}
/**
* Node table and node list initialisation
*/
private void initNodeTables() {
// Create our node list storage object
nodeList = new NodeList(settingsPath, EXITFAVOURITES, GUARDWHITELIST);
entm = new ExitNodeTableModel();
entm.setColumnName(LOCAL.getString("exittable_col1"), 0);
entm.setColumnName(LOCAL.getString("exittable_col2"), 1);
entm.setColumnName(LOCAL.getString("exittable_col3"), 2);
entm.setColumnName(LOCAL.getString("exittable_col4"), 3);
entm.setColumnName(LOCAL.getString("exittable_col5"), 4);
entm.addTableModelListener(new javax.swing.event.TableModelListener() {
@Override
public void tableChanged(TableModelEvent e) {
if (e.getType() == TableModelEvent.UPDATE) {
if (e.getColumn() == 4) {
nodeList.saveExitFavourites();
// Force favourites recalc
intThresholdExceeded = 255;
// Do node auto selection in 5 secs
intAutoSelectCheck = 5;
}
}
}
});
nodeList.setExitNodeTableModel(entm);
jTableExitNodes.setModel(entm);
// Adjust table column widths
adjustExitTableColumns();
}
private void clearFavourites() {
for (int i = 0; i < entm.getRowCount(); i++) {
entm.setValueAt(false, i, 4);
}
}
/**
* Main tor process initialisation
*/
private void initTorMain() {
intBeginTesting = TESTING_DISABLED;
nf = new NetFunctions();
tmf = new TorMonFrame();
tmf.setTitle(LOCAL.getString("wintitle_tormonitor"));
tmf.setIconImage(new javax.swing.ImageIcon(iconPath + ICONFILE).getImage());
// Initialise the Tor main client event handler
tcMain = new TorController(clientLocation, cachePath) {
private int intNodeFailCount;
@Override
public void controllerEventFired(int event, Object data) {
Logger.getGlobal().logp(Level.INFO, SelekTOR.class.getName(),
"controllerEventFired() on Port=" + getListenPort(),
getEventMessage(event) + ", Data=" + data);
switch (event) {
case TOR_BRIDGE:
nodeList.addBridge((String) data);
break;
case TOR_NOROUTE:
if (boolNetEnabled) {
boolNetEnabled = false;
boolFirstRun = true;
updateProgramStatus(LOCAL.getString("progstatus_nonet"));
dn.setNotificationBody(LOCAL.getString("progstatus_nonet"));
dn.raiseNotification();
setComponentsEnabled(false);
}
break;
case TOR_DIRINFO_STALE:
// Deliberate fallthrough here
case TOR_NOEXITS:
// Ensure client is fully running as multiple TOR_NOEXITS can
// be generated at startup especially if folks are torrenting via Tor
if (getStatus() < STATUS_IDLE) {
break;
}
updateProgramStatus(LOCAL.getString("circuit_status_none"));
intNodeFailCount = 0;
resetBestNode();
strRequestedExit = getBestNode();
if (strRequestedExit == null) {
strRequestedExit = EMPTYSTR;
}
stop();
setSilentBootEnabled(true);
setStartupDelay(intTimeoutStartupDelayMsec);
start(TOR_RESTARTED);
break;
case TOR_CLOCK_ERROR:
// Deliberate fallthrough here
case TOR_BOOT_FATAL:
Logger.getGlobal().logp(Level.SEVERE, SelekTOR.class.getName(),
"controllerEventFired() on Port=" + getListenPort(), getEventMessage(event) + ", Data=" + data);
openFatalErrorDialog((String) data);
cleanupExit();
break;
case TOR_BOOT_TIMEOUT:
stop();
setStartupDelay(intTimeoutStartupDelayMsec);
start(TOR_BOOTED);
break;
case TOR_MESSAGE:
updateProgramStatus((String) data);
break;
case TOR_BOOTED:
boolNetEnabled = true;
regenNodelist();
break;
case TOR_RESTARTED:
boolNetEnabled = true;
activateNode(strRequestedExit);
break;
case EVENT_CIRCUIT_FAILED:
// Deliberate fallthrough here
case EVENT_CIRCUITS_FAILED:
switch (++intNodeFailCount) {
case 1:
// Retry
updateProgramStatus(LOCAL.getString("progstatus_nodefailretry"));
intThresholdExceeded = 254;
intAutoSelectCheck = 2;
break;
case 2:
// Get the next best node
updateProgramStatus(LOCAL.getString("progstatus_nodefail"));
intThresholdExceeded = 4;
intAutoSelectCheck = 2;
break;
case 3:
// Get the next best node and trigger test cycle
updateProgramStatus(LOCAL.getString("progstatus_nodefail"));
intNodeFailCount = 0;
intThresholdExceeded = 4;
intAutoSelectCheck = 2;
if (intBeginTesting > 2) {
intBeginTesting = 2;
}
break;
}
break;
case EVENT_CIRCUITS_BUILT:
if (!strRequestedExit.isEmpty()) {
NodeItem ni = nodeList.getNode(strRequestedExit);
if (ni == null) {
activateNode(strRequestedExit = EMPTYSTR);
break;
}
if (ni.getCircuitHops() != null) {
tcMain.activateCircuit(ni.getCircuitHops());
break;
}
}
case EVENT_CIRCUIT_BUILT:
intNodeFailCount = 0;
intThresholdExceeded = 0;
intLatencyCheck = 1;
// Trigger node testing
if (intBeginTesting == TESTING_DISABLED) {
intBeginTesting = 2;
}
if (boolFirstRun) {
boolFirstRun = false;
// Update geoip check
updateGeoipCheck();
}
break;
case EVENT_LATENCY_DONE:
if (niActiveExit != null) {
niActiveExit.setStreams(getActiveStreams().size());
niActiveExit.setLatency(getLatency());
updateGUINodeInfo(niActiveGuard, niActiveMiddle, niActiveExit);
// Check for threshold override
if (intThresholdExceeded >= 100) {
break;
}
if (niActiveExit.getLatency() > lngThreshold) {
intThresholdExceeded++;
if (niActiveExit.getLatency() > MAXTHRESHOLD) {
// If we have 3 (15 sec) of outright latency failures then trigger test cycle
if (intThresholdExceeded > 2) {
intAutoSelectCheck = 2;
if (intBeginTesting > 2) {
intBeginTesting = 2;
}
}
break;
}
// If we have only have one favourite then effectively
// ignore latency
if (nodeList.getNumberOfFavs() == 1) {
intThresholdExceeded = 0;
break;
}
if (niActiveExit.getStreams() > 0) {
// If we have active streams then do new selection after 1 minute
// of threshold excesses
if (intThresholdExceeded > 11) {
intAutoSelectCheck = 2;
}
} else {
// If we have no active streams then do new selection after 15 secs
// of threshold excesses
if (intThresholdExceeded > 2) {
intAutoSelectCheck = 2;
}
}
break;
}
intThresholdExceeded = 0;
}
break;
}
}
};
// Tor main initial startup conditions
tcMain.setTorrcOption("PidFile", cachePath + strSocksPort + OSFunction.getFileSeparator() + "tor.pid" );
tcMain.setTorrcOption("Log", "notice file " + cachePath + strSocksPort + OSFunction.getFileSeparator() + "notice.log");
tcMain.setTorrcOption("ClientOnly", "1");
tcMain.setTorrcOption("StrictNodes", "1");
tcMain.setTorrcOption("UseMicrodescriptors", "0");
tcMain.setTorrcOption("UseEntryGuards", "1");
tcMain.setTorrcOption("NumEntryGuards", "3");
// default is 600 but I think this helps anon
tcMain.setTorrcOption("MaxCircuitDirtiness", "120");
tcMain.setTorrcOption("GeoIPExcludeUnknown", "1");
if (strExcludeNodes != null) {
tcMain.setTorrcOption("ExcludeNodes", strExcludeNodes);
}
if (strExitNodes != null) {
tcMain.setTorrcOption("ExitNodes", strExitNodes);
}
if (strSocksPort != null && strSocksHost != null) {
tcMain.setTorrcOption("SocksPort", strSocksHost + ':' + strSocksPort);
}
if (strDNSPort != null) {
tcMain.setTorrcOption("DNSPort", strDNSHost + ':' + strDNSPort);
}
if (strHTTPPort != null) {
tcMain.setTorrcOption("HTTPTunnelPort", strHTTPHost + ':' + strHTTPPort);
}
//breaks tcMain.setTorrcOption("ControlSocket", "/run/tor/control");
//breaks tcMain.setTorrcOption("ControlSocketsGroupWritable", "1");
// broken model
// tcMain.setTorrcOption("SocksPolicy", "accept 127.0.0.1/32");
// tcMain.setTorrcOption("SocksPolicy", "reject *");
tcMain.setStdoutTextArea(tmf.getStdoutTextArea());
tcMain.setListenPort(sp.getInt("PREF_LISTENPORT"));
tcMain.setOwnershipID(OSFunction.getOurProcessID());
strSecret = sp.getString("PREF_SECRET");
strHash = Utilities.getTorHashPassword(strSecret);
tcMain.setTorrcOption("HashedControlPassword", strHash);
tcMain.setControlPassword(strSecret, strHash);
tcMain.setTorrcOption("SandBox", "0");
}
/**
* Test thread initialisation
*
* @param nothreads
*/
private void initTestThreads(int nothreads) {
TorController tcTest;
// Main testing procedure here, event driven this just handles process declaration
// Initialise our tor testing thread prior to booting it
while (alTestThreads.size() < nothreads) {
tcTest = new TorController(clientLocation, cachePath) {
private NodeItem ni;
@Override
public void controllerEventFired(int event, Object data) {
Logger.getGlobal().logp(Level.INFO, SelekTOR.class.getName(),
"controllerEventFired() on Port=" + getListenPort(), getEventMessage(event) + ", Data=" + data);
switch (event) {
case TOR_NOROUTE:
if (boolNetEnabled) {
abortTesting();
stopTestClients();
updateGUINodeInfo(niActiveGuard = null, niActiveMiddle = null, niActiveExit = null);
tcMain.stop();
tcMain.setSilentBootEnabled(true);
tcMain.setStartupDelay(intTimeoutStartupDelayMsec);
tcMain.start(TOR_BOOTED);
}
break;
case TOR_BOOT_TIMEOUT:
case TOR_BOOT_FATAL:
ni = null;
stop();
setSilentBootEnabled(true);
setStartupDelay(intTimeoutStartupDelayMsec);
start(TOR_BOOTED);
break;
case TOR_RESTARTED:
// Deliberate fallthrough here
case TOR_BOOTED:
// Deliberate fallthrough here
ni = null;
case EVENT_TESTING_DONE:
if (ni != null) {
if (intActiveNodeTests > 0) {
intActiveNodeTests--;
}
Logger.getGlobal().logp(Level.INFO, SelekTOR.class.getName(),
"controllerEventFired() on Port=" + getListenPort(), "Completed Testing of " + ni.getNickName());
if (getBestLatency() < LATENCY_FAIL) {
ni.setTestStatus(NodeItem.TESTSTATUS_PASSED);
// Store best circuit using its latency as a key
entm.setTestFieldValues(ni.getFingerprint(),
getBestLatency(),
LOCAL.getString("circuit_status_passed"),
getBestHops());
} else if ((Integer) data > 0) {
ni.setTestStatus(NodeItem.TESTSTATUS_FAILED);
// If we have circuits that failed testing
entm.setTestFieldValues(ni.getFingerprint(),
LATENCY_FAIL,
LOCAL.getString("circuit_status_failed"), null);
} else {
// If we have no circuits
ni.setTestStatus(NodeItem.TESTSTATUS_FAILED);
entm.setTestFieldValues(ni.getFingerprint(),
LATENCY_FAIL,
LOCAL.getString("circuit_status_none"), null);
stop();
setSilentBootEnabled(true);
setStartupDelay(intTimeoutStartupDelayMsec);
start(TOR_RESTARTED);
break;
}
}
ni = null;
// Ensure test thread is ready
if (getStatus() != STATUS_IDLE) {
break;
}
// No more nodes to test
if (alTestQueue.isEmpty()) {
// Check to see that all testing threads have completed
if (intActiveNodeTests <= 0) {
stopTestClients();
// Re-Enable testing menu button
jMenuTesting.setEnabled(true);
// intActiveNodeTests will be -1 if testing was aborted
if (intActiveNodeTests == 0) {
// Start next test in 10 minutes
intBeginTesting = 600;
// Force change on next Autoselection check
intThresholdExceeded = 255;
// Force Autoselection check in 1 second
intAutoSelectCheck = 1;
}
return;
}
return;
}
// Fetch node item from queue
while (!alTestQueue.isEmpty()) {
String finger = alTestQueue.get(0);
alTestQueue.remove(0);
ni = nodeList.getNode(finger);
if (ni != null) {
intActiveNodeTests++;
entm.setValueAt(LOCAL.getString("circuit_status_creating_3hop"),
ni.getFingerprint(), 3);
Logger.getGlobal().logp(Level.INFO, SelekTOR.class.getName(),
"controllerEventFired() on Port=" + getListenPort(), "Begun testing node " + ni.getNickName());
testNode(ni.getFingerprint());
} else {
Logger.getGlobal().logp(Level.INFO, SelekTOR.class.getName(),
"controllerEventFired() on Port=" + getListenPort(), finger + " node not found in nodelist ");
entm.setValueAt(LOCAL.getString("circuit_status_failed"),
finger, 3);
}
break;
}
break;
case EVENT_CIRCUIT_BUILT:
if (ni != null) {
entm.setValueAt(LOCAL.getString("circuit_status_testing"), ni.getFingerprint(), 3);
}
break;
case EVENT_ABORTED:
if (intActiveNodeTests > 0) {
intActiveNodeTests--;
}
if (ni != null) {
entm.setValueAt(LOCAL.getString("circuit_status_aborted"),
ni.getFingerprint(), 3);
ni.setTestStatus(NodeItem.TESTSTATUS_UNKNOWN);
ni = null;
}
break;
case TOR_DIRINFO_STALE:
case TOR_NOEXITS:
if (intActiveNodeTests > 0) {
intActiveNodeTests--;
}
if (ni != null) {
entm.setTestFieldValues(ni.getFingerprint(),
LATENCY_FAIL,
LOCAL.getString("circuit_status_noroute"), null);
ni.setTestStatus(NodeItem.TESTSTATUS_FAILED);
ni = null;
stop();
setSilentBootEnabled(true);
setStartupDelay(intTimeoutStartupDelayMsec);
start(TOR_RESTARTED);
}
break;
}
}
};
tcTest.setTorrcOption("ClientOnly", "1");
tcTest.setTorrcOption("StrictNodes", "1");
tcTest.setTorrcOption("UseMicrodescriptors", "0");
tcTest.setTorrcOption("UseEntryGuards", "1");
tcTest.setTorrcOption("NumEntryGuards", "3");
tcTest.setOwnershipID(tcMain.getOwnershipID());
tcTest.setControlPassword(strSecret, strHash);
tcTest.setTorrcOption("HashedControlPassword", strHash);
tcTest.setCLIOption("quiet", EMPTYSTR);
// Add this this tor process thread to our thread queue
alTestThreads.add(tcTest);
}
strSecret = strHash = null;
}
/**
* Auto select next best node based on latency
*
*/
private void autoSelectNode() {
String finger;
switch (intThresholdExceeded) {
case 255:
intThresholdExceeded = 0;
// Recaculate best nodes
calcBestNodes();
resetBestNode();
finger = getBestNode();
break;
case 254:
// this will re-apply previously selected node
finger = strRequestedExit;
strRequestedExit = EMPTYSTR;
break;
default:
// Indicate node has failed testing
NodeItem ni = null;
if (niActiveExit != null && nodeList.getNumberOfFavs() != 1) {
ni = nodeList.getNode(niActiveExit.getFingerprint());
if (ni != null) {
ni.setTestStatus(NodeItem.TESTSTATUS_FAILED);
}
}
// Get next best node
finger = getBestNode();
break;
}
intThresholdExceeded = 0;
// Check to see if finger is valid
if (finger != null && !finger.isEmpty()) {
if (!finger.contentEquals(strRequestedExit)) {
strRequestedExit = finger;
updateProgramStatus(LOCAL.getString("progstatus_autoswitch")
+ " " + activateNode(strRequestedExit) + ".");
}
} else {
updateProgramStatus(LOCAL.getString("progstatus_nodefailtorchoose"));
strRequestedExit = EMPTYSTR;
activateNode(strRequestedExit);
}
}
/**
* Set latency threshold value and update its corresponding label
*
* @param threshold
*/
private void setThreshold(long threshold) {
lngThreshold = threshold;
jTableExitNodes.setToolTipText(LOCAL.getString("ttip_threshold")
+ ": " + lngThreshold + " ms");
}
/**
* Calculate best nodes based on latency and also generate the latency
* threshold value
*/
private void calcBestNodes() {
long l;
long summation = 0;
long mean = TorController.LATENCY_FAIL;
int i = 0;
ArrayList<String> alBestNodes = new ArrayList<>();
ArrayList<String> alBestFavs = new ArrayList<>();
TableRowSorter trs = new TableRowSorter<>(entm);
trs.toggleSortOrder(2);
for (int idx = 0; idx < entm.getRowCount(); idx++) {
NodeItem ni = entm.getNodeItemAt(trs.convertRowIndexToModel(idx));
if (ni.getTestStatus() == NodeItem.TESTSTATUS_FAILED) {
continue;
}
if (ni.isFavourite()) {
alBestFavs.add(ni.getFingerprint());
}
// Calculate our new weighted threshold value
l = ni.getTestLatency();
if (l >= mean) {
continue;
}
summation += l;
mean = (summation / (i + 1)) * 3;
i++;
alBestNodes.add(ni.getFingerprint());
}
// New threshold result, prevent divide by zero
if (i == 0) {
setThreshold(MAXTHRESHOLD);
} else {
setThreshold((summation / i) + 100);
}
if (alBestFavs.isEmpty()) {
while (alBestNodes.size() > 5) {
alBestNodes.remove(alBestNodes.remove(alBestNodes.size() - 1));
}
strArrBestNodes = alBestNodes.toArray(new String[alBestNodes.size()]);
} else {
strArrBestNodes = alBestFavs.toArray(new String[alBestFavs.size()]);
}
}
private void resetTestFields() {
for (int i = 0; i < entm.getRowCount(); i++) {
entm.setValueAt(TorController.LATENCY_FAIL, i, 2);
entm.setValueAt(LOCAL.getString("textfield_unknown"), i, 3);
entm.setValueAt(null, i, 6);
}
}
/**
* Begin the test cycle
*/
private void runTestingCycle() {
// Setting intBeginTesting to -1 prevents re-triggering of testing cycle until it has completed
intBeginTesting = TESTING_ACTIVE;
// Update table status column to show unknown and reset the latency column to 9999
intActiveNodeTests = 0;
jMenuTesting.setEnabled(false);
jTableExitNodes.getRowSorter().setSortKeys(null);
resetTestFields();
// Add all nodes to the individual test thread queues
alTestQueue.addAll(nodeList.getExitNodes(true, false));
// Some more inititalisation of test process threads
long delay = 0;
int listenport = tcMain.getListenPort();
for (TorController tc : alTestThreads) {
listenport += 2;
tc.setListenPort(listenport);
tc.setCachedDataFolder(tcMain.getListenPort());
tc.setBridges(sp.getString("PREF_TORBRIDGE"));
tc.setEntryNodes(tcMain.getEntryGuardsAsCSV());
tc.setTestingURL(TESTURL);
tc.setBoolTorOption("SafeSocks", sp.getBool("PREF_SAFESOCKS"));
tc.setBoolTorOption("TestSocks", sp.getBool("PREF_TESTSOCKS"));
tc.setBoolTorOption("AvoidDiskWrites", sp.getBool("PREF_AVOIDDISK"));
tc.setBoolTorOption("SafeLogging", sp.getBool("PREF_SAFELOG"));
tc.setGeoIP4(geoipPath);
tc.setGeoIP6(geoip6Path);
tc.setExternalArgs(sp.getString("PREF_TORARGS"));
tc.setLogLevel(sp.getInt("PREF_TORLOGLEV"));
tc.setSilentBootEnabled(true);
tc.setStartupDelay(delay);
delay += intTimeoutSocketMsec;
tc.start();
}
}
/**
* Cleanly abort any node testing
*/
private void abortTesting() {
intBeginTesting = TESTING_DISABLED;
for (TorController tcTest : alTestThreads) {
tcTest.abortActions();
}
intActiveNodeTests = -1;
alTestQueue.clear();
jMenuTesting.setEnabled(true);
}
/**
* Terminate all test threads cleanly, this is permanent and would require a
* call to initTestThreads prior to starting them again
*/
private void stopTestClients() {
for (TorController tc : alTestThreads) {
tc.stop();
}
}
/**
* Gets the node with the best circuit hops
*
* @return String with the best circuit hops or empty string if we don't
* have any or null if we have run out of good nodes
*/
private String getBestNode() {
// Check for no table or empty table
if (strArrBestNodes == null || strArrBestNodes.length == 0) {
intBestNodeIndex = 0;
return EMPTYSTR;
}
// Check for end of table
if (intBestNodeIndex > (strArrBestNodes.length - 1)) {
intBestNodeIndex = 0;
if (intBeginTesting > 2) {
intBeginTesting = 2;
}
return null;
}
return strArrBestNodes[intBestNodeIndex++];
}
/**
* Reset to the best node
*/
private void resetBestNode() {
intBestNodeIndex = 0;
}
/**
* Update program status message
*
* @param message
*/
private synchronized void updateProgramStatus(String message) {
if (message != null) {
jLabStatus.setText(message);
Logger.getGlobal().log(Level.INFO, "updateProgramStatus {0}", message);
}
}
private void getFreshNodeInfo() {
TorCircuit tc = tcMain.getLatestCircuit();
if (tc == null) {
return;
}
// Get active guard node item
String finger = tc.getGuard(TorCircuit.FINGER);
niActiveGuard = nodeList.getNode(finger).clone();
// Get exitnode info
finger = tc.getExit(TorCircuit.FINGER);
niActiveExit = (NodeItem) nodeList.getNode(finger).clone();
niActiveExit.setCircuitHops(tc.getHops());
niActiveExit.setLatency(TorController.LATENCY_FAIL);
// Get active middle node item
finger = tc.getMiddleMan(TorCircuit.FINGER);
niActiveMiddle = nodeList.getNode(finger).clone();
}
/**
* Convenience method to refresh all the GUI labels related to Node
* information
*
* @param niexit Requires the active node item to be provided
*/
private void updateGUINodeInfo(NodeItem niguard, NodeItem nimiddle, NodeItem niexit) {
if (nimiddle == null) {
jLabelMiddleStable.setText(LOCAL.getString("textfield_unknown"));
jLabelMiddleBw.setText(LOCAL.getString("textfield_unknown"));
jLabelMiddleNick.setText(LOCAL.getString("textfield_unknown"));
jLabelMiddleIP.setText(LOCAL.getString("textfield_unknown"));
jLabelMiddleCountry.setText(LOCAL.getString("textfield_unknown"));
jButtonMiddleNodeDetails.setEnabled(false);
} else {
jLabelMiddleNick.setText(nimiddle.getNickName());
jLabelMiddleIP.setText(nimiddle.getIPAddress());
jLabelMiddleCountry.setText(nimiddle.getCountryName());
jLabelMiddleBw.setText(String.valueOf(nimiddle.getBandwidth()) + " MB\\s");
jLabelMiddleStable.setText(nimiddle.getStability());
jButtonMiddleNodeDetails.setEnabled(true);
}
if (niexit == null) {
intLatencyCheck = 0;
intAutoSelectCheck = 0;
jLabelExitNick.setText(LOCAL.getString("textfield_unknown"));
jLabelExitIP.setText(LOCAL.getString("textfield_unknown"));
jLabelExitCountry.setText(LOCAL.getString("textfield_unknown"));
jLabelExitBw.setText(LOCAL.getString("textfield_unknown"));
jLabelExitStable.setText(LOCAL.getString("textfield_unknown"));
jLabelTorLatency.setText(LOCAL.getString("textfield_unknown"));
jLabelStreams.setText(LOCAL.getString("textfield_unknown"));
jLabelGuardStable.setText(LOCAL.getString("textfield_unknown"));
jLabelGuardBw.setText(LOCAL.getString("textfield_unknown"));
jLabelGuardNick.setText(LOCAL.getString("textfield_unknown"));
jLabelGuardIP.setText(LOCAL.getString("textfield_unknown"));
jLabelGuardCountry.setText(LOCAL.getString("textfield_unknown"));
jButtonExitNodeDetails.setEnabled(false);
jButtonGuardNodeDetails.setEnabled(false);
jMenuItemTorCheck.setEnabled(false);
} else {
jLabelExitNick.setText(niexit.getNickName());
jLabelExitIP.setText(niexit.getIPAddress());
jLabelExitCountry.setText(niexit.getCountryName());
jLabelExitBw.setText(String.valueOf(niexit.getBandwidth()) + " MB\\s");
jLabelExitStable.setText(niexit.getStability());
jButtonExitNodeDetails.setEnabled(true);
jLabelGuardNick.setText(niguard.getNickName());
jLabelGuardIP.setText(niguard.getIPAddress());
jLabelGuardCountry.setText(niguard.getCountryName());
jLabelGuardBw.setText(String.valueOf(niguard.getBandwidth()) + " MB\\s");
jLabelGuardStable.setText(niguard.getStability());
jMenuItemTorCheck.setEnabled(true);
jButtonGuardNodeDetails.setEnabled(true);
if (niexit.getLatency() > 5000) {
jLabelTorLatency.setText("> 5000 ms");
} else {
jLabelTorLatency.setText(String.valueOf(niexit.getLatency()) + " ms");
}
jLabelStreams.setText(String.valueOf(niexit.getStreams()));
updateProgramStatus(LOCAL.getString("progstatus_nodeactive3hop").replace("$nodename", niActiveExit.getNickName()));
dn.raiseNotification();
}
String text = LOCAL.getString("label_country") + " : " + sp.getString("PREF_ISOCOUNTRY");
text += "\n" + LOCAL.getString("traymenu_proxymode" + (sp.getInt("PREF_PROXY_MODE") + 1));
text += "\n" + LOCAL.getString("traytool_guardnode") + " : " + jLabelGuardNick.getText();
text += "\n" + LOCAL.getString("traytool_exitnode") + " : " + jLabelExitNick.getText();
text += "\n" + LOCAL.getString("label_torlatency") + " : " + jLabelTorLatency.getText();
text += "\n" + LOCAL.getString("label_streams") + " : " + jLabelStreams.getText();
sti.setInfoTip(text);
}
/**
* Convenience method to update the exit node table
*
*/
private void updateExitNodeTable() {
try {
strArrBestNodes = null;
intRowSelected = -1;
// Set in an empty model while we do the update of its model to avoid event collision issues
jTableExitNodes.setModel(new ExitNodeTableModel());
nodeList.refreshExitTableModel(strExitISOCode);
jTableExitNodes.setModel(entm);
resetTestFields();
calcBestNodes();
} catch (Exception ex) {
Logger.getGlobal().logp(Level.WARNING, this.getClass().getName(), "updateExitNodeTable()", EMPTYSTR, ex);
}
updateGUINodeInfo(null, null, null);
setComponentsEnabled(true);
}
/**
* Adjust exit table column widths
*/
private void adjustExitTableColumns() {
// Adjust table column widths
String col3 = LOCAL.getString("circuit_status_creating_2hop");
if (col3.length() > 6) {
col3 = col3.substring(0, col3.length() - 2);
} else {
col3 = "XXXXXXXXXXXXXXXXXX";
}
Utilities.adjustTableColumnWidth(jTableExitNodes,
"XXXXXXXXXXXXXXXXXX",
jTableExitNodes.getColumnName(1) + "X",
jTableExitNodes.getColumnName(2) + "X",
col3,
jTableExitNodes.getColumnName(4) + "X");
}
/**
* Returns the selected fingerprint
*
* @param row
* @return Fingerprint as String
*/
private String getSelectedFinger(int row) {
return (String) entm.getValueAt(row, 5);
}
/**
* Tests first to see if node is in the exitnode list
*
* @param finger
* @return true if specified node is in the exit node table
*/
private boolean isValidExit(String finger) {
return nodeList.getExitNodes(true, false).contains(finger);
}
/**
* Activates specified node with fingerprint finger, also returns the node
* name
*
* @param finger
* @return Node name
*/
private String activateNode(String fingerprint) {
String result = EMPTYSTR;
updateGUINodeInfo(niActiveGuard = null, niActiveMiddle = null, niActiveExit = null);
if (boolFirstRun) {
tcMain.closeCircuitsExcept("", true);
}
if (fingerprint.isEmpty()) {
// Get a list of exit nodes based on auto node selection mode
ArrayList<String> alFingers = nodeList.getExitNodes(false, true);
if (alFingers.isEmpty()) {
// Get a list of all exit nodes
alFingers = nodeList.getExitNodes(true, true);
}
if (alFingers.isEmpty()) {
// Get a list of all exit nodes
alFingers = nodeList.getExitNodes(true, true);
}
// Randomly select from given list of nodes
Random rand = new Random();
int idx = rand.nextInt(alFingers.size());
fingerprint = alFingers.get(idx);
tcMain.activateNodes(fingerprint, 1);
} else if (!fingerprint.startsWith("$")) {
tcMain.activateNodes(fingerprint, 1);
} else {
NodeItem ni = nodeList.getNode(fingerprint);
tcMain.activateNodes(fingerprint, 1);
if (ni != null) {
ni.setTestStatus(NodeItem.TESTSTATUS_PASSED);
result = ni.getNickName();
} else {
result = fingerprint;
}
}
return result;
}
/**
* Called when the country is changed via the combo box change event
*
*/
private void countryChanged() {
// Some essential resets of variables
niActiveExit = null;
// Get selected country
String iso = (String) jComboCountry.getSelectedItem();
iso = iso.substring(0, 2);
if (!strExitISOCode.contentEquals(iso)) {
// Save new country to properties file
sp.setString("PREF_ISOCOUNTRY", strExitISOCode = iso);
sp.save();
}
rebuildPatternPac();
updateExitNodeTable();
adjustExitTableColumns();
updateProgramStatus(LOCAL.getString("progstatus_waitfortor"));
activateNode(strRequestedExit = EMPTYSTR);
}
/**
* Cleans up pac files and proxies
*/
private void pacCleanup() {
if (pacFactory != null) {
pacFactory.restoreProxyPrefs(false);
pacFactory.deleteProxyPrefs();
pacFactory.deleteAllPAC();
}
}
/**
* The main application exit routine also does cleanup before exiting
*
*/
public final void cleanupExit() {
try {
setVisible(false);
// Need to ensure various processes are cleanly terminated before we can exit
if (tmr != null) {
tmr.stop();
}
if (sti != null) {
sti.dispose();
}
if (nodeList != null) {
nodeList.terminate();
}
if (tmf != null) {
tmf.dispose();
}
// Terminate all tor threads
if (tcMain != null) {
tcMain.stop();
}
stopTestClients();
pacCleanup();
if (sp.getBool("PREF_CACHEDELETE")) {
SimpleFile.secureWipeFolder(cachePath);
}
} catch (Exception ex) {
}
Logger.getGlobal().log(Level.INFO, "Cleanup completed, shutting down");
dispose();
System.exit(0);
}
/**
* Change visibilty of gUI
*
*/
private void initGUIVisibility() {
// Bring up gui
pack();
setLocationRelativeTo(this);
Utilities.registerWindow();
if (sp.getBool("PREF_HIDETOTRAY")) {
if (sp.getBool("PREF_HIDE_MIN") && sti.isLoaded()) {
setVisible(false);
} else {
setVisible(true);
SwingUtilities.invokeLater(new java.lang.Runnable() {
@Override
public void run() {
repaint();
setExtendedState(Frame.ICONIFIED);
}
});
}
} else {
setVisible(true);
}
}
/**
* Toggle GUI visibility
*/
private void toggleGUIVisibility() {
if (OSFunction.isLinux()) {
requestFocus();
}
SwingUtilities.invokeLater(new java.lang.Runnable() {
@Override
public void run() {
if (!isVisible()) {
setVisible(true);
setExtendedState(Frame.NORMAL);
return;
}
if ((getExtendedState() & Frame.ICONIFIED) != 0) {
setExtendedState(Frame.NORMAL);
toFront();
} else {
if (OSFunction.isLinux()) {
switch (desktopname) {
case "kde4":
if (compositor.contentEquals("kwin")) {
if (getFocusOwner() == null) {
setVisible(false);
setVisible(true);
return;
}
}
break;
case "mate":
if (compositor.contentEquals("compiz")) {
if (getFocusOwner() == null) {
setExtendedState(Frame.NORMAL);
toFront();
return;
}
} else if (getFocusOwner() == null) {
setVisible(false);
setVisible(true);
return;
}
break;
default:
if (getFocusOwner() == null) {
setExtendedState(Frame.NORMAL);
toFront();
return;
}
break;
}
}
if (sp.getBool("PREF_HIDE_MIN") && sti.isLoaded()) {
setVisible(false);
} else {
setExtendedState(Frame.ICONIFIED);
}
}
}
});
}
/**
* Open the about dialog
*/
private void openAboutDialog() {
AboutDialog ad = new AboutDialog(this, true);
ad.setButtonCloseText(LOCAL.getString("button_close"));
ad.setButtonVisitText(LOCAL.getString("button_visitus"));
ad.setButtonContactText(LOCAL.getString("button_contactus"));
ad.setTitle(LOCAL.getString("wintitle_about").replace("$appname", APPNAME));
ad.setContactURL(CONTACT);
ad.setHomeURL(HOMEPAGE_SSL);
ad.setAppLogo(new javax.swing.ImageIcon(iconPath + ICONFILE));
String desc = LOCAL.getString("appdesc").replace("$appname", APPNAME);
desc = desc.replace("$appver", APPVER) + "\n\nCopyright 2009-2017\nAlistair Neil";
ad.setAppDescription(desc);
ad.setLocationRelativeTo(this);
ad.pack();
ad.setVisible(true);
}
/**
* Open the licensing dialog
*/
private void openLicenseDialog() {
TextResourceDialog trd = new TextResourceDialog(this, true);
trd.setTitle(LOCAL.getString("dlg_license_title"));
trd.setURLButtonText(LOCAL.getString("button_translations"));
trd.setButtonURL(LOCAL.getString("gpltransurl"));
trd.setCloseButtonText(LOCAL.getString("button_close"));
trd.setTitle(LOCAL.getString("dlg_license_title").replace("$appname", APPNAME));
trd.setText(Utilities.getTextFromResource("/resources/license.txt"));
trd.setLocationRelativeTo(this);
trd.setVisible(true);
}
/**
* Open the licensing dialog
*/
private void openCreditsDialog() {
TextResourceDialog trd = new TextResourceDialog(this, true);
trd.setTitle(LOCAL.getString("dlg_credits_title"));
trd.setButtonURL(PATREON);
trd.setURLButtonText(LOCAL.getString("button_patreon"));
trd.setCloseButtonText(LOCAL.getString("button_close"));
trd.setTitle(LOCAL.getString("dlg_credits_title").replace("$appname", APPNAME));
trd.setText(LOCAL.getString("dlg_credits_body") + "\n\n"
+ Utilities.getTextFromResource("/resources/credits.txt"));
trd.setLocationRelativeTo(this);
trd.setVisible(true);
}
/**
* Open the user pattern export file chooser
*/
private void openPatternExport() {
File[] files = pacFactory.getPatternsFiles();
if (files.length == 0) {
InfoDialog id = createInfoDialog();
id.createWarn(LOCAL.getString("dlg_exportuser_title"),
LOCAL.getString("dlg_exportuser_body"));
id.setContinueButtonText(LOCAL.getString("button_close"));
id.setCancelVisible(false);
id.pack();
id.setVisible(true);
return;
}
// Lets choose our zip filename or overwrite an existing zip file
JFileChooser jfc = new JFileChooser();
jfc.setDialogTitle(LOCAL.getString("dlg_saveuser_title"));
if (jfc.showSaveDialog(this) != JFileChooser.APPROVE_OPTION) {
return;
}
pacFactory.exportUserPatterns(jfc.getSelectedFile().getAbsolutePath(), files);
}
/**
* Open the pattern import file chooser
*/
private void openPatternImport() {
JFileChooser jfc = new JFileChooser();
ExtensionFileFilter filter = new ExtensionFileFilter(LOCAL.getString("fileext_pattern"), new String[]{"zip"});
jfc.setFileFilter(filter);
jfc.setDialogTitle(LOCAL.getString("dlg_import_title"));
if (jfc.showOpenDialog(this) != JFileChooser.APPROVE_OPTION) {
return;
}
InfoDialog id = createInfoDialog();
if (pacFactory.importPatterns(jfc.getSelectedFile().getAbsolutePath())) {
rebuildPatternPac();
id.createWarn(LOCAL.getString("dlg_import_success_title"),
LOCAL.getString("dlg_import_success_body"));
id.setCancelVisible(false);
id.pack();
id.setVisible(true);
} else {
id.createWarn(LOCAL.getString("dlg_import_fail_title"),
LOCAL.getString("dlg_import_fail_body"));
id.setCancelVisible(false);
id.pack();
id.setVisible(true);
}
}
/**
* Open the pattern editor
*/
private void openPatternEditorDialog() {
PatternsEditor pe = new PatternsEditor(this, true, pacFactory);
pe.populateCountryComboBox(nodeList.getValidatedCountries());
pe.setSelectedCountry((String) jComboCountry.getSelectedItem());
pe.setTitle(LOCAL.getString("wintitle_patternedit").replace("$appname", APPNAME));
pe.pack();
pe.setLocationRelativeTo(this);
pe.setVisible(true);
sp.setString("PREF_DONOT_PROXY", pacFactory.getDoNotProxy());
if (sp.getChangedProperties().contains("PREF_DONOT_PROXY")) {
sp.save();
}
if (pe.getReturnStatus() == PatternsEditor.APPLY) {
rebuildPatternPac();
}
}
/**
* Open Quick Add pattern dialog
*/
private void openQuickAddDialog() {
QuickAddDialog qad = new QuickAddDialog(this, true);
qad.pack();
qad.setLocationRelativeTo(this);
qad.setVisible(true);
if (qad.getReturnStatus() == QuickAddDialog.APPLY && strExitISOCode != null) {
pacFactory.addToPatternFile(strExitISOCode, qad.getDescription(), qad.getPattern());
rebuildPatternPac();
}
}
/**
* Open Tor client to old dialog
*/
private void openToOldDialog() {
openFatalErrorDialog(LOCAL.getString("dlg_toold_body"));
}
/**
* Open the fatal error dialog
*
* @param errmessage
*/
private void openFatalErrorDialog(String errmessage) {
String text = "\n\n" + LOCAL.getString("dlg_error_body").replace("$appname", APPNAME);
InfoDialog id = createInfoDialog();
id.setSize(500, 450);
id.createInfo(LOCAL.getString("dlg_error_title"), errmessage + text);
id.setModal(true);
id.pack();
id.setLocationRelativeTo(this);
id.pack();
id.setVisible(true);
}
/**
* Open the guards node setting dialog
*/
private void openGuardsSettingDialog() {
GuardNodeDialog gnd = new GuardNodeDialog(this, true);
gnd.setNodeList(nodeList);
gnd.pack();
gnd.setLocationRelativeTo(this);
gnd.setVisible(true);
if (gnd.getReturnStatus() == GuardNodeDialog.APPLY) {
if (sp.getString("PREF_TORBRIDGE").isEmpty()) {
updateProgramStatus(LOCAL.getString("progstatus_applychanges"));
abortAllTorThreads();
applyMainTorSettings();
tcMain.start();
}
}
}
/**
* Open the standard out dialog
*/
private void openTorMonitor() {
tmf.setLocationRelativeTo(this);
tmf.setVisible(true);
}
/**
* Called when proxy mode is changed by the user
*
* @param mode Proxy mode
*/
private void proxyModeChanged(int mode) {
sp.setInt("PREF_PROXY_MODE", mode);
sp.save();
dn.setNotificationBody(LOCAL.getString("traymenu_proxymode" + (sp.getInt("PREF_PROXY_MODE") + 1)));
applyProxyChanges(mode);
}
/**
* Apply any proxy changes based on current proxy mode
*
* @param mode Proxy mode
*/
private void applyProxyChanges(int mode) {
if (tcMain == null) {
return;
}
switch (mode) {
case PacFactory.PROXY_DISABLED:
pacFactory.restoreProxyPrefs(true);
pacFactory.deleteAllPAC();
break;
case PacFactory.PROXY_PATTERN:
pacFactory.createPacFile(strExitISOCode, tcMain.getListenPort());
break;
case PacFactory.PROXY_ALL:
pacFactory.createPacFile("proxyall", tcMain.getListenPort());
break;
}
}
/**
* Rebuilds pattern pacfile but only if we are in pattern mode
*/
private void rebuildPatternPac() {
if (sp.getInt("PREF_PROXY_MODE") == PacFactory.PROXY_PATTERN) {
applyProxyChanges(sp.getInt("PREF_PROXY_MODE"));
}
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
popupTable = new javax.swing.JPopupMenu();
jMenuNodeDetails = new javax.swing.JMenuItem();
jMenuWhois = new javax.swing.JMenuItem();
jMenuTesting = new javax.swing.JMenuItem();
jMenuItemGUI = new javax.swing.JMenuItem();
jMenuItemQuitx = new javax.swing.JMenuItem();
buttonGroupProxy = new javax.swing.ButtonGroup();
buttonGroupProxyTray = new javax.swing.ButtonGroup();
jCheckTrayProxyDisable = new javax.swing.JCheckBoxMenuItem();
jCheckTrayProxyByPattern = new javax.swing.JCheckBoxMenuItem();
jCheckTrayProxyAll = new javax.swing.JCheckBoxMenuItem();
jPanelMain = new javax.swing.JPanel();
jLabelCountry = new javax.swing.JLabel();
jComboCountry = new javax.swing.JComboBox<>();
jScrollPaneExitNodes = new javax.swing.JScrollPane();
jTableExitNodes = new javax.swing.JTable();
jPanelNodeInfo = new javax.swing.JPanel();
jLabel5 = new javax.swing.JLabel();
jLabelGuardBw = new javax.swing.JLabel();
jLabel10 = new javax.swing.JLabel();
jLabelGuardStable = new javax.swing.JLabel();
jLabelGuard = new javax.swing.JLabel();
jLabel8 = new javax.swing.JLabel();
jLabelGuardNick = new javax.swing.JLabel();
jLabelGuardIP = new javax.swing.JLabel();
jLabel9 = new javax.swing.JLabel();
jLabelGuardCountry = new javax.swing.JLabel();
jLabel12 = new javax.swing.JLabel();
jLabelExitNick = new javax.swing.JLabel();
jLabelExitIP = new javax.swing.JLabel();
jLabelMiddle = new javax.swing.JLabel();
jLabelExit = new javax.swing.JLabel();
jLabelMiddleNick = new javax.swing.JLabel();
jLabelMiddleIP = new javax.swing.JLabel();
jLabelMiddleCountry = new javax.swing.JLabel();
jButtonExitNodeDetails = new javax.swing.JButton();
jButtonGuardNodeDetails = new javax.swing.JButton();
jButtonMiddleNodeDetails = new javax.swing.JButton();
jLabelMiddleBw = new javax.swing.JLabel();
jLabelExitBw = new javax.swing.JLabel();
jLabelMiddleStable = new javax.swing.JLabel();
jLabelExitStable = new javax.swing.JLabel();
jLabelExitCountry = new javax.swing.JLabel();
jLabel4 = new javax.swing.JLabel();
jLabelTorLatency = new javax.swing.JLabel();
jLabelStreams = new javax.swing.JLabel();
jLabel6 = new javax.swing.JLabel();
jButtonSetGuards = new javax.swing.JButton();
jLabStatus = new javax.swing.JLabel();
jButtonClearFavs = new javax.swing.JButton();
jMenuBar = new javax.swing.JMenuBar();
jMenuMenu = new javax.swing.JMenu();
jMenuItemPrefs = new javax.swing.JMenuItem();
jMenuItemAddPattern = new javax.swing.JMenuItem();
jMenuItemPatternEdit = new javax.swing.JMenuItem();
jMenuItemStdout = new javax.swing.JMenuItem();
jMenuItemExport = new javax.swing.JMenuItem();
jMenuItemImport = new javax.swing.JMenuItem();
jMenuItemGeoip = new javax.swing.JMenuItem();
jMenuItemQuit = new javax.swing.JMenuItem();
jMenuProxy = new javax.swing.JMenu();
jCheckProxyDisable = new javax.swing.JCheckBoxMenuItem();
jCheckProxyByPattern = new javax.swing.JCheckBoxMenuItem();
jCheckProxyAll = new javax.swing.JCheckBoxMenuItem();
jMenuHelp = new javax.swing.JMenu();
jMenuItemDebugLog = new javax.swing.JMenuItem();
jMenuItemHelp = new javax.swing.JMenuItem();
jMenuItemTorMan = new javax.swing.JMenuItem();
jMenuItemTorCheck = new javax.swing.JMenuItem();
jMenuItemAbout = new javax.swing.JMenuItem();
jMenuItemLicense = new javax.swing.JMenuItem();
popupTable.addPopupMenuListener(new javax.swing.event.PopupMenuListener() {
public void popupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) {
popupTablePopupMenuWillBecomeVisible(evt);
}
public void popupMenuWillBecomeInvisible(javax.swing.event.PopupMenuEvent evt) {
}
public void popupMenuCanceled(javax.swing.event.PopupMenuEvent evt) {
}
});
jMenuNodeDetails.setText(LOCAL.getString("table_popup_details")); // NOI18N
jMenuNodeDetails.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jMenuNodeDetailsActionPerformed(evt);
}
});
popupTable.add(jMenuNodeDetails);
jMenuWhois.setText(LOCAL.getString("table_popup_whois")); // NOI18N
jMenuWhois.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jMenuWhoisActionPerformed(evt);
}
});
popupTable.add(jMenuWhois);
jMenuTesting.setText(LOCAL.getString("table_popup_begintest")); // NOI18N
jMenuTesting.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jMenuTestingActionPerformed(evt);
}
});
popupTable.add(jMenuTesting);
jMenuItemGUI.setBackground(new Color(jMenuBar.getBackground().getRGB()));
jMenuItemGUI.setForeground(new Color(jMenuBar.getForeground().getRGB()));
jMenuItemGUI.setText(LOCAL.getString("traymenu_showgui")); // NOI18N
jMenuItemGUI.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jMenuItemGUIActionPerformed(evt);
}
});
jMenuItemQuitx.setText(LOCAL.getString("menu_quit")); // NOI18N
jMenuItemQuitx.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jMenuItemQuitxActionPerformed(evt);
}
});
jCheckTrayProxyDisable.setText(LOCAL.getString("combo_proxymode1")); // NOI18N
jCheckTrayProxyDisable.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
jCheckTrayProxyDisableItemStateChanged(evt);
}
});
jCheckTrayProxyByPattern.setText(LOCAL.getString("combo_proxymode2")); // NOI18N
jCheckTrayProxyByPattern.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
jCheckTrayProxyByPatternItemStateChanged(evt);
}
});
jCheckTrayProxyAll.setText(LOCAL.getString("combo_proxymode3")); // NOI18N
jCheckTrayProxyAll.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
jCheckTrayProxyAllItemStateChanged(evt);
}
});
setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE);
setResizable(false);
addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(java.awt.event.WindowEvent evt) {
formWindowClosing(evt);
}
});
jPanelMain.setFont(jPanelMain.getFont().deriveFont(jPanelMain.getFont().getStyle() | java.awt.Font.BOLD, jPanelMain.getFont().getSize()+1));
jLabelCountry.setFont(jLabelCountry.getFont().deriveFont(jLabelCountry.getFont().getStyle() | java.awt.Font.BOLD));
jLabelCountry.setText(LOCAL.getString("label_activecountry")); // NOI18N
jComboCountry.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
jComboCountryItemStateChanged(evt);
}
});
jTableExitNodes.setAutoCreateRowSorter(true);
jTableExitNodes.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {
{},
{},
{},
{}
},
new String [] {
}
));
jTableExitNodes.setToolTipText(LOCAL.getString("ttip_threshold") +" : "+ LOCAL.getString("textfield_unknown")
);
jTableExitNodes.setComponentPopupMenu(popupTable);
jTableExitNodes.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
jTableExitNodes.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent evt) {
jTableExitNodesMouseClicked(evt);
}
});
jScrollPaneExitNodes.setViewportView(jTableExitNodes);
jPanelNodeInfo.setBorder(javax.swing.BorderFactory.createTitledBorder(null, LOCAL.getString("panel_info"), javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, jPanelMain.getFont())); // NOI18N
jPanelNodeInfo.setFont(jPanelNodeInfo.getFont().deriveFont(jPanelNodeInfo.getFont().getStyle() | java.awt.Font.BOLD));
jLabel5.setFont(jLabel5.getFont().deriveFont(jLabel5.getFont().getStyle() | java.awt.Font.BOLD));
jLabel5.setText(LOCAL.getString("label_bandwidth")); // NOI18N
jLabelGuardBw.setText(LOCAL.getString("textfield_unknown")); // NOI18N
jLabelGuardBw.setBorder(javax.swing.BorderFactory.createEtchedBorder());
jLabel10.setFont(jLabel10.getFont().deriveFont(jLabel10.getFont().getStyle() | java.awt.Font.BOLD));
jLabel10.setText(LOCAL.getString("label_stable")); // NOI18N
jLabelGuardStable.setText(LOCAL.getString("textfield_unknown")); // NOI18N
jLabelGuardStable.setBorder(javax.swing.BorderFactory.createEtchedBorder());
jLabelGuard.setFont(jLabelGuard.getFont().deriveFont(jLabelGuard.getFont().getStyle() | java.awt.Font.BOLD));
jLabelGuard.setText(LOCAL.getString("label_guard")); // NOI18N
jLabel8.setFont(jLabel8.getFont().deriveFont(jLabel8.getFont().getStyle() | java.awt.Font.BOLD));
jLabel8.setText(LOCAL.getString("label_ip")); // NOI18N
jLabelGuardNick.setText(LOCAL.getString("textfield_unknown")); // NOI18N
jLabelGuardNick.setBorder(javax.swing.BorderFactory.createEtchedBorder());
java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("resources/MessagesBundle"); // NOI18N
jLabelGuardIP.setText(bundle.getString("textfield_unknown")); // NOI18N
jLabelGuardIP.setBorder(javax.swing.BorderFactory.createEtchedBorder());
jLabel9.setFont(jLabel9.getFont().deriveFont(jLabel9.getFont().getStyle() | java.awt.Font.BOLD));
jLabel9.setText(LOCAL.getString("label_country")); // NOI18N
jLabelGuardCountry.setText(bundle.getString("textfield_unknown")); // NOI18N
jLabelGuardCountry.setBorder(javax.swing.BorderFactory.createEtchedBorder());
jLabel12.setFont(jLabel12.getFont().deriveFont(jLabel12.getFont().getStyle() | java.awt.Font.BOLD));
jLabel12.setText(LOCAL.getString("label_nickname")); // NOI18N
jLabelExitNick.setText(LOCAL.getString("textfield_unknown")); // NOI18N
jLabelExitNick.setBorder(javax.swing.BorderFactory.createEtchedBorder());
jLabelExitIP.setText(bundle.getString("textfield_unknown")); // NOI18N
jLabelExitIP.setBorder(javax.swing.BorderFactory.createEtchedBorder());
jLabelMiddle.setFont(jLabelMiddle.getFont().deriveFont(jLabelMiddle.getFont().getStyle() | java.awt.Font.BOLD));
jLabelMiddle.setText(LOCAL.getString("label_middle")); // NOI18N
jLabelExit.setFont(jLabelExit.getFont().deriveFont(jLabelExit.getFont().getStyle() | java.awt.Font.BOLD));
jLabelExit.setText(LOCAL.getString("label_exit")); // NOI18N
jLabelMiddleNick.setText(bundle.getString("textfield_unknown")); // NOI18N
jLabelMiddleNick.setBorder(javax.swing.BorderFactory.createEtchedBorder());
jLabelMiddleIP.setText(bundle.getString("textfield_unknown")); // NOI18N
jLabelMiddleIP.setBorder(javax.swing.BorderFactory.createEtchedBorder());
jLabelMiddleCountry.setText(bundle.getString("textfield_unknown")); // NOI18N
jLabelMiddleCountry.setBorder(javax.swing.BorderFactory.createEtchedBorder());
jButtonExitNodeDetails.setText(LOCAL.getString("button_details")); // NOI18N
jButtonExitNodeDetails.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonExitNodeDetailsActionPerformed(evt);
}
});
jButtonGuardNodeDetails.setText(LOCAL.getString("button_details")); // NOI18N
jButtonGuardNodeDetails.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonGuardNodeDetailsActionPerformed(evt);
}
});
jButtonMiddleNodeDetails.setText(LOCAL.getString("button_details")); // NOI18N
jButtonMiddleNodeDetails.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonMiddleNodeDetailsActionPerformed(evt);
}
});
jLabelMiddleBw.setText(LOCAL.getString("textfield_unknown")); // NOI18N
jLabelMiddleBw.setBorder(javax.swing.BorderFactory.createEtchedBorder());
jLabelExitBw.setText(LOCAL.getString("textfield_unknown")); // NOI18N
jLabelExitBw.setBorder(javax.swing.BorderFactory.createEtchedBorder());
jLabelMiddleStable.setText(LOCAL.getString("textfield_unknown")); // NOI18N
jLabelMiddleStable.setBorder(javax.swing.BorderFactory.createEtchedBorder());
jLabelExitStable.setText(LOCAL.getString("textfield_unknown")); // NOI18N
jLabelExitStable.setBorder(javax.swing.BorderFactory.createEtchedBorder());
jLabelExitCountry.setText(bundle.getString("textfield_unknown")); // NOI18N
jLabelExitCountry.setBorder(javax.swing.BorderFactory.createEtchedBorder());
jLabel4.setFont(jLabel4.getFont().deriveFont(jLabel4.getFont().getStyle() | java.awt.Font.BOLD));
jLabel4.setText(LOCAL.getString("label_torlatency")); // NOI18N
jLabelTorLatency.setText(LOCAL.getString("textfield_unknown")); // NOI18N
jLabelTorLatency.setBorder(javax.swing.BorderFactory.createEtchedBorder());
jLabelStreams.setText(LOCAL.getString("textfield_unknown")); // NOI18N
jLabelStreams.setBorder(javax.swing.BorderFactory.createEtchedBorder());
jLabel6.setFont(jLabel6.getFont().deriveFont(jLabel6.getFont().getStyle() | java.awt.Font.BOLD));
jLabel6.setText(LOCAL.getString("label_streams")); // NOI18N
javax.swing.GroupLayout jPanelNodeInfoLayout = new javax.swing.GroupLayout(jPanelNodeInfo);
jPanelNodeInfo.setLayout(jPanelNodeInfoLayout);
jPanelNodeInfoLayout.setHorizontalGroup(
jPanelNodeInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanelNodeInfoLayout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanelNodeInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel10)
.addComponent(jLabel9)
.addComponent(jLabel8)
.addComponent(jLabel12)
.addComponent(jLabel5))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(jPanelNodeInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addGroup(jPanelNodeInfoLayout.createSequentialGroup()
.addComponent(jLabelGuard)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jButtonGuardNodeDetails))
.addComponent(jLabelGuardIP, javax.swing.GroupLayout.DEFAULT_SIZE, 200, Short.MAX_VALUE)
.addComponent(jLabelGuardCountry, javax.swing.GroupLayout.DEFAULT_SIZE, 200, Short.MAX_VALUE)
.addComponent(jLabelGuardBw, javax.swing.GroupLayout.DEFAULT_SIZE, 200, Short.MAX_VALUE)
.addComponent(jLabelGuardStable, javax.swing.GroupLayout.DEFAULT_SIZE, 200, Short.MAX_VALUE)
.addComponent(jLabelGuardNick, javax.swing.GroupLayout.DEFAULT_SIZE, 200, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(jPanelNodeInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addGroup(jPanelNodeInfoLayout.createSequentialGroup()
.addComponent(jLabel4)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabelTorLatency, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGroup(jPanelNodeInfoLayout.createSequentialGroup()
.addComponent(jLabelMiddle)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jButtonMiddleNodeDetails))
.addComponent(jLabelMiddleIP, javax.swing.GroupLayout.DEFAULT_SIZE, 200, Short.MAX_VALUE)
.addComponent(jLabelMiddleCountry, javax.swing.GroupLayout.DEFAULT_SIZE, 200, Short.MAX_VALUE)
.addComponent(jLabelMiddleBw, javax.swing.GroupLayout.DEFAULT_SIZE, 200, Short.MAX_VALUE)
.addComponent(jLabelMiddleStable, javax.swing.GroupLayout.DEFAULT_SIZE, 200, Short.MAX_VALUE)
.addComponent(jLabelMiddleNick, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(jPanelNodeInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
.addComponent(jLabelExitStable, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 200, Short.MAX_VALUE)
.addComponent(jLabelExitBw, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 200, Short.MAX_VALUE)
.addComponent(jLabelExitCountry, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 200, Short.MAX_VALUE)
.addComponent(jLabelExitIP, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 200, Short.MAX_VALUE)
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanelNodeInfoLayout.createSequentialGroup()
.addComponent(jLabel6)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabelStreams, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanelNodeInfoLayout.createSequentialGroup()
.addComponent(jLabelExit)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jButtonExitNodeDetails))
.addComponent(jLabelExitNick, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 200, Short.MAX_VALUE))
.addContainerGap())
);
jPanelNodeInfoLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {jLabel10, jLabel12, jLabel5, jLabel8, jLabel9});
jPanelNodeInfoLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {jLabelExitBw, jLabelExitCountry, jLabelExitIP, jLabelExitNick, jLabelExitStable, jLabelMiddleBw, jLabelMiddleCountry, jLabelMiddleIP, jLabelMiddleStable});
jPanelNodeInfoLayout.setVerticalGroup(
jPanelNodeInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanelNodeInfoLayout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanelNodeInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
.addComponent(jLabelGuard)
.addComponent(jButtonGuardNodeDetails)
.addComponent(jLabelMiddle)
.addComponent(jButtonMiddleNodeDetails)
.addComponent(jLabelExit)
.addComponent(jButtonExitNodeDetails))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanelNodeInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanelNodeInfoLayout.createSequentialGroup()
.addComponent(jLabelExitNick)
.addGap(0, 0, 0)
.addComponent(jLabelExitIP)
.addGap(0, 0, 0)
.addComponent(jLabelExitCountry)
.addGap(0, 0, 0)
.addComponent(jLabelExitBw)
.addGap(0, 0, 0)
.addComponent(jLabelExitStable))
.addGroup(jPanelNodeInfoLayout.createSequentialGroup()
.addComponent(jLabelMiddleNick)
.addGap(0, 0, 0)
.addComponent(jLabelMiddleIP)
.addGap(0, 0, 0)
.addComponent(jLabelMiddleCountry)
.addGap(0, 0, 0)
.addComponent(jLabelMiddleBw)
.addGap(0, 0, 0)
.addComponent(jLabelMiddleStable))
.addGroup(jPanelNodeInfoLayout.createSequentialGroup()
.addGroup(jPanelNodeInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabelGuardNick)
.addComponent(jLabel12))
.addGap(0, 0, 0)
.addGroup(jPanelNodeInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabelGuardIP)
.addComponent(jLabel8))
.addGap(0, 0, 0)
.addGroup(jPanelNodeInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel9)
.addComponent(jLabelGuardCountry))
.addGroup(jPanelNodeInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel5)
.addComponent(jLabelGuardBw))
.addGap(0, 0, 0)
.addGroup(jPanelNodeInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabelGuardStable)
.addComponent(jLabel10))))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(jPanelNodeInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabelStreams, javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(jLabel6, javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(jLabelTorLatency, javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(jLabel4, javax.swing.GroupLayout.Alignment.TRAILING))
.addContainerGap())
);
jPanelNodeInfoLayout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {jLabelExitBw, jLabelExitCountry, jLabelExitIP, jLabelExitNick, jLabelExitStable, jLabelGuardBw, jLabelGuardCountry, jLabelGuardIP, jLabelGuardNick, jLabelGuardStable, jLabelMiddleBw, jLabelMiddleCountry, jLabelMiddleIP, jLabelMiddleNick, jLabelMiddleStable});
jButtonSetGuards.setText(LOCAL.getString("button_setguards")); // NOI18N
jButtonSetGuards.setToolTipText(LOCAL.getString("button_setguards")); // NOI18N
jButtonSetGuards.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonSetGuardsActionPerformed(evt);
}
});
jLabStatus.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
jLabStatus.setText(LOCAL.getString("textfield_unknown")); // NOI18N
jButtonClearFavs.setText(LOCAL.getString("button_clearfavs")); // NOI18N
jButtonClearFavs.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonClearFavsActionPerformed(evt);
}
});
javax.swing.GroupLayout jPanelMainLayout = new javax.swing.GroupLayout(jPanelMain);
jPanelMain.setLayout(jPanelMainLayout);
jPanelMainLayout.setHorizontalGroup(
jPanelMainLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanelMainLayout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanelMainLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabStatus, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jScrollPaneExitNodes)
.addComponent(jPanelNodeInfo, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(jPanelMainLayout.createSequentialGroup()
.addGroup(jPanelMainLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanelMainLayout.createSequentialGroup()
.addComponent(jComboCountry, javax.swing.GroupLayout.PREFERRED_SIZE, 260, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jButtonSetGuards)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jButtonClearFavs))
.addComponent(jLabelCountry))
.addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())
);
jPanelMainLayout.setVerticalGroup(
jPanelMainLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanelMainLayout.createSequentialGroup()
.addContainerGap()
.addComponent(jLabelCountry)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanelMainLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jComboCountry, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jButtonSetGuards)
.addComponent(jButtonClearFavs))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPaneExitNodes, javax.swing.GroupLayout.DEFAULT_SIZE, 182, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jPanelNodeInfo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabStatus)
.addContainerGap())
);
jMenuMenu.setMnemonic(LOCAL.getString("menu_menu").charAt(0));
jMenuMenu.setText(LOCAL.getString("menu_menu")); // NOI18N
jMenuItemPrefs.setMnemonic('P');
jMenuItemPrefs.setText(LOCAL.getString("menu_prefs")); // NOI18N
jMenuItemPrefs.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jMenuItemPrefsActionPerformed(evt);
}
});
jMenuMenu.add(jMenuItemPrefs);
jMenuItemAddPattern.setText(LOCAL.getString("menu_quickadd")); // NOI18N
jMenuItemAddPattern.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jMenuItemAddPatternActionPerformed(evt);
}
});
jMenuMenu.add(jMenuItemAddPattern);
jMenuItemPatternEdit.setText(LOCAL.getString("menu_patternedit")); // NOI18N
jMenuItemPatternEdit.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jMenuItemPatternEditActionPerformed(evt);
}
});
jMenuMenu.add(jMenuItemPatternEdit);
jMenuItemStdout.setText(LOCAL.getString("menu_tormonitor")); // NOI18N
jMenuItemStdout.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jMenuItemStdoutActionPerformed(evt);
}
});
jMenuMenu.add(jMenuItemStdout);
jMenuItemExport.setText(LOCAL.getString("menu_export")); // NOI18N
jMenuItemExport.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jMenuItemExportActionPerformed(evt);
}
});
jMenuMenu.add(jMenuItemExport);
jMenuItemImport.setText(LOCAL.getString("menu_import")); // NOI18N
jMenuItemImport.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jMenuItemImportActionPerformed(evt);
}
});
jMenuMenu.add(jMenuItemImport);
jMenuItemGeoip.setText(LOCAL.getString("menu_geoip")); // NOI18N
jMenuItemGeoip.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jMenuItemGeoipActionPerformed(evt);
}
});
jMenuMenu.add(jMenuItemGeoip);
jMenuItemQuit.setMnemonic('Q');
jMenuItemQuit.setText(LOCAL.getString("menu_quit")); // NOI18N
jMenuItemQuit.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jMenuItemQuitActionPerformed(evt);
}
});
jMenuMenu.add(jMenuItemQuit);
jMenuBar.add(jMenuMenu);
jMenuProxy.setMnemonic(LOCAL.getString("menu_proxy").charAt(0));
jMenuProxy.setText(LOCAL.getString("menu_proxy")); // NOI18N
jCheckProxyDisable.setText(LOCAL.getString("combo_proxymode1")); // NOI18N
jCheckProxyDisable.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
jCheckProxyDisableItemStateChanged(evt);
}
});
jMenuProxy.add(jCheckProxyDisable);
jCheckProxyByPattern.setText(LOCAL.getString("combo_proxymode2")); // NOI18N
jCheckProxyByPattern.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
jCheckProxyByPatternItemStateChanged(evt);
}
});
jMenuProxy.add(jCheckProxyByPattern);
jCheckProxyAll.setText(LOCAL.getString("combo_proxymode3")); // NOI18N
jCheckProxyAll.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
jCheckProxyAllItemStateChanged(evt);
}
});
jMenuProxy.add(jCheckProxyAll);
jMenuBar.add(jMenuProxy);
jMenuHelp.setMnemonic(LOCAL.getString("menu_help").charAt(0));
jMenuHelp.setText(LOCAL.getString("menu_help")); // NOI18N
jMenuItemDebugLog.setVisible(false);
jMenuItemDebugLog.setText(LOCAL.getString("menu_debuglog")); // NOI18N
jMenuItemDebugLog.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jMenuItemDebugLogActionPerformed(evt);
}
});
jMenuHelp.add(jMenuItemDebugLog);
jMenuItemHelp.setMnemonic('C');
jMenuItemHelp.setText(LOCAL.getString("menu_helpcontents")); // NOI18N
jMenuItemHelp.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jMenuItemHelpActionPerformed(evt);
}
});
jMenuHelp.add(jMenuItemHelp);
jMenuItemTorMan.setText(LOCAL.getString("menu_tormanual")); // NOI18N
jMenuItemTorMan.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jMenuItemTorManActionPerformed(evt);
}
});
jMenuHelp.add(jMenuItemTorMan);
jMenuItemTorCheck.setMnemonic('T');
jMenuItemTorCheck.setText(LOCAL.getString("menu_torcheck")); // NOI18N
jMenuItemTorCheck.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jMenuItemTorCheckActionPerformed(evt);
}
});
jMenuHelp.add(jMenuItemTorCheck);
jMenuItemAbout.setMnemonic('A');
jMenuItemAbout.setText(LOCAL.getString("menu_about")); // NOI18N
jMenuItemAbout.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jMenuItemAboutActionPerformed(evt);
}
});
jMenuHelp.add(jMenuItemAbout);
jMenuItemLicense.setText(LOCAL.getString("menu_license")); // NOI18N
jMenuItemLicense.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jMenuItemLicenseActionPerformed(evt);
}
});
jMenuHelp.add(jMenuItemLicense);
jMenuBar.add(jMenuHelp);
setJMenuBar(jMenuBar);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanelMain, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanelMain, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
pack();
}// </editor-fold>//GEN-END:initComponents
private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
if (sp.getBool("PREF_MINONCLOSE")) {
// Used to provide clean shut down when a WM_CLOSE and Taskkill are called
// posted externally
if (!isVisible() && OSFunction.isWindows()) {
cleanupExit();
return;
}
if (sp.getBool("PREF_HIDE_MIN") && sti.isLoaded()) {
setVisible(false);
} else {
setExtendedState(Frame.ICONIFIED);
}
} else {
cleanupExit();
}
}//GEN-LAST:event_formWindowClosing
private void jComboCountryItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_jComboCountryItemStateChanged
switch (evt.getStateChange()) {
case ItemEvent.DESELECTED:
abortTesting();
break;
case ItemEvent.SELECTED:
countryChanged();
break;
}
}//GEN-LAST:event_jComboCountryItemStateChanged
private void jMenuItemPrefsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemPrefsActionPerformed
SwingUtilities.invokeLater(new java.lang.Runnable() {
@Override
public void run() {
openPreferencesDialog();
}
});
}//GEN-LAST:event_jMenuItemPrefsActionPerformed
private void jMenuItemAddPatternActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemAddPatternActionPerformed
openQuickAddDialog();
}//GEN-LAST:event_jMenuItemAddPatternActionPerformed
private void jMenuItemPatternEditActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemPatternEditActionPerformed
SwingUtilities.invokeLater(new java.lang.Runnable() {
@Override
public void run() {
openPatternEditorDialog();
}
});
}//GEN-LAST:event_jMenuItemPatternEditActionPerformed
private void jMenuItemImportActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemImportActionPerformed
SwingUtilities.invokeLater(new java.lang.Runnable() {
@Override
public void run() {
openPatternImport();
}
});
}//GEN-LAST:event_jMenuItemImportActionPerformed
private void jMenuItemQuitActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemQuitActionPerformed
cleanupExit();
}//GEN-LAST:event_jMenuItemQuitActionPerformed
private void jMenuItemDebugLogActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemDebugLogActionPerformed
Utilities.editFile(settingsPath + "status.log");
}//GEN-LAST:event_jMenuItemDebugLogActionPerformed
private void jMenuItemHelpActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemHelpActionPerformed
SwingUtilities.invokeLater(new java.lang.Runnable() {
@Override
public void run() {
Utilities.openFileExternally(DOCSPATH + "help-" + OSFunction.getLangCode() + ".html");
}
});
}//GEN-LAST:event_jMenuItemHelpActionPerformed
private void jMenuItemTorCheckActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemTorCheckActionPerformed
SwingUtilities.invokeLater(new java.lang.Runnable() {
@Override
public void run() {
String link = TORCHECK + "?lang="
+ LOCAL.toWebLanguageTag();
Utilities.openFileExternally(link);
}
});
}//GEN-LAST:event_jMenuItemTorCheckActionPerformed
private void jMenuItemAboutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemAboutActionPerformed
SwingUtilities.invokeLater(new java.lang.Runnable() {
@Override
public void run() {
openAboutDialog();
}
});
}//GEN-LAST:event_jMenuItemAboutActionPerformed
private void jMenuItemLicenseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemLicenseActionPerformed
openLicenseDialog();
}//GEN-LAST:event_jMenuItemLicenseActionPerformed
private void jMenuWhoisActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuWhoisActionPerformed
String finger = (String) entm.getValueAt(intRowSelected, 5);
NodeItem ni = nodeList.getNode(finger);
if (ni != null) {
Utilities.openFileExternally("https://www.networksolutions.com/whois/results.jsp?ip=" + ni.getIPAddress());
}
}//GEN-LAST:event_jMenuWhoisActionPerformed
private void jMenuTestingActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuTestingActionPerformed
abortTesting();
intBeginTesting = 4;
}//GEN-LAST:event_jMenuTestingActionPerformed
private void popupTablePopupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) {//GEN-FIRST:event_popupTablePopupMenuWillBecomeVisible
jMenuWhois.setEnabled(intRowSelected > -1);
jMenuNodeDetails.setEnabled(intRowSelected > -1);
}//GEN-LAST:event_popupTablePopupMenuWillBecomeVisible
private void jMenuNodeDetailsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuNodeDetailsActionPerformed
String finger = (String) entm.getValueAt(intRowSelected, 5);
finger = finger.replace("$", EMPTYSTR);
Utilities.openFileExternally(ATLAS + "#details/" + finger);
}//GEN-LAST:event_jMenuNodeDetailsActionPerformed
private void jButtonExitNodeDetailsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonExitNodeDetailsActionPerformed
String finger = niActiveExit.getFingerprint();
finger = finger.replace("$", EMPTYSTR);
Utilities.openFileExternally(ATLAS + "#details/" + finger);
}//GEN-LAST:event_jButtonExitNodeDetailsActionPerformed
private void jMenuItemStdoutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemStdoutActionPerformed
SwingUtilities.invokeLater(new java.lang.Runnable() {
@Override
public void run() {
openTorMonitor();
}
});
}//GEN-LAST:event_jMenuItemStdoutActionPerformed
private void jMenuItemTorManActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemTorManActionPerformed
SwingUtilities.invokeLater(new java.lang.Runnable() {
@Override
public void run() {
Utilities.openFileExternally(TORPROJECT + "docs/tor-manual.html");
}
});
}//GEN-LAST:event_jMenuItemTorManActionPerformed
private void jButtonGuardNodeDetailsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonGuardNodeDetailsActionPerformed
String finger = niActiveGuard.getFingerprint();
finger = finger.replace("$", EMPTYSTR);
Utilities.openFileExternally(ATLAS + "#details/" + finger);
}//GEN-LAST:event_jButtonGuardNodeDetailsActionPerformed
private void jButtonSetGuardsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonSetGuardsActionPerformed
SwingUtilities.invokeLater(new java.lang.Runnable() {
@Override
public void run() {
openGuardsSettingDialog();
}
});
}//GEN-LAST:event_jButtonSetGuardsActionPerformed
private void jMenuItemGUIActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemGUIActionPerformed
toggleGUIVisibility();
}//GEN-LAST:event_jMenuItemGUIActionPerformed
private void jMenuItemQuitxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemQuitxActionPerformed
cleanupExit();
}//GEN-LAST:event_jMenuItemQuitxActionPerformed
private void jButtonMiddleNodeDetailsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonMiddleNodeDetailsActionPerformed
String finger = niActiveMiddle.getFingerprint();
finger = finger.replace("$", EMPTYSTR);
Utilities.openFileExternally(ATLAS + "#details/" + finger);
}//GEN-LAST:event_jButtonMiddleNodeDetailsActionPerformed
private void jMenuItemExportActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemExportActionPerformed
SwingUtilities.invokeLater(new java.lang.Runnable() {
@Override
public void run() {
openPatternExport();
}
});
}//GEN-LAST:event_jMenuItemExportActionPerformed
private void jCheckProxyDisableItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_jCheckProxyDisableItemStateChanged
if (evt.getStateChange() == ItemEvent.SELECTED) {
jCheckTrayProxyDisable.setSelected(true);
if (jCheckProxyDisable.isEnabled()) {
proxyModeChanged(PacFactory.PROXY_DISABLED);
}
}
}//GEN-LAST:event_jCheckProxyDisableItemStateChanged
private void jCheckProxyByPatternItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_jCheckProxyByPatternItemStateChanged
if (evt.getStateChange() == ItemEvent.SELECTED) {
jCheckTrayProxyByPattern.setSelected(true);
if (jCheckProxyByPattern.isEnabled()) {
proxyModeChanged(PacFactory.PROXY_PATTERN);
}
}
}//GEN-LAST:event_jCheckProxyByPatternItemStateChanged
private void jCheckProxyAllItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_jCheckProxyAllItemStateChanged
if (evt.getStateChange() == ItemEvent.SELECTED) {
jCheckTrayProxyAll.setSelected(true);
if (jCheckProxyAll.isEnabled()) {
proxyModeChanged(PacFactory.PROXY_ALL);
}
}
}//GEN-LAST:event_jCheckProxyAllItemStateChanged
private void jCheckTrayProxyDisableItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_jCheckTrayProxyDisableItemStateChanged
if (evt.getStateChange() == ItemEvent.SELECTED) {
jCheckProxyDisable.setSelected(true);
}
}//GEN-LAST:event_jCheckTrayProxyDisableItemStateChanged
private void jCheckTrayProxyByPatternItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_jCheckTrayProxyByPatternItemStateChanged
if (evt.getStateChange() == ItemEvent.SELECTED) {
jCheckProxyByPattern.setSelected(true);
}
}//GEN-LAST:event_jCheckTrayProxyByPatternItemStateChanged
private void jCheckTrayProxyAllItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_jCheckTrayProxyAllItemStateChanged
if (evt.getStateChange() == ItemEvent.SELECTED) {
jCheckProxyAll.setSelected(true);
}
}//GEN-LAST:event_jCheckTrayProxyAllItemStateChanged
private void jMenuItemGeoipActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemGeoipActionPerformed
SwingUtilities.invokeLater(new java.lang.Runnable() {
@Override
public void run() {
updateGeoip();
}
});
}//GEN-LAST:event_jMenuItemGeoipActionPerformed
private void jButtonClearFavsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonClearFavsActionPerformed
clearFavourites();
}//GEN-LAST:event_jButtonClearFavsActionPerformed
private void jTableExitNodesMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jTableExitNodesMouseClicked
if (evt.getButton() != MouseEvent.BUTTON1) {
return;
}
try {
// Get row selection
intRowSelected = jTableExitNodes.getSelectedRow();
if (intRowSelected > -1) {
intRowSelected = jTableExitNodes.convertRowIndexToModel(intRowSelected);
}
} catch (Exception ex) {
}
}//GEN-LAST:event_jTableExitNodesMouseClicked
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.ButtonGroup buttonGroupProxy;
private javax.swing.ButtonGroup buttonGroupProxyTray;
private javax.swing.JButton jButtonClearFavs;
private javax.swing.JButton jButtonExitNodeDetails;
private javax.swing.JButton jButtonGuardNodeDetails;
private javax.swing.JButton jButtonMiddleNodeDetails;
private javax.swing.JButton jButtonSetGuards;
private javax.swing.JCheckBoxMenuItem jCheckProxyAll;
private javax.swing.JCheckBoxMenuItem jCheckProxyByPattern;
private javax.swing.JCheckBoxMenuItem jCheckProxyDisable;
private javax.swing.JCheckBoxMenuItem jCheckTrayProxyAll;
private javax.swing.JCheckBoxMenuItem jCheckTrayProxyByPattern;
private javax.swing.JCheckBoxMenuItem jCheckTrayProxyDisable;
private javax.swing.JComboBox<String> jComboCountry;
private javax.swing.JLabel jLabStatus;
private javax.swing.JLabel jLabel10;
private javax.swing.JLabel jLabel12;
private javax.swing.JLabel jLabel4;
private javax.swing.JLabel jLabel5;
private javax.swing.JLabel jLabel6;
private javax.swing.JLabel jLabel8;
private javax.swing.JLabel jLabel9;
private javax.swing.JLabel jLabelCountry;
private javax.swing.JLabel jLabelExit;
private javax.swing.JLabel jLabelExitBw;
private javax.swing.JLabel jLabelExitCountry;
private javax.swing.JLabel jLabelExitIP;
private javax.swing.JLabel jLabelExitNick;
private javax.swing.JLabel jLabelExitStable;
private javax.swing.JLabel jLabelGuard;
private javax.swing.JLabel jLabelGuardBw;
private javax.swing.JLabel jLabelGuardCountry;
private javax.swing.JLabel jLabelGuardIP;
private javax.swing.JLabel jLabelGuardNick;
private javax.swing.JLabel jLabelGuardStable;
private javax.swing.JLabel jLabelMiddle;
private javax.swing.JLabel jLabelMiddleBw;
private javax.swing.JLabel jLabelMiddleCountry;
private javax.swing.JLabel jLabelMiddleIP;
private javax.swing.JLabel jLabelMiddleNick;
private javax.swing.JLabel jLabelMiddleStable;
private javax.swing.JLabel jLabelStreams;
private javax.swing.JLabel jLabelTorLatency;
private javax.swing.JMenuBar jMenuBar;
private javax.swing.JMenu jMenuHelp;
private javax.swing.JMenuItem jMenuItemAbout;
private javax.swing.JMenuItem jMenuItemAddPattern;
private javax.swing.JMenuItem jMenuItemDebugLog;
private javax.swing.JMenuItem jMenuItemExport;
private javax.swing.JMenuItem jMenuItemGUI;
private javax.swing.JMenuItem jMenuItemGeoip;
private javax.swing.JMenuItem jMenuItemHelp;
private javax.swing.JMenuItem jMenuItemImport;
private javax.swing.JMenuItem jMenuItemLicense;
private javax.swing.JMenuItem jMenuItemPatternEdit;
private javax.swing.JMenuItem jMenuItemPrefs;
private javax.swing.JMenuItem jMenuItemQuit;
private javax.swing.JMenuItem jMenuItemQuitx;
private javax.swing.JMenuItem jMenuItemStdout;
private javax.swing.JMenuItem jMenuItemTorCheck;
private javax.swing.JMenuItem jMenuItemTorMan;
private javax.swing.JMenu jMenuMenu;
private javax.swing.JMenuItem jMenuNodeDetails;
private javax.swing.JMenu jMenuProxy;
private javax.swing.JMenuItem jMenuTesting;
private javax.swing.JMenuItem jMenuWhois;
private javax.swing.JPanel jPanelMain;
private javax.swing.JPanel jPanelNodeInfo;
private javax.swing.JScrollPane jScrollPaneExitNodes;
private javax.swing.JTable jTableExitNodes;
private javax.swing.JPopupMenu popupTable;
// End of variables declaration//GEN-END:variables
}