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
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
|
|
}
|