First commit

This commit is contained in:
emdee 2022-11-02 08:12:45 +00:00
parent 40bff34006
commit 57d60609e2
179 changed files with 59241 additions and 0 deletions

47
src/SelekTOR.java Normal file
View file

@ -0,0 +1,47 @@
/*
* Copyright (C) 2014 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.
*/
/**
* Explanation of why this is in the default package
*
* @author Alistair Neil <info@dazzleships.net>
*
* The app launcher is here in the default package which should not normally be
* used. The method java uses to launche its apps is not fully compatible with
* various Linux launchers panels such as Dockbarx or Unity launchers and thus
* confuses those apps. By putting this simple launch handle here in the default
* package the Linux dockpanel launchers should function correctly when it
* commes to application pinning.
*
*/
public class SelekTOR {
/**
* @param args the command line arguments
*/
public static void main(final String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new client.SelekTOR(args);
}
});
}
}

View file

@ -0,0 +1,246 @@
/*
* 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.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.table.DefaultTableModel;
/**
*
* @author Alistair Neil <info@dazzleships.net>
*/
public class ExitNodeTableModel extends DefaultTableModel {
private final List<String> salFinger = Collections.synchronizedList(new ArrayList<String>());
private final String[] columnNames = new String[5];
private NodeItem ni;
public ExitNodeTableModel() {
}
/**
* Clear the table model of all data
*/
public void clear() {
getDataVector().clear();
salFinger.clear();
}
/**
* Get the number of columns
*
* @return columns as integer
*/
@Override
public int getColumnCount() {
return columnNames.length;
}
/**
* Test if the cell is editable
*
* @param row Cell row
* @param col Cell column
* @return True if editable
*/
@Override
public boolean isCellEditable(int row, int col) {
return col == 4;
}
/**
* Set value with given fingerprint at given column
*
* @param value Value
* @param finger Fingerprint
* @param col Column
*/
public void setValueAt(Object value, String finger, int col) {
setValueAt(value, salFinger.indexOf(finger), col);
}
/**
* Convenience method to set the testing field cell values for a specific
* fingerprint, the hops field is hidden and does npt show up in table
*
* @param finger Fingerprint
* @param latency Latency value
* @param status Status value
* @param hops Hops value
*/
public synchronized void setTestFieldValues(String finger, long latency, String status, String hops) {
int row = salFinger.indexOf(finger);
if (row > -1) {
ni = (NodeItem) super.getValueAt(row, 0);
ni.setTestLatency(latency);
ni.setTestingMessage(status);
ni.setCircuitHops(hops);
fireTableRowsUpdated(row, row);
}
}
/**
* Get row nodeitem
*
* @param row
* @return a nodeitem
*/
public NodeItem getNodeItemAt(int row) {
return (NodeItem) super.getValueAt(row, 0);
}
/**
* Set cell value at row,col
*
* @param value
* @param row
* @param col
*/
@Override
public void setValueAt(Object value, int row, int col) {
try {
ni = (NodeItem) super.getValueAt(row, 0);
switch (col) {
case 1:
ni.setBandwidth((Float) value);
break;
case 2:
ni.setTestLatency((Long) value);
break;
case 3:
ni.setTestingMessage((String) value);
break;
case 4:
ni.setFavouriteEnabled((Boolean) value);
break;
case 5:
salFinger.set(row, (String) value);
ni.setFingerprint((String) value);
return;
case 6:
ni.setCircuitHops((String) value);
return;
}
fireTableCellUpdated(row, col);
} catch (Exception ex) {
}
}
/**
* Get cell value as object at row,col
*
* @param row
* @param col
* @return value as object
*/
@Override
public Object getValueAt(int row, int col) {
ni = (NodeItem) super.getValueAt(row, 0);
Object obj = null;
switch (col) {
case 0:
obj = ni.getNickName();
break;
case 1:
obj = ni.getBandwidth();
break;
case 2:
obj = ni.getTestLatency();
break;
case 3:
obj = ni.getTestingMessage();
break;
case 4:
obj = ni.isFavourite();
break;
case 5:
obj = ni.getFingerprint();
break;
case 6:
obj = ni.getCircuitHops();
break;
case 7:
obj = ni.getTestStatus();
break;
}
return obj;
}
/**
* Add rowdata with given data object array
*
* @param rowData
*/
@Override
public void addRow(Object[] rowData) {
super.addRow(rowData);
salFinger.add(((NodeItem) rowData[0]).getFingerprint());
}
/**
* Get column name at given index
*
* @param index
* @return name as string
*/
@Override
public String getColumnName(int index) {
return columnNames[index];
}
/**
* Set the column name at the specified index
*
* @param name
* @param index
*/
public void setColumnName(String name, int index) {
if (index < columnNames.length) {
columnNames[index] = name;
}
}
/**
* Get column class at given index
*
* @param index
* @return Class
*/
@Override
public Class getColumnClass(int index) {
Class cl;
switch (index) {
case 1:
cl = Float.class;
break;
case 2:
cl = Long.class;
break;
case 4:
cl = Boolean.class;
break;
default:
cl = String.class;
break;
}
return cl;
}
}

View file

@ -0,0 +1,177 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.6" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
<NonVisualComponents>
<Container class="javax.swing.JPopupMenu" name="popupTable">
<Events>
<EventHandler event="popupMenuWillBecomeVisible" listener="javax.swing.event.PopupMenuListener" parameters="javax.swing.event.PopupMenuEvent" handler="popupTablePopupMenuWillBecomeVisible"/>
</Events>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout">
<Property name="useNullLayout" type="boolean" value="true"/>
</Layout>
<SubComponents>
<MenuItem class="javax.swing.JMenuItem" name="jMenuNodeDetails">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="table_popup_details" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jMenuNodeDetailsActionPerformed"/>
</Events>
</MenuItem>
<MenuItem class="javax.swing.JMenuItem" name="jMenuWhois">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="table_popup_whois" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jMenuWhoisActionPerformed"/>
</Events>
</MenuItem>
</SubComponents>
</Container>
</NonVisualComponents>
<Properties>
<Property name="defaultCloseOperation" type="int" value="2"/>
<Property name="title" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="wintitle_guardnodes" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
<Property name="resizable" type="boolean" value="false"/>
</Properties>
<SyntheticProperties>
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
</SyntheticProperties>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Component id="jButtonClear" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<Component id="jButtonClose" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jButtonApply" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="jTextArea1" max="32767" attributes="0"/>
<Component id="jScrollPane1" alignment="0" max="32767" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="jTextArea1" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jScrollPane1" pref="367" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jButtonClear" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jButtonApply" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jButtonClose" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTable" name="jTableGuards">
<Properties>
<Property name="autoCreateRowSorter" type="boolean" value="true"/>
<Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor">
<JTableSelectionModel selectionMode="0"/>
</Property>
</Properties>
<Events>
<EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="jTableGuardsMouseClicked"/>
</Events>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JButton" name="jButtonClear">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="button_clearguards" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="ttip_clearguards" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButtonClearActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="jButtonApply">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="button_apply" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButtonApplyActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="jButtonClose">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="button_close" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButtonCloseActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JTextArea" name="jTextArea1">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="columns" type="int" value="40"/>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="new javax.swing.JLabel().getFont()" type="code"/>
</Property>
<Property name="lineWrap" type="boolean" value="true"/>
<Property name="rows" type="int" value="2"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="label_guard_minimum" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
<Property name="wrapStyleWord" type="boolean" value="true"/>
<Property name="disabledTextColor" type="java.awt.Color" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection component="jTextArea1" name="foreground" type="property"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 0]"/>
</Property>
<Property name="opaque" type="boolean" value="false"/>
<Property name="requestFocusEnabled" type="boolean" value="false"/>
</Properties>
</Component>
</SubComponents>
</Form>

View file

@ -0,0 +1,299 @@
/*
* 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.event.MouseEvent;
import javax.swing.event.TableModelEvent;
import lib.GTKFixes;
import lib.Localisation;
import lib.Utilities;
/**
*
* @author Alistair Neil <info@dazzleships.net>
*/
public class GuardNodeDialog extends javax.swing.JDialog {
public static final int CANCEL = 0;
public static final int APPLY = 1;
public static final int RESET = 2;
private static final String ATLAS = "https://atlas.torproject.org/";
private static final Localisation LOCAL = new Localisation("resources/MessagesBundle");
private int intRowSelected = -1;
private int returnStatus = CANCEL;
private final GuardNodeTableModel gntm;
private NodeList nl;
/**
* Creates new form GuardNodeDialog
*
* @param parent
* @param modal
*/
public GuardNodeDialog(java.awt.Frame parent, boolean modal) {
super(parent, modal);
initComponents();
GTKFixes.fixTextAreaColor(jTextArea1);
jTableGuards.setComponentPopupMenu(popupTable);
gntm = new GuardNodeTableModel();
gntm.setColumnName(LOCAL.getString("guardtable_col1"), 0);
gntm.setColumnName(LOCAL.getString("guardtable_col2"), 1);
gntm.setColumnName(LOCAL.getString("guardtable_col3"), 2);
gntm.setColumnName(LOCAL.getString("guardtable_col4"), 3);
gntm.addTableModelListener(new javax.swing.event.TableModelListener() {
@Override
public void tableChanged(TableModelEvent e) {
if (gntm.getEnabledCount() >= 3 || gntm.getEnabledCount() == 0) {
jButtonApply.setEnabled(true);
} else {
jButtonApply.setEnabled(false);
}
}
});
jTableGuards.setModel(gntm);
adjustGuardTableColumns();
}
/**
* Set the nodelist
*
* @param nl
*/
public void setNodeList(NodeList nl) {
this.nl = nl;
this.nl.setGuardNodeTableModel(gntm);
this.nl.refreshGuardTableModel();
adjustGuardTableColumns();
}
/**
* Adjust guard table column widths
*/
private void adjustGuardTableColumns() {
// Adjust table column widths
Utilities.adjustTableColumnWidth(jTableGuards,
"XXXXXXXXXXXXXXXXXXXXXXXXXXX",
"XXXXXXXXXXXXXXXXXXXXXXXXXXX",
"XXXXXXXXXXXXXXX",
"XXXXXXXXXXXXXXX");
}
private void clearSelections() {
for (int row = 0; row < jTableGuards.getRowCount(); row++) {
jTableGuards.setValueAt(false, row, 3);
}
}
private void doClose(int retStatus) {
returnStatus = retStatus;
setVisible(false);
dispose();
}
/**
* @return the return status of this dialog - one of RET_OK or RET_CANCEL
*/
public int getReturnStatus() {
return returnStatus;
}
/**
* 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.
*/
@SuppressWarnings("unchecked")
// <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();
jScrollPane1 = new javax.swing.JScrollPane();
jTableGuards = new javax.swing.JTable();
jButtonClear = new javax.swing.JButton();
jButtonApply = new javax.swing.JButton();
jButtonClose = new javax.swing.JButton();
jTextArea1 = new javax.swing.JTextArea();
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);
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
setTitle(LOCAL.getString("wintitle_guardnodes")); // NOI18N
setResizable(false);
jTableGuards.setAutoCreateRowSorter(true);
jTableGuards.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
jTableGuards.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent evt) {
jTableGuardsMouseClicked(evt);
}
});
jScrollPane1.setViewportView(jTableGuards);
jButtonClear.setText(LOCAL.getString("button_clearguards")); // NOI18N
jButtonClear.setToolTipText(LOCAL.getString("ttip_clearguards")); // NOI18N
jButtonClear.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonClearActionPerformed(evt);
}
});
jButtonApply.setText(LOCAL.getString("button_apply")); // NOI18N
jButtonApply.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonApplyActionPerformed(evt);
}
});
jButtonClose.setText(LOCAL.getString("button_close")); // NOI18N
jButtonClose.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonCloseActionPerformed(evt);
}
});
jTextArea1.setEditable(false);
jTextArea1.setColumns(40);
jTextArea1.setFont(new javax.swing.JLabel().getFont());
jTextArea1.setLineWrap(true);
jTextArea1.setRows(2);
jTextArea1.setText(LOCAL.getString("label_guard_minimum")); // NOI18N
jTextArea1.setWrapStyleWord(true);
jTextArea1.setDisabledTextColor(jTextArea1.getForeground());
jTextArea1.setEnabled(false);
jTextArea1.setMinimumSize(new java.awt.Dimension(0, 0));
jTextArea1.setOpaque(false);
jTextArea1.setRequestFocusEnabled(false);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jButtonClear)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jButtonClose)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jButtonApply))
.addComponent(jTextArea1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jScrollPane1))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jTextArea1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 367, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jButtonClear)
.addComponent(jButtonApply)
.addComponent(jButtonClose))
.addContainerGap())
);
pack();
}// </editor-fold>//GEN-END:initComponents
private void jButtonCloseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonCloseActionPerformed
doClose(CANCEL);
}//GEN-LAST:event_jButtonCloseActionPerformed
private void jButtonApplyActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonApplyActionPerformed
nl.saveGuardWhitelist();
doClose(APPLY);
}//GEN-LAST:event_jButtonApplyActionPerformed
private void jButtonClearActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonClearActionPerformed
clearSelections();
}//GEN-LAST:event_jButtonClearActionPerformed
private void jMenuNodeDetailsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuNodeDetailsActionPerformed
String finger = (String) gntm.getValueAt(intRowSelected, 4);
finger = finger.replace("$", "");
Utilities.openFileExternally(ATLAS + "#details/" + finger);
}//GEN-LAST:event_jMenuNodeDetailsActionPerformed
private void jMenuWhoisActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuWhoisActionPerformed
String finger = (String) gntm.getValueAt(intRowSelected, 4);
NodeItem ni = nl.getNode(finger);
if (ni != null) {
Utilities.openFileExternally("https://www.networksolutions.com/whois/results.jsp?ip=" + ni.getIPAddress());
}
}//GEN-LAST:event_jMenuWhoisActionPerformed
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 jTableGuardsMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jTableGuardsMouseClicked
if (evt.getButton() != MouseEvent.BUTTON1) {
return;
}
intRowSelected = jTableGuards.getSelectedRow();
if (intRowSelected > 0) {
intRowSelected = jTableGuards.convertRowIndexToModel(intRowSelected);
}
}//GEN-LAST:event_jTableGuardsMouseClicked
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton jButtonApply;
private javax.swing.JButton jButtonClear;
private javax.swing.JButton jButtonClose;
private javax.swing.JMenuItem jMenuNodeDetails;
private javax.swing.JMenuItem jMenuWhois;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JTable jTableGuards;
private javax.swing.JTextArea jTextArea1;
private javax.swing.JPopupMenu popupTable;
// End of variables declaration//GEN-END:variables
}

View file

@ -0,0 +1,203 @@
/*
* 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.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.table.DefaultTableModel;
/**
*
* @author Alistair Neil <info@dazzleships.net>
*/
public class GuardNodeTableModel extends DefaultTableModel {
private final List<String> salFinger = Collections.synchronizedList(new ArrayList<String>());
private final String[] columnNames = {"GuardNode", "Country", "BW (MB\\s)", "Trusted"};
private NodeItem ni;
private int enabledcount;
public GuardNodeTableModel() {
}
public int getEnabledCount() {
return enabledcount;
}
/**
* Clear the table model of all data
*/
public void clear() {
getDataVector().clear();
salFinger.clear();
enabledcount = 0;
}
/**
* Get the number of columns
*
* @return columns as integer
*/
@Override
public int getColumnCount() {
return columnNames.length;
}
/**
* Test if the cell is editable
*
* @param row Cell row
* @param col Cell column
* @return True if editable
*/
@Override
public boolean isCellEditable(int row, int col) {
return col == 3;
}
/**
* Set value with given fingerprint at given column
*
* @param value Value
* @param finger Fingerprint
* @param col Column
*/
public void setValueAt(Object value, String finger, int col) {
setValueAt(value, salFinger.indexOf(finger), col);
}
/**
* Set cell value at row,col
*
* @param value
* @param row
* @param col
*/
@Override
public void setValueAt(Object value, int row, int col) {
try {
ni = (NodeItem) super.getValueAt(row, 0);
if (col == 3) {
ni.setGuardEnabled((Boolean) value);
if (ni.isGuardEnabled()) {
enabledcount++;
} else {
if (enabledcount > 0) {
enabledcount--;
}
}
fireTableCellUpdated(row, col);
}
} catch (Exception ex) {
}
}
/**
* Get cell value as object at row,col
*
* @param row
* @param col
* @return value as object
*/
@Override
public Object getValueAt(int row, int col) {
ni = (NodeItem) super.getValueAt(row, 0);
Object obj = null;
switch (col) {
case 0:
obj = ni.getNickName();
break;
case 1:
obj = ni.getCountryName();
break;
case 2:
obj = ni.getBandwidth();
break;
case 3:
obj = ni.isGuardEnabled();
break;
case 4:
obj = ni.getFingerprint();
break;
}
return obj;
}
/**
* Add rowdata with given data object array
*
* @param rowData
*/
@Override
public void addRow(Object[] rowData) {
super.addRow(rowData);
ni = (NodeItem) rowData[0];
if (ni.isGuardEnabled()) {
enabledcount++;
}
salFinger.add(ni.getFingerprint());
}
/**
* Get column name at given index
*
* @param index
* @return name as string
*/
@Override
public String getColumnName(int index) {
return columnNames[index];
}
/**
* Set the column name at the specified index
*
* @param name
* @param index
*/
public void setColumnName(String name, int index) {
if (index < columnNames.length) {
columnNames[index] = name;
}
}
/**
* Get column class at given index
*
* @param index
* @return Class
*/
@Override
public Class getColumnClass(int index) {
Class cl;
switch (index) {
case 2:
cl = Float.class;
break;
case 3:
cl = Boolean.class;
break;
default:
cl = String.class;
break;
}
return cl;
}
}

405
src/client/NodeItem.java Normal file
View file

@ -0,0 +1,405 @@
/*
* 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.text.DecimalFormat;
/**
*
* @author Alistair Neil <info@dazzleships.net>
*/
public class NodeItem extends Object implements Cloneable {
public static final int TYPE_EXIT = 1;
public static final int TYPE_GUARD = 2;
public static final int TESTSTATUS_UNKNOWN = 0;
public static final int TESTSTATUS_PASSED = 1;
public static final int TESTSTATUS_FAILED = 2;
private int type;
private boolean exitFavourite;
private boolean guardEnabled;
private boolean httpSupported;
private String stable;
private String countrycode;
private String countryname;
private String nickname;
private String finger;
private String ipaddress;
private String testingmess;
private String circuithops;
private int teststatus;
private float bandwidth;
private int streams;
private long latency;
private long testlatency;
public NodeItem() {
this.type = 0;
this.exitFavourite = false;
this.guardEnabled = false;
this.httpSupported = false;
this.countrycode = null;
this.latency = 9999;
this.testlatency = this.latency;
this.bandwidth = 0;
this.streams = 0;
this.countrycode = "";
this.countryname = "";
this.stable = "";
this.testingmess = "";
this.ipaddress = "";
this.finger = "";
this.nickname = "";
this.teststatus = TESTSTATUS_UNKNOWN;
}
/**
* Set Node type
*
* @param mask
*/
public final void setType(int mask) {
this.type |= mask;
}
/**
* Clear node type
*/
public final void clearType() {
this.type = 0;
}
public boolean isNonUnique() {
return (nickname.contains("Default")
|| nickname.contains("default")
|| nickname.contains("Unnamed"));
}
/**
* Is exit node
*
* @return true if an exit node
*/
public final boolean isExit() {
return (type & TYPE_EXIT) != 0;
}
public boolean isHttpSupported() {
return httpSupported;
}
public void setHttpSupported(boolean supported) {
httpSupported = supported;
}
/**
* Is Guard node
*
* @return true if guard node
*/
public final boolean isGuard() {
return (type & TYPE_GUARD) != 0;
}
/**
* Set circuit hops
*
* @param hops
*/
public final void setCircuitHops(String hops) {
circuithops = hops;
}
/**
* Get circuit hops
*
* @return Circuit hops as String
*/
public final String getCircuitHops() {
return circuithops;
}
/**
* Set Nodeitem testing status message
*
* @param text
*/
public final void setTestingMessage(String text) {
this.testingmess = text;
}
/**
* Set testing status flag
*
* @param status
*/
public final void setTestStatus(int status) {
teststatus = status;
}
/**
* Get testing status flag
*
* @return test status
*/
public final int getTestStatus() {
return teststatus;
}
/**
* Get Node item status
*
* @return Nodeitem testing status message as string
*/
public final String getTestingMessage() {
return testingmess;
}
/**
* Set Nodeitem latency value in ms
*
* @param latency
*/
public final void setLatency(long latency) {
this.latency = latency;
}
/**
* Get Nodeitem latency in ms
*
* @return Latency value in ms
*/
public final long getLatency() {
return latency;
}
/**
* Set Nodeitem test latency value in ms
*
* @param latency
*/
public final void setTestLatency(long latency) {
this.testlatency = latency;
}
/**
* Get Nodeitem test latency in ms
*
* @return Latency value in ms
*/
public final long getTestLatency() {
return testlatency;
}
/**
* Set exit enabled status of Nodeitem
*
* @param enabled
*/
public final void setFavouriteEnabled(boolean enabled) {
this.exitFavourite = enabled;
}
/**
* Get exit enabled status of Nodeitem
*
* @return true if enabled
*/
public final boolean isFavourite() {
return exitFavourite;
}
/**
* Set guard enabled status of Nodeitem
*
* @param enabled
*/
public final void setGuardEnabled(boolean enabled) {
this.guardEnabled = enabled;
}
/**
* Get guard enabled status of Nodeitem
*
* @return true if enabled
*/
public final boolean isGuardEnabled() {
return guardEnabled;
}
/**
* Set Nodeitem stability yes/no/unknown
*
* @param stability
*/
public final void setStable(String stability) {
this.stable = stability;
}
/**
* Get Nodeitem stability
*
* @return Stability
*/
public final String getStability() {
return stable;
}
/**
* Set Nodeitem with its two letter country code abbreviation
*
* @param abrv
*/
public final void setCountryCode(String abrv) {
countrycode = abrv;
}
/**
* Get nodeitem two letter country code abbreviation
*
* @return Country code as string
*/
public final String getCountryCode() {
return countrycode;
}
/**
* Set Nodeitem with its full country name
*
* @param name
*/
public final void setCountryName(String name) {
countryname = name;
}
/**
* Get nodeitem full country name
*
* @return Country name as string
*/
public final String getCountryName() {
return countryname;
}
/**
* Set nodeitem name
*
* @param name
*/
public final void setNickName(String name) {
nickname = name;
}
/**
* Get nodeitem unique name
*
* @return Node name as string
*/
public final String getNickName() {
return nickname;
}
/**
* Set node item bandwidth
*
* @param bw
*/
public final void setBandwidth(float bw) {
bandwidth = bw;
}
/**
* Get nodeitem bandwith
*
* @return Bandwidth as long, in kb/s
*/
public final float getBandwidth() {
Float result;
try {
DecimalFormat df = new DecimalFormat("#0.##");
result = Float.parseFloat(df.format(bandwidth).replace(",", "."));
} catch (Exception ex) {
result = (float) 0;
}
return result;
}
/**
* Set nodeitem number of streams
*
* @param streams
*/
public final void setStreams(int streams) {
this.streams = streams;
}
/**
* Get nodeitems active streams
*
* @return Number of active streams as int
*/
public final int getStreams() {
return streams;
}
/**
* Set nodeitem fingerprint
*
* @param fp
*/
public final void setFingerprint(String fp) {
finger = fp;
}
/**
* Get nodeitems fingerprint
*
* @return Tor node fingerprint as string
*/
public final String getFingerprint() {
return finger;
}
/**
* Set nodeitem ip address
*
* @param ip
*/
public final void setIPAddress(String ip) {
ipaddress = ip;
}
/**
* Get nodeitem ip address
*
* @return IP address as a string
*/
public final String getIPAddress() {
return ipaddress;
}
@Override
public NodeItem clone() {
try {
return (NodeItem) super.clone();
} catch (CloneNotSupportedException ex) {
return null;
}
}
}

757
src/client/NodeList.java Normal file
View file

@ -0,0 +1,757 @@
/*
* 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.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.regex.Pattern;
import lib.Localisation;
import lib.SimpleFile;
/**
*
* @author Alistair Neil <info@dazzleships.net>
*/
public class NodeList {
public static final int NODELIST_IDLE = 0;
public static final int NODELIST_BUILDING = 1;
public static final int NODELIST_BUILT = 2;
public static final int NODELIST_FAILED = 3;
public static final int NODELIST_TERMINATED = 4;
private static final String EMPTYSTRING = "";
private static final Localisation LOCAL = new Localisation("resources/MessagesBundle");
private ExitNodeTableModel entm;
private GuardNodeTableModel gntm;
private int intStatus = NODELIST_IDLE;
private HashMap<String, NodeItem> hmNode;
private final HashMap<String, NodeItem> hmBridges;
private final ArrayList<String> alCountries;
private TorController tc;
private final String exitFavouritesFile;
private final String guardFavouritesFile;
private final String filepath;
private volatile boolean boolAbortActions;
private final Pattern pattspace = Pattern.compile(" ");
private int nooffavs;
public NodeList(String filepath, String exitfavourites, String guardfavouritesfile) {
this.hmNode = new HashMap<>();
this.hmBridges = new HashMap<>();
this.filepath = filepath;
this.alCountries = new ArrayList<>();
this.exitFavouritesFile = exitfavourites;
this.guardFavouritesFile = guardfavouritesfile;
}
/**
* Get node item from its fingerprint
*
* @param key or fingerprint
* @return NodeItem
*/
public final NodeItem getNode(String key) {
String temp;
NodeItem ni = hmNode.get(key);
if (ni == null) {
// No bridge found so must be a new node not currently in nodelist
ArrayList<String> alRouterInfo = getRouterDesc(key);
if (alRouterInfo != null) {
alRouterInfo.addAll(getRouterStatus(key));
ni = new NodeItem();
temp = filterRouterInfo(alRouterInfo, "router ");
if (temp == null) {
return null;
}
String[] data = pattspace.split(temp);
ni.setFingerprint(key);
ni.setNickName(data[0]);
ni.setIPAddress(data[1]);
String isocode = tc.getCountryFromIP(ni.getIPAddress());
if (isocode == null || isocode.contentEquals("??")) {
isocode = "U1";
}
ni.setCountryCode(isocode);
ni.setCountryName(LOCAL.getDisplayCountry(isocode));
temp = filterRouterInfo(alRouterInfo, "bandwidth ");
data = pattspace.split(temp);
ni.setBandwidth(getLowestBandwidth(data));
temp = filterRouterInfo(alRouterInfo, "s ");
if (temp == null) {
// We probably have a bridge
ni.setType(NodeItem.TYPE_GUARD);
ni.setStable(LOCAL.getString("text_yes"));
return ni;
}
if (temp.contains("Guard")) {
ni.setType(NodeItem.TYPE_GUARD);
}
if (temp.contains("Stable")) {
ni.setStable(LOCAL.getString("text_yes"));
} else {
ni.setStable(LOCAL.getString("text_no"));
}
if (temp.contains("Exit") && !temp.contains("BadExit")) {
ni.setType(NodeItem.TYPE_EXIT);
temp = filterRouterInfo(alRouterInfo, "p ");
if (temp.startsWith("accept")) {
temp = temp.replace("accept ", "");
if (!containsPort(temp, 80) && !containsPort(temp, 443)) {
return ni;
}
} else {
temp = temp.replace("reject ", "");
if (containsPort(temp, 80) || containsPort(temp, 443)) {
return ni;
}
}
ni.setHttpSupported(true);
}
}
}
return ni;
}
public ArrayList<String> getRouterDesc(String finger) {
ArrayList<String> alResult = tc.getInfo("desc/id/" + finger);
if (alResult == null) {
return null;
}
alResult.remove("250 OK");
if (alResult.isEmpty()) {
return null;
}
return alResult;
}
public ArrayList<String> getRouterStatus(String finger) {
ArrayList<String> alResult = tc.getInfo("ns/id/" + finger);
if (alResult == null) {
return null;
}
alResult.remove("250 OK");
if (alResult.isEmpty()) {
return null;
}
return alResult;
}
public String filterRouterInfo(ArrayList<String> alInfo, String field) {
for (String s : alInfo) {
if (s.startsWith(field)) {
return s.replace(field, "");
}
}
return null;
}
/**
* Get the process status
*
* @return status
*/
public final int getCurrentStatus() {
return intStatus;
}
/**
* Generate the nodelist
*
* @param tc
*/
public final void refreshNodelist(TorController tc) {
boolAbortActions = false;
intStatus = NODELIST_BUILDING;
this.tc = tc;
boolean boolSuccess = populateNodeMap();
if (boolSuccess) {
boolSuccess = fetchFingerData();
}
if (boolSuccess) {
intStatus = NODELIST_BUILT;
} else if (boolAbortActions) {
intStatus = NODELIST_TERMINATED;
} else {
intStatus = NODELIST_FAILED;
}
}
/**
* Update internal node mappings
*
*/
private boolean populateNodeMap() {
String strFlags;
String data[];
String temp;
String strNick;
String strIP;
String strCountryName;
String strCountryCode;
String strPerms;
String strDirPort;
String strOrPort;
NodeItem ni;
SimpleFile sfConsensus = new SimpleFile(tc.getDataFolder() + SimpleFile.getSeparator() + "cached-consensus");
hmNode.clear();
alCountries.clear();
sfConsensus.openBufferedRead();
while (!boolAbortActions) {
temp = sfConsensus.readLine();
// Test for end of node info file
if (temp.startsWith("directory-footer")) {
break;
}
// Test for node info line
if (temp.startsWith("r ")) {
data = pattspace.split(temp);
strNick = data[1];
strIP = data[6];
strOrPort = data[7];
strDirPort = data[8];
// Read flags line
while (true) {
strFlags = sfConsensus.readLine();
if (strFlags.startsWith("s ")) {
break;
}
}
// Ignore certain types of node
if (!strFlags.contains("Running")
|| !strFlags.contains("Valid")) {
continue;
}
// Read port permissions line
while (true) {
strPerms = sfConsensus.readLine();
if (strPerms.startsWith("p ")) {
break;
}
}
// Check if Tor is fully active
if (tc.getStatus() < TorController.STATUS_IDLE) {
boolAbortActions = false;
alCountries.clear();
break;
}
// Get country code from ip address
strCountryCode = tc.getCountryFromIP(strIP);
if (strCountryCode == null || strCountryCode.contains("??")) {
strCountryCode = "U1";
}
// If we get GEOIP errors then abort
if (strCountryCode.startsWith("551 GEOIP")) {
alCountries.clear();
break;
}
// Get country name
strCountryName = LOCAL.getDisplayCountry(strCountryCode);
ni = new NodeItem();
// Update our node item fields now that we have validated our node
ni.setCountryCode(strCountryCode);
ni.setCountryName(strCountryName);
ni.setNickName(strNick);
ni.setIPAddress(strIP);
// Get stableflag
if (strFlags.contains("Stable")) {
ni.setStable(LOCAL.getString("text_yes"));
} else {
ni.setStable(LOCAL.getString("text_no"));
}
hmNode.put(strOrPort + strDirPort + ":" + strIP, ni);
// Check if a guard node
if (strFlags.contains("Guard")) {
ni.setType(NodeItem.TYPE_GUARD);
}
// Check if an exit node also exclude nodes flagged as bad exits
if (strFlags.contains("Exit") && !strFlags.contains("BadExit")) {
ni.setType(NodeItem.TYPE_EXIT);
// Simple test on port permissions, we will only allow node
// if it accepts connections on port 80 and 443 for web browsing
if (strPerms.startsWith("p accept")) {
strPerms = strPerms.replace("p accept ", "");
if (!containsPort(strPerms, 80)) {
continue;
}
if (!containsPort(strPerms, 443)) {
continue;
}
} else {
strPerms = strPerms.replace("p reject ", "");
if (containsPort(strPerms, 80)) {
continue;
}
if (containsPort(strPerms, 443)) {
continue;
}
}
ni.setHttpSupported(true);
// Ensure we only add exit country info in once to validated countries list
if (!alCountries.contains(strCountryCode + "," + strCountryName)) {
alCountries.add(strCountryCode + "," + strCountryName);
}
}
}
}
sfConsensus.closeFile();
// Sort our country validation list
if (alCountries.isEmpty()) {
return false;
} else {
Collections.sort(alCountries, Collator.getInstance());
}
return !boolAbortActions;
}
/**
* Update internal finger mappings
*
*/
private boolean fetchFingerData() {
int idx;
String line;
String data[];
String ipaddress;
String finger;
String strOrPort;
String strDirPort;
String key;
boolean result;
String guardwhitelist = getGuardFavouritesAsCSV();
NodeItem ni;
HashMap<String, NodeItem> hmNodeReplacement = new HashMap<>();
SimpleFile sfDescriptors = new SimpleFile(tc.getDataFolder() + SimpleFile.getSeparator() + "cached-descriptors");
SimpleFile sfDescriptorsNew = new SimpleFile(tc.getDataFolder() + SimpleFile.getSeparator() + "cached-descriptors.new");
if (!sfDescriptorsNew.exists() || sfDescriptorsNew.getFile().length() == 0) {
sfDescriptorsNew = null;
}
sfDescriptors.openBufferedRead();
try {
while (!boolAbortActions) {
line = sfDescriptors.readLine();
// If line is null we have then processed the main descriptors file
if (line == null) {
// Check if their is a descriptors new file
if (sfDescriptorsNew == null) {
break;
} else {
sfDescriptors.closeFile();
sfDescriptors = sfDescriptorsNew;
sfDescriptors.openBufferedRead();
sfDescriptorsNew = null;
continue;
}
}
if (line.startsWith("router ")) {
data = pattspace.split(line);
ipaddress = data[2];
strOrPort = data[3];
strDirPort = data[5];
key = strOrPort + strDirPort + ":";
if (!hmNode.containsKey(key + ipaddress)) {
continue;
}
// Get fingerprint
while (true) {
line = sfDescriptors.readLine();
idx = line.indexOf("fingerprint");
if (idx > -1) {
line = line.substring(idx + 12);
break;
}
}
finger = "$" + line.replace(" ", EMPTYSTRING);
// Get bandwidth
while (true) {
line = sfDescriptors.readLine();
idx = line.indexOf("bandwidth");
if (idx > -1) {
line = line.substring(idx + 10);
break;
}
}
data = pattspace.split(line);
ni = hmNode.get(key + ipaddress);
ni.setFingerprint(finger);
ni.setGuardEnabled(guardwhitelist.contains(finger));
ni.setBandwidth(getLowestBandwidth(data));
hmNodeReplacement.put(finger, ni);
}
}
result = !boolAbortActions;
} catch (Exception ex) {
result = false;
}
sfDescriptors.closeFile();
// Replace our original ipaddress keyed nodemap with our fingerprint keyed nodemap
hmNode = hmNodeReplacement;
return result;
}
/**
* Return the lowest bandwidth
*
* @param data
* @return bandwidth as float
*/
private float getLowestBandwidth(String[] data) {
float bw = 1000000;
float tmp;
for (String s : data) {
tmp = Float.parseFloat(s) / 1000000;
if (tmp < bw) {
bw = tmp;
}
}
return bw;
}
/**
* Add newly learned bridge to nodelist
*
* @param bridgedata
*/
public void addBridge(String bridgedata) {
Pattern pat = Pattern.compile(" ");
bridgedata = bridgedata.substring(bridgedata.indexOf('$'));
String[] data = pat.split(bridgedata);
int index = data[0].indexOf('~');
if (index < 0) {
index = data[0].indexOf('=');
}
NodeItem ni = new NodeItem();
ni.setFingerprint(data[0].substring(0, index));
ni.setIPAddress(data[2]);
ni.setNickName(data[0].substring(index + 1));
hmBridges.put(ni.getFingerprint(), ni);
}
/**
* Clear any learned bridges
*/
public void clearBridges() {
hmBridges.clear();
}
/**
* Test to check supplied data contains the specified port
*
* @param data
* @param port
* @return True if data contains specified port
*/
private boolean containsPort(String data, int port) {
String strRanges[];
String[] strPorts;
int rangemin;
int rangemax;
Pattern pattcomma = Pattern.compile(",");
Pattern pattminus = Pattern.compile("-");
strRanges = pattcomma.split(data);
for (String s : strRanges) {
// Test to see if its a range of ports
if (s.contains("-")) {
strPorts = pattminus.split(s);
rangemin = Integer.parseInt(strPorts[0]);
rangemax = Integer.parseInt(strPorts[1]);
if (port >= rangemin && port <= rangemax) {
return true;
}
} else {
// We have a single port
rangemin = Integer.parseInt(s);
if (port == rangemin) {
return true;
}
}
}
return false;
}
/**
* Gets validated countries, a valid country is any country with active exit
* nodes
*
* @return String array of countries
*/
public final String[] getValidatedCountries() {
return alCountries.toArray(new String[alCountries.size()]);
}
/**
* Gets validated country codes, a valid country is any country with active
* exit nodes
*
* @return String array of country abbreviations
*/
public final String[] getValidatedCountryCodes() {
String[] result = new String[alCountries.size()];
int idx = 0;
for (String s : alCountries) {
result[idx++] = s.substring(0, 2);
}
return result;
}
/**
* Set the guard node view table model
*
* @param gntm
*/
public final void setGuardNodeTableModel(GuardNodeTableModel gntm) {
this.gntm = gntm;
}
/**
* Set the exit node view table model
*
* @param entm
*/
public final void setExitNodeTableModel(ExitNodeTableModel entm) {
this.entm = entm;
}
/**
* Get a list of exitnodes, if all is false then it returns only favourited
* nodes, if omitfailednodes is true then don't include nodes that failed
* testing
*
* @param all
* @param omitfailednodes
* @return ArrayList of exit nodes
*/
public final ArrayList<String> getExitNodes(boolean all, boolean omitfailednodes) {
ArrayList<String> al = new ArrayList<>();
for (int i = 0; i < entm.getRowCount(); i++) {
int teststatus = (Integer) entm.getValueAt(i, 7);
if (omitfailednodes && teststatus == NodeItem.TESTSTATUS_FAILED) {
continue;
}
boolean fave = (Boolean) entm.getValueAt(i, 4) | all;
if (fave) {
al.add((String) entm.getValueAt(i, 5));
}
}
return al;
}
/**
* Get a string of comma separated exitnodes, if all is false then it
* returns only favourited nodes, if omitfailednodes is true then don't
* include nodes that failed testing
*
* @param all
* @param omitfailednodes
* @return String of exitnodes in csv format
*/
public final String getExitNodesAsString(boolean all, boolean omitfailednodes) {
String result = getExitNodes(all, omitfailednodes).toString();
result = result.replace("[", "").replace(" ", "").replace("]", "");
return result;
}
/**
* Get a list of all guard nodes guard nodes
*
* @return ArrayList of guard nodes
*/
public final ArrayList<String> getGuardNodes() {
ArrayList<String> al = new ArrayList<>();
if (gntm == null) {
return al;
}
for (int i = 0; i < gntm.getRowCount(); i++) {
al.add((String) gntm.getValueAt(i, 3));
}
return al;
}
/**
* Get guard favourites
*
* @return CSV string of guard entry fingerprints
*/
public final String getGuardFavouritesAsCSV() {
StringBuilder sbResult = new StringBuilder();
String line;
String sep = "";
if (guardFavouritesFile == null) {
return sbResult.toString();
}
SimpleFile sf = new SimpleFile(filepath + guardFavouritesFile);
if (!sf.exists()) {
return sbResult.toString();
}
sf.openBufferedRead();
while ((line = sf.readLine()) != null) {
sbResult.append(sep);
sbResult.append(line);
if (sep.isEmpty()) {
sep = ",";
}
}
sf.closeFile();
return sbResult.toString();
}
/**
* Update the guard node table model
*/
public final void refreshGuardTableModel() {
if (gntm == null) {
return;
}
NodeItem ni;
gntm.clear();
// Populate model
for (String s : hmNode.keySet()) {
ni = hmNode.get(s);
if (ni.isGuard()) {
Object[] rowData = new Object[]{ni};
gntm.addRow(rowData);
}
}
}
/**
* Update the table model based on supplied country
*
*
* @param isocountry in the format "GB,Great Britain"
*/
public final void refreshExitTableModel(String isocountry) {
if (entm == null) {
return;
}
NodeItem ni;
entm.clear();
String abbrv = isocountry;
String favourites = "";
if (exitFavouritesFile != null) {
SimpleFile sf = new SimpleFile(filepath + exitFavouritesFile);
if (sf.exists()) {
sf.openBufferedRead();
favourites = sf.readEntireFile().trim();
sf.closeFile();
}
}
// Populate model
nooffavs = 0;
for (String s : hmNode.keySet()) {
ni = hmNode.get(s);
if (ni.isExit() && ni.isHttpSupported() && ni.getCountryCode().contentEquals(abbrv)) {
ni.setLatency(9999);
ni.setTestingMessage(LOCAL.getString("textfield_unknown"));
// Whitelisting here
ni.setFavouriteEnabled(favourites.contains(ni.getIPAddress()));
if (ni.isFavourite()) {
nooffavs++;
}
Object[] rowData = new Object[]{ni};
entm.addRow(rowData);
}
}
}
/**
* Get the number of active favourites
*
* @return number of favs as int
*/
public int getNumberOfFavs() {
return nooffavs;
}
/**
* Ensures any threaded actions will terminate themselves
*/
public final void terminate() {
boolAbortActions = true;
}
/**
* Save exit node whitelist
*/
public void saveExitFavourites() {
if (exitFavouritesFile == null) {
return;
}
SimpleFile sf = new SimpleFile(filepath + exitFavouritesFile);
sf.openBufferedWrite();
NodeItem ni;
nooffavs = 0;
for (String s : hmNode.keySet()) {
ni = hmNode.get(s);
if (ni.isExit() && ni.isFavourite()) {
nooffavs++;
sf.writeFile(ni.getIPAddress(), 1);
}
}
sf.closeFile();
}
/**
* Save exit node blacklist
*
* @return number of active guards
*/
public int saveGuardWhitelist() {
int activeguards = 0;
if (guardFavouritesFile == null) {
return activeguards;
}
SimpleFile sf = new SimpleFile(filepath + guardFavouritesFile);
sf.openBufferedWrite();
NodeItem ni;
for (String s : hmNode.keySet()) {
ni = hmNode.get(s);
if (ni.isGuard() && ni.isGuardEnabled()) {
sf.writeFile(ni.getFingerprint(), 1);
activeguards++;
}
}
sf.closeFile();
return activeguards;
}
}

721
src/client/PacFactory.java Normal file
View file

@ -0,0 +1,721 @@
/*
* 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.io.File;
import java.util.ArrayList;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import lib.OSFunction;
import lib.SimpleFile;
/**
*
* @author Alistair Neil <info@dazzleships.net>
*/
public class PacFactory {
public static final String FILEUSER = "user";
private static final String FILEEXT = ".txt";
public static final int PROXY_DISABLED = 0;
public static final int PROXY_PATTERN = 1;
public static final int PROXY_ALL = 2;
private static final String PACFILE_EXT = ".pac";
private static final String PATTERNFIRSTLINE = "### Pattern File, Do not remove or modify this line ###";
private String strKDEProxyPrefsBackup;
private String strGnome3ProxyPrefsBackup;
private String strPACPath;
private String strBackupFolder;
private String strPatternsFolder;
private String strTempFolder;
private String strDefaultProxy = "";
private String strDoNotProxy = "";
private String strActiveCountry;
private String strActivePacName = "";
private final Random randgen;
public PacFactory() {
randgen = new Random(System.currentTimeMillis());
}
/**
* Get the active country code
*
* @return Active country
*/
public String getActiveCountry() {
return strActiveCountry;
}
/**
* Create and/or activate a pacfile for a specific country
*
* @param isocountry
* @param port
*/
public void createPacFile(String isocountry, int port) {
// Generate a pseudo random pac name
String pacname = createRandomName() + PACFILE_EXT;
savePACFile(pacname, getPacRules(isocountry, String.valueOf(port)));
setProxyAutoConfigURL("file://" + strPACPath.replace("\\", "/") + pacname);
strActiveCountry = isocountry;
if (!strActivePacName.isEmpty()) {
this.deletePAC(strActivePacName);
}
strActivePacName = pacname;
}
/**
* Get pac rules for a specific country Can also be used for getting direct
* rule and proxy all rules, by setting countrycode to "direct" or
* "proxyall"
*
* @param countrycode
* @param port
* @return An arraylist of rules
*/
private ArrayList<String> getPacRules(String country, String port) {
ArrayList<String> result = new ArrayList<>();
// If country code is null then generate proxy all traffic rules
if (country.contentEquals("proxyall")) {
addSocksRule(result, "127.0.0.1", port);
return result;
}
if (country.contentEquals("direct")) {
addDirectMatchingRule(result, null);
return result;
}
Pattern pat = Pattern.compile(",");
String[] split;
// Create our pattern rules storage list
ArrayList<String> patternrules = new ArrayList<>();
// Add in do not proxy rules
if (!strDoNotProxy.isEmpty()) {
split = pat.split(strDoNotProxy);
for (String s : split) {
if (!s.isEmpty()) {
addDirectMatchingRule(result, "*" + s + "*");
}
}
}
// Get default patterns
loadPatternsList(country, patternrules);
for (String s : patternrules) {
split = pat.split(s);
if (split.length < 3) {
break;
}
if (split[2].contentEquals("true")) {
if (split[1].contentEquals("*")) {
addSocksRule(result, "127.0.0.1", port);
return result;
} else {
addSocksMatchingRule(result, split[1], "127.0.0.1", port);
}
}
}
if (strDefaultProxy.isEmpty()) {
addDirectMatchingRule(result, null);
} else {
addProxyRule(result, strDefaultProxy);
}
return result;
}
/**
*
* @param rules
* @param proxy
*/
public void addProxyRule(ArrayList<String> rules, String proxy) {
rules.add("\treturn \"PROXY " + proxy + "\";");
}
/**
* Add a socks rule to a supplied list
*
* @param rules
* @param host
* @param port
*/
public void addSocksRule(ArrayList<String> rules, String host, String port) {
String rule = "\treturn \"SOCKS5 " + host + ":" + port + "\";";
rules.add(rule);
}
/**
*
* @param rules
* @param pattern
*/
public void addDirectMatchingRule(ArrayList<String> rules, String pattern) {
String rule;
if (pattern == null) {
rule = "\treturn \"DIRECT\";";
} else {
rule = "\tif (shExpMatch(url, \"" + pattern + "\"))\n"
+ "\t{\n"
+ "\t\treturn \"DIRECT\";\n"
+ "\t}";
}
rules.add(rule);
}
/**
* Add socks pattern mayching rule to a supllied list
*
* @param rules
* @param pattern
* @param host
* @param port
*/
public void addSocksMatchingRule(ArrayList<String> rules, String pattern, String host, String port) {
String rule = "\tif (shExpMatch(url, \"" + pattern + "\"))\n"
+ "\t{\n"
+ "\t\treturn \"SOCKS5 " + host + ":" + port + "\";\n"
+ "\t}";
rules.add(rule);
}
/**
* Load a patterns list from a file
*
* @param country
* @param list
*/
public void loadPatternsList(String country, ArrayList<String> list) {
String line;
int idxs, idxe;
SimpleFile sfPatternFile = new SimpleFile(strPatternsFolder + country.substring(0, 2) + "_" + FILEUSER + FILEEXT);
if (sfPatternFile.exists()) {
sfPatternFile.openBufferedRead();
while ((line = sfPatternFile.readLine()) != null) {
idxs = line.indexOf('<');
idxe = line.indexOf('>');
if (idxs == 0 && idxe == (line.length() - 1)) {
list.add(line.substring(idxs + 1, idxe) + "," + FILEUSER);
}
}
sfPatternFile.closeFile();
}
}
/**
* Delete patterns file for a given country and type, where type is either
* "def" or "user"
*
* @param country
* @param type
*/
public void deletePatternsFile(String country, String type) {
SimpleFile sfPatternFile = new SimpleFile(strPatternsFolder + country.substring(0, 2) + "_" + type + FILEEXT);
sfPatternFile.delete();
}
/**
* Save a patterns list by filename
*
* @param country
* @param list
* @param type
*/
public void savePatternsList(String country, String type, ArrayList<String> list) {
SimpleFile sfPatternFile = new SimpleFile(strPatternsFolder + country.substring(0, 2) + "_" + type + FILEEXT);
sfPatternFile.openBufferedWrite();
sfPatternFile.writeFile(PATTERNFIRSTLINE, 1);
for (String s : list) {
sfPatternFile.writeFile("<" + s + ">", 1);
}
sfPatternFile.closeFile();
}
/**
* Create folder in which pattern files will be stored
*
* @param folder
*/
public final void setPatternsFolder(String folder) {
strPatternsFolder = folder + SimpleFile.getSeparator();
SimpleFile.createFolder(strPatternsFolder);
}
/**
* Set folder where pac files will be generated
*
* @param folder
*/
public final void setPACFolder(String folder) {
strPACPath = folder;
SimpleFile.createFolder(folder);
}
/**
* Set folder where system proxy settings will be backed up
*
* @param folder
*/
public final void setBackupFolder(String folder) {
strBackupFolder = folder + SimpleFile.getSeparator();
SimpleFile.createFolder(strBackupFolder);
if (OSFunction.getGsettingsPath() != null) {
strGnome3ProxyPrefsBackup = strBackupFolder + "gnome3_proxy.txt";
} else {
strGnome3ProxyPrefsBackup = null;
}
if (OSFunction.getKDEProxyPath() != null) {
strKDEProxyPrefsBackup = strBackupFolder + "kde_proxy.txt";
} else {
strKDEProxyPrefsBackup = null;
}
}
/**
* Set the temp folder for file extractions
*
* @param path
*/
public final void setTempFolder(String path) {
strTempFolder = path;
}
/**
* Generic backup of proxy settings
*
*/
public void backupProxyPrefs() {
backupGnomeProxyPrefs();
backupKDEProxyPrefs();
}
/**
* Gnome backup of proxy settings
*
*/
private void backupGnomeProxyPrefs() {
if (strBackupFolder == null) {
return;
}
SimpleFile sfProxyPrefs;
try {
if (strGnome3ProxyPrefsBackup != null) {
sfProxyPrefs = new SimpleFile(strGnome3ProxyPrefsBackup);
if (!sfProxyPrefs.exists()) {
sfProxyPrefs.openBufferedWrite();
sfProxyPrefs.writeFile(OSFunction.getGnome3Pref("org.gnome.system.proxy", "mode"), 1);
sfProxyPrefs.writeFile(OSFunction.getGnome3Pref("org.gnome.system.proxy", "autoconfig-url"), 1);
sfProxyPrefs.closeFile();
}
}
} catch (Exception ex) {
Logger.getGlobal().logp(Level.SEVERE, this.getClass().getName(), "backupGnomeProxyPrefs()", "", ex);
}
}
/**
* KDE backup of proxy settings
*
*/
private void backupKDEProxyPrefs() {
if (strBackupFolder == null) {
return;
}
SimpleFile sfProxyPrefs;
try {
if (strKDEProxyPrefsBackup != null) {
sfProxyPrefs = new SimpleFile(strKDEProxyPrefsBackup);
if (!sfProxyPrefs.exists()) {
sfProxyPrefs.openBufferedWrite();
sfProxyPrefs.writeFile(OSFunction.getKDEPref("Proxy Settings", "Proxy Config Script", ""), 1);
sfProxyPrefs.writeFile(OSFunction.getKDEPref("Proxy Settings", "ProxyType", "0"), 1);
sfProxyPrefs.closeFile();
}
}
} catch (Exception ex) {
Logger.getGlobal().logp(Level.SEVERE, this.getClass().getName(), "backupKDEProxyPrefs()", "", ex);
}
}
/**
* Generic restore of proxy settings, for ease of use
*
*/
public void restoreProxyPrefs(boolean resetonfail) {
restoreGnomeProxyPrefs(resetonfail);
restoreKDEProxyPrefs(resetonfail);
}
/**
* Gnome specific restore of proxy settings
*
*/
private void restoreGnomeProxyPrefs(boolean resetonfail) {
SimpleFile sfProxyPrefs;
try {
// Restore gnome3 proxy prefs
if (strGnome3ProxyPrefsBackup != null) {
sfProxyPrefs = new SimpleFile(strGnome3ProxyPrefsBackup);
if (sfProxyPrefs.exists()) {
sfProxyPrefs.openBufferedRead();
String mode = sfProxyPrefs.readLine();
String url = sfProxyPrefs.readLine();
sfProxyPrefs.closeFile();
if (url != null && mode != null && !mode.isEmpty()) {
// Restore original settings from file
OSFunction.setGnome3Pref("org.gnome.system.proxy", "mode", mode);
OSFunction.setGnome3Pref("org.gnome.system.proxy", "autoconfig-url", url);
}
} else {
if (resetonfail) {
setGnomeProxyAutoConfigURL(null);
}
}
}
} catch (Exception ex) {
Logger.getGlobal().logp(Level.SEVERE, this.getClass().getName(), "restoreGnomeProxyPrefs()", "", ex);
}
}
/**
* KDE specific restore of proxy settings
*
*/
private void restoreKDEProxyPrefs(boolean resetonfail) {
SimpleFile sfProxyPrefs;
try {
// Restore kde proxy prefs
if (strKDEProxyPrefsBackup != null) {
sfProxyPrefs = new SimpleFile(strKDEProxyPrefsBackup);
if (sfProxyPrefs.exists()) {
sfProxyPrefs.openBufferedRead();
String url = sfProxyPrefs.readLine();
String type = sfProxyPrefs.readLine();
sfProxyPrefs.closeFile();
if (url != null && type != null) {
if (!SimpleFile.exists(url)) {
url = "";
}
OSFunction.setKDEPref("Proxy Settings", "Proxy Config Script", url);
OSFunction.setKDEPref("Proxy Settings", "ProxyType", type);
}
} else {
if (resetonfail) {
setKDEProxyAutoConfigURL(null);
}
}
}
} catch (Exception ex) {
Logger.getGlobal().logp(Level.SEVERE, this.getClass().getName(), "restoreKDEProxyPrefs()", "", ex);
}
}
/**
* Generic proxy prefs delete, for ease of use
*/
public void deleteProxyPrefs() {
deleteGnomeProxyPrefs();
deleteKDEProxyPrefs();
}
/**
* Generic delete of backed up gnome proxy settings
*
* @return boolean True if successful
*/
private boolean deleteGnomeProxyPrefs() {
if (strBackupFolder == null) {
return false;
}
boolean result = true;
// Delete Gnome3 prefs
if (strGnome3ProxyPrefsBackup != null) {
result = SimpleFile.delete(strGnome3ProxyPrefsBackup);
}
return result;
}
/**
* Generic delete of backed up KDE proxy settings
*
* @return boolean True if successful
*/
private boolean deleteKDEProxyPrefs() {
if (strBackupFolder == null) {
return false;
}
boolean result = true;
// Delete Kde prefs
if (strKDEProxyPrefsBackup != null) {
result = SimpleFile.delete(strKDEProxyPrefsBackup);
}
return result;
}
/**
* Generic set proxy config
*
* @param url
*/
public void setProxyAutoConfigURL(String url) {
setGnomeProxyAutoConfigURL(url);
setKDEProxyAutoConfigURL(url);
}
/**
* Set Gnome proxy config
*
* @param url
*/
private void setGnomeProxyAutoConfigURL(String url) {
if (strGnome3ProxyPrefsBackup != null) {
if (url == null) {
OSFunction.resetGnome3Pref("org.gnome.system.proxy", "mode");
OSFunction.resetGnome3Pref("org.gnome.system.proxy", "autoconfig-url");
} else {
OSFunction.setGnome3Pref("org.gnome.system.proxy", "mode", "auto");
OSFunction.setGnome3Pref("org.gnome.system.proxy", "autoconfig-url", url);
}
}
}
/**
* Set KDE proxy config
*
* @param url
*/
private void setKDEProxyAutoConfigURL(String url) {
if (strKDEProxyPrefsBackup != null) {
if (url == null) {
OSFunction.setKDEPref("Proxy Settings", "Proxy Config Script", "");
OSFunction.setKDEPref("Proxy Settings", "ProxyType", 0);
} else {
OSFunction.setKDEPref("Proxy Settings", "Proxy Config Script", url);
OSFunction.setKDEPref("Proxy Settings", "ProxyType", 2);
}
}
}
/**
* Save pac file using given filename
*
* @param filename
* @param ruleslist
*/
private void savePACFile(String filename, ArrayList<String> ruleslist) {
SimpleFile sfPacFile = new SimpleFile(strPACPath + filename);
sfPacFile.openBufferedWrite();
sfPacFile.writeFile("//" + filename, 1);
String temp = "function FindProxyForURL(url, host) {";
sfPacFile.writeFile(temp, 1);
for (String s : ruleslist) {
sfPacFile.writeFile(s, 1);
}
sfPacFile.writeFile("}", 1);
sfPacFile.closeFile();
}
/**
* Delete specified pac file
*
* @param filename
* @return boolean true if action successful
*/
public boolean deletePAC(String filename) {
return SimpleFile.delete(strPACPath + filename);
}
/**
* Delete all pac files
*/
public void deleteAllPAC() {
SimpleFile sf = new SimpleFile(strPACPath);
sf.setFileFilter(PACFILE_EXT);
sf.deleteFileList(sf.getFileList());
}
/**
* Get a pseudo random numerical name
*
* @return String
*/
private String createRandomName() {
// Create new filename with a random number to modify filename from
// previous one to force auto reload of pac settings in browser
int pacNumber = randgen.nextInt();
if (pacNumber < 0) {
pacNumber = 0 - pacNumber;
}
return String.valueOf(pacNumber);
}
/**
* Set default proxy url
*
* @param proxyurl
*/
public void setDefaultProxy(String proxyurl) {
strDefaultProxy = proxyurl;
}
/**
* Set do not proxy
*
* @param hostcsv
*/
public void setDoNotProxy(String hostcsv) {
strDoNotProxy = hostcsv;
}
/**
* Get value of comma separated host or ip list
*
* @return String value
*/
public String getDoNotProxy() {
return strDoNotProxy;
}
/**
* Adds pattern to an existing pattern file
*
* @param country
* @param description
* @param pattern
*/
public void addToPatternFile(String country, String description, String pattern) {
if (strPatternsFolder == null || pattern.isEmpty()) {
return;
}
SimpleFile sfPatternFile = new SimpleFile(strPatternsFolder + SimpleFile.getSeparator() + country.substring(0, 2) + "_" + FILEUSER + FILEEXT);
sfPatternFile.openBufferedAppend();
sfPatternFile.writeFile("<" + description + "," + pattern + ",true>", 1);
sfPatternFile.closeFile();
}
/**
* Get an array of user pattern files
*
* @return array of files
*/
public File[] getPatternsFiles() {
SimpleFile sf = new SimpleFile(strPatternsFolder);
sf.setFileFilter(FILEUSER + FILEEXT);
return sf.getFileList();
}
/**
* Export user patterns
*
* @param filename
* @param files
*/
public void exportUserPatterns(String filename, File[] files) {
// Append .zip extension if we need to
if (!filename.endsWith(".zip")) {
filename += ".zip";
}
// Add user pattern files to zip
SimpleFile sf = new SimpleFile(filename);
sf.openZipStream(9);
sf.addFilesToZip(files);
sf.closeZipStream();
}
/**
* Import patterns
*
* @param filename
* @return true if succesful
*/
public boolean importPatterns(String filename) {
// Import patterns
boolean success = false;
SimpleFile sf = new SimpleFile(filename);
String destpath;
// Check existence
if (sf.exists()) {
// Get temporary path to extraction folder
if (strTempFolder == null) {
destpath = OSFunction.getTempFolder(null)
+ getClass().getName();
} else {
destpath = strTempFolder + getClass().getName();
}
// Create temp extraction folder
SimpleFile.createFolder(destpath);
// Extract files to temp folder
success = sf.extractZipTo(destpath);
if (success) {
// Get list of files
sf.setFileName(destpath);
sf.setFileFilter(".txt");
File[] files = sf.getFileList();
// Verify each file before copying them over
String firstLine;
try {
if (files.length == 0) {
throw new Exception();
}
for (File f : files) {
// Verify valid pattern file by checking first line of file
sf.setFile(f);
sf.openBufferedRead();
firstLine = sf.readLine();
sf.closeFile();
if (firstLine != null) {
if (firstLine.toLowerCase().contains("pattern file")) {
SimpleFile.copyFromTo(f.getAbsolutePath(), strPatternsFolder + f.getName());
} else {
success = false;
break;
}
}
}
} catch (Exception ex) {
success = false;
}
}
// Delete temporary files
SimpleFile.deleteFolder(destpath);
}
return success;
}
}

View file

@ -0,0 +1,202 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.6" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
<Properties>
<Property name="defaultCloseOperation" type="int" value="2"/>
<Property name="title" type="java.lang.String" value="Proxy Pattern Editor"/>
<Property name="iconImage" type="java.awt.Image" editor="org.netbeans.modules.form.ComponentChooserEditor">
<ComponentRef name="null"/>
</Property>
<Property name="resizable" type="boolean" value="false"/>
</Properties>
<SyntheticProperties>
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
</SyntheticProperties>
<Events>
<EventHandler event="windowClosing" listener="java.awt.event.WindowListener" parameters="java.awt.event.WindowEvent" handler="closeDialog"/>
</Events>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane1" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="jComboCountry" min="-2" pref="264" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="jButtonDeletePattern" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jButtonAddPattern" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<Component id="jButtonCancel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jButtonSave" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="jLabel17" min="-2" max="-2" attributes="1"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jTextDoNotProxy" max="32767" attributes="1"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jComboCountry" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="jScrollPane1" pref="341" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jTextDoNotProxy" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jLabel17" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jButtonDeletePattern" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jButtonCancel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jButtonSave" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jButtonAddPattern" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JButton" name="jButtonSave">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="button_save" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButtonSaveActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="jButtonCancel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="button_close" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButtonCancelActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JComboBox" name="jComboCountry">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="new javax.swing.DefaultComboBoxModel&lt;&gt;(new String[] { &quot;Item 1&quot;, &quot;Item 2&quot;, &quot;Item 3&quot;, &quot;Item 4&quot; })" type="code"/>
</Property>
</Properties>
<Events>
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="jComboCountryItemStateChanged"/>
</Events>
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new javax.swing.JComboBox&lt;&gt;()"/>
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="&lt;String&gt;"/>
</AuxValues>
</Component>
<Component class="javax.swing.JButton" name="jButtonDeletePattern">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="button_delete" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButtonDeletePatternActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="jButtonAddPattern">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="button_addnew" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButtonAddPatternActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="jLabel1">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="label_editcountry" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTable" name="jTablePatterns">
<Properties>
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.editors2.TableModelEditor">
<Table columnCount="0" rowCount="0"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="ttip_patterntable" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
<Property name="autoResizeMode" type="int" value="3"/>
<Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor">
<JTableSelectionModel selectionMode="2"/>
</Property>
<Property name="tableHeader" type="javax.swing.table.JTableHeader" editor="org.netbeans.modules.form.editors2.JTableHeaderEditor">
<TableHeader reorderingAllowed="false" resizingAllowed="false"/>
</Property>
</Properties>
<Events>
<EventHandler event="mouseReleased" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="jTablePatternsMouseReleased"/>
<EventHandler event="keyReleased" listener="java.awt.event.KeyListener" parameters="java.awt.event.KeyEvent" handler="jTablePatternsKeyReleased"/>
</Events>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JLabel" name="jLabel17">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="label_donotproxy" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="jTextDoNotProxy">
<Properties>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="ttip_donotproxy" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="focusLost" listener="java.awt.event.FocusListener" parameters="java.awt.event.FocusEvent" handler="jTextDoNotProxyFocusLost"/>
<EventHandler event="keyReleased" listener="java.awt.event.KeyListener" parameters="java.awt.event.KeyEvent" handler="jTextDoNotProxyKeyReleased"/>
</Events>
</Component>
</SubComponents>
</Form>

View file

@ -0,0 +1,602 @@
/*
* 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 lib.InfoDialog;
import java.awt.Component;
import java.awt.FontMetrics;
import java.awt.Frame;
import java.awt.event.ItemEvent;
import java.util.ArrayList;
import java.util.regex.Pattern;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import lib.Localisation;
/**
*
* @author Alistair Neil, <info@dazzleships.net>
*/
public final class PatternsEditor extends javax.swing.JDialog {
public static final int CANCEL = 0;
public static final int APPLY = 1;
private final PACTableModel pactm = new PACTableModel();
private PacFactory pacFactory = null;
private String strChange = null;
private Frame parent = null;
private String strSelectedCountry = null;
private static final Localisation LOCAL = new Localisation("resources/MessagesBundle");
/**
* Creates a PatternsEditor dialog
*
* @param parent Parent frame
* @param modal Modality
* @param pacfactory PacFactory being edited
*/
public PatternsEditor(java.awt.Frame parent, boolean modal, PacFactory pacfactory) {
super(parent, modal);
this.parent = parent;
pacFactory = pacfactory;
initComponents();
pactm.setColumnName(LOCAL.getString("patterntable_col1"), 0);
pactm.setColumnName(LOCAL.getString("patterntable_col2"), 1);
pactm.setColumnName(LOCAL.getString("patterntable_col3"), 2);
jTablePatterns.setModel(pactm);
jTablePatterns.setDefaultRenderer(String.class, new CustomTableCellRenderer());
// Adjust our column widths
adjustTableColumnWidth(0, "AAAAAAAAAA");
adjustTableColumnWidth(1, "AAAAAAAAAAAAAAAAAAAAAAAA");
adjustTableColumnWidth(2, "AAA");
jTablePatterns.setRowHeight(jLabel1.getHeight() + 1);
jTablePatterns.setShowGrid(true);
jTextDoNotProxy.setText(pacFactory.getDoNotProxy());
}
/**
* Populate the country combobox with a list of countries
*
* @param countries String[] of countries
*/
public void populateCountryComboBox(String[] countries) {
jComboCountry.setModel(new DefaultComboBoxModel<>(countries));
jComboCountry.setSelectedIndex(-1);
}
/**
* Set the selected country
*
* @param country
*/
public void setSelectedCountry(String country) {
jComboCountry.setSelectedItem(country);
}
/**
* Populate the patterns table
*
* @param patterns an ArrayList<String> of pattern rules
*/
private void populatePatternsTable(ArrayList<String> patterns) {
// Clear all entries from table
while (pactm.getRowCount() > 0) {
pactm.removeRow(0);
}
// If patterns null just return;
if (patterns == null) {
strChange = pactm.toString() + jTextDoNotProxy.getText();
return;
}
// Populate table
Pattern pat = Pattern.compile(",");
String[] split;
Object[] obj = new Object[3];
for (String s : patterns) {
split = pat.split(s);
if (split.length < 4) {
continue;
}
obj[0] = split[0];
obj[1] = split[1];
try {
obj[2] = Boolean.valueOf(split[2]);
} catch (Exception ex) {
obj[2] = true;
}
pactm.addRow(obj, (split[3]).contains("user"));
}
strChange = pactm.toString() + jTextDoNotProxy.getText();
}
/**
* Test to see if patterns table has changed
*
* @return boolean True if changed
*/
private boolean isPatternsTableChanged() {
if (strChange == null) {
return false;
}
String temp = pactm.toString() + jTextDoNotProxy.getText();
return (!temp.contentEquals(strChange));
}
/**
* Save patterns and rebuild active country pac if required
*/
private void savePatterns() {
String s;
Boolean b;
ArrayList<String> listUser = new ArrayList<>();
int rowCount = pactm.getRowCount();
if (rowCount > 0) {
for (int i = 0; i < rowCount; i++) {
s = pactm.getValueAt(i, 0) + "," + pactm.getValueAt(i, 1);
b = (Boolean) pactm.getValueAt(i, 2);
if (b) {
s += ",true";
} else {
s += ",false";
}
listUser.add(s);
}
}
if (listUser.isEmpty()) {
pacFactory.deletePatternsFile(strSelectedCountry, PacFactory.FILEUSER);
} else {
pacFactory.savePatternsList(strSelectedCountry, PacFactory.FILEUSER, listUser);
}
pacFactory.setDoNotProxy(jTextDoNotProxy.getText());
strChange = pactm.toString() + jTextDoNotProxy.getText();
}
/**
* This is a check to see if any pattern save are required before exiting
* the pattern editor
*/
private int saveOnExitCheck() {
int result = CANCEL;
if (jButtonSave.isEnabled()) {
jComboCountry.hidePopup();
InfoDialog id = new InfoDialog(parent);
id.createWarn(LOCAL.getString("dlg_patterneditsave_title"),
LOCAL.getString("dlg_patterneditsave_body"));
id.setVisible(true);
strChange = null;
if (id.getReturnStatus() == InfoDialog.OK) {
savePatterns();
result = APPLY;
}
jButtonSave.setEnabled(isPatternsTableChanged());
}
return result;
}
/**
* Will adjust table column widths based on fontmetrics
*
* @param col Column to be adjusted
* @param text Text string to adjust for
*/
private void adjustTableColumnWidth(int col, String text) {
FontMetrics ourFontMetrics = getFontMetrics(jTablePatterns.getTableHeader().getFont());
jTablePatterns.getColumn(jTablePatterns.getColumnName(col)).setPreferredWidth(ourFontMetrics.stringWidth(text));
}
/**
* @return the return status of this dialog - one of RET_OK or RET_CANCEL
*/
public int getReturnStatus() {
return returnStatus;
}
/**
* 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() {
jButtonSave = new javax.swing.JButton();
jButtonCancel = new javax.swing.JButton();
jComboCountry = new javax.swing.JComboBox<>();
jButtonDeletePattern = new javax.swing.JButton();
jButtonAddPattern = new javax.swing.JButton();
jLabel1 = new javax.swing.JLabel();
jScrollPane1 = new javax.swing.JScrollPane();
jTablePatterns = new javax.swing.JTable();
jLabel17 = new javax.swing.JLabel();
jTextDoNotProxy = new javax.swing.JTextField();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
setTitle("Proxy Pattern Editor");
setIconImage(null);
setResizable(false);
addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(java.awt.event.WindowEvent evt) {
closeDialog(evt);
}
});
jButtonSave.setText(LOCAL.getString("button_save")); // NOI18N
jButtonSave.setEnabled(false);
jButtonSave.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonSaveActionPerformed(evt);
}
});
jButtonCancel.setText(LOCAL.getString("button_close")); // NOI18N
jButtonCancel.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonCancelActionPerformed(evt);
}
});
jComboCountry.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
jComboCountry.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
jComboCountryItemStateChanged(evt);
}
});
jButtonDeletePattern.setText(LOCAL.getString("button_delete")); // NOI18N
jButtonDeletePattern.setEnabled(false);
jButtonDeletePattern.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonDeletePatternActionPerformed(evt);
}
});
jButtonAddPattern.setText(LOCAL.getString("button_addnew")); // NOI18N
jButtonAddPattern.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonAddPatternActionPerformed(evt);
}
});
jLabel1.setText(LOCAL.getString("label_editcountry")); // NOI18N
jTablePatterns.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {
},
new String [] {
}
));
jTablePatterns.setToolTipText(LOCAL.getString("ttip_patterntable")); // NOI18N
jTablePatterns.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_LAST_COLUMN);
jTablePatterns.setSelectionMode(javax.swing.ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
jTablePatterns.getTableHeader().setResizingAllowed(false);
jTablePatterns.getTableHeader().setReorderingAllowed(false);
jTablePatterns.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseReleased(java.awt.event.MouseEvent evt) {
jTablePatternsMouseReleased(evt);
}
});
jTablePatterns.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyReleased(java.awt.event.KeyEvent evt) {
jTablePatternsKeyReleased(evt);
}
});
jScrollPane1.setViewportView(jTablePatterns);
jLabel17.setText(LOCAL.getString("label_donotproxy")); // NOI18N
jTextDoNotProxy.setToolTipText(LOCAL.getString("ttip_donotproxy")); // NOI18N
jTextDoNotProxy.addFocusListener(new java.awt.event.FocusAdapter() {
public void focusLost(java.awt.event.FocusEvent evt) {
jTextDoNotProxyFocusLost(evt);
}
});
jTextDoNotProxy.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyReleased(java.awt.event.KeyEvent evt) {
jTextDoNotProxyKeyReleased(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1)
.addGroup(layout.createSequentialGroup()
.addComponent(jComboCountry, javax.swing.GroupLayout.PREFERRED_SIZE, 264, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel1))
.addGroup(layout.createSequentialGroup()
.addComponent(jButtonDeletePattern)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jButtonAddPattern)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jButtonCancel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jButtonSave))
.addGroup(layout.createSequentialGroup()
.addComponent(jLabel17)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jTextDoNotProxy)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel1)
.addComponent(jComboCountry, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 341, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jTextDoNotProxy, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel17))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jButtonDeletePattern)
.addComponent(jButtonCancel)
.addComponent(jButtonSave)
.addComponent(jButtonAddPattern))
.addContainerGap())
);
pack();
}// </editor-fold>//GEN-END:initComponents
private void jButtonSaveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonSaveActionPerformed
savePatterns();
jButtonSave.setEnabled(isPatternsTableChanged());
doClose(APPLY);
}//GEN-LAST:event_jButtonSaveActionPerformed
private void jButtonCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonCancelActionPerformed
doClose(saveOnExitCheck());
}//GEN-LAST:event_jButtonCancelActionPerformed
/**
* Closes the dialog
*/
private void closeDialog(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_closeDialog
doClose(CANCEL);
}//GEN-LAST:event_closeDialog
private void jComboCountryItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_jComboCountryItemStateChanged
if (evt.getStateChange() != ItemEvent.SELECTED) {
return;
}
saveOnExitCheck();
// Check for no entries
if (jComboCountry.getItemCount() == 0) {
jTablePatterns.setEnabled(false);
jButtonDeletePattern.setEnabled(false);
jButtonAddPattern.setEnabled(false);
jButtonSave.setEnabled(false);
populatePatternsTable(null);
return;
}
// We reach here if we have selected a valid country
jTablePatterns.setEnabled(true);
jButtonAddPattern.setEnabled(true);
strSelectedCountry = (String) jComboCountry.getSelectedItem();
ArrayList<String> patterns = new ArrayList<>();
pacFactory.loadPatternsList(strSelectedCountry, patterns);
populatePatternsTable(patterns);
}//GEN-LAST:event_jComboCountryItemStateChanged
private void jTablePatternsMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jTablePatternsMouseReleased
jButtonDeletePattern.setEnabled(jTablePatterns.isCellEditable(jTablePatterns.getSelectedRow(), 0));
jButtonSave.setEnabled(isPatternsTableChanged());
}//GEN-LAST:event_jTablePatternsMouseReleased
private void jButtonDeletePatternActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonDeletePatternActionPerformed
int[] i;
while (true) {
i = jTablePatterns.getSelectedRows();
if (i.length == 0) {
break;
}
pactm.removeRow(i[0]);
}
jButtonDeletePattern.setEnabled(false);
jButtonSave.setEnabled(isPatternsTableChanged());
}//GEN-LAST:event_jButtonDeletePatternActionPerformed
private void jTablePatternsKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_jTablePatternsKeyReleased
jButtonSave.setEnabled(isPatternsTableChanged());
}//GEN-LAST:event_jTablePatternsKeyReleased
private void jButtonAddPatternActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonAddPatternActionPerformed
QuickAddDialog qad = new QuickAddDialog(parent, true);
qad.setTitle("Add new pattern");
qad.setLocationRelativeTo(this);
qad.setVisible(true);
if (qad.getReturnStatus() == QuickAddDialog.CANCEL) {
return;
}
if (!qad.getPattern().isEmpty()) {
pactm.addRow(new Object[]{qad.getDescription(), qad.getPattern(), Boolean.TRUE}, true);
}
jButtonSave.setEnabled(isPatternsTableChanged());
}//GEN-LAST:event_jButtonAddPatternActionPerformed
private void jTextDoNotProxyKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_jTextDoNotProxyKeyReleased
jButtonSave.setEnabled(isPatternsTableChanged());
}//GEN-LAST:event_jTextDoNotProxyKeyReleased
private void jTextDoNotProxyFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_jTextDoNotProxyFocusLost
jButtonSave.setEnabled(isPatternsTableChanged());
}//GEN-LAST:event_jTextDoNotProxyFocusLost
private void doClose(int retStatus) {
returnStatus = retStatus;
setVisible(false);
dispose();
}
/**
* CustomTableCellRenderer
*/
public class CustomTableCellRenderer extends DefaultTableCellRenderer {
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
Component c = super.getTableCellRendererComponent(table, value,
isSelected, hasFocus, row, column);
// Only for specific cell
if (table.isRowSelected(row)) {
return c;
}
if (column < 2) {
if (table.getModel().isCellEditable(row, column)) {
c.setBackground(javax.swing.UIManager.getDefaults().getColor("Table.background"));
} else {
c.setBackground(javax.swing.UIManager.getDefaults().getColor("control"));
}
}
return c;
}
}
/**
* PACTableModel class
*/
public class PACTableModel extends DefaultTableModel {
@SuppressWarnings("rawtypes")
private final String[] columnNames = {"Description", "Pattern", "Enabled"};
private final Class[] types = new Class[]{
java.lang.String.class, java.lang.String.class, java.lang.Boolean.class
};
private final ArrayList<Boolean> rowedit = new ArrayList<>();
public void addRow(Object[] obj, boolean editable) {
addRow(obj);
rowedit.add(editable);
}
/**
* Constructor
*/
public PACTableModel() {
}
/**
* Get column count as integer
*
* @return columns as integer
*/
@Override
public int getColumnCount() {
return types.length;
}
/**
* Get column class
*
* @param columnIndex
* @return object Class
*/
@Override
@SuppressWarnings("rawtypes")
public Class getColumnClass(int columnIndex) {
return types[columnIndex];
}
/**
* Test if cell at given row, col is editable
*
* @param row
* @param column
* @return True if editable
*/
@Override
public boolean isCellEditable(int row, int column) {
if (column == 2) {
return true;
} else {
return rowedit.get(row);
}
}
/**
* Get column name at given index
*
* @param index
* @return name as string
*/
@Override
public String getColumnName(int index) {
return columnNames[index];
}
/**
* Set the column name at the specified index
*
* @param name
* @param index
*/
public void setColumnName(String name, int index) {
if (index < columnNames.length) {
columnNames[index] = name;
}
}
/**
* Returns all data as a single string
*
* @return string
*/
@Override
public String toString() {
return getDataVector().toString();
}
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton jButtonAddPattern;
private javax.swing.JButton jButtonCancel;
private javax.swing.JButton jButtonDeletePattern;
private javax.swing.JButton jButtonSave;
private javax.swing.JComboBox<String> jComboCountry;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel17;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JTable jTablePatterns;
private javax.swing.JTextField jTextDoNotProxy;
// End of variables declaration//GEN-END:variables
private int returnStatus = CANCEL;
}

635
src/client/PrefsDialog.form Normal file
View file

@ -0,0 +1,635 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.8" maxVersion="1.8" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
<Properties>
<Property name="defaultCloseOperation" type="int" value="2"/>
<Property name="iconImage" type="java.awt.Image" editor="org.netbeans.modules.form.ComponentChooserEditor">
<ComponentRef name="null"/>
</Property>
<Property name="resizable" type="boolean" value="false"/>
</Properties>
<SyntheticProperties>
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
</SyntheticProperties>
<Events>
<EventHandler event="windowClosing" listener="java.awt.event.WindowListener" parameters="java.awt.event.WindowEvent" handler="closeDialog"/>
</Events>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="jButtonDefaults" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<Component id="jButtonCancel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jButtonApply" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
<Component id="jTabPrefs" alignment="0" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="jTabPrefs" max="32767" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jButtonApply" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jButtonCancel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jButtonDefaults" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JTabbedPane" name="jTabPrefs">
<Events>
<EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="jTabPrefsStateChanged"/>
</Events>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="jPanelBasicPrefs">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="true" component="jPanelBasicPrefs" property="font" relativeSize="true" size="0"/>
</FontInfo>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription">
<JTabbedPaneConstraints tabName="Basic">
<Property name="tabTitle" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="tab_basic" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</JTabbedPaneConstraints>
</Constraint>
</Constraints>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="jPanelGeneralPrefs" max="32767" attributes="1"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="jPanelGeneralPrefs" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JPanel" name="jPanelGeneralPrefs">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
<TitledBorder title="General Settings">
<ResourceString PropertyName="titleX" bundle="resources/MessagesBundle.properties" key="panel_general" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
<Connection PropertyName="font" component="jPanelBasicPrefs" name="font" type="property"/>
<Connection PropertyName="color" component="jPanelBasicPrefs" name="foreground" type="property"/>
</TitledBorder>
</Border>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jCheckAutostart" alignment="0" min="-2" max="-2" attributes="3"/>
<Component id="jCheckHideTray" min="-2" max="-2" attributes="3"/>
<Component id="jCheckCacheDelete" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="jCheckHideMin" alignment="0" min="-2" max="-2" attributes="3"/>
<Component id="jCheckDisableNotify" alignment="0" min="-2" max="-2" attributes="3"/>
</Group>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jCheckAppUpdate" min="-2" max="-2" attributes="2"/>
<Component id="jCheckGeoUpdate" alignment="0" min="-2" max="-2" attributes="2"/>
<Component id="jCheckDisableTray" alignment="0" min="-2" max="-2" attributes="3"/>
<Component id="jCheckMinOnClose" min="-2" max="-2" attributes="3"/>
</Group>
<EmptySpace pref="39" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jCheckAutostart" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jCheckGeoUpdate" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jCheckHideTray" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jCheckDisableTray" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jCheckHideMin" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jCheckMinOnClose" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jCheckCacheDelete" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jCheckAppUpdate" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="jCheckDisableNotify" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="132" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JCheckBox" name="jCheckHideTray">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="chkbox_hidetotray" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="ttip_hidetotray" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JCheckBox" name="jCheckAppUpdate">
<Properties>
<Property name="selected" type="boolean" value="true"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="chkbox_checkforupdates" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="ttip_checkforupdates" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JCheckBox" name="jCheckAutostart">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="chkbox_autostart" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="ttip_autostart" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JCheckBox" name="jCheckDisableTray">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="chkbox_disabletray" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="ttip_disabletray" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="jCheckDisableTrayItemStateChanged"/>
</Events>
</Component>
<Component class="javax.swing.JCheckBox" name="jCheckMinOnClose">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="chkbox_minonclose" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="ttip_minonclose" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JCheckBox" name="jCheckCacheDelete">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="chkbox_securedelete" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="ttip_securedelete" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JCheckBox" name="jCheckDisableNotify">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="chkbox_disablenotify" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="ttip_disablenotify" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JCheckBox" name="jCheckHideMin">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="chkbox_hidemin" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="ttip_hidemin" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JCheckBox" name="jCheckGeoUpdate">
<Properties>
<Property name="selected" type="boolean" value="true"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="chkbox_geocheck" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="ttip_geocheck" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="jPanelAdvancedPrefs">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription">
<JTabbedPaneConstraints tabName="Advanced">
<Property name="tabTitle" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="tab_advanced" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</JTabbedPaneConstraints>
</Constraint>
</Constraints>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0">
<Component id="jPanel1" max="32767" attributes="0"/>
<Component id="jPanelTorPrefs" max="32767" attributes="1"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="jPanelTorPrefs" max="32767" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="jPanel1" max="32767" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JPanel" name="jPanelTorPrefs">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
<TitledBorder title="Tor Client Settings">
<ResourceString PropertyName="titleX" bundle="resources/MessagesBundle.properties" key="panel_torclientset" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
<Connection PropertyName="font" component="jPanelBasicPrefs" name="font" type="property"/>
<Connection PropertyName="color" component="jPanelBasicPrefs" name="foreground" type="property"/>
</TitledBorder>
</Border>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jLabel14" alignment="0" min="-2" max="-2" attributes="1"/>
<Component id="jLabel15" alignment="0" min="-2" max="-2" attributes="1"/>
<Component id="jLabel12" alignment="0" min="-2" max="-2" attributes="1"/>
<Component id="jLabel13" alignment="0" min="-2" max="-2" attributes="1"/>
<Component id="jLabel11" alignment="0" min="-2" max="-2" attributes="1"/>
<Component id="jLabel6" alignment="0" min="-2" max="-2" attributes="1"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="jCheckSafeSocks" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="jCheckTestSocks" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="jCheckAvoidDisk" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="jComboLogLev" min="-2" pref="145" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="jCheckSafeLog" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="jTextTorBridge" min="-2" pref="259" max="-2" attributes="1"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jButtonGetBridges" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="jSpinnerMainPort" min="-2" max="-2" attributes="2"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jLabelPortRanges" min="-2" max="-2" attributes="2"/>
</Group>
<Component id="jTextTorArgs" alignment="0" max="32767" attributes="1"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="2" attributes="0">
<Component id="jLabelPortRanges" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="jSpinnerMainPort" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="jLabel6" alignment="2" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel11" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jTextTorBridge" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jButtonGetBridges" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel14" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jCheckSafeSocks" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jCheckTestSocks" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel12" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jComboLogLev" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jCheckSafeLog" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel15" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jCheckAvoidDisk" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel13" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jTextTorArgs" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="jLabel6">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="label_listenport" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JSpinner" name="jSpinnerMainPort">
<Properties>
<Property name="model" type="javax.swing.SpinnerModel" editor="org.netbeans.modules.form.editors2.SpinnerModelEditor">
<SpinnerModel initial="9054" maximum="9999" minimum="9054" numberType="java.lang.Integer" stepSize="1" type="number"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="ttip_listenport" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabelPortRanges">
<Properties>
<Property name="text" type="java.lang.String" value="Currently active port ranges, 9052 to 9063"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel11">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="label_bridgeaddress" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="jTextTorBridge">
<Properties>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="ttip_bridgeaddress" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="jButtonGetBridges">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="button_getbridges" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButtonGetBridgesActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JCheckBox" name="jCheckSafeSocks">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="chkbox_safesocks" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="ttip_safesocks" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel12">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="label_torlogging" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JCheckBox" name="jCheckTestSocks">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="chkbox_testsocks" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="ttip_testsocks" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel13">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="label_torargs" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="jTextTorArgs">
<Properties>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="ttip_extraargs" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel14">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="label_torsocks" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JCheckBox" name="jCheckAvoidDisk">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="chkbox_diskavoid" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="ttip_avoiddisk" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel15">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="label_diskoptions" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JComboBox" name="jComboLogLev">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="new DefaultComboBoxModel&lt;&gt;(new String[] {LOCAL.getString(&quot;combo_loglev1&quot;),LOCAL.getString(&quot;combo_loglev2&quot;),LOCAL.getString(&quot;combo_loglev3&quot;)})" type="code"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="ttip_combo_loglevel" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new javax.swing.JComboBox&lt;&gt;()"/>
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="&lt;String&gt;"/>
</AuxValues>
</Component>
<Component class="javax.swing.JCheckBox" name="jCheckSafeLog">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="chkbox_safelog" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="ttip_safelogging" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="jPanel1">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
<TitledBorder title="Network Settings">
<ResourceString PropertyName="titleX" bundle="resources/MessagesBundle.properties" key="panel_network" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
<Connection PropertyName="font" component="jPanelBasicPrefs" name="font" type="property"/>
<Connection PropertyName="color" component="jPanelBasicPrefs" name="foreground" type="property"/>
</TitledBorder>
</Border>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="jLabel16" min="-2" max="-2" attributes="1"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jTextHTTPProxy" max="32767" attributes="1"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel16" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jTextHTTPProxy" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="jLabel16">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="label_defaultproxy" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="jTextHTTPProxy">
<Properties>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="ttip_defaultproxy" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Container>
</SubComponents>
</Container>
<Component class="javax.swing.JButton" name="jButtonCancel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="button_close" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButtonCancelActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="jButtonApply">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="button_apply" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButtonApplyActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="jButtonDefaults">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="button_prefdefaults" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButtonDefaultsActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Form>

608
src/client/PrefsDialog.java Normal file
View file

@ -0,0 +1,608 @@
/*
* 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 javax.swing.DefaultComboBoxModel;
import lib.Localisation;
import lib.SimpleProps;
import lib.Utilities;
/**
*
* @author Alistair Neil, <info@dazzleships.net>
*/
public final class PrefsDialog extends javax.swing.JDialog {
public static final int CANCEL = 0;
public static final int APPLY = 1;
public static final int RESET = 2;
private static final Localisation LOCAL = new Localisation("resources/MessagesBundle");
private final SimpleProps sp;
private final String disabledprefs;
/**
* Creates a preferences editor dialog
*
* @param parent Parent Frame
* @param sp
* @param disabledprefs
*/
public PrefsDialog(java.awt.Frame parent, SimpleProps sp, String disabledprefs) {
super(parent, true);
this.sp = sp;
this.disabledprefs = disabledprefs;
initComponents();
loadBasicPrefs(false);
loadAdvancedPrefs(false);
}
/**
* @return the return status of this dialog - one of RET_OK or RET_CANCEL
*/
public int getReturnStatus() {
return returnStatus;
}
public void loadBasicPrefs(boolean usedefault) {
sp.setDefaultModeEnabled(usedefault);
jCheckAutostart.setSelected(sp.getBool("PREF_AUTOSTART"));
jCheckDisableTray.setSelected(sp.getBool("PREF_NOSYSTRAY"));
jCheckHideMin.setEnabled(!jCheckDisableTray.isSelected());
jCheckHideTray.setSelected(sp.getBool("PREF_HIDETOTRAY"));
jCheckAppUpdate.setSelected(sp.getBool("PREF_UPDATECHECK"));
jCheckMinOnClose.setSelected(sp.getBool("PREF_MINONCLOSE"));
jCheckCacheDelete.setSelected(sp.getBool("PREF_CACHEDELETE"));
jCheckDisableNotify.setSelected(sp.getBool("PREF_DISABLE_NOTIFY"));
jCheckHideMin.setSelected(sp.getBool("PREF_HIDE_MIN"));
jCheckGeoUpdate.setSelected(sp.getBool("PREF_GEOCHECK"));
if (disabledprefs.contains("jCheckDisableTray")) {
jCheckDisableTray.setEnabled(false);
jCheckHideMin.setEnabled(false);
}
jCheckAppUpdate.setVisible(!disabledprefs.contains("jCheckAppUpdate"));
sp.setDefaultModeEnabled(false);
updatePortRanges(sp.getInt("PREF_TOR_TESTHREADS"));
}
/**
* Load the preferences
*
* @param usedefault
*/
public void loadAdvancedPrefs(boolean usedefault) {
sp.setDefaultModeEnabled(usedefault);
jTextHTTPProxy.setText(sp.getString("PREF_HTTP_PROXY"));
jSpinnerMainPort.setValue(sp.getInt("PREF_LISTENPORT"));
jTextTorBridge.setText(sp.getString("PREF_TORBRIDGE"));
jTextTorArgs.setText(sp.getString("PREF_TORARGS"));
jComboLogLev.setSelectedIndex(sp.getInt("PREF_TORLOGLEV"));
jCheckSafeSocks.setSelected(sp.getBool("PREF_SAFESOCKS"));
jCheckTestSocks.setSelected(sp.getBool("PREF_TESTSOCKS"));
jCheckAvoidDisk.setSelected(sp.getBool("PREF_AVOIDDISK"));
jCheckSafeLog.setSelected(sp.getBool("PREF_SAFELOG"));
sp.setDefaultModeEnabled(false);
}
/**
* Save preferences
*/
public void savePreferences() {
sp.setInt("PREF_LISTENPORT", (Integer) jSpinnerMainPort.getValue());
sp.setInt("PREF_TORLOGLEV", jComboLogLev.getSelectedIndex());
sp.setBool("PREF_AUTOSTART", jCheckAutostart.isSelected());
sp.setBool("PREF_NOSYSTRAY", jCheckDisableTray.isSelected());
sp.setBool("PREF_HIDETOTRAY", jCheckHideTray.isSelected());
sp.setBool("PREF_UPDATECHECK", jCheckAppUpdate.isSelected());
sp.setBool("PREF_MINONCLOSE", jCheckMinOnClose.isSelected());
sp.setBool("PREF_SAFESOCKS", jCheckSafeSocks.isSelected());
sp.setBool("PREF_TESTSOCKS", jCheckTestSocks.isSelected());
sp.setBool("PREF_AVOIDDISK", jCheckAvoidDisk.isSelected());
sp.setBool("PREF_SAFELOG", jCheckSafeLog.isSelected());
sp.setBool("PREF_CACHEDELETE", jCheckCacheDelete.isSelected());
sp.setBool("PREF_DISABLE_NOTIFY", jCheckDisableNotify.isSelected());
sp.setBool("PREF_HIDE_MIN", jCheckHideMin.isSelected());
sp.setBool("PREF_GEOCHECK", jCheckGeoUpdate.isSelected());
sp.setString("PREF_HTTP_PROXY", jTextHTTPProxy.getText());
sp.setString("PREF_TORBRIDGE", jTextTorBridge.getText());
sp.setString("PREF_TORARGS", jTextTorArgs.getText());
}
/**
* Update displayed port ranges to reflect any port changes
*/
private void updatePortRanges(int threads) {
int intBasePort = sp.getInt("PREF_LISTENPORT");
String strRanges = LOCAL.getString("label_portranges");
strRanges = strRanges.replace("$portmin", String.valueOf(intBasePort));
strRanges = strRanges.replace("$portmax", String.valueOf(intBasePort + (threads * 2) + 1));
jLabelPortRanges.setText(strRanges);
}
/**
* 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() {
jTabPrefs = new javax.swing.JTabbedPane();
jPanelBasicPrefs = new javax.swing.JPanel();
jPanelGeneralPrefs = new javax.swing.JPanel();
jCheckHideTray = new javax.swing.JCheckBox();
jCheckAppUpdate = new javax.swing.JCheckBox();
jCheckAutostart = new javax.swing.JCheckBox();
jCheckDisableTray = new javax.swing.JCheckBox();
jCheckMinOnClose = new javax.swing.JCheckBox();
jCheckCacheDelete = new javax.swing.JCheckBox();
jCheckDisableNotify = new javax.swing.JCheckBox();
jCheckHideMin = new javax.swing.JCheckBox();
jCheckGeoUpdate = new javax.swing.JCheckBox();
jPanelAdvancedPrefs = new javax.swing.JPanel();
jPanelTorPrefs = new javax.swing.JPanel();
jLabel6 = new javax.swing.JLabel();
jSpinnerMainPort = new javax.swing.JSpinner();
jLabelPortRanges = new javax.swing.JLabel();
jLabel11 = new javax.swing.JLabel();
jTextTorBridge = new javax.swing.JTextField();
jButtonGetBridges = new javax.swing.JButton();
jCheckSafeSocks = new javax.swing.JCheckBox();
jLabel12 = new javax.swing.JLabel();
jCheckTestSocks = new javax.swing.JCheckBox();
jLabel13 = new javax.swing.JLabel();
jTextTorArgs = new javax.swing.JTextField();
jLabel14 = new javax.swing.JLabel();
jCheckAvoidDisk = new javax.swing.JCheckBox();
jLabel15 = new javax.swing.JLabel();
jComboLogLev = new javax.swing.JComboBox<>();
jCheckSafeLog = new javax.swing.JCheckBox();
jPanel1 = new javax.swing.JPanel();
jLabel16 = new javax.swing.JLabel();
jTextHTTPProxy = new javax.swing.JTextField();
jButtonCancel = new javax.swing.JButton();
jButtonApply = new javax.swing.JButton();
jButtonDefaults = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
setIconImage(null);
setResizable(false);
addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(java.awt.event.WindowEvent evt) {
closeDialog(evt);
}
});
jTabPrefs.addChangeListener(new javax.swing.event.ChangeListener() {
public void stateChanged(javax.swing.event.ChangeEvent evt) {
jTabPrefsStateChanged(evt);
}
});
jPanelBasicPrefs.setFont(jPanelBasicPrefs.getFont().deriveFont(jPanelBasicPrefs.getFont().getStyle() | java.awt.Font.BOLD));
jPanelGeneralPrefs.setBorder(javax.swing.BorderFactory.createTitledBorder(null, LOCAL.getString("panel_general"), javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, jPanelBasicPrefs.getFont(), jPanelBasicPrefs.getForeground())); // NOI18N
jCheckHideTray.setText(LOCAL.getString("chkbox_hidetotray")); // NOI18N
jCheckHideTray.setToolTipText(LOCAL.getString("ttip_hidetotray")); // NOI18N
jCheckAppUpdate.setSelected(true);
jCheckAppUpdate.setText(LOCAL.getString("chkbox_checkforupdates")); // NOI18N
jCheckAppUpdate.setToolTipText(LOCAL.getString("ttip_checkforupdates")); // NOI18N
jCheckAutostart.setText(LOCAL.getString("chkbox_autostart")); // NOI18N
jCheckAutostart.setToolTipText(LOCAL.getString("ttip_autostart")); // NOI18N
jCheckDisableTray.setText(LOCAL.getString("chkbox_disabletray")); // NOI18N
jCheckDisableTray.setToolTipText(LOCAL.getString("ttip_disabletray")); // NOI18N
jCheckDisableTray.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
jCheckDisableTrayItemStateChanged(evt);
}
});
jCheckMinOnClose.setText(LOCAL.getString("chkbox_minonclose")); // NOI18N
jCheckMinOnClose.setToolTipText(LOCAL.getString("ttip_minonclose")); // NOI18N
jCheckCacheDelete.setText(LOCAL.getString("chkbox_securedelete")); // NOI18N
jCheckCacheDelete.setToolTipText(LOCAL.getString("ttip_securedelete")); // NOI18N
jCheckDisableNotify.setText(LOCAL.getString("chkbox_disablenotify")); // NOI18N
jCheckDisableNotify.setToolTipText(LOCAL.getString("ttip_disablenotify")); // NOI18N
jCheckHideMin.setText(LOCAL.getString("chkbox_hidemin")); // NOI18N
jCheckHideMin.setToolTipText(LOCAL.getString("ttip_hidemin")); // NOI18N
jCheckGeoUpdate.setSelected(true);
jCheckGeoUpdate.setText(LOCAL.getString("chkbox_geocheck")); // NOI18N
jCheckGeoUpdate.setToolTipText(LOCAL.getString("ttip_geocheck")); // NOI18N
javax.swing.GroupLayout jPanelGeneralPrefsLayout = new javax.swing.GroupLayout(jPanelGeneralPrefs);
jPanelGeneralPrefs.setLayout(jPanelGeneralPrefsLayout);
jPanelGeneralPrefsLayout.setHorizontalGroup(
jPanelGeneralPrefsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanelGeneralPrefsLayout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanelGeneralPrefsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jCheckAutostart)
.addComponent(jCheckHideTray)
.addComponent(jCheckCacheDelete)
.addComponent(jCheckHideMin)
.addComponent(jCheckDisableNotify))
.addGap(18, 18, 18)
.addGroup(jPanelGeneralPrefsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jCheckAppUpdate)
.addComponent(jCheckGeoUpdate)
.addComponent(jCheckDisableTray)
.addComponent(jCheckMinOnClose))
.addContainerGap(39, Short.MAX_VALUE))
);
jPanelGeneralPrefsLayout.setVerticalGroup(
jPanelGeneralPrefsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanelGeneralPrefsLayout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanelGeneralPrefsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jCheckAutostart)
.addComponent(jCheckGeoUpdate))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanelGeneralPrefsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jCheckHideTray)
.addComponent(jCheckDisableTray))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanelGeneralPrefsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jCheckHideMin)
.addComponent(jCheckMinOnClose))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanelGeneralPrefsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jCheckCacheDelete)
.addComponent(jCheckAppUpdate))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jCheckDisableNotify)
.addContainerGap(132, Short.MAX_VALUE))
);
javax.swing.GroupLayout jPanelBasicPrefsLayout = new javax.swing.GroupLayout(jPanelBasicPrefs);
jPanelBasicPrefs.setLayout(jPanelBasicPrefsLayout);
jPanelBasicPrefsLayout.setHorizontalGroup(
jPanelBasicPrefsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanelBasicPrefsLayout.createSequentialGroup()
.addContainerGap()
.addComponent(jPanelGeneralPrefs, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addContainerGap())
);
jPanelBasicPrefsLayout.setVerticalGroup(
jPanelBasicPrefsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanelBasicPrefsLayout.createSequentialGroup()
.addContainerGap()
.addComponent(jPanelGeneralPrefs, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addContainerGap())
);
jTabPrefs.addTab(LOCAL.getString("tab_basic"), jPanelBasicPrefs); // NOI18N
jPanelTorPrefs.setBorder(javax.swing.BorderFactory.createTitledBorder(null, LOCAL.getString("panel_torclientset"), javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, jPanelBasicPrefs.getFont(), jPanelBasicPrefs.getForeground())); // NOI18N
jLabel6.setText(LOCAL.getString("label_listenport")); // NOI18N
jSpinnerMainPort.setModel(new javax.swing.SpinnerNumberModel(9050, 9050, 9999, 1));
jSpinnerMainPort.setToolTipText(LOCAL.getString("ttip_listenport")); // NOI18N
jLabelPortRanges.setText("Currently active port ranges, 9052 to 9063");
jLabel11.setText(LOCAL.getString("label_bridgeaddress")); // NOI18N
jTextTorBridge.setToolTipText(LOCAL.getString("ttip_bridgeaddress")); // NOI18N
jButtonGetBridges.setText(LOCAL.getString("button_getbridges")); // NOI18N
jButtonGetBridges.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonGetBridgesActionPerformed(evt);
}
});
jCheckSafeSocks.setText(LOCAL.getString("chkbox_safesocks")); // NOI18N
jCheckSafeSocks.setToolTipText(LOCAL.getString("ttip_safesocks")); // NOI18N
jLabel12.setText(LOCAL.getString("label_torlogging")); // NOI18N
jCheckTestSocks.setText(LOCAL.getString("chkbox_testsocks")); // NOI18N
jCheckTestSocks.setToolTipText(LOCAL.getString("ttip_testsocks")); // NOI18N
jLabel13.setText(LOCAL.getString("label_torargs")); // NOI18N
jTextTorArgs.setToolTipText(LOCAL.getString("ttip_extraargs")); // NOI18N
jLabel14.setText(LOCAL.getString("label_torsocks")); // NOI18N
jCheckAvoidDisk.setText(LOCAL.getString("chkbox_diskavoid")); // NOI18N
jCheckAvoidDisk.setToolTipText(LOCAL.getString("ttip_avoiddisk")); // NOI18N
jLabel15.setText(LOCAL.getString("label_diskoptions")); // NOI18N
jComboLogLev.setModel(new DefaultComboBoxModel<>(new String[] {LOCAL.getString("combo_loglev1"),LOCAL.getString("combo_loglev2"),LOCAL.getString("combo_loglev3")}));
jComboLogLev.setToolTipText(LOCAL.getString("ttip_combo_loglevel")); // NOI18N
jCheckSafeLog.setText(LOCAL.getString("chkbox_safelog")); // NOI18N
jCheckSafeLog.setToolTipText(LOCAL.getString("ttip_safelogging")); // NOI18N
javax.swing.GroupLayout jPanelTorPrefsLayout = new javax.swing.GroupLayout(jPanelTorPrefs);
jPanelTorPrefs.setLayout(jPanelTorPrefsLayout);
jPanelTorPrefsLayout.setHorizontalGroup(
jPanelTorPrefsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanelTorPrefsLayout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanelTorPrefsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel14)
.addComponent(jLabel15)
.addComponent(jLabel12)
.addComponent(jLabel13)
.addComponent(jLabel11)
.addComponent(jLabel6))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanelTorPrefsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addGroup(jPanelTorPrefsLayout.createSequentialGroup()
.addComponent(jCheckSafeSocks)
.addGap(18, 18, 18)
.addComponent(jCheckTestSocks))
.addComponent(jCheckAvoidDisk)
.addGroup(jPanelTorPrefsLayout.createSequentialGroup()
.addComponent(jComboLogLev, javax.swing.GroupLayout.PREFERRED_SIZE, 145, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(jCheckSafeLog))
.addGroup(jPanelTorPrefsLayout.createSequentialGroup()
.addComponent(jTextTorBridge, javax.swing.GroupLayout.PREFERRED_SIZE, 259, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jButtonGetBridges))
.addGroup(jPanelTorPrefsLayout.createSequentialGroup()
.addComponent(jSpinnerMainPort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabelPortRanges))
.addComponent(jTextTorArgs))
.addContainerGap())
);
jPanelTorPrefsLayout.setVerticalGroup(
jPanelTorPrefsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanelTorPrefsLayout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanelTorPrefsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
.addComponent(jLabelPortRanges)
.addComponent(jSpinnerMainPort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel6))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanelTorPrefsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel11)
.addComponent(jTextTorBridge, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jButtonGetBridges))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanelTorPrefsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel14)
.addComponent(jCheckSafeSocks)
.addComponent(jCheckTestSocks))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanelTorPrefsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel12)
.addComponent(jComboLogLev, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jCheckSafeLog))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(jPanelTorPrefsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel15)
.addComponent(jCheckAvoidDisk))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(jPanelTorPrefsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel13)
.addComponent(jTextTorArgs, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap())
);
jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder(null, LOCAL.getString("panel_network"), javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, jPanelBasicPrefs.getFont(), jPanelBasicPrefs.getForeground())); // NOI18N
jLabel16.setText(LOCAL.getString("label_defaultproxy")); // NOI18N
jTextHTTPProxy.setToolTipText(LOCAL.getString("ttip_defaultproxy")); // NOI18N
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addComponent(jLabel16)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jTextHTTPProxy)
.addContainerGap())
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel16)
.addComponent(jTextHTTPProxy, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap())
);
javax.swing.GroupLayout jPanelAdvancedPrefsLayout = new javax.swing.GroupLayout(jPanelAdvancedPrefs);
jPanelAdvancedPrefs.setLayout(jPanelAdvancedPrefsLayout);
jPanelAdvancedPrefsLayout.setHorizontalGroup(
jPanelAdvancedPrefsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanelAdvancedPrefsLayout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanelAdvancedPrefsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jPanelTorPrefs, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap())
);
jPanelAdvancedPrefsLayout.setVerticalGroup(
jPanelAdvancedPrefsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanelAdvancedPrefsLayout.createSequentialGroup()
.addContainerGap()
.addComponent(jPanelTorPrefs, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addContainerGap())
);
jTabPrefs.addTab(LOCAL.getString("tab_advanced"), jPanelAdvancedPrefs); // NOI18N
jButtonCancel.setText(LOCAL.getString("button_close")); // NOI18N
jButtonCancel.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonCancelActionPerformed(evt);
}
});
jButtonApply.setText(LOCAL.getString("button_apply")); // NOI18N
jButtonApply.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonApplyActionPerformed(evt);
}
});
jButtonDefaults.setText(LOCAL.getString("button_prefdefaults")); // NOI18N
jButtonDefaults.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonDefaultsActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jButtonDefaults)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jButtonCancel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jButtonApply)
.addContainerGap())
.addComponent(jTabPrefs)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jTabPrefs)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jButtonApply)
.addComponent(jButtonCancel)
.addComponent(jButtonDefaults))
.addContainerGap())
);
pack();
}// </editor-fold>//GEN-END:initComponents
private void jButtonApplyActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonApplyActionPerformed
savePreferences();
updatePortRanges(sp.getInt("PREF_TOR_TESTHREADS"));
doClose(APPLY);
}//GEN-LAST:event_jButtonApplyActionPerformed
private void jButtonCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonCancelActionPerformed
doClose(CANCEL);
}//GEN-LAST:event_jButtonCancelActionPerformed
/**
* Closes the dialog
*/
private void closeDialog(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_closeDialog
doClose(CANCEL);
}//GEN-LAST:event_closeDialog
private void jButtonGetBridgesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonGetBridgesActionPerformed
Utilities.openFileExternally("https://bridges.torproject.org/bridges?lang="
+ LOCAL.toWebLanguageTag());
}//GEN-LAST:event_jButtonGetBridgesActionPerformed
private void jButtonDefaultsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonDefaultsActionPerformed
switch (jTabPrefs.getSelectedIndex()) {
// Basic tab
case 0:
loadBasicPrefs(true);
break;
// Advanced tab
case 1:
loadAdvancedPrefs(true);
break;
}
}//GEN-LAST:event_jButtonDefaultsActionPerformed
private void jTabPrefsStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_jTabPrefsStateChanged
switch (jTabPrefs.getSelectedIndex()) {
case 0:
jButtonDefaults.setToolTipText(LOCAL.getString("ttip_resetbasicprefs"));
break;
case 1:
jButtonDefaults.setToolTipText(LOCAL.getString("ttip_resetadvprefs"));
break;
}
}//GEN-LAST:event_jTabPrefsStateChanged
private void jCheckDisableTrayItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_jCheckDisableTrayItemStateChanged
jCheckHideMin.setEnabled(!jCheckDisableTray.isSelected());
}//GEN-LAST:event_jCheckDisableTrayItemStateChanged
private void doClose(int retStatus) {
returnStatus = retStatus;
setVisible(false);
dispose();
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton jButtonApply;
private javax.swing.JButton jButtonCancel;
private javax.swing.JButton jButtonDefaults;
private javax.swing.JButton jButtonGetBridges;
private javax.swing.JCheckBox jCheckAppUpdate;
private javax.swing.JCheckBox jCheckAutostart;
private javax.swing.JCheckBox jCheckAvoidDisk;
private javax.swing.JCheckBox jCheckCacheDelete;
private javax.swing.JCheckBox jCheckDisableNotify;
private javax.swing.JCheckBox jCheckDisableTray;
private javax.swing.JCheckBox jCheckGeoUpdate;
private javax.swing.JCheckBox jCheckHideMin;
private javax.swing.JCheckBox jCheckHideTray;
private javax.swing.JCheckBox jCheckMinOnClose;
private javax.swing.JCheckBox jCheckSafeLog;
private javax.swing.JCheckBox jCheckSafeSocks;
private javax.swing.JCheckBox jCheckTestSocks;
private javax.swing.JComboBox<String> jComboLogLev;
private javax.swing.JLabel jLabel11;
private javax.swing.JLabel jLabel12;
private javax.swing.JLabel jLabel13;
private javax.swing.JLabel jLabel14;
private javax.swing.JLabel jLabel15;
private javax.swing.JLabel jLabel16;
private javax.swing.JLabel jLabel6;
private javax.swing.JLabel jLabelPortRanges;
private javax.swing.JPanel jPanel1;
private javax.swing.JPanel jPanelAdvancedPrefs;
private javax.swing.JPanel jPanelBasicPrefs;
private javax.swing.JPanel jPanelGeneralPrefs;
private javax.swing.JPanel jPanelTorPrefs;
private javax.swing.JSpinner jSpinnerMainPort;
private javax.swing.JTabbedPane jTabPrefs;
private javax.swing.JTextField jTextHTTPProxy;
private javax.swing.JTextField jTextTorArgs;
private javax.swing.JTextField jTextTorBridge;
// End of variables declaration//GEN-END:variables
private int returnStatus = CANCEL;
}

View file

@ -0,0 +1,138 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.6" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
<Properties>
<Property name="defaultCloseOperation" type="int" value="2"/>
<Property name="title" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="dlg_quickadd_title" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
<Property name="iconImage" type="java.awt.Image" editor="org.netbeans.modules.form.ComponentChooserEditor">
<ComponentRef name="null"/>
</Property>
<Property name="resizable" type="boolean" value="false"/>
</Properties>
<SyntheticProperties>
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
</SyntheticProperties>
<Events>
<EventHandler event="windowClosing" listener="java.awt.event.WindowListener" parameters="java.awt.event.WindowEvent" handler="closeDialog"/>
</Events>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jPanelPreferences" alignment="0" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jPanelPreferences" min="-2" max="-2" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JPanel" name="jPanelPreferences">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="true" component="jPanelPreferences" property="font" relativeSize="true" size="0"/>
</FontInfo>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jLabel1" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="jTextDescription" alignment="1" pref="343" max="32767" attributes="1"/>
<Component id="jLabel2" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="jTextPattern" alignment="0" pref="343" max="32767" attributes="1"/>
<Group type="102" alignment="1" attributes="0">
<Component id="jButtonCancel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jButtonApply" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
<Component id="jTextDescription" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jLabel2" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
<Component id="jTextPattern" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jButtonApply" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jButtonCancel" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="jLabel1">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="label_quickadd_desc" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="jTextDescription">
</Component>
<Component class="javax.swing.JLabel" name="jLabel2">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="label_quickadd_pattern" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="jTextPattern">
</Component>
<Component class="javax.swing.JButton" name="jButtonCancel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="button_cancel" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButtonCancelActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="jButtonApply">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="button_addnew" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButtonApplyActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Form>

View file

@ -0,0 +1,214 @@
/*
* 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 lib.Localisation;
/**
*
* @author Alistair Neil, <info@dazzleships.net>
*/
public final class QuickAddDialog extends javax.swing.JDialog {
private static final Localisation LOCAL = new Localisation("resources/MessagesBundle");
public static final int CANCEL = 0;
public static final int APPLY = 1;
public static final int RESET = 2;
/**
* Creates a quick add patterns dialog
*
* @param parent parent frame
* @param modal modality
*/
public QuickAddDialog(java.awt.Frame parent, boolean modal) {
super(parent, modal);
initComponents();
}
/**
* Set text that appears on the Apply button
*
* @param text
*/
public void setApplyText(String text) {
jButtonApply.setText(text);
}
/**
* Set the test that appears in both fields
*
* @param desc
* @param pattern
*/
public void setFields(String desc, String pattern) {
jTextDescription.setText(desc);
jTextPattern.setText(pattern);
}
/**
* Get contents of description field
*
* @return String text
*/
public String getDescription() {
return jTextDescription.getText();
}
/**
* Get contents of the pattern field
*
* @return String text
*/
public String getPattern() {
return jTextPattern.getText();
}
/**
* @return the return status of this dialog - one of RET_OK or RET_CANCEL
*/
public int getReturnStatus() {
return returnStatus;
}
/**
* 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() {
jPanelPreferences = new javax.swing.JPanel();
jLabel1 = new javax.swing.JLabel();
jTextDescription = new javax.swing.JTextField();
jLabel2 = new javax.swing.JLabel();
jTextPattern = new javax.swing.JTextField();
jButtonCancel = new javax.swing.JButton();
jButtonApply = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
setTitle(LOCAL.getString("dlg_quickadd_title")); // NOI18N
setIconImage(null);
setResizable(false);
addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(java.awt.event.WindowEvent evt) {
closeDialog(evt);
}
});
jPanelPreferences.setFont(jPanelPreferences.getFont().deriveFont(jPanelPreferences.getFont().getStyle() | java.awt.Font.BOLD));
jLabel1.setText(LOCAL.getString("label_quickadd_desc")); // NOI18N
jLabel2.setText(LOCAL.getString("label_quickadd_pattern")); // NOI18N
jButtonCancel.setText(LOCAL.getString("button_cancel")); // NOI18N
jButtonCancel.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonCancelActionPerformed(evt);
}
});
jButtonApply.setText(LOCAL.getString("button_addnew")); // NOI18N
jButtonApply.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonApplyActionPerformed(evt);
}
});
javax.swing.GroupLayout jPanelPreferencesLayout = new javax.swing.GroupLayout(jPanelPreferences);
jPanelPreferences.setLayout(jPanelPreferencesLayout);
jPanelPreferencesLayout.setHorizontalGroup(
jPanelPreferencesLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanelPreferencesLayout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanelPreferencesLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel1)
.addComponent(jTextDescription, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 343, Short.MAX_VALUE)
.addComponent(jLabel2)
.addComponent(jTextPattern, javax.swing.GroupLayout.DEFAULT_SIZE, 343, Short.MAX_VALUE)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanelPreferencesLayout.createSequentialGroup()
.addComponent(jButtonCancel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jButtonApply)))
.addContainerGap())
);
jPanelPreferencesLayout.setVerticalGroup(
jPanelPreferencesLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanelPreferencesLayout.createSequentialGroup()
.addContainerGap()
.addComponent(jLabel1)
.addGap(0, 0, 0)
.addComponent(jTextDescription, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel2)
.addGap(0, 0, 0)
.addComponent(jTextPattern, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanelPreferencesLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jButtonApply)
.addComponent(jButtonCancel))
.addContainerGap())
);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanelPreferences, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanelPreferences, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
);
pack();
}// </editor-fold>//GEN-END:initComponents
private void jButtonApplyActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonApplyActionPerformed
doClose(APPLY);
}//GEN-LAST:event_jButtonApplyActionPerformed
private void jButtonCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonCancelActionPerformed
doClose(CANCEL);
}//GEN-LAST:event_jButtonCancelActionPerformed
/**
* Closes the dialog
*/
private void closeDialog(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_closeDialog
doClose(CANCEL);
}//GEN-LAST:event_closeDialog
private void doClose(int retStatus) {
returnStatus = retStatus;
setVisible(false);
dispose();
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton jButtonApply;
private javax.swing.JButton jButtonCancel;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JPanel jPanelPreferences;
private javax.swing.JTextField jTextDescription;
private javax.swing.JTextField jTextPattern;
// End of variables declaration//GEN-END:variables
private int returnStatus = CANCEL;
}

1018
src/client/SelekTOR.form Normal file

File diff suppressed because it is too large Load diff

3595
src/client/SelekTOR.java Normal file

File diff suppressed because it is too large Load diff

236
src/client/TorCircuit.java Normal file
View file

@ -0,0 +1,236 @@
/*
* 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.util.regex.Pattern;
/**
*
* @author Alistair Neil <info@dazzleships.net>
*/
public final class TorCircuit {
public static final int FINGER = 0;
public static final int NICKNAME = 1;
private String[] dataCirc;
private String[] dataHops;
private String circuitinfo;
/**
* Constructor
*/
public TorCircuit() {
}
/**
* Constructor, Create circuit object with given circuit
*
* @param circuit
*/
public TorCircuit(String circuit) {
setCircuit(circuit);
}
/**
* Set circuit to supplied circuit
*
* @param circuit
*/
public void setCircuit(String circuit) {
circuitinfo = circuit;
Pattern pattern = Pattern.compile(" ");
dataCirc = pattern.split(circuit);
setHops(dataCirc[2]);
}
/**
* Get circuit
*
* @return circuit as string
*/
public String getCircuit() {
return circuitinfo;
}
/**
* Set hops
*
* @param hops
*/
public void setHops(String hops) {
Pattern pattern = Pattern.compile(",");
dataHops = pattern.split(hops);
}
/**
* Get current circuit ID
*
* @return ID as string
*/
public String getID() {
return dataCirc[0];
}
/**
* Get current circuit status
*
* @return status as string
*/
public String getStatus() {
return dataCirc[1];
}
/**
* Get current circuits build flags
*
* @return build flags as string
*/
public String getBuildFlags() {
return dataCirc[3].substring(12);
}
/**
* Get current circuits purpose
*
* @return purpose as string
*/
public String getPurpose() {
return dataCirc[4].substring(8);
}
/**
* Get current circuits timestamp
*
* @return timestamp as string
*/
public String getTimestamp() {
return dataCirc[5].substring(13);
}
/**
* Get circuit hops
*
* @return circuit hops as string
*/
public String getHops() {
return dataCirc[2];
}
/**
* Get current circuits guard or entry node
*
* @return guard node as string
*/
public String getGuardHop() {
String result = null;
try {
result = dataHops[0];
} catch (Exception ex) {
}
return result;
}
/**
* Get current circuits middle node if any, returns exit node for a two hop
* circuit
*
* @return middleman node as string
*/
public String getMiddleHop() {
String result = null;
try {
if (dataHops.length < 3) {
result = "";
} else {
result = dataHops[1];
}
} catch (Exception ex) {
}
return result;
}
/**
* Get current circuits exit node
*
* @return exit node as string
*/
public String getExitHop() {
String result = null;
try {
result = dataHops[dataHops.length - 1];
} catch (Exception ex) {
}
return result;
}
/**
* Get Guardnode finger or nick
*
* @param type 0 = finger, 1 = nick
* @return fingerprint as string
*/
public String getGuard(int type) {
return getFromNodeHop(getGuardHop(), type);
}
/**
* Get Middleman
*
* @param type 0 = finger, 1 = nick
* @return fingerprint as string
*/
public String getMiddleMan(int type) {
return getFromNodeHop(getMiddleHop(), type);
}
/**
* Get Exitnode
*
* @param type 0 = finger, 1 = nick
* @return fingerprint as string
*/
public String getExit(int type) {
return getFromNodeHop(getExitHop(), type);
}
/**
* Get fingerprint of given node Nodeinfo is in the format of
* fingerprint~name or fingerprint=name
*
* @param nodeinfo
* @param type 0 = finger, 1 = nickname
* @return fingerprint as string
*/
public static String getFromNodeHop(String nodeinfo, int type) {
Pattern pattern;
try {
if (nodeinfo.contains("~")) {
pattern = Pattern.compile("~");
} else {
pattern = Pattern.compile("=");
}
String[] result = pattern.split(nodeinfo);
if (result.length > 0) {
return result[type];
}
} catch (Exception ex) {
}
return null;
}
}

File diff suppressed because it is too large Load diff

195
src/client/TorMonFrame.form Normal file
View file

@ -0,0 +1,195 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JFrameFormInfo">
<Properties>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[554, 492]"/>
</Property>
</Properties>
<SyntheticProperties>
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
</SyntheticProperties>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jPanelMain" alignment="0" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jPanelMain" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JPanel" name="jPanelMain">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="true" component="jPanelMain" property="font" relativeSize="true" size="0"/>
</FontInfo>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jPanel1" alignment="0" max="32767" attributes="0"/>
<Component id="jPanel2" alignment="0" max="32767" attributes="0"/>
<Group type="102" alignment="1" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
<Component id="jButtonClose" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="jPanel1" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jPanel2" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jButtonClose" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JPanel" name="jPanel1">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
<TitledBorder title="Startup Arguments">
<ResourceString PropertyName="titleX" bundle="resources/MessagesBundle.properties" key="panel_startupargs" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
<Connection PropertyName="font" component="jPanelMain" name="font" type="property"/>
</TitledBorder>
</Border>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="jScrollPane1" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="jScrollPane1" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTextArea" name="jTextAreaLaunch">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="columns" type="int" value="38"/>
<Property name="lineWrap" type="boolean" value="true"/>
<Property name="rows" type="int" value="7"/>
</Properties>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="jPanel2">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
<TitledBorder title="StdOut Monitor">
<ResourceString PropertyName="titleX" bundle="resources/MessagesBundle.properties" key="panel_stdout" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
<Connection PropertyName="font" component="jPanelMain" name="font" type="property"/>
</TitledBorder>
</Border>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="jScrollPaneStdOut" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="jScrollPaneStdOut" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JScrollPane" name="jScrollPaneStdOut">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTextArea" name="jTextAreaStdOut">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="columns" type="int" value="38"/>
<Property name="rows" type="int" value="8"/>
</Properties>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Container>
<Component class="javax.swing.JButton" name="jButtonClose">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="resources/MessagesBundle.properties" key="button_close" replaceFormat="LOCAL.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButtonCloseActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Form>

191
src/client/TorMonFrame.java Normal file
View file

@ -0,0 +1,191 @@
/*
* 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 javax.swing.JTextArea;
import lib.GTKFixes;
import lib.Localisation;
import lib.OSFunction;
/**
*
* @author Alistair Neil <info@dazzleships.net>
*/
public class TorMonFrame extends javax.swing.JFrame {
private static final Localisation LOCAL = new Localisation("resources/MessagesBundle");
/**
* Creates new form TorMonFrame
*/
public TorMonFrame() {
initComponents();
jTextAreaLaunch.setOpaque(OSFunction.isWindows());
jTextAreaStdOut.setOpaque(OSFunction.isWindows());
GTKFixes.fixTextAreaColor(jTextAreaLaunch);
GTKFixes.fixTextAreaColor(jTextAreaStdOut);
}
/**
* Set launch command text
*
* @param command
*/
public void setLaunchString(String command) {
jTextAreaLaunch.setText(command);
jTextAreaLaunch.setCaretPosition(0);
}
public JTextArea getStdoutTextArea() {
return jTextAreaStdOut;
}
/**
* 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.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
jPanelMain = new javax.swing.JPanel();
jPanel1 = new javax.swing.JPanel();
jScrollPane1 = new javax.swing.JScrollPane();
jTextAreaLaunch = new javax.swing.JTextArea();
jPanel2 = new javax.swing.JPanel();
jScrollPaneStdOut = new javax.swing.JScrollPane();
jTextAreaStdOut = new javax.swing.JTextArea();
jButtonClose = new javax.swing.JButton();
setMinimumSize(new java.awt.Dimension(554, 492));
jPanelMain.setFont(jPanelMain.getFont().deriveFont(jPanelMain.getFont().getStyle() | java.awt.Font.BOLD));
jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder(null, LOCAL.getString("panel_startupargs"), javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, jPanelMain.getFont())); // NOI18N
jTextAreaLaunch.setEditable(false);
jTextAreaLaunch.setColumns(38);
jTextAreaLaunch.setLineWrap(true);
jTextAreaLaunch.setRows(7);
jScrollPane1.setViewportView(jTextAreaLaunch);
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addComponent(jScrollPane1)
.addContainerGap())
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())
);
jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder(null, LOCAL.getString("panel_stdout"), javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, jPanelMain.getFont())); // NOI18N
jTextAreaStdOut.setEditable(false);
jTextAreaStdOut.setColumns(38);
jTextAreaStdOut.setRows(8);
jScrollPaneStdOut.setViewportView(jTextAreaStdOut);
javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
jPanel2.setLayout(jPanel2Layout);
jPanel2Layout.setHorizontalGroup(
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel2Layout.createSequentialGroup()
.addContainerGap()
.addComponent(jScrollPaneStdOut)
.addContainerGap())
);
jPanel2Layout.setVerticalGroup(
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup()
.addContainerGap()
.addComponent(jScrollPaneStdOut)
.addContainerGap())
);
jButtonClose.setText(LOCAL.getString("button_close")); // NOI18N
jButtonClose.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonCloseActionPerformed(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(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanelMainLayout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE)
.addComponent(jButtonClose)))
.addContainerGap())
);
jPanelMainLayout.setVerticalGroup(
jPanelMainLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanelMainLayout.createSequentialGroup()
.addContainerGap()
.addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jButtonClose)
.addContainerGap())
);
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.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
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 jButtonCloseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonCloseActionPerformed
this.setVisible(false);
}//GEN-LAST:event_jButtonCloseActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton jButtonClose;
private javax.swing.JPanel jPanel1;
private javax.swing.JPanel jPanel2;
private javax.swing.JPanel jPanelMain;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JScrollPane jScrollPaneStdOut;
private javax.swing.JTextArea jTextAreaLaunch;
private javax.swing.JTextArea jTextAreaStdOut;
// End of variables declaration//GEN-END:variables
}

845
src/client/TorProcess.java Normal file
View file

@ -0,0 +1,845 @@
/*
* 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.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import javax.swing.JTextArea;
import javax.swing.text.BadLocationException;
import lib.ClientProcess;
import lib.SimpleFile;
/**
*
* @author Alistair Neil <info@dazzleships.net>
*/
public class TorProcess extends ClientProcess {
public static final int LOG_DEBUG = 0;
public static final int LOG_INFO = 1;
public static final int LOG_NOTICE = 2;
private static final String TORCONFIGFILE = "torrc";
public static final String EMPTYSTRING = "";
// Event constants
public static final int TOR_MESSAGE = 0;
public static final int TOR_BOOT_TIMEOUT = 1;
public static final int TOR_BOOT_FATAL = 2;
public static final int TOR_BOOT_ERROR = 3;
public static final int TOR_CLOCK_ERROR = 4;
public static final int TOR_NOROUTE = 5;
public static final int TOR_BOOTED = 6;
public static final int TOR_RESTARTED = 7;
public static final int TOR_NOEXITS = 8;
public static final int TOR_STOPPED = 9;
public static final int TOR_BRIDGE = 10;
public static final int TOR_NEWCIRC = 11;
public static final int TOR_DIRINFO_STALE = 12;
public static final int TOR_NOHOP0 = 13;
public static final int TOR_NONET_ACTIVITY = 14;
private static final String[] EVENTMESSAGES = new String[]{
"TOR_MESSAGE", "TOR_BOOT_TIMEOUT", "TOR_BOOT_FATAL", "TOR_BOOT_ERROR",
"TOR_CLOCK_ERROR", "TOR_NOROUTE", "TOR_BOOTED", "TOR_RESTARTED",
"TOR_NOEXITS", "TOR_STOPPED", "TOR_BRIDGE", "TOR_NEWCIRC",
"TOR_DIRINFO_STALE", "TOR_NOHOP0", "TOR_NONET_ACTIVITY"
};
private final LinkedHashMap<String, String> lhmCLIOptions;
private final LinkedHashMap<String, String> lhmTorrcOptions;
private final String strClientLocation;
private final String strConfigFolder;
private String strSecret;
private String strCachedDataFolder;
private String invCommas = "\"";
private String strExternalArgs = "";
private String strBridges = "";
private int intListenPort;
private int intInitialBootEvent;
private int loglev = LOG_NOTICE;
private float version = 9999;
private int maxlines = 50;
private int nolines;
private JTextArea jtxtstdout;
private boolean boolSilentBoot;
/**
* Constructor
*
* @param clientpath Path to Tor client
* @param configfolder Filepath to torrc
*/
public TorProcess(String clientpath, String configfolder) {
setSilentBootEnabled(false);
strClientLocation = clientpath;
this.intInitialBootEvent = TOR_BOOTED;
this.strConfigFolder = configfolder;
this.lhmCLIOptions = new LinkedHashMap<>();
this.lhmTorrcOptions = new LinkedHashMap<>();
// All our initialisation
if (SimpleFile.getSeparator().compareTo("/") == 0) {
this.invCommas = "";
}
}
/**
* Starts Tor process, and issues booted event on completion
*
*/
public final void startProcess() {
setStartupTimeout(60);
// Cache age check
float age = getCacheAge();
Logger.getGlobal().logp(Level.INFO, TorProcess.class.getName(),
"start() on Port=" + getListenPort(), "Cache age = " + (int) age + " minutes.");
if (age > 180) {
deleteCacheData();
Logger.getGlobal().logp(Level.INFO, TorProcess.class.getName(),
"start() on Port=" + getListenPort(), "Cache stale, deleting old cache data.");
}
// Some essential initialisation
String strConfig = strClientLocation
+ " -f " + invCommas
+ getConfigFilePath()
+ invCommas
+ " " + getCLIOptionsAsString()
+ " " + strExternalArgs;
Logger.getGlobal().logp(Level.INFO, TorProcess.class.getName(),
"start() on Port=" + getListenPort(),
"INFO: starting with " + strConfig );
super.start(strConfig);
}
/**
* Set the Tor stdout log level
*
* @param lev
*/
public final void setLogLevel(int lev) {
loglev = lev;
}
/**
* Set external user provided startup arguments
*
* @param torargs
*/
public final void setExternalArgs(String torargs) {
strExternalArgs = torargs;
}
/**
* Set the listening port
*
* @param port
*/
public final void setListenPort(int port) {
// Setup listening port and control port
if (intListenPort == port) {
return;
}
intListenPort = port;
setCLIOption("SocksPort", "127.0.0.1:" + String.valueOf(port));
setCLIOption("ControlSocket", "/run/tor/control");
setCLIOption("ControlPort", "127.0.0.1:" + String.valueOf(port + 1));
// Finish of by creating the default config file and data folders
createDataFolder();
}
/**
* Set the event that is issued on process boot completion
*
* @param event
*/
public final void setInitialBootEvent(int event) {
intInitialBootEvent = event;
}
/**
* Client event handler, can be overriden by parent class
*
* @param data line data from standard output of Tor client
*/
@Override
public final void clientProcessEventFired(String data) {
Logger.getGlobal().logp(Level.FINER, TorProcess.class.getName(),
"clientProcessEventFired() on Port=" + getListenPort(), data);
if (!data.isEmpty()) {
appendStdout(data);
}
// Check for process stopped
if (getClientStatus() == CLIENT_STOPPED) {
torProcessEventFired(TOR_STOPPED, null);
return;
}
// Check for timeout
if (getClientStatus() == CLIENT_TIMEDOUT) {
torProcessEventFired(TOR_BOOT_TIMEOUT, null);
return;
}
if (getClientStatus() == CLIENT_RUNNING) {
// Check to see if we need to copy cache
if (strCachedDataFolder != null) {
SimpleFile.copyFolderContents(strCachedDataFolder, getDataFolder() + SimpleFile.getSeparator(), "torrc");
strCachedDataFolder = null;
}
// Check for fatal tor process startup errors
if (data.contains("[warn] Our clock")) {
torProcessEventFired(TOR_CLOCK_ERROR, data);
return;
}
// Check for errors
if (data.contains("exception") || data.contains("[err]")) {
torProcessEventFired(TOR_BOOT_FATAL, data);
return;
}
// Check for network unreachable
if (data.contains("NOROUTE")) {
torProcessEventFired(TOR_NOROUTE, data);
return;
}
// Check new tor bridge
if (data.contains("[notice] new bridge")) {
torProcessEventFired(TOR_BRIDGE, data);
return;
}
// Check for conditions that may prevent circuit building
if (data.contains("directory information is no longer up-to-date")) {
torProcessEventFired(TOR_DIRINFO_STALE, data);
return;
}
// Check for conditions that will prevent circuit building
if (data.contains("All routers are down")) {
torProcessEventFired(TOR_NOEXITS, data);
return;
}
// Check for Tor retrying on new circuit
if (data.contains("Retrying on a new circuit")) {
torProcessEventFired(TOR_NEWCIRC, data);
return;
}
// Check for Tor failed to find hop zero
if (data.contains("Failed to find node for hop 0")) {
torProcessEventFired(TOR_NOHOP0, data);
return;
}
// Check for no net activity
if (data.contains("Tor has not observed any network activity")) {
torProcessEventFired(TOR_NONET_ACTIVITY, data);
return;
}
// Check for a bootstrap message
if (data.contains("Bootstrapped")) {
// If silent then dont fire bootstrapping messages
if (!boolSilentBoot) {
torProcessEventFired(TOR_MESSAGE, data.substring(data.indexOf(']') + 2));
}
int percent = getPercentage(data);
// Set startup timeout based on percentage of Tor progression
if (percent >= 15) {
setStartupTimeout(60);
}
if (percent >= 40) {
setStartupTimeout(120);
}
if (percent >= 80) {
setStartupTimeout(30);
}
// Check for initial bootup completion
if (percent >= 100) {
setStartupTimeout(-1);
torProcessEventFired(intInitialBootEvent, null);
intInitialBootEvent = TOR_BOOTED;
setSilentBootEnabled(false);
}
}
}
}
/**
* Get percentage value from bootstrap message
*
* @param data
* @return percentage as and int
*/
private int getPercentage(String data) {
int result = -1;
int idx1 = data.indexOf("Bootstrapped ");
if (idx1 > -1) {
idx1 += 13;
int idx2 = data.indexOf('%', idx1);
if (idx2 > -1) {
String temp = data.substring(idx1, idx2);
result = Integer.parseInt(temp);
}
}
return result;
}
/**
* Enable/Disable bootstrap message events on startup
*
* @param enabled
*/
public final void setSilentBootEnabled(boolean enabled) {
boolSilentBoot = enabled;
}
/**
* Get textual representation on an event
*
* @param event
* @return Event as text
*/
public String getEventMessage(int event) {
return EVENTMESSAGES[event];
}
/**
* Called if an event was fired, will be overidden by sub class
*
* @param event
* @param data
*/
public void torProcessEventFired(int event, String data) {
}
public final void setControlPassword(String secret, String hashpass) {
strSecret = secret;
setCLIOption("hashedcontrolpassword", hashpass);
}
/**
* Get the currently set authentification secret
*
* @return String
*/
public final String getSecret() {
return strSecret;
}
/**
* Set Tor bridges, supports multiple addresses
*
* @param bridges
*/
public final void setBridges(String bridges) {
clearCLIOption("UseBridges");
clearCLIOption("Bridge");
clearCLIOption("UpdateBridgesFromAuthority");
strBridges = "";
if (bridges == null || bridges.isEmpty()) {
return;
}
StringBuilder sbBridgesOption = new StringBuilder();
String sep = "";
String[] arrBridges = Pattern.compile(",").split(bridges);
for (String s : arrBridges) {
sbBridgesOption.append(sep);
sbBridgesOption.append(s);
if (sep.isEmpty()) {
sep = " --Bridge ";
}
}
strBridges = bridges;
setCLIOption("UseBridges", "1");
setCLIOption("UpdateBridgesFromAuthority", "1");
setCLIOption("Bridge", sbBridgesOption.toString());
}
/**
* Validate bridge addresses
*
* @param bridges
* @return true if valid
*/
public boolean validateBridges(String bridges) {
if (bridges.isEmpty()) {
return true;
}
String[] arrBridges = Pattern.compile(",").split(bridges);
for (String s : arrBridges) {
if (!validateHostPort(s)) {
return false;
}
}
return true;
}
/**
* Validate a host:port ipv4 address
*
* @param hostport
* @return true if valid
*/
public final boolean validateHostPort(String hostport) {
try {
URI uri = new URI("my://" + hostport); // may throw URISyntaxException
if (uri.getHost() == null || uri.getPort() == -1) {
return false;
}
} catch (Exception ex) {
return false;
}
return true;
}
/**
* Get bridges
*
* @return bridges as csv string
*/
public final String getBridges() {
return strBridges;
}
/**
* Set Ownership process id, useful for proper process termination in event
* of a crash
*
* @param processid
*/
public void setOwnershipID(String processid) {
this.setCLIOption("__OwningControllerProcess", processid);
}
/**
* Return the currently set process ownership ID
*
* @return String process id
*/
public String getOwnershipID() {
return getCLIOptions("__OwningControllerProcess");
}
/**
* Set the path to the geoip file
*
* @param filepath File location
*/
public final void setGeoIP4(String filepath) {
if (filepath != null) {
if (SimpleFile.exists(filepath)) {
setTorrcOption("GeoIPFile", invCommas + filepath + invCommas);
} else {
clearTorrcOption("GeoIPFile");
}
} else {
clearTorrcOption("GeoIPFile");
}
}
/**
* Set the path to the geoip file
*
* @param filepath File location
*/
public final void setGeoIP6(String filepath) {
if (filepath != null) {
if (SimpleFile.exists(filepath)) {
setTorrcOption("GeoIPv6File", invCommas + filepath + invCommas);
} else {
clearTorrcOption("GeoIPv6File");
}
} else {
clearTorrcOption("GeoIPv6File");
}
}
/**
* Get Tor client location as a filepath
*
* @return filepath as string
*/
public final String getClientLocation() {
return strClientLocation;
}
/**
* Get the path to the configuration file
*
* @return String Path to configuration file
*/
public final String getConfigFilePath() {
return getDataFolder() + File.separator + TORCONFIGFILE;
}
/**
* Get a previously added tor option string
*
* @param option Tor option key
* @return String Tor option value
*/
public final String getCLIOptions(String option) {
return lhmCLIOptions.get(option);
}
/**
* Add a tor option string which is passed to the tor client on startup. See
* Tor documentation for valid options.
*
* @param option
* @param value
*/
public final void setCLIOption(String option, String value) {
lhmCLIOptions.put(option, value);
}
/**
* Add a tor option boolean value
*
* @param option
* @param value
*/
public final void setBoolTorOption(String option, boolean value) {
lhmCLIOptions.remove(option);
if (value) {
lhmCLIOptions.put(option, "1");
} else {
lhmCLIOptions.put(option, "0");
}
}
/**
* Get a previously added tor option string
*
* @param option Tor option key
* @return String Tor option value
*/
public final String getTorrcOption(String option) {
return lhmTorrcOptions.get(option);
}
/**
* Add a torrc option string See Tor documentation for valid options.
*
* @param option
* @param value
*/
public final void setTorrcOption(String option, String value) {
if (value.startsWith("\"")) {
value = value.replace('\\', '/');
}
lhmTorrcOptions.put(option, value);
}
/**
* Gets all the currently set torrc options as single String
*
* @return String Tor client formatted cli arguments
*/
public final String getTorrcOptionsAsString() {
Iterator<String> iterator = lhmTorrcOptions.keySet().iterator();
String key;
StringBuilder sbResult = new StringBuilder();
while (iterator.hasNext()) {
key = iterator.next();
sbResult.append(key);
sbResult.append(" ");
sbResult.append(lhmTorrcOptions.get(key));
sbResult.append("\r\n");
}
return sbResult.toString();
}
/**
* Remove previously add torrc option
*
* @param option
*/
public final void clearTorrcOption(String option) {
lhmTorrcOptions.remove(option);
}
/**
* Get a previously added tor option boolean value
*
* @param option Tor option key
* @return Boolean value
*/
public final boolean getCLIOptionBool(String option) {
return lhmCLIOptions.get(option).contentEquals("1");
}
/**
* Remove previously add tor option
*
* @param option
*/
public final void clearCLIOption(String option) {
lhmCLIOptions.remove(option);
}
/**
* Gets all the currently set tor options as single String for use as
* arguments passed to tor client
*
* @return String Tor cleint formatted cli arguments
*/
public final String getCLIOptionsAsString() {
Iterator<String> iterator = lhmCLIOptions.keySet().iterator();
String key;
String value;
StringBuilder sbResult = new StringBuilder();
while (iterator.hasNext()) {
key = iterator.next();
sbResult.append("--");
sbResult.append(key);
sbResult.append(" ");
value = lhmCLIOptions.get(key);
if (!value.isEmpty()) {
sbResult.append(value);
sbResult.append(" ");
}
}
return sbResult.toString().trim();
}
/**
* Get the listening port
*
* @return port
*/
public final int getListenPort() {
return intListenPort;
}
/**
* Get the control port
*
* @return port
*/
public final int getControlPort() {
return intListenPort + 1;
}
/**
* Creates the default Tor config file
*/
public final void createDefaultConfig() {
SimpleFile sfTorrc = new SimpleFile(getConfigFilePath());
sfTorrc.openBufferedWrite();
sfTorrc.writeFile(getTorrcOptionsAsString(), 0);
switch (loglev) {
case LOG_DEBUG:
sfTorrc.writeFile("log debug stdout", 1);
break;
case LOG_INFO:
sfTorrc.writeFile("log info stdout", 1);
break;
case LOG_NOTICE:
sfTorrc.writeFile("log notice stdout", 1);
break;
}
sfTorrc.writeFile(EMPTYSTRING, 1);
sfTorrc.closeFile();
}
/**
* Delete the configuration file
*/
public final void deleteConfigFile() {
SimpleFile.delete(getConfigFilePath());
}
/**
* Creates a data folder for the Tor client to put its cache data
*/
public final void createDataFolder() {
String folder = getDataFolder();
if (folder != null) {
setTorrcOption("DataDirectory", invCommas + getDataFolder() + invCommas);
SimpleFile.createFolder(getDataFolder());
}
}
/**
* Get the datafolder being used by tor client
*
* @return Path to datafolder
*/
public final String getDataFolder() {
if (strConfigFolder == null) {
return null;
}
return strConfigFolder + String.valueOf(intListenPort);
}
/**
* Get the age of the file cache in minutes
*
* @return age of cache in minutes
*/
public float getCacheAge() {
String path = getDataFolder() + SimpleFile.getSeparator()
+ "cached-consensus";
if (SimpleFile.exists(path)) {
return SimpleFile.getAgeOfFile(path, SimpleFile.PERIOD_MINUTES);
} else {
return -1;
}
}
/**
* Delete Tor cache data
*/
public final void deleteCacheData() {
SimpleFile.secureWipe(getDataFolder() + SimpleFile.getSeparator() + "cached-consensus");
SimpleFile.secureWipe(getDataFolder() + SimpleFile.getSeparator() + "cached-certs");
SimpleFile.secureWipe(getDataFolder() + SimpleFile.getSeparator() + "cached-descriptors");
SimpleFile.secureWipe(getDataFolder() + SimpleFile.getSeparator() + "cached-descriptors.new");
SimpleFile.secureWipe(getDataFolder() + SimpleFile.getSeparator() + "lock");
SimpleFile.secureWipe(getDataFolder() + SimpleFile.getSeparator() + "state");
}
/**
* This populates the the current folder whose name is derived from the
* listening port with data from the given source folder derived by the
* given port number. This effectively allows each Tor client spawned to
* have its Tor cache data copied from the first Tor client launched instead
* of having to go to the net and fetch it and thus start up is a lot
* faster. I was actually mildly suprised that this actually works.
*
* @param port
*/
public final void setCachedDataFolder(int port) {
if (port < 0) {
strCachedDataFolder = null;
return;
}
strCachedDataFolder = strConfigFolder + String.valueOf(port);
}
/**
* Get the currently set cached data folder
*
* @return path to cached data folder as String
*/
public final String getCachedDataFolder() {
return strCachedDataFolder;
}
/**
* Set the text area that will receive Stdout output
*
* @param jta
*/
public void setStdoutTextArea(JTextArea jta) {
jtxtstdout = jta;
}
/**
* Set the maximum no of lines to display in the Stdout output
*
* @param lines
*/
public void setMaxHistory(int lines) {
maxlines = lines;
}
/**
* Clear the Stdout text area
*/
public void clearStdout() {
if (jtxtstdout != null) {
jtxtstdout.setText("");
}
nolines = 0;
}
/**
* Append text to the StdOut text area
*
* @param text
*/
private void appendStdout(String text) {
if (jtxtstdout == null) {
return;
}
jtxtstdout.append(text + "\n");
if (++nolines > maxlines) {
try {
int end = jtxtstdout.getLineEndOffset(0);
jtxtstdout.replaceRange("", 0, end);
} catch (BadLocationException ex) {
}
}
jtxtstdout.setCaretPosition(jtxtstdout.getText().length());
}
/**
* Get Tor version as float
*
* @return Tor version as String
*/
public final float getVersion() {
if (version == 9999) {
BufferedReader br;
String strVer = "";
Process proc;
try {
proc = Runtime.getRuntime().exec(strClientLocation + " --version");
br = new BufferedReader(new InputStreamReader(proc.getInputStream()), 256);
String line;
while (true) {
line = br.readLine();
if (line == null) {
break;
}
strVer = line;
}
br.close();
proc.destroy();
proc.waitFor();
} catch (IOException | InterruptedException ex) {
Logger.getLogger(TorProcess.class.getName()).log(Level.SEVERE, null, ex);
}
int idx = strVer.indexOf("ion");
if (idx > -1) {
strVer = strVer.substring(idx + 4).replace(".", "");
idx = strVer.indexOf(' ');
if (idx > -1) {
strVer = strVer.substring(0, idx);
}
try {
version = Float.parseFloat("0." + strVer) * 10;
} catch (Exception ex) {
Logger.getGlobal().logp(Level.SEVERE, this.getClass().getName(), "getVersion() Port=" + intListenPort, "", ex);
}
}
}
return version;
}
}

135
src/lib/AboutDialog.form Normal file
View file

@ -0,0 +1,135 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.5" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
<Properties>
<Property name="defaultCloseOperation" type="int" value="2"/>
<Property name="title" type="java.lang.String" value="Title"/>
<Property name="resizable" type="boolean" value="false"/>
</Properties>
<SyntheticProperties>
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
</SyntheticProperties>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="jPanel1" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="jPanel1" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JPanel" name="jPanel1">
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Component id="jButtonVisit" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jButtonContact" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<Component id="jButtonClose" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<Component id="jLabelAppLogo" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jTextAreaVersion" min="-2" pref="183" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="jLabelAppLogo" max="32767" attributes="3"/>
<Component id="jTextAreaVersion" max="32767" attributes="3"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="2" attributes="0">
<Component id="jButtonVisit" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="jButtonContact" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="jButtonClose" alignment="2" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JButton" name="jButtonVisit">
<Properties>
<Property name="text" type="java.lang.String" value="Visit Us"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButtonVisitActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="jButtonContact">
<Properties>
<Property name="text" type="java.lang.String" value="Contact Us"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButtonContactActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="jButtonClose">
<Properties>
<Property name="text" type="java.lang.String" value="Close"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButtonCloseActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="jLabelAppLogo">
<Properties>
<Property name="verticalAlignment" type="int" value="1"/>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[128, 128]"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextArea" name="jTextAreaVersion">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="columns" type="int" value="15"/>
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection component="jPanel1" name="foreground" type="property"/>
</Property>
<Property name="lineWrap" type="boolean" value="true"/>
<Property name="rows" type="int" value="5"/>
<Property name="wrapStyleWord" type="boolean" value="true"/>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="null"/>
</Property>
<Property name="focusable" type="boolean" value="false"/>
<Property name="opaque" type="boolean" value="false"/>
</Properties>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Form>

233
src/lib/AboutDialog.java Normal file
View file

@ -0,0 +1,233 @@
/*
* 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 lib;
import java.awt.Image;
import javax.swing.ImageIcon;
/**
*
* @author Alistair Neil, <info@dazzleships.net>
*/
public class AboutDialog extends javax.swing.JDialog {
private String strHome = null;
private String strContact = null;
/**
* Creates new About Dialog
*
* @param parent
* @param modal
*/
public AboutDialog(java.awt.Frame parent, boolean modal) {
super(parent, modal);
initComponents();
}
/**
* Set appliction description
*
* @param text
*/
public void setAppDescription(String text) {
jTextAreaVersion.setText(text);
}
/**
* Set application logo
*
* @param ii
*/
public void setAppLogo(ImageIcon ii) {
Image im = ii.getImage().getScaledInstance(jLabelAppLogo.getWidth(), jLabelAppLogo.getHeight(), Image.SCALE_SMOOTH);
ii.setImage(im);
jLabelAppLogo.setIcon(ii);
}
/**
* Set home url
*
* @param home
*/
public void setHomeURL(String home) {
strHome = home;
}
/**
* Set contact url
*
* @param contact
*/
public void setContactURL(String contact) {
strContact = contact;
}
/**
* Set text on Contact button
*
* @param text
*/
public void setButtonContactText(String text) {
jButtonContact.setText(text);
}
/**
* Set text on Visit button
*
* @param text
*/
public void setButtonVisitText(String text) {
jButtonVisit.setText(text);
}
/**
* Set text on Close button
*
* @param text
*/
public void setButtonCloseText(String text) {
jButtonClose.setText(text);
}
/**
* 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() {
jPanel1 = new javax.swing.JPanel();
jButtonVisit = new javax.swing.JButton();
jButtonContact = new javax.swing.JButton();
jButtonClose = new javax.swing.JButton();
jLabelAppLogo = new javax.swing.JLabel();
jTextAreaVersion = new javax.swing.JTextArea();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
setTitle("Title");
setResizable(false);
jButtonVisit.setText("Visit Us");
jButtonVisit.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonVisitActionPerformed(evt);
}
});
jButtonContact.setText("Contact Us");
jButtonContact.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonContactActionPerformed(evt);
}
});
jButtonClose.setText("Close");
jButtonClose.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonCloseActionPerformed(evt);
}
});
jLabelAppLogo.setVerticalAlignment(javax.swing.SwingConstants.TOP);
jLabelAppLogo.setPreferredSize(new java.awt.Dimension(128, 128));
jTextAreaVersion.setEditable(false);
jTextAreaVersion.setColumns(15);
jTextAreaVersion.setForeground(jPanel1.getForeground());
jTextAreaVersion.setLineWrap(true);
jTextAreaVersion.setRows(5);
jTextAreaVersion.setWrapStyleWord(true);
jTextAreaVersion.setBorder(null);
jTextAreaVersion.setFocusable(false);
jTextAreaVersion.setOpaque(false);
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(jButtonVisit)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jButtonContact)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jButtonClose))
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(jLabelAppLogo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jTextAreaVersion, javax.swing.GroupLayout.PREFERRED_SIZE, 183, javax.swing.GroupLayout.PREFERRED_SIZE))
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(jLabelAppLogo, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jTextAreaVersion))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
.addComponent(jButtonVisit)
.addComponent(jButtonContact)
.addComponent(jButtonClose)))
);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addContainerGap())
);
pack();
}// </editor-fold>//GEN-END:initComponents
private void jButtonVisitActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonVisitActionPerformed
if (strHome != null) {
Utilities.openFileExternally(strHome);
}
}//GEN-LAST:event_jButtonVisitActionPerformed
private void jButtonContactActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonContactActionPerformed
if (strContact != null) {
Utilities.openFileExternally(strContact);
}
}//GEN-LAST:event_jButtonContactActionPerformed
private void jButtonCloseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonCloseActionPerformed
dispose();
}//GEN-LAST:event_jButtonCloseActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton jButtonClose;
private javax.swing.JButton jButtonContact;
private javax.swing.JButton jButtonVisit;
private javax.swing.JLabel jLabelAppLogo;
private javax.swing.JPanel jPanel1;
private javax.swing.JTextArea jTextAreaVersion;
// End of variables declaration//GEN-END:variables
}

233
src/lib/ClientProcess.java Normal file
View file

@ -0,0 +1,233 @@
/*
* 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 lib;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.SwingWorker;
/**
*
* @author Alistair Neil <info@dazzleships.net>
*/
public class ClientProcess {
public static final int CLIENT_STOPPED = 0;
public static final int CLIENT_RUNNING = 1;
public static final int CLIENT_TIMEDOUT = 2;
private long initialdelay = 0;
private volatile long startupTimeout;
private SwingWorker<ArrayList<String>, String> swWorker;
private volatile Process procApplication;
private PrintWriter pwWriter;
private volatile Thread threadSleep;
private int intStatus = CLIENT_STOPPED;
/**
* Constructor
*/
public ClientProcess() {
setStartupTimeout(15);
}
/**
* Set the initial delay that is executed prior to starting the process
*
* @param ms
*/
public final void setStartupDelay(long ms) {
initialdelay = ms;
}
/**
* Set startup timeout
*
* @param seconds
*/
public final void setStartupTimeout(long seconds) {
startupTimeout = seconds * 1000;
}
/**
* Starts the client process
*
* @param processpath
*/
public final void start(final String processpath) {
swWorker = new SwingWorker<ArrayList<String>, String>() {
String line;
int endstatus;
@Override
protected ArrayList<String> doInBackground() {
BufferedReader brProcInput = null;
BufferedReader brProcError = null;
try {
endstatus = CLIENT_STOPPED;
if (isCancelled()) {
return null;
}
threadSleep = Thread.currentThread();
if (initialdelay > 0) {
try {
Thread.sleep(initialdelay);
} catch (InterruptedException ex) {
}
}
threadSleep = null;
initialdelay = 0;
if (isCancelled()) {
return null;
}
procApplication = Runtime.getRuntime().exec(processpath);
if (procApplication == null) {
return null;
}
brProcInput = new BufferedReader(new InputStreamReader(procApplication.getInputStream()), 512);
brProcError = new BufferedReader(new InputStreamReader(procApplication.getErrorStream()), 512);
pwWriter = new PrintWriter(procApplication.getOutputStream());
long timeout = System.currentTimeMillis() + startupTimeout;
while (!isCancelled()) {
if (brProcInput.ready()) {
timeout = System.currentTimeMillis() + startupTimeout;
// Read process notifications
line = brProcInput.readLine();
publish(line);
}
if (brProcError.ready()) {
timeout = System.currentTimeMillis() + startupTimeout;
// Read process notifications
line = brProcError.readLine();
publish(line);
}
if (System.currentTimeMillis() > timeout && startupTimeout > 0) {
endstatus = CLIENT_TIMEDOUT;
break;
}
threadSleep = Thread.currentThread();
try {
Thread.sleep(20);
} catch (InterruptedException ex) {
}
threadSleep = null;
}
} catch (Exception ex) {
Logger.getGlobal().logp(Level.INFO, ClientProcess.class.getName(),
"SwingWorker Loop Exception", ex.getMessage());
} finally {
// Cleanup resources
try {
if (brProcInput != null) {
brProcInput.close();
}
if (brProcError != null) {
brProcError.close();
}
pwWriter.close();
// Destroy process
if (procApplication != null) {
procApplication.getOutputStream().close();
procApplication.getInputStream().close();
procApplication.getErrorStream().close();
procApplication.destroy();
}
} catch (Exception ex) {
Logger.getGlobal().logp(Level.INFO, ClientProcess.class.getName(),
"SwingWorker Cleanup", ex.getMessage());
}
}
return null;
}
@Override
protected void process(List<String> chunks) {
for (String s : chunks) {
if (s != null) {
clientProcessEventFired(s);
}
}
}
@Override
protected void done() {
intStatus = endstatus;
clientProcessEventFired("");
}
};
intStatus = CLIENT_RUNNING;
clientProcessEventFired("");
// Start client process
swWorker.execute();
}
public final int getClientStatus() {
return intStatus;
}
/**
* Return the client system process
*
* @return a process
*/
public final Process getProcess() {
return procApplication;
}
/**
* Stops the client process
*
*/
public final void stopProcess() {
if (threadSleep != null) {
threadSleep.interrupt();
}
if (swWorker != null) {
swWorker.cancel(true);
}
try {
procApplication.waitFor();
} catch (Exception ex) {
Logger.getGlobal().logp(Level.INFO, ClientProcess.class.getName(),
"stopProcess", ex.getMessage());
}
}
/**
* Send a message to the process
*
* @param message
*/
public final void sendMessage(String message) {
pwWriter.write(message);
}
/**
* Event from the process, should be overriden by sub class
*
* @param data
*/
public void clientProcessEventFired(String data) {
}
}

120
src/lib/DesktopNotify.java Normal file
View file

@ -0,0 +1,120 @@
/*
* 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 lib;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* This class handles desktop notifications
*
* @author Alistair Neil <info@dazzleships.net>
*/
public class DesktopNotify {
private final String iconpath;
private String notifytitle;
private String notifybody;
private String notifysendpath;
private final SwingTrayIcon sti;
private boolean enabled;
private boolean supported = true;
public DesktopNotify(SwingTrayIcon sti, String iconpath) {
this.sti = sti;
this.iconpath = iconpath;
if (OSFunction.isLinux()) {
this.notifysendpath = OSFunction.findFile("notify-send", "/usr/bin/");
if (this.notifysendpath == null) {
Logger.getGlobal().log(Level.WARNING, "notify-send not found.");
this.supported = false;
}
}
}
/**
* Is notifications supported
*
* @return true if supported
*/
public boolean isSupported() {
return supported;
}
/**
* Are notifications enabled
*
* @return true if enabled
*/
public boolean isEnabled() {
return enabled;
}
/**
* Disable/Enable notifications
*
* @param enabled
*/
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
/**
* Set desktop notification title
*
* @param text
*/
public void setNotificationTitle(String text) {
notifytitle = text;
}
/**
* Set desktop notification body
*
* @param text
*/
public void setNotificationBody(String text) {
notifybody = text;
}
/**
* Raise a notification
*
*/
public void raiseNotification() {
if (notifybody == null || notifytitle == null || !enabled) {
return;
}
if (OSFunction.isWindows()) {
if (sti != null) {
sti.displayMessage(notifytitle, notifybody);
}
} else {
if (notifysendpath != null) {
OSFunction.launchProcess("notify-send", "-u", "normal",
"-i", iconpath, notifytitle, notifybody);
}
}
notifybody = null;
}
public String getNotifySendPath() {
return notifysendpath;
}
}

View file

@ -0,0 +1,90 @@
/*
* 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 lib;
import java.io.File;
import javax.swing.filechooser.FileFilter;
/**
*
* @author Alistair Neil, <info@dazzleships.net>
* Taken from Oracle documentation.
*/
public class ExtensionFileFilter extends FileFilter {
String description;
String extensions[];
/**
* Convenience constructor for a single extension
*
* @param description
* @param extension
*/
public ExtensionFileFilter(String description, String extension) {
this(description, new String[]{extension});
}
/**
* Convenience constructor for a multiple extensions
*
* @param description
* @param extensions
*/
public ExtensionFileFilter(String description, String extensions[]) {
if (description == null) {
this.description = extensions[0];
} else {
this.description = description;
}
this.extensions = extensions.clone();
toLower(this.extensions);
}
private void toLower(String array[]) {
for (int i = 0, n = array.length; i < n; i++) {
array[i] = array[i].toLowerCase();
}
}
/**
* Get description
*
* @return String
*/
@Override
public String getDescription() {
return description;
}
@Override
public boolean accept(File file) {
if (file.isDirectory()) {
return true;
} else {
String path = file.getAbsolutePath().toLowerCase();
for (int i = 0, n = extensions.length; i < n; i++) {
String extension = extensions[i];
if ((path.endsWith(extension) && (path.charAt(path.length() - extension.length() - 1)) == '.')) {
return true;
}
}
}
return false;
}
}

128
src/lib/GTKFixes.java Normal file
View file

@ -0,0 +1,128 @@
/*
* 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 lib;
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.BorderFactory;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.event.MenuEvent;
/**
*
* @author Alistair Neil <info@dazzleships.net>
*/
public class GTKFixes {
public static void fixMenubarHeight(JMenuBar jmb, JMenuItem jmi) {
jmb.setPreferredSize(new Dimension(jmb.getPreferredSize().width, jmi.getPreferredSize().height));
}
/**
* Fixes incorrect JMenu selectionForeground and selectionBackground
* highlighting
*
* @param jms Array of JMenus or single JMenu
*/
public static void fixMenuSelectionColor(JMenu... jms) {
// If gtk laf not installed then do nothing
if (!UIManager.getLookAndFeel().getID().contentEquals("GTK")) {
return;
}
for (final JMenu jm : jms) {
final Color bgfixed = new Color(((Color) UIManager.get("Menu.selectionBackground")).getRGB());
final Color fgfixed = new Color(((Color) UIManager.get("Menu.selectionForeground")).getRGB());
final Color fgnormal = jm.getForeground();
final Color bgnormal = new Color(((Color) UIManager.get("Menu.background")).getRGB());
jm.setText(" " + jm.getText() + " ");
jm.addMenuListener(new javax.swing.event.MenuListener() {
@Override
public void menuSelected(MenuEvent e) {
jm.setOpaque(true);
jm.setForeground(fgfixed);
jm.setBackground(bgfixed);
}
@Override
public void menuDeselected(MenuEvent e) {
jm.setOpaque(false);
jm.setForeground(fgnormal);
jm.setBackground(bgnormal);
}
@Override
public void menuCanceled(MenuEvent e) {
jm.setOpaque(false);
jm.setForeground(fgnormal);
jm.setBackground(bgnormal);
}
});
}
}
/**
* Fixes incorrect JMenu border outline
*
* @param jms Array of JMenus or single JMenu
*/
public static void fixJMenuPopupBorder(JMenu... jms) {
// If gtk laf not installed then do nothing
if (!UIManager.getLookAndFeel().getID().contentEquals("GTK")) {
return;
}
for (final JMenu jm : jms) {
jm.getPopupMenu().setBorder(BorderFactory.createLineBorder(
new Color(UIManager.getColor("PopupMenu.background").getRGB()).darker(), 1));
}
}
public static void fixTrayMenuPopupBorder(TrayPopupMenu tpm) {
tpm.setBorder(BorderFactory.createLineBorder(
new Color(UIManager.getColor("PopupMenu.background").getRGB()).darker(), 1));
}
/**
* Fixes incorrect JMenu selectionForeground highlighting
*
* @param jmi Array of JMenuItems or single JMenuItem
*/
public static void fixMenuItemFgColor(JMenuItem... jmi) {
// If gtk laf not installed then do nothing
if (!UIManager.getLookAndFeel().getID().contentEquals("GTK")) {
return;
}
for (final JMenuItem jm : jmi) {
final Color fgfixed = new Color(UIManager.getColor("MenuItem.foreground").getRGB());
jm.setForeground(fgfixed);
}
}
public static void fixTextAreaColor(JTextArea jta) {
if (OSFunction.isLinux()) {
jta.setForeground(UIManager.getColor("JLabel.foreground"));
jta.setBackground(UIManager.getColor("JLabel.background"));
}
}
}

139
src/lib/InfoDialog.form Normal file
View file

@ -0,0 +1,139 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.5" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
<Properties>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[410, 165]"/>
</Property>
<Property name="resizable" type="boolean" value="false"/>
</Properties>
<SyntheticProperties>
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
</SyntheticProperties>
<Events>
<EventHandler event="windowClosing" listener="java.awt.event.WindowListener" parameters="java.awt.event.WindowEvent" handler="closeDialog"/>
</Events>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="jPanelMain" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="jPanelMain" max="32767" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JPanel" name="jPanelMain">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="true" component="jPanelMain" property="font" relativeSize="true" size="2"/>
</FontInfo>
</Property>
<Property name="opaque" type="boolean" value="false"/>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="jCheckBoxOption" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="63" max="32767" attributes="0"/>
<Component id="jButtonCancel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jButtonContinue" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="jScrollPane2" alignment="0" max="32767" attributes="0"/>
<Component id="jProgressBar" alignment="0" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="jScrollPane2" pref="304" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jProgressBar" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jCheckBoxOption" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jButtonContinue" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jButtonCancel" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JButton" name="jButtonCancel">
<Properties>
<Property name="text" type="java.lang.String" value="Cancel"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButtonCancelActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JCheckBox" name="jCheckBoxOption">
<Properties>
<Property name="text" type="java.lang.String" value="Disable this notification."/>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="jButtonContinue">
<Properties>
<Property name="text" type="java.lang.String" value="Continue"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButtonContinueActionPerformed"/>
</Events>
</Component>
<Container class="javax.swing.JScrollPane" name="jScrollPane2">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTextArea" name="jTextInfo">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="columns" type="int" value="20"/>
<Property name="lineWrap" type="boolean" value="true"/>
<Property name="rows" type="int" value="5"/>
<Property name="wrapStyleWord" type="boolean" value="true"/>
</Properties>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JProgressBar" name="jProgressBar">
<Properties>
<Property name="string" type="java.lang.String" value=""/>
<Property name="stringPainted" type="boolean" value="true"/>
</Properties>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Form>

549
src/lib/InfoDialog.java Normal file
View file

@ -0,0 +1,549 @@
/*
* 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 lib;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import javax.swing.JProgressBar;
import javax.swing.JTextArea;
import javax.swing.Timer;
import javax.swing.WindowConstants;
/**
*
* @author Alistair Neil, <info@dazzleships.net>
*/
public class InfoDialog extends javax.swing.JDialog {
public static final int CANCEL_BUTTON = 0;
public static final int CANCEL_WINDOW = 1;
public static final int OK = 2;
private Color fg = null;
private final Frame parent;
private String strButtClose;
private String strTitle = "";
private final Font fontDefault;
private Timer tmrAutoClose;
private Timer tmrButtonLock;
/**
* Creates new InfoDialog, for parent frame with modality modal
*
* @param parent
*/
public InfoDialog(Frame parent) {
super(parent, true);
this.parent = parent;
initComponents();
jCheckBoxOption.setVisible(false);
jProgressBar.setVisible(false);
fg = jTextInfo.getForeground();
fontDefault = jTextInfo.getFont();
setContinueButtonText("Continue");
setCancelButtonText("Cancel");
setCloseButtonText("Close");
}
@Override
public final Font getFont() {
return jPanelMain.getFont();
}
/**
* Convenience methods
*
* @param title
*/
public final void createInfo(String title) {
createInfo(title, null);
}
/**
*
* @param title
* @param info
*/
public final void createInfo(String title, String info) {
super.setTitle(strTitle + " " + title);
setModal(true);
setCancelVisible(false);
setContinueButtonText(strButtClose);
jProgressBar.setVisible(false);
FontMetrics fm = getFontMetrics(getFont());
int width = fm.stringWidth(getTitle());
if (width > getWidth()) {
setSize(width, getHeight());
}
jTextInfo.setFont(fontDefault);
jTextInfo.setForeground(fg);
jTextInfo.setText("");
if (info != null) {
jTextInfo.setText(info);
}
jTextInfo.setCaretPosition(0);
setLocationRelativeTo(parent);
}
/**
* Set dialog title
*
* @param title
*/
@Override
public final void setTitle(String title) {
strTitle = title;
super.setTitle(strTitle);
}
/**
*
* @param title
*/
public final void createWarn(String title) {
createWarn(title, null);
}
/**
* Create warning dialog
*
* @param title
* @param info
*/
public final void createWarn(String title, String info) {
super.setTitle(strTitle + " " + title);
setModal(true);
setCancelVisible(true);
jProgressBar.setVisible(false);
FontMetrics fm = getFontMetrics(getFont());
int width = fm.stringWidth(getTitle());
if (width > getWidth()) {
setSize(width, getHeight());
}
jTextInfo.setFont(fontDefault);
jTextInfo.setForeground(fg);
jTextInfo.setText("");
if (info != null) {
jTextInfo.setText(info);
}
setLocationRelativeTo(parent);
jTextInfo.setCaretPosition(0);
}
/**
* Create progress bar dialog
*
* @param title
* @param info
*/
public final void createProgress(String title, String info) {
super.setTitle(strTitle + " " + title);
setModal(true);
setCancelVisible(true);
jProgressBar.setVisible(true);
FontMetrics fm = getFontMetrics(getFont());
int width = fm.stringWidth(getTitle());
if (width > getWidth()) {
setSize(width, getHeight());
}
jTextInfo.setFont(fontDefault);
jTextInfo.setForeground(fg);
jTextInfo.setText("");
if (info != null) {
jTextInfo.setText(info);
}
setLocationRelativeTo(parent);
jTextInfo.setCaretPosition(0);
}
/**
* Overridable handle for a progress based task
*
* @param status
* @param jpb
*/
public void progressTask(int status, JProgressBar jpb) {
}
/**
* Create error dialog
*
* @param title
*/
public final void createError(String title) {
createError(title, null);
}
/**
* Create error dialog
*
* @param title
* @param info
*/
public final void createError(String title, String info) {
super.setTitle(strTitle + " " + title);
setModal(true);
setCancelVisible(false);
setContinueButtonText(strButtClose);
jProgressBar.setVisible(false);
FontMetrics fm = getFontMetrics(getFont());
int width = fm.stringWidth(getTitle());
if (width > getWidth()) {
setSize(width, getHeight());
}
jTextInfo.setFont(fontDefault);
jTextInfo.setForeground(fg);
jTextInfo.setText("");
if (info != null) {
jTextInfo.setText(info);
}
setLocationRelativeTo(parent);
jTextInfo.setCaretPosition(0);
}
public final void setTimeLock(final int secs) {
jButtonCancel.setEnabled(false);
jButtonContinue.setEnabled(false);
this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
final String buttontext = jButtonCancel.getText();
tmrButtonLock = new Timer(1000, new java.awt.event.ActionListener() {
int localsecs = secs;
@Override
public void actionPerformed(ActionEvent e) {
localsecs--;
if (localsecs == 0) {
tmrButtonLock.stop();
jButtonCancel.setText(buttontext);
jButtonCancel.setEnabled(true);
jButtonContinue.setEnabled(true);
} else {
jButtonCancel.setText(buttontext + " (" + localsecs + ")");
}
}
});
jButtonCancel.setText(buttontext + " (" + secs + ")");
tmrButtonLock.start();
}
public final void setCloseButtonText(String text) {
strButtClose = text;
}
public final void setCancelButtonText(String text) {
jButtonCancel.setText(text);
}
public final void setContinueButtonText(String text) {
jButtonContinue.setText(text);
}
public final void setCheckBoxText(String text) {
jCheckBoxOption.setText(text);
}
/**
* Enable/Disable Autoscrolling
*
* @param enabled
*/
public final void setAutoScrollEnabled(boolean enabled) {
jTextInfo.setAutoscrolls(enabled);
}
/**
* Append text to the information area, Scrolling should be enabled
*
* @param text
*/
public final void appendInfoText(String text) {
jTextInfo.append(text);
jTextInfo.setCaretPosition(jTextInfo.getText().length());
}
/**
* Set whether the forms checkbox is enabled
*
* @param enabled
*/
public final void setCheckBoxVisible(boolean enabled) {
jCheckBoxOption.setVisible(enabled);
}
/**
* Set check box selection status
*
* @param checked
*/
public final void setCheckBoxEnabled(boolean checked) {
jCheckBoxOption.setSelected(checked);
}
/**
* Test to see if checkbox is selected
*
* @return boolean True if selected
*/
public final boolean isCheckBoxSelected() {
return jCheckBoxOption.isSelected();
}
/**
* Set info font
*
* @param font
* @param sizeoffset
*/
public final void setFont(String font, int sizeoffset) {
jTextInfo.setFont(new Font(font, jTextInfo.getFont().getStyle(),
jTextInfo.getFont().getSize() + sizeoffset));
}
/**
* Set the form auto close period in milliseconds
*
* @param millis
*/
public final void setAutoClose(int millis) {
tmrAutoClose = new Timer(millis, new java.awt.event.ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
tmrAutoClose.stop();
doClose(CANCEL_WINDOW);
}
});
tmrAutoClose.start();
}
public final JTextArea getTextArea() {
return jTextInfo;
}
/**
* @return the return status of this dialog - one of RET_OK or RET_CANCEL
*/
public final int getReturnStatus() {
return returnStatus;
}
/**
* Set dialog message body
*
* @param text
*/
public final void setInfoText(String text) {
jTextInfo.setText(text);
}
/**
* Set dialog message body, and font colour
*
* @param text
* @param fgcolor
*/
public final void setInfoText(String text, Color fgcolor) {
jTextInfo.setForeground(fgcolor);
jTextInfo.setText(text);
}
/**
* Set whether Cancel button is enabled
*
* @param enabled
*/
public final void setCancelEnabled(boolean enabled) {
jButtonCancel.setEnabled(enabled);
}
/**
* Set whether Cancel button is visible
*
* @param visible
*/
public final void setCancelVisible(boolean visible) {
jButtonCancel.setVisible(visible);
}
/**
* Set whether Ok button is enabled
*
* @param enabled
*/
public final void setAckEnabled(boolean enabled) {
jButtonContinue.setEnabled(enabled);
}
/**
* Set whether OK button is visible
*
* @param visible
*/
public final void setAckVisible(boolean visible) {
jButtonContinue.setVisible(visible);
}
public void setVisibleWithFocus(boolean visible) {
super.setVisible(visible);
this.requestFocus();
}
/**
* 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() {
jPanelMain = new javax.swing.JPanel();
jButtonCancel = new javax.swing.JButton();
jCheckBoxOption = new javax.swing.JCheckBox();
jButtonContinue = new javax.swing.JButton();
jScrollPane2 = new javax.swing.JScrollPane();
jTextInfo = new javax.swing.JTextArea();
jProgressBar = new javax.swing.JProgressBar();
setMinimumSize(new java.awt.Dimension(410, 165));
setResizable(false);
addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(java.awt.event.WindowEvent evt) {
closeDialog(evt);
}
});
jPanelMain.setFont(jPanelMain.getFont().deriveFont(jPanelMain.getFont().getStyle() | java.awt.Font.BOLD, jPanelMain.getFont().getSize()+2));
jPanelMain.setOpaque(false);
jButtonCancel.setText("Cancel");
jButtonCancel.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonCancelActionPerformed(evt);
}
});
jCheckBoxOption.setText("Disable this notification.");
jButtonContinue.setText("Continue");
jButtonContinue.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonContinueActionPerformed(evt);
}
});
jTextInfo.setEditable(false);
jTextInfo.setColumns(20);
jTextInfo.setLineWrap(true);
jTextInfo.setRows(5);
jTextInfo.setWrapStyleWord(true);
jScrollPane2.setViewportView(jTextInfo);
jProgressBar.setString("");
jProgressBar.setStringPainted(true);
javax.swing.GroupLayout jPanelMainLayout = new javax.swing.GroupLayout(jPanelMain);
jPanelMain.setLayout(jPanelMainLayout);
jPanelMainLayout.setHorizontalGroup(
jPanelMainLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanelMainLayout.createSequentialGroup()
.addComponent(jCheckBoxOption)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 63, Short.MAX_VALUE)
.addComponent(jButtonCancel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jButtonContinue))
.addComponent(jScrollPane2)
.addComponent(jProgressBar, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
jPanelMainLayout.setVerticalGroup(
jPanelMainLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanelMainLayout.createSequentialGroup()
.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 304, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jProgressBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanelMainLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jCheckBoxOption)
.addComponent(jButtonContinue)
.addComponent(jButtonCancel)))
);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jPanelMain, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jPanelMain, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addContainerGap())
);
pack();
}// </editor-fold>//GEN-END:initComponents
private void jButtonCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonCancelActionPerformed
doClose(CANCEL_BUTTON);
}//GEN-LAST:event_jButtonCancelActionPerformed
/**
* Closes the dialog
*/
private void closeDialog(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_closeDialog
if (tmrButtonLock == null || !tmrButtonLock.isRunning()) {
doClose(CANCEL_WINDOW);
}
}//GEN-LAST:event_closeDialog
private void jButtonContinueActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonContinueActionPerformed
doClose(OK);
}//GEN-LAST:event_jButtonContinueActionPerformed
private void doClose(int retStatus) {
if (jProgressBar.isVisible()) {
progressTask(retStatus, jProgressBar);
return;
}
if (tmrAutoClose != null) {
tmrAutoClose.stop();
tmrAutoClose = null;
}
if (tmrButtonLock != null) {
tmrButtonLock.stop();
tmrButtonLock = null;
}
returnStatus = retStatus;
setVisible(false);
dispose();
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton jButtonCancel;
private javax.swing.JButton jButtonContinue;
private javax.swing.JCheckBox jCheckBoxOption;
private javax.swing.JPanel jPanelMain;
private javax.swing.JProgressBar jProgressBar;
private javax.swing.JScrollPane jScrollPane2;
private javax.swing.JTextArea jTextInfo;
// End of variables declaration//GEN-END:variables
private int returnStatus = CANCEL_BUTTON;
}

109
src/lib/Localisation.java Normal file
View file

@ -0,0 +1,109 @@
/*
* 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 Version 2 as published by
* the Free Software Foundation.
*
* 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 lib;
import java.util.Locale;
import java.util.ResourceBundle;
/**
*
* @author Alistair Neil, <info@dazzleships.net>
*/
public final class Localisation {
// Private Stuff
private final ResourceBundle resourceBundle;
private String encoding = null;
public Localisation(String resource) {
String strSupportedLangs = "fr,en,pt";
encoding = this.getString("encoding");
if (!strSupportedLangs.contains(getLocale().getLanguage())) {
Locale.setDefault(new Locale("en", "GB"));
resourceBundle = ResourceBundle.getBundle(resource, Locale.getDefault());
} else {
resourceBundle = ResourceBundle.getBundle(resource);
}
}
/**
* Get the locale
*
* @return The locale
*/
public Locale getLocale() {
return Locale.getDefault();
}
public String toWebLanguageTag() {
return getLocale().toLanguageTag().replace('-', '_');
}
/**
* Get the country name for supplied iso2 code
*
* @param iso2
* @return Localised country name
*/
public String getDisplayCountry(String iso2) {
switch (iso2) {
case "A1":
case "A2":
case "O1":
case "U1":
return getString("iso" + iso2);
default:
Locale obj = new Locale("", iso2);
return obj.getDisplayCountry();
}
}
/**
* Get localised string using given key
*
* @param key
* @return localised string
*/
public String getString(String key) {
try {
if (!encoding.contentEquals("encoding")) {
byte[] text = resourceBundle.getString(key).getBytes("ISO8859-1");
return new String(text, encoding);
} else {
return resourceBundle.getString(key);
}
} catch (Exception ex) {
}
return key;
}
/**
* Get an array of localised strings using a key array or multiple keys
*
* @param keys
* @return localised string array
*/
public String[] getStrings(String... keys) {
String[] result = new String[keys.length];
int i = 0;
for (String key : keys) {
result[i++] = getString(key);
}
return result;
}
}

430
src/lib/NetFunctions.java Normal file
View file

@ -0,0 +1,430 @@
/*
* 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 lib;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.Proxy;
import java.net.Socket;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Locale;
import java.util.TimeZone;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JProgressBar;
/**
*
* @author Alistair Neil, <info@dazzleships.net>
*/
public class NetFunctions {
public static final int CONNECTION_FAILED = 0;
public static final int FILE_LOCAL_ISNEWER = 1;
public static final int FILE_RETRIEVED = 2;
public static final int FILE_FAILED = 3;
public static final int EVENT_URLOK = 1;
public static final int EVENT_URLFAILED = 2;
public static final int EVENT_NETLATENCY = 3;
public static final long LATENCY_FAIL = 9999;
public static final long LATENCY_UNKNOWN = 0;
private int intSocketTimeout = 8000;
private JProgressBar jpb;
public NetFunctions() {
}
/**
* Set default socket timeout
*
* @param timeout
*/
public void setSocketTimeout(int timeout) {
intSocketTimeout = timeout;
}
public void setProgressBar(JProgressBar jpb) {
this.jpb = jpb;
}
/**
* Save the contents of a URL to a file
*
* @param destfile File destination path
* @param sourceurl URL
* @param socket
* @param force Forces update regardless of age
* @return int File retieval status code
*/
public int saveURLContentToFile(String destfile, String sourceurl, Socket socket, boolean force) {
// Get a handle to our local file
File f = new File(destfile);
InputStream is = openStreamToURL(sourceurl, socket);
HttpPage hp = new HttpPage(is);
int result = FILE_FAILED;
try {
socket.setSoTimeout(intSocketTimeout);
hp.retrieveHeader();
if (hp.isHeaderOK()) {
result = FILE_LOCAL_ISNEWER;
if (hp.getLastModified() > f.lastModified() || force) {
if (hp.saveBodyToFile(destfile, jpb)) {
result = FILE_RETRIEVED;
Logger.getGlobal().logp(Level.INFO, this.getClass().getName(), "saveURLContentToFile", "Http body content retrieved");
} else {
Logger.getGlobal().logp(Level.WARNING, this.getClass().getName(), "saveURLContentToFile", "Failed to retrieve Http body content");
}
}
} else {
Logger.getGlobal().logp(Level.WARNING, this.getClass().getName(), "saveURLContentToFile", "Failed to retrieve Http header");
}
} catch (IOException ex) {
Logger.getGlobal().logp(Level.WARNING, this.getClass().getName(), "saveURLContentToFile", ex.getMessage());
} finally {
try {
is.close();
socket.close();
} catch (Exception ex) {
}
}
return result;
}
/**
* Make sure ipaddress is valid number
*
* @param ipaddress
* @return true if a valid ip address
*/
public boolean isIPAddress(String ipaddress) {
ipaddress = ipaddress.replace(".", "");
try {
Long.parseLong(ipaddress);
return true;
} catch (NumberFormatException ex) {
}
return false;
}
/**
* Get latency non threaded version
*
* @param surl Testing url
* @param proxy Specify a proxy, null == no proxy
* @param timeout Specify a timeout before declaring failure
* @return long latency in milliseconds
*/
public long getLatency(String surl, Proxy proxy, int timeout) {
long lngStart;
long lngResult;
HttpURLConnection conn = null;
try {
URL url = new URL(surl);
if (proxy == null) {
conn = (HttpURLConnection) url.openConnection();
} else {
conn = (HttpURLConnection) url.openConnection(proxy);
}
conn.setDoInput(true);
conn.setDefaultUseCaches(false);
conn.setConnectTimeout(timeout);
lngStart = System.currentTimeMillis();
conn.connect();
lngResult = System.currentTimeMillis() - lngStart;
} catch (IOException ex) {
lngResult = LATENCY_FAIL;
Logger.getGlobal().log(Level.WARNING, "getLatency {0}", ex.getMessage());
}
if (conn != null) {
conn.disconnect();
}
return lngResult;
}
/**
* Check web for updates and return version string if an update is available
*
* @param sourceurl URL to check
* @param s Socket
* @return String new version number
*/
public String getURLContentAsString(String sourceurl, Socket s) {
String result = null;
try {
s.setSoTimeout(intSocketTimeout);
try (InputStream is = openStreamToURL(sourceurl, s)) {
HttpPage hp = new HttpPage(is);
hp.retrieveHeader();
if (hp.isHeaderOK()) {
result = hp.getBodyAsString();
}
is.close();
}
} catch (Exception ex) {
Logger.getGlobal().log(Level.WARNING, "getURLAsString", ex.getMessage());
result = null;
} finally {
try {
s.close();
} catch (Exception ex) {
}
}
return result;
}
/**
* Open an inputstream to the given url on the given socket
*
* @param surl
* @param s
* @return inputstream
*/
public InputStream openStreamToURL(String surl, Socket s) {
URI uri;
try {
uri = new URI(surl);
String host = uri.getHost();
String path = uri.getRawPath();
if (path == null) {
return null;
}
PrintWriter request = new PrintWriter(s.getOutputStream());
request.print("GET " + path + " HTTP/1.1\r\n"
+ "Host: " + host + "\r\n"
+ "Connection: close\r\n\r\n"
);
request.flush();
InputStream inStream = s.getInputStream();
return inStream;
} catch (URISyntaxException | IOException ex) {
}
return null;
}
/**
* Store an http formatted web page
*/
public static final class HttpPage {
public static final String PATTERN_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss zzz";
public static final String PATTERN_RFC1036 = "EEEE, dd-MMM-yy HH:mm:ss zzz";
public static final String PATTERN_ASCTIME = "EEE MMM d HH:mm:ss yyyy";
private final TimeZone GMT = TimeZone.getTimeZone("GMT");
private final SimpleDateFormat format = new SimpleDateFormat("", Locale.US);
private final HashMap<String, String> hm = new HashMap<>();
private final InputStream israw;
/**
* Store webpage from the given input stream
*
* @param is
*/
public HttpPage(InputStream is) {
format.setTimeZone(GMT);
israw = is;
}
private String readLine(InputStream is) {
byte data;
String line = "";
String term = "";
try {
while (!"\r\n".equals(term)) {
data = (byte) is.read();
if (data == -1) {
return null;
}
line += String.valueOf((char) data);
if (((char) data) == '\r' || ((char) data) == '\n') {
term += String.valueOf((char) data);
} else {
term = "";
}
}
line = line.trim();
} catch (Exception ex) {
line = null;
}
return line;
}
/**
* Retrieve http header info
*/
public final void retrieveHeader() {
int colonpos;
String key;
String value;
String line;
try {
line = readLine(israw);
hm.put("Header-Response", line);
while (true) {
line = readLine(israw);
if (line.isEmpty()) {
if (hm.get("Content-Length") == null) {
line = readLine(israw);
if (!line.isEmpty()) {
try {
long contentsize = Long.parseLong(line, 16);
hm.put("Content-Length", String.valueOf(contentsize));
} catch (Exception ex) {
}
}
}
break;
}
colonpos = line.indexOf(':');
key = line.substring(0, colonpos);
value = line.substring(colonpos + 1);
hm.put(key, value.trim());
}
} catch (Exception ex) {
Logger.getGlobal().log(Level.WARNING, "retrieveHeader()", ex.getMessage());
hm.clear();
}
}
/**
* Retrieve http body as string should only be used with text content
*
* @return null if failed, otherwise returns the contents
*/
public final String getBodyAsString() {
String result = "";
try {
String temp = hm.get("Content-Length");
if (temp == null) {
return null;
}
long contentsize = Long.parseLong(temp);
while (contentsize-- != 0) {
result += (char) israw.read();
}
} catch (NumberFormatException | IOException ex) {
result = null;
Logger.getGlobal().log(Level.WARNING, "getBodyAsString()", ex.getMessage());
}
return result;
}
/**
* Save http body to a file, applies to all types of content
*
* @param dest File destination
* @param jpb Progress bar
* @return true if successful
*/
public final boolean saveBodyToFile(String dest, JProgressBar jpb) {
try {
String temp = hm.get("Content-Length");
if (temp == null) {
return false;
}
long contentsize = Long.parseLong(temp);
long bytereset = contentsize / 102;
long bytecount = bytereset;
int progress = 0;
File f = new File(dest);
try (FileOutputStream fos = new FileOutputStream(f)) {
if (jpb != null) {
jpb.setString(null);
}
while (contentsize-- != 0) {
fos.write(israw.read());
if (bytecount-- == 0) {
bytecount = bytereset;
if (jpb != null) {
jpb.setValue(progress++);
}
}
}
fos.close();
return true;
}
} catch (NumberFormatException | IOException ex) {
Logger.getGlobal().log(Level.WARNING, "saveBody()", ex.getMessage());
}
return false;
}
/**
* Get various properties of the web page
*
* @param key
* @return property string
*/
public final String getProperty(String key) {
return hm.get(key);
}
private long getHttpDate(String adate) {
try {
format.applyPattern(PATTERN_RFC1123);
return format.parse(adate).getTime();
} catch (Exception ex) {
}
try {
format.applyPattern(PATTERN_RFC1036);
return format.parse(adate).getTime();
} catch (Exception ex) {
}
try {
format.applyPattern(PATTERN_ASCTIME);
return format.parse(adate).getTime();
} catch (Exception ex) {
}
return -1;
}
public final long getLastModified() {
return getHttpDate(hm.get("Last-Modified"));
}
public final long getServerDate() {
return getHttpDate(hm.get("Date"));
}
public final long getExpires() {
return getHttpDate(hm.get("Expires"));
}
public final boolean isHeaderOK() {
String temp = hm.get("Content-Length");
if (temp == null) {
return false;
}
temp = hm.get("Header-Response");
if (temp == null) {
return false;
}
return temp.contains("200 OK");
}
}
}

870
src/lib/OSFunction.java Normal file
View file

@ -0,0 +1,870 @@
/*
* 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 lib;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.util.ArrayList;
import java.util.Locale;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
*
* @author Alistair Neil <info@dazzleships.net>
*/
public class OSFunction {
private static ArrayList<String> alProcesses;
/**
* Get process id
*
* @return Process id or -1 if not found
*/
public static String getOurProcessID() {
RuntimeMXBean rtb = ManagementFactory.getRuntimeMXBean();
String processName = rtb.getName();
Integer pid = tryPattern(processName);
return String.valueOf(pid);
}
/**
* Get process id from a process
*
* @param process
* @return process id as String
*/
public static String getProcessID(String process) {
Pattern pattern = Pattern.compile(" +");
String[] result = pattern.split(process.trim());
if (isWindows()) {
return result[1];
} else {
return result[0];
}
}
private static Integer tryPattern(String processName) {
Integer result = null;
Pattern pattern = Pattern.compile("^([0-9]+)@.+$", Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(processName);
if (matcher.matches()) {
result = Integer.parseInt(matcher.group(1));
}
return result;
}
/**
* Get OS version
*
* @return String OS version
*/
public static String getOSVersion() {
return System.getProperty("os.version");
}
/**
* Get user name
*
* @return String User name
*/
public static String getUserName() {
return System.getProperty("user.name");
}
/**
* Get users home folder
*
* @return String path to home folder
*/
public static String getUsersHomeFolder() {
return System.getProperty("user.home");
}
/**
* Get file separator
*
* @return String separator
*/
public static String getFileSeparator() {
return System.getProperty("file.separator");
}
/**
* Get users documents folder (Windows only)
*
* @return String path to documents folder
*/
public static String getUsersDocFolder() {
String strReturn = getUsersHomeFolder() + "\\Documents";
if (isWinXP()) {
strReturn = getUsersHomeFolder() + "\\My Documents";
}
return strReturn;
}
/**
* Get user settings path
*
* @return String path to user settings folder
*/
public static String getUserSettingsPath() {
String userSettingsPath;
if (isWindows()) {
userSettingsPath = getUsersHomeFolder() + "\\Application Data\\";
} else {
userSettingsPath = getUsersHomeFolder() + "/";
}
return userSettingsPath;
}
/**
* Get a specified application's settings folder, if null return this
* applications setting folder
*
* @param appname Application settings folder name
* @param appseries Application series (optional)
* @return String Path to the applications setting folder
*/
public static String getAppSettingsPath(String appname, String appseries) {
String appSettingsPath = getUserSettingsPath();
if (appname == null) {
return appSettingsPath;
}
if (isLinux()) {
appname = "." + appname;
}
appSettingsPath += appname + getFileSeparator();
if (appseries != null) {
appSettingsPath += appseries + getFileSeparator();
}
return appSettingsPath;
}
/**
* Get users current folder
*
* @return String Path to current folder
*/
public static String getUsersCurrentFolder() {
return System.getProperty("user.dir");
}
/**
* Get users temp folder
*
* @param path
* @return String Path to users temp folder
*/
public static String getTempFolder(String path) {
String result = System.getProperty("java.io.tmpdir");
String sep = "";
if (isLinux()) {
sep = getFileSeparator();
}
result += sep;
if (path != null && !path.isEmpty()) {
if (isWindows()) {
sep = getFileSeparator();
}
result = result + path + sep;
}
return result;
}
/**
* Get OS name, convenience method
*
* @return String
*/
public static String getOSName() {
return System.getProperty("os.name").toLowerCase();
}
/**
* Get OS architecture, convenience method
*
* @return String
*/
public static String getOSArch() {
return System.getProperty("os.arch");
}
/**
* Generic test for Windows platform
*
* @return boolean True if Windows
*/
public static boolean isWindows() {
return getOSName().contains("windows");
}
/**
* Specific test for Win 7
*
* @return boolean True if Win 7
*/
public static boolean isWin7() {
return getOSName().startsWith("windows 7");
}
/**
* Specific test for Win 8
*
* @return boolean True if Win 8
*/
public static boolean isWin8() {
return getOSName().startsWith("windows 8");
}
/**
* Specific test for Win 10
*
* @return boolean True if Win 10
*/
public static boolean isWin10() {
return getOSName().startsWith("windows 10");
}
/**
* Specific test for Win XP
*
* @return boolean True if Win XP
*/
public static boolean isWinXP() {
return getOSName().contentEquals("windows");
}
/**
* Generic test for Linux platform
*
* @return boolean True if Linux
*/
public static boolean isLinux() {
return getOSName().contains("linux");
}
/**
* Find a specific file, requires a series of paths where it might be found
* to be provided
*
* @param fname
* @param paths
* @return String path to file or null
*/
public static String findFile(String fname, String... paths) {
for (String s : paths) {
if (new File(s + fname).exists()) {
return s + fname;
}
}
return null;
}
/**
* Test to see if their are multiple instances of the this app running
*
* @param appname
* @return True if multiple instance
*/
public static boolean isMultipleInstance(String appname) {
if (alProcesses == null) {
alProcesses = getLiveProcesses();
}
ArrayList<String> processes = OSFunction.filterProcesses(appname);
return OSFunction.filterProcesses(processes, "java").size() > 1;
}
/**
* Cached list of processes
*
* @return list
*/
public static ArrayList<String> getCachedProcesses() {
return alProcesses;
}
/**
* Find processes matching the contents of filter
*
* @param processes
* @param filter
* @return ArrayList of matching processes
*/
public static ArrayList<String> filterProcesses(ArrayList<String> processes, String filter) {
ArrayList<String> result = new ArrayList<>();
if (processes != null && !processes.isEmpty()) {
if (filter != null) {
for (String s : processes) {
if (s.contains(filter)) {
result.add(s);
}
}
}
}
return result;
}
/**
* Find processes matching the contents of filter
*
* @param filter
* @return ArrayList of matching processes
*/
public static ArrayList<String> filterProcesses(String filter) {
ArrayList<String> result = new ArrayList<>();
if (!alProcesses.isEmpty()) {
if (filter != null) {
for (String s : alProcesses) {
if (s.contains(filter)) {
result.add(s);
}
}
}
}
return result;
}
/**
* Generic kill process with matching pid
*
* @param pid
* @return String kill result or null if failed
*/
public static String killProcess(String pid) {
if (isWindows()) {
return killProcessWindows(pid);
}
if (isLinux()) {
return killProcessLinux(pid);
}
return null;
}
/**
* Windows specific kill process with matching pid
*
* @param pid
* @return String kill result or null if failed
*/
private static String killProcessWindows(String pid) {
Process processKill;
try {
processKill = Runtime.getRuntime().exec("taskkill /F /pid " + pid);
return getProcessResult(processKill);
} catch (IOException ex) {
Logger.getGlobal().logp(Level.WARNING, OSFunction.class.getName(), "killProcessWindows", "", ex);
}
try {
processKill = Runtime.getRuntime().exec("tskill " + pid);
return getProcessResult(processKill);
} catch (IOException ex) {
Logger.getGlobal().logp(Level.WARNING, OSFunction.class.getName(), "killProcessWindows", "", ex);
}
return null;
}
/**
* Linux specific specific kill process with matching pid
*
* @param pid
* @return String kill result or null if failed
*/
private static String killProcessLinux(String pid) {
Process processKill = null;
try {
processKill = Runtime.getRuntime().exec("kill -9 " + pid);
} catch (IOException ex) {
Logger.getGlobal().logp(Level.WARNING, OSFunction.class.getName(), "killProcessLinux", "", ex);
}
return getProcessResult(processKill);
}
/**
* Set a files hidden status (Windows only)
*
* @param filepath Path to file includes filename
* @param hidden True/False
*/
public static void setFileHidden(String filepath, boolean hidden) {
if (isWindows()) {
try {
if (hidden) {
Runtime.getRuntime().exec("Attrib.exe +H " + filepath).waitFor();
} else {
Runtime.getRuntime().exec("Attrib.exe -H " + filepath).waitFor();
}
} catch (IOException | InterruptedException ex) {
Logger.getGlobal().logp(Level.WARNING, OSFunction.class.getName(), "setFileHidden", "", ex);
}
}
}
/**
* Get gnome 3 preference using schema name and key name
*
* @param schema
* @param key
* @return String preference value
*/
public static String getGnome3Pref(String schema, String key) {
Process p = launchProcess("gsettings", "get", schema, key);
String result = getProcessResult(p);
if (result != null) {
result = result.replace("'", "").replace("[", "").replace("]", "");
}
return result;
}
/**
* Set a gnome 3 boolean value using schema name and key name
*
* @param schema
* @param key
* @param value
*/
public static void setGnome3Pref(String schema, String key, boolean value) {
setGnome3Pref(schema, key, String.valueOf(value));
}
/**
* Set a gnome 3 string value using schema name and key name
*
* @param schema
* @param key
* @param value
*/
public static void setGnome3Pref(String schema, String key, String value) {
if (value == null || value.isEmpty()) {
resetGnome3Pref(schema, key);
} else {
launchProcess("gsettings", "set", schema, key, "'" + value + "'");
}
}
/**
* Reset a gnome3 value to its default. If key is null, it will reset the
* whole schema tree to its defaults
*
* @param schema
* @param key
*/
public static void resetGnome3Pref(String schema, String key) {
if (key == null) {
launchProcess("gsettings", "reset", schema);
} else {
launchProcess("gsettings", "reset", schema, key);
}
}
/**
* Get a kde preference string value using group name, key name and return
* contents of def on failure
*
* @param group
* @param key
* @param def
* @return String Preference value
*/
public static String getKDEPref(String group, String key, String def) {
// If exists read the file contents and find the matching key
String strKdePath = getKDEProxyPath();
if (strKdePath == null) {
return null;
}
String strTemp = null;
SimpleFile sf = new SimpleFile(strKdePath);
sf.openBufferedRead();
while ((strTemp = sf.readLine()) != null) {
if (strTemp.contains("[" + group + "]")) {
break;
}
}
if (strTemp == null) {
return def;
}
while ((strTemp = sf.readLine()) != null) {
if (strTemp.contains(key)) {
break;
}
}
sf.closeFile();
if (strTemp == null) {
return def;
}
strTemp = strTemp.substring(strTemp.indexOf('=') + 1);
return strTemp;
}
/**
* Set a kde string preference value using group name, key name
*
* @param group
* @param key
* @param value
*/
public static void setKDEPref(String group, String key, String value) {
// If exists read the file contents and find the matching key
String strKdePath = getKDEProxyPath();
if (strKdePath == null) {
return;
}
SimpleFile sf = new SimpleFile(strKdePath);
// Get file contents into a array list for further processing
String strTemp;
ArrayList<String> listContents = new ArrayList<>();
sf.openBufferedRead();
while ((strTemp = sf.readLine()) != null) {
listContents.add(strTemp);
}
sf.closeFile();
// Process contents of file and write it back out
sf.openBufferedWrite();
// Find Group entry
boolean entryfound = false;
while (!listContents.isEmpty()) {
strTemp = listContents.get(0);
sf.writeFile(strTemp, 1);
listContents.remove(0);
if (strTemp.contentEquals("[" + group + "]")) {
entryfound = true;
break;
}
}
// If no group entry found then write one
if (!entryfound) {
sf.writeFile("", 1);
sf.writeFile("[" + group + "]", 1);
}
// Find key entry
while (!listContents.isEmpty()) {
strTemp = listContents.get(0);
listContents.remove(0);
if (strTemp.contains(key)) {
break;
}
sf.writeFile(strTemp, 1);
}
sf.writeFile(key + "=" + value, 1);
// Write out rest of file
while (!listContents.isEmpty()) {
strTemp = listContents.get(0);
listContents.remove(0);
sf.writeFile(strTemp, 1);
}
sf.closeFile();
}
/**
* Set a kde boolean preference value using group name, key name
*
* @param group
* @param key
* @param value
*/
public static void setKDEPref(String group, String key, boolean value) {
setKDEPref(group, key, String.valueOf(value));
}
/**
* Set a kde integer preference value using group name, key name
*
* @param group
* @param key
* @param value
*/
public static void setKDEPref(String group, String key, int value) {
setKDEPref(group, key, String.valueOf(value));
}
/**
* Test for KDE installed (Linux only)
*
* @return String path to kde proxy file or null
*/
public static String getKDEProxyPath() {
if (isLinux()) {
File f = new File(getUsersHomeFolder() + "/.config/kioslaverc");
if (f.exists()) {
return f.getAbsolutePath();
}
f = new File(getUsersHomeFolder() + "/.kde/share/config/kioslaverc");
if (f.exists()) {
return f.getAbsolutePath();
}
f = new File(getUsersHomeFolder() + "/.kde4/share/config/kioslaverc");
if (f.exists()) {
return f.getAbsolutePath();
}
}
return null;
}
/**
* Test if gsettings installed (Linux only)
*
* @return String path to gsetttings
*/
public static String getGsettingsPath() {
// Verify if gsettings is installed
return findFile("gsettings", "/usr/bin/");
}
/**
* Convenience method to get the first resultant output of an executed
* process as a String
*
* @param aprocess
* @return String Process result
*/
public static String getProcessResult(Process aprocess) {
if (aprocess == null) {
return null;
}
return getProcessOutput(aprocess.getInputStream()).toString();
}
/**
* Obtain all output of an executed process.
*
* @param is
* @return ArrayList of Strings containing all generated output
*/
public static ArrayList<String> getProcessOutput(InputStream is) {
String line;
ArrayList<String> arrList = new ArrayList<>();
try {
try (BufferedReader input = new BufferedReader(new InputStreamReader(is))) {
while ((line = input.readLine()) != null) {
if (line.isEmpty()) {
continue;
}
arrList.add(line);
}
}
return arrList;
} catch (IOException ex) {
Logger.getGlobal().logp(Level.SEVERE, OSFunction.class.getName(), "getProcessResults", "", ex);
}
return null;
}
/**
* Launch an external process with arguments
*
* @param command
* @return Process
*/
public static Process launchProcess(String... command) {
try {
Process p = Runtime.getRuntime().exec(command);
if (p == null) {
Logger.getGlobal().logp(Level.WARNING, OSFunction.class.getName(), "launchProcess", "Failed Process", "");
}
return p;
} catch (IOException ex) {
Logger.getGlobal().logp(Level.WARNING, OSFunction.class.getName(), "launchProcess", "", ex);
}
return null;
}
/**
* Gets list of active system processes
*
* @return Arraylist of system process
*/
public static ArrayList<String> getLiveProcesses() {
if (isWindows()) {
return getActiveProcessesWindows();
} else {
return getActiveProcessesLinux();
}
}
/**
* Windows specific refresh or internal list of active system processes
*/
private static ArrayList<String> getActiveProcessesWindows() {
ArrayList<String> alResult = new ArrayList<>();
try {
Logger.getGlobal().info("refreshActiveProcessesWindows()");
Process p = Runtime.getRuntime().exec(System.getenv("windir") + "\\system32\\" + "tasklist.exe /v");
alResult = getProcessOutput(p.getInputStream());
if (alResult.size() > 1) {
// Remove second entry
alResult.remove(1);
}
return alResult;
} catch (IOException ex) {
Logger.getGlobal().logp(Level.WARNING, OSFunction.class.getName(), "refreshActiveProcessesWindows", "", ex);
}
return alResult;
}
/**
* Linux specific refresh or internal list of active system processes
*/
private static ArrayList<String> getActiveProcessesLinux() {
ArrayList<String> alResult = new ArrayList<>();
try {
Process process = Runtime.getRuntime().exec("ps ax");
alResult = getProcessOutput(process.getInputStream());
return alResult;
} catch (IOException ex) {
Logger.getGlobal().logp(Level.WARNING, OSFunction.class.getName(), "refreshActiveProcessesLinux", "", ex);
}
return alResult;
}
/**
* Get the name of the compositor
*
* @return name as String
*/
public static String getCompositor() {
String result = "unknown";
if (isWin7() || isWin8() || isWin10()) {
return "DWM";
}
if (isWindows()) {
return getOSName();
}
if (alProcesses == null) {
alProcesses = getLiveProcesses();
}
for (String s : alProcesses) {
if (s.contains("kwin")) {
result = "kwin";
break;
}
if (s.contains("compton")) {
result = "compton";
break;
}
if (s.contains("cinnamon")) {
result = "clutter";
break;
}
if (s.contains("marco")) {
result = "marco";
break;
}
if (s.contains("compiz")) {
result = "compiz";
break;
}
}
return result;
}
/**
* Get the name of the active desktop
*
* @return name as String
*/
public static String getActiveDesktop() {
if (isWindows()) {
return getOSName();
}
String result = "unknown";
if (alProcesses == null) {
alProcesses = getLiveProcesses();
}
for (String s : alProcesses) {
if (s.contains("cinnamon-session")) {
result = "cinnamon";
break;
}
if (s.contains("xfce4-session")) {
result = "xfce";
break;
}
if (s.contains("mate-session")) {
result = "mate";
break;
}
if (s.contains("gnome-shell")) {
result = "gnome3";
break;
}
if (s.contains("unity-settings-daemon")) {
result = "unity";
break;
}
if (s.contains("lxsession")) {
result = "lxde";
break;
}
if (s.contains("plasma-desktop")) {
result = "kde4";
break;
}
if (s.contains("plasmashell")) {
result = "kde5";
break;
}
if (s.contains("enlightenment")) {
result = "enlightenment";
break;
}
}
return result;
}
/**
* Clear active processes, mainly to reduce memory consumption when were
* done with them
*/
public static void clearActiveProcesses() {
alProcesses.clear();
alProcesses = null;
}
/**
* Get default language iso code
*
* @return language iso code
*/
public static String getLangCode() {
return Locale.getDefault().getLanguage();
}
}

895
src/lib/SimpleFile.java Normal file
View file

@ -0,0 +1,895 @@
/*
* 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 lib;
import java.io.*;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
/**
*
* @author Alistair Neil info@dazzleships.net
*/
public class SimpleFile {
public static final int PERIOD_MINUTES = 0;
public static final int PERIOD_HOURS = 1;
public static final int PERIOD_DAYS = 2;
public static final int NOTFOUND = 0;
public static final int FILEDELETEOK = 1;
public static final int FILEDELETEFAIL = 2;
private final int blockreadsize = 1024;
private BufferedReader br;
private BufferedWriter bw;
private ZipOutputStream zos;
private File f;
private String filter = "";
public SimpleFile() {
}
/**
* Constructor
*
* @param pathname
*/
public SimpleFile(String pathname) {
f = new File(pathname);
}
/**
* Set filename
*
* @param pathname
*/
public final void setFileName(String pathname) {
f = new File(pathname);
}
/**
* Set file
*
* @param file
*/
public final void setFile(File file) {
f = file;
}
/**
* Get file
*
* @return file
*/
public final File getFile() {
return f;
}
/**
* Close file and any resources such as buffered readers/writers that are
* attached to it.
*/
public final void closeFile() {
if (br != null) {
try {
br.close();
} catch (IOException ex) {
Logger.getLogger(SimpleFile.class.getName()).log(Level.SEVERE, null, ex);
}
br = null;
}
if (bw != null) {
try {
bw.close();
} catch (IOException ex) {
Logger.getLogger(SimpleFile.class.getName()).log(Level.SEVERE, null, ex);
}
bw = null;
}
}
/**
* Sets the file filter
*
* @param filter
*/
public final void setFileFilter(String filter) {
this.filter = filter;
}
/**
* Gets the current file filter
*
* @return Returns the file filter
*/
public final String getFileFilter() {
return filter;
}
public final static String getSeparator() {
return File.separator;
}
/**
* Creates a new folder
*
* @return True if successful
*/
public final boolean createFolder() {
if (f.exists()) {
return true;
}
return f.mkdirs();
}
/**
* Creates a new folder
*
* @param path The location of the new folder
* @return True if successful
*/
public final static boolean createFolder(String path) {
File fl = new File(path);
if (fl.exists()) {
return true;
}
return fl.mkdirs();
}
/**
* Create a new file
*
* @return True if file exist or is created
*/
public final boolean createFile() {
boolean createNewFile = true;
if (!f.exists()) {
try {
createFolder(f.getParent());
createNewFile = f.createNewFile();
} catch (IOException ex) {
createNewFile = false;
}
}
return createNewFile;
}
/**
* Gets the file list at the specified directory location based on filter
* contents
*
* @return An array of Files
*/
public final File[] getFileList() {
File[] arrFilesCache;
if (filter.isEmpty()) {
arrFilesCache = f.listFiles();
} else {
arrFilesCache = f.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.getPath().contains(filter);
}
});
}
return arrFilesCache;
}
public final File getOldestFile() {
long lngLastAge = new Date().getTime();
File oldest = null;
File[] arrFiles = getFileList();
for (File fi : arrFiles) {
if (fi.lastModified() < lngLastAge) {
lngLastAge = fi.lastModified();
oldest = fi;
}
}
return oldest;
}
public final static void walkFileTree(String path, ArrayList<File> files) {
walkFileTree(path, files, "");
}
public final static void walkFileTree(String path, ArrayList<File> files, final String filter) {
File[] arrFilesCache;
File root = new File(path);
if (filter.isEmpty()) {
arrFilesCache = root.listFiles();
} else {
arrFilesCache = root.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.getPath().contains(filter);
}
});
}
if (arrFilesCache == null) {
return;
}
for (File f : arrFilesCache) {
if (f.isDirectory()) {
walkFileTree(f.getAbsolutePath(), files, filter);
} else {
files.add(f);
}
}
}
/**
* Deletes the supplied list of files, be very carefull with this
*
* @param files
*/
public final void deleteFileList(File[] files) {
for (File fx : files) {
if (fx.isFile()) {
boolean delete = fx.delete();
}
}
}
/**
* Delete folder and its contents using specified folder path
*
* @param folder
* @return boolean True if successful
*/
public final static boolean deleteFolder(String folder) {
if (OSFunction.isLinux() && folder.contentEquals("/")) {
return false;
}
return deleteFolder(new File(folder));
}
/**
* Delete a folder and all of its contents works recursively
*
*/
private static boolean deleteFolder(File folder) {
if (!folder.exists()) {
return false;
}
for (File fx : folder.listFiles()) {
if (fx.isDirectory()) {
deleteFolder(fx);
} else {
boolean delete = fx.delete();
}
}
return folder.delete();
}
/**
* Wipe folder and its contents using specified folder path
*
* @param folder
*/
public final static void secureWipeFolder(String folder) {
if (OSFunction.isLinux() && folder.contentEquals("/")) {
return;
}
secureWipeFolder(new File(folder));
}
/**
* Wipe folder and its contents using specified File
*
* @param folder
*/
public final static void secureWipeFolder(File folder) {
if (!folder.exists()) {
return;
}
for (File fx : folder.listFiles()) {
if (fx.isDirectory()) {
secureWipeFolder(fx);
} else {
secureWipe(fx);
}
}
folder = renameTo(folder, "0000000");
folder.delete();
}
/**
* Wipe file using specified filename
*
* @param filename
*/
public final static void secureWipe(String filename) {
secureWipe(new File(filename));
}
/**
* Wipe file using specified File
*
* @param f
*/
public final static void secureWipe(File f) {
if (!f.exists()) {
return;
}
FileOutputStream fos = null;
byte b[] = new byte[4096];
long i = f.length() / 4096;
int remainder = (int) (f.length() % 4096);
byte r[] = new byte[remainder];
try {
// Overwrite with zeros
fos = new FileOutputStream(f, false);
while (i-- > 0) {
fos.write(b);
fos.flush();
}
fos.write(r);
fos.close();
// Zero file length
b = new byte[0];
fos = new FileOutputStream(f, false);
fos.write(b);
} catch (IOException ex) {
Logger.getLogger(SimpleFile.class
.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
if (fos != null) {
fos.close();
}
// Rename file
f = renameTo(f, "0000000000");
// Delete file
f.delete();
} catch (IOException ex) {
}
}
}
public final static File renameTo(File f, String newname) {
String path = f.getParent();
if (path != null) {
path += File.separator + newname;
File nf = new File(path);
if (f.renameTo(nf)) {
return nf;
}
}
return f;
}
/**
* Copy multiple files from one folder to another
*
* @param from The from path
* @param to The to path
* @param ignore
*/
public final static void copyFolderContents(String from, String to, String ignore) {
try {
File ourFile = new File(from);
for (File fx : ourFile.listFiles()) {
if (!ignore.contains(fx.getName())) {
copyFromTo(fx.getAbsolutePath(), to + fx.getName());
}
}
} catch (Exception ex) {
Logger.getGlobal().logp(Level.WARNING, "SimpleFile", "copyFolderContents()", "", ex);
}
}
/**
* Returns an array of filenames, array if populated from the offset value
* onwards
*
* @param offset
* @return An array of filenames
*/
public final String[] getFilenames(int offset) {
String filename;
File[] fileList = getFileList();
String[] result = new String[fileList.length + offset];
try {
for (int i = 0; i < fileList.length; i++) {
filename = fileList[i].getName();
result[i + offset] = filename.substring(0, filename.indexOf('.'));
}
return result;
} catch (Exception ex) {
Logger.getGlobal().logp(Level.WARNING, this.getClass().getName(), "getFilenames(int offset)", "", ex);
return null;
}
}
/**
* Test to see if path exists
*
* @return Returns true if file exists
*/
public final boolean exists() {
return f.exists();
}
/**
* Test to see if path exists
*
* @param pathname The pathname to check for
* @return Returns true if file exists
*/
public final static boolean exists(String pathname) {
return new File(pathname).exists();
}
/**
* Deletes file
*
* @return Returns true if successful
*/
public final boolean delete() {
return f.delete();
}
/**
* Deletes the specified file
*
* @param filename
* @return Returns true if successful
*/
public final static boolean delete(String filename) {
return new File(filename).delete();
}
/**
*
* @param toname
* @return Returns true if successful
*/
public final boolean renameFile(String toname) {
return f.renameTo(new File(toname));
}
/**
* Opens a buffered file for read
*
* @return Returns null if failed
*/
public final BufferedReader openBufferedRead() {
try {
br = new BufferedReader(new FileReader(f));
return br;
} catch (FileNotFoundException ex) {
}
return null;
}
/**
* Use this if you need access to a file within a jar
*
*/
public final void openBufferedResource() {
try {
String path = f.getPath();
path = path.replace('\\', '/');
InputStream is = getClass().getResourceAsStream(path);
br = new BufferedReader(new InputStreamReader(is));
} catch (Exception ex) {
Logger.getGlobal().logp(Level.WARNING, this.getClass().getName(), "openBufferedRead(int filehandle)", "", ex);
}
}
/**
* Opens a buffered file for append
*
*/
public final void openBufferedAppend() {
try {
bw = new BufferedWriter(new FileWriter(f, true));
} catch (IOException ex) {
Logger.getGlobal().logp(Level.WARNING, this.getClass().getName(), "openBufferedAppend()", "", ex);
}
}
/**
* Read a single line from a text file
*
* @return Contents as String
*/
public final String readLine() {
try {
return br.readLine();
} catch (IOException ex) {
Logger.getGlobal().logp(Level.WARNING, this.getClass().getName(), "readLine(int filehandle)", "", ex);
}
return null;
}
/**
* Read bytes from previously opened BufferedReader
*
* @return Returns the entire contents from a file
*/
public final String readEntireFile() {
char[] cb = new char[blockreadsize];
StringBuilder sb = new StringBuilder();
int bytes;
try {
while (br.ready()) {
bytes = br.read(cb);
sb.append(cb, 0, bytes);
}
return sb.toString();
} catch (IOException ex) {
Logger.getGlobal().logp(Level.WARNING, this.getClass().getName(), "readEntireFile()", "", ex);
}
return "";
}
public final FileInputStream openFileInputStream(String filename) {
try {
return new FileInputStream(new File(filename));
} catch (FileNotFoundException ex) {
Logger.getGlobal().logp(Level.WARNING, this.getClass().getName(), "openFileInputStream()", "", ex);
return null;
}
}
/**
* Opens a file output stream
*
* @return Returns Opened file output stream
*/
public final FileOutputStream openFileOutputStream() {
try {
return new FileOutputStream(f);
} catch (FileNotFoundException ex) {
Logger.getGlobal().logp(Level.WARNING, this.getClass().getName(), "openFileOutputStream()", "", ex);
return null;
}
}
/**
* Opens a buffered file for write
*
*/
public final void openBufferedWrite() {
try {
bw = new BufferedWriter(new FileWriter(f));
} catch (IOException ex) {
Logger.getGlobal().logp(Level.WARNING, this.getClass().getName(), "openBufferedWrite()", "", ex);
}
}
public final void flushWriter() {
try {
bw.flush();
} catch (IOException ex) {
}
}
/**
* Write to a previously opened output file
*
* @param data The data to be written
* @param newlines The number of newlines to generate
*/
public final void writeFile(String data, int newlines) {
try {
bw.write(data);
while (newlines > 0) {
bw.newLine();
newlines--;
}
} catch (IOException ex) {
Logger.getGlobal().logp(Level.WARNING, this.getClass().getName(),
"writeToFile(" + data + "," + String.valueOf(newlines) + ")", "", ex);
}
}
/**
* Write to a previously opened output file
*
* @param data The character data to be written
* @param nochars
*/
public final void writeFile(char[] data, int nochars) {
try {
bw.write(data, 0, nochars);
} catch (IOException ex) {
Logger.getGlobal().logp(Level.WARNING, this.getClass().getName(), "writeToFile()", "", ex);
}
}
/**
* Copy file to
*
* @param frompath
* @param topath
*/
public final static void copyFromTo(String frompath, String topath) {
try {
Path source = new File(frompath).toPath();
Path dest = new File(topath).toPath();
Files.copy(source, dest, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException ex) {
Logger.getGlobal().logp(Level.WARNING, "SimpleFile", "copyFromTo()", "", ex);
}
}
public final static void mergeFiles(String srcpath1, String srcpath2, String destpath) {
try (OutputStream os = new FileOutputStream(new File(destpath))) {
Path source = new File(srcpath1).toPath();
Files.copy(source, os);
source = new File(srcpath2).toPath();
Files.copy(source, os);
os.close();
} catch (IOException ex) {
Logger.getGlobal().logp(Level.WARNING, "SimpleFile", "mergeFiles", "", ex);
}
}
/**
* Get the age of a specified file
*
* @param filepath
* @param period
* @return Age of file as float
*/
public final static float getAgeOfFile(String filepath, int period) {
File fx = new File(filepath);
if (!fx.exists()) {
return -1;
}
float fltAge = System.currentTimeMillis() - fx.lastModified();
switch (period) {
case PERIOD_MINUTES:
return fltAge / 60000;
case PERIOD_HOURS:
return fltAge / (60000 * 60);
case PERIOD_DAYS:
return fltAge / (60000 * 60 * 24);
}
return -1;
}
/**
* Test to see our file is older in minutes, returns true if it is
*
* @param filename
* @param minutes
* @return boolean
*/
public final static boolean isMinutesOlder(String filename, long minutes) {
long lngAge = System.currentTimeMillis() - new File(filename).lastModified();
return lngAge > (60000 * minutes);
}
/**
* Test to see our file is older in hours, returns true if it is
*
* @param filename
* @param hours
* @return boolean
*/
public final static boolean isHoursOlder(String filename, long hours) {
long lngAge = System.currentTimeMillis() - new File(filename).lastModified();
return lngAge > (60000 * 60 * hours);
}
/**
* Test to see our file is older in days, returns true if it is
*
* @param filename
* @param days
* @return boolean
*/
public final static boolean isDaysOlder(String filename, long days) {
long lngAge = System.currentTimeMillis() - new File(filename).lastModified();
return lngAge > (60000 * 60 * 24 * days);
}
/**
* Opens a zipstream. returns false if it fails
*
* @param level
* @return an open zipstream
*/
public final boolean openZipStream(int level) {
try {
zos = new ZipOutputStream(new FileOutputStream(f.getAbsolutePath()));
if (level < 0 || level > 9) {
level = 6;
}
zos.setLevel(level);
return true;
} catch (FileNotFoundException ex) {
}
return false;
}
/**
* Close a zip stream
*/
public final void closeZipStream() {
if (zos != null) {
try {
zos.close();
} catch (IOException ex) {
}
}
}
public final static void compress(String source, String dest) {
final Path pathSource = Paths.get(source);
try {
final ZipOutputStream outputStream = new ZipOutputStream(new FileOutputStream(dest));
Files.walkFileTree(pathSource, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) {
try {
Path targetFile = pathSource.relativize(file);
outputStream.putNextEntry(new ZipEntry(targetFile.toString()));
byte[] bytes = Files.readAllBytes(file);
outputStream.write(bytes, 0, bytes.length);
outputStream.closeEntry();
} catch (IOException e) {
}
return FileVisitResult.CONTINUE;
}
});
outputStream.close();
} catch (IOException e) {
}
}
/**
* Add files to a zip file
*
* @param srcfiles An array of Files
* @return boolean True if successful
*/
public final boolean addFilesToZip(File... srcfiles) {
FileInputStream in = null;
if (srcfiles == null || srcfiles.length == 0) {
return false;
}
try {
for (File fx : srcfiles) {
in = new FileInputStream(fx);
// name the file inside the zip file
zos.putNextEntry(new ZipEntry(fx.getName()));
byte[] b = Files.readAllBytes(Paths.get(fx.getAbsolutePath()));
zos.write(b, 0, b.length);
in.close();
}
return true;
} catch (IOException ex) {
} finally {
try {
if (in != null) {
in.close();
}
} catch (IOException ex) {
}
}
return false;
}
/**
* Extracts a zip file to a supplied location
*
* @param destpath Destination for contents of zip file
* @return True if successful
*/
public final boolean extractZipTo(String destpath) {
FileOutputStream fos;
final int BUFFER = 2048;
try {
FileInputStream fis = new FileInputStream(f);
try (ZipInputStream zin = new ZipInputStream(new BufferedInputStream(fis))) {
ZipEntry entry;
while ((entry = zin.getNextEntry()) != null) {
int count;
byte data[] = new byte[BUFFER];
try {
fos = new FileOutputStream(destpath + File.separator + entry.getName());
} catch (FileNotFoundException ex) {
continue;
}
try (BufferedOutputStream dest = new BufferedOutputStream(fos, 2048)) {
while ((count = zin.read(data, 0, BUFFER)) != -1) {
dest.write(data, 0, count);
}
dest.flush();
dest.close();
}
fos.close();
}
zin.close();
fis.close();
}
return true;
} catch (IOException ex) {
Logger.getGlobal().logp(Level.WARNING, this.getClass().getName(), "extractZipTo()", "", ex);
}
return false;
}
public final static boolean objectWrite(String filepath, Object o) {
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(new FileOutputStream(new File(filepath)));
} catch (FileNotFoundException ex) {
} catch (IOException ex) {
}
if (oos == null) {
return false;
}
try {
oos.writeObject(o);
oos.close();
return true;
} catch (IOException ex) {
}
return false;
}
public final static Object objectRead(String filepath, Object defObject) {
ObjectInputStream oos = null;
try {
oos = new ObjectInputStream(new FileInputStream(new File(filepath)));
} catch (FileNotFoundException ex) {
} catch (IOException ex) {
}
if (oos == null) {
return defObject;
}
Object result = defObject;
try {
result = oos.readObject();
} catch (IOException | ClassNotFoundException ex) {
}
return result;
}
}

289
src/lib/SimpleProps.java Normal file
View file

@ -0,0 +1,289 @@
/*
* 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 lib;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author Alistair Neil <info@dazzleships.net>
*/
public final class SimpleProps {
private final File fileStore;
private final String comment;
private final ArrayList<String> alChanged;
private boolean boolDefaultEnabled;
private final Properties defProps = new Properties();
private Properties appProps;
/**
* Constructor, requires
*
* @param filepath
* @param comment
*/
public SimpleProps(String filepath, String comment) {
alChanged = new ArrayList<>();
fileStore = new File(filepath);
this.comment = comment;
}
/**
* Enable/disable default mode
*
* @param enabled
*/
public void setDefaultModeEnabled(boolean enabled) {
boolDefaultEnabled = enabled;
}
/**
* Set a long number property
*
* @param property
* @param num
*/
public void setLong(String property, long num) {
String value = String.valueOf(num);
setString(property, value);
}
/**
* Get a long number property
*
* @param property
* @return A long number
*/
public long getLong(String property) {
try {
if (boolDefaultEnabled) {
return Long.parseLong(defProps.getProperty(property));
} else {
return Long.parseLong(appProps.getProperty(property));
}
} catch (NumberFormatException ex) {
Logger.getGlobal().logp(Level.WARNING, this.getClass().getName(), "getLong", "", ex);
return -1;
}
}
/**
* Set a integer number property
*
* @param property
* @param num
*/
public void setInt(String property, int num) {
String value = String.valueOf(num);
setString(property, value);
}
/**
* Get an integer number property
*
* @param property
* @return an integer
*/
public int getInt(String property) {
try {
if (boolDefaultEnabled) {
return Integer.parseInt(defProps.getProperty(property));
} else {
return Integer.parseInt(appProps.getProperty(property));
}
} catch (NumberFormatException ex) {
Logger.getGlobal().logp(Level.WARNING, this.getClass().getName(), "getInt", "", ex);
return -1;
}
}
/**
* Set a boolean property
*
* @param property
* @param enabled
*/
public void setBool(String property, boolean enabled) {
if (enabled) {
setString(property, "true");
} else {
setString(property, "false");
}
}
/**
* Get a boolean property
*
* @param property
* @return boolean
*/
public boolean getBool(String property) {
try {
String result;
if (boolDefaultEnabled) {
result = defProps.getProperty(property).toLowerCase();
} else {
result = appProps.getProperty(property).toLowerCase();
}
return result.contentEquals("true");
} catch (Exception ex) {
Logger.getGlobal().logp(Level.WARNING, this.getClass().getName(), "getBool", "", ex);
return false;
}
}
/**
* Set a String property
*
* @param key
* @param value
* @return String
*/
public Object setString(String key, String value) {
value = value.trim();
if (boolDefaultEnabled) {
return defProps.setProperty(key, value);
}
String prop = appProps.getProperty(key);
if (prop == null) {
prop = "null";
}
if (prop.contentEquals(value)) {
if (alChanged.contains(key)) {
alChanged.remove(key);
}
} else {
if (!alChanged.contains(key)) {
alChanged.add(key);
}
}
return appProps.setProperty(key, value);
}
/**
* Get a String property
*
* @param key
* @return String or null
*/
public String getString(String key) {
try {
String prop;
if (boolDefaultEnabled) {
prop = defProps.getProperty(key);
} else {
prop = appProps.getProperty(key);
}
if (prop == null) {
prop = "";
}
return prop;
} catch (Exception ex) {
Logger.getGlobal().logp(Level.WARNING, this.getClass().getName(), "getString", "", ex);
return null;
}
}
/**
* Save to xml file
*/
public void save() {
alChanged.clear();
OutputStream os = null;
try {
os = new FileOutputStream(fileStore);
appProps.storeToXML(os, comment);
} catch (Exception ex) {
Logger.getLogger(SimpleProps.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
if (os != null) {
os.close();
}
} catch (Exception ex) {
}
}
}
/**
* Load from xml file
*/
public void load() {
InputStream is = null;
try {
if (!fileStore.exists()) {
fileStore.getParentFile().mkdirs();
fileStore.createNewFile();
save();
}
is = new FileInputStream(fileStore);
appProps.loadFromXML(is);
} catch (IOException ex) {
Logger.getLogger(SimpleProps.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
if (is != null) {
is.close();
}
} catch (Exception ex) {
}
}
alChanged.clear();
}
/**
* Delete the properties file store
*
* @return true if successful
*/
public boolean delete() {
if (fileStore.exists()) {
return fileStore.delete();
}
return false;
}
/**
* Get a comma separated list of properties that were changed
*
* @return A String of property keys that were changed
*/
public String getChangedProperties() {
return alChanged.toString();
}
/**
* Reset to defaults
*/
public void resetToDefaults() {
appProps = new Properties(defProps);
alChanged.clear();
}
}

502
src/lib/SwingTrayIcon.java Normal file
View file

@ -0,0 +1,502 @@
/*
* 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 lib;
import java.awt.AWTEvent;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GraphicsConfiguration;
import java.awt.Insets;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.Window.Type;
import java.awt.event.AWTEventListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.regex.Pattern;
import javax.swing.BorderFactory;
import javax.swing.JDialog;
import javax.swing.JTextArea;
import javax.swing.JToolTip;
import javax.swing.JWindow;
import javax.swing.UIManager;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
/**
*
* @author Alistair Neil <info@dazzleships.net>
*/
public final class SwingTrayIcon {
private InfoTip infoToolTip;
private JDialog jdiagPopup;
private TrayPopupMenu trayPopupMenu;
private AWTEventListener awtEventListen;
private volatile boolean mouseExited = false;
private SystemTray st = null;
private GraphicsConfiguration gc = null;
private Point mouseloc;
private TrayIcon ti;
private boolean loaded;
public SwingTrayIcon(GraphicsConfiguration gc, String resourcepath) {
loaded = false;
if (!SystemTray.isSupported()) {
return;
}
try {
st = SystemTray.getSystemTray();
ClassLoader cl = this.getClass().getClassLoader();
ti = new TrayIcon(new javax.swing.ImageIcon(cl.getResource(resourcepath)).getImage());
} catch (Exception ex) {
return;
}
ti.setImageAutoSize(true);
this.gc = gc;
initDiagPopup();
if (OSFunction.isLinux()) {
infoToolTip = new InfoTip();
infoToolTip.setFocusable(false);
}
initMouseHandler();
}
private void initMouseHandler() {
// We need a global mouse listener due to the way TrayIcon intercepts
// mousemovements but doesnt feed all the events back to us
awtEventListen = new java.awt.event.AWTEventListener() {
@Override
public void eventDispatched(AWTEvent event) {
// Catch mouse event so we can easily get coords
final MouseEvent e = (MouseEvent) event;
if (!(e.getSource() instanceof TrayIcon)) {
return;
}
mouseloc = MouseInfo.getPointerInfo().getLocation();
switch (e.getID()) {
case MouseEvent.MOUSE_ENTERED:
if (infoToolTip == null || trayPopupMenu.isVisible()) {
return;
}
mouseExited = false;
// Raise tooltip
Thread t = new Thread(new java.lang.Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
}
if (!trayPopupMenu.isVisible() && !mouseExited) {
infoToolTip.setLocation(getPlacementPosition(mouseloc, infoToolTip.getWidth(), infoToolTip.getHeight(), true));
infoToolTip.setVisible(true);
} else {
infoToolTip.setVisible(false);
}
}
});
t.start();
break;
case MouseEvent.MOUSE_EXITED:
mouseExited = true;
if (infoToolTip != null) {
infoToolTip.setVisible(false);
}
break;
case MouseEvent.MOUSE_RELEASED:
if (e.getButton() == MouseEvent.BUTTON3) {
if (infoToolTip != null) {
infoToolTip.setVisible(false);
}
mouseExited = true;
raisePopupMenu(mouseloc);
}
break;
}
}
};
Toolkit.getDefaultToolkit().addAWTEventListener(awtEventListen, AWTEvent.MOUSE_EVENT_MASK);
}
/**
* Initialise our hidden dialog which we use to grab focus so that the
* popumenu can be closed whenever we click on the desktop
*/
private void initDiagPopup() {
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
jdiagPopup = new JDialog();
jdiagPopup.setUndecorated(true);
jdiagPopup.setMinimumSize(new Dimension(0, 0));
jdiagPopup.setBounds(new Rectangle(0, 0));
jdiagPopup.setType(Type.POPUP);
jdiagPopup.setFocusable(false);
jdiagPopup.setAutoRequestFocus(false);
try {
jdiagPopup.setLocation(new Point(screenSize.width, screenSize.height));
jdiagPopup.setOpacity(0);
} catch (Exception ex) {
}
jdiagPopup.addComponentListener(new java.awt.event.ComponentListener() {
@Override
public void componentResized(ComponentEvent e) {
}
@Override
public void componentMoved(ComponentEvent e) {
}
@Override
public void componentShown(ComponentEvent e) {
trayPopupMenu.setVisible(true);
}
@Override
public void componentHidden(ComponentEvent e) {
}
});
}
public void dispose() {
// Remove from system tray
unload();
// Cleanup assets that may prevent shutdown
if (ti != null) {
for (MouseListener ml : ti.getMouseListeners()) {
ti.removeMouseListener(ml);
}
}
if (awtEventListen != null) {
Toolkit.getDefaultToolkit().removeAWTEventListener(awtEventListen);
awtEventListen = null;
}
if (trayPopupMenu != null) {
for (PopupMenuListener pml : trayPopupMenu.getPopupMenuListeners()) {
trayPopupMenu.removePopupMenuListener(pml);
}
trayPopupMenu = null;
}
if (jdiagPopup != null) {
for (ComponentListener cl : jdiagPopup.getComponentListeners()) {
jdiagPopup.removeComponentListener(cl);
}
jdiagPopup.dispose();
jdiagPopup = null;
}
if (infoToolTip != null) {
infoToolTip.dispose();
infoToolTip = null;
}
st = null;
}
public void disable() {
unload();
st = null;
}
/**
* Set tray right click popup
*
* @param tpm
*/
public void setTrayPopupMenu(TrayPopupMenu tpm) {
trayPopupMenu = tpm;
if (tpm == null || ti == null) {
return;
}
trayPopupMenu.setFocusable(false);
// Add popup menu listener to detect when it is hidden
trayPopupMenu.addPopupMenuListener(new javax.swing.event.PopupMenuListener() {
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
}
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
jdiagPopup.setVisible(false);
}
@Override
public void popupMenuCanceled(PopupMenuEvent e) {
jdiagPopup.setVisible(false);
}
});
trayPopupMenu.setEnabled(true);
trayPopupMenu.setInvoker(jdiagPopup);
}
/**
* Open tray popup
*
*/
private void raisePopupMenu(Point mouseloc) {
if (trayPopupMenu != null) {
// Set onscreen location of trayPopup
Point p = getPlacementPosition(mouseloc, trayPopupMenu.getVisibleRect().width, trayPopupMenu.getHeight(), false);
trayPopupMenu.setLocation(p);
jdiagPopup.setVisible(true);
}
}
/**
* Calculate onscreen placement position based on mouse pointer position
*
* @param boxwidth
* @param boxheight
* @param centre
* @return Point
*/
private Point getPlacementPosition(Point coords, int boxwidth, int boxheight, boolean istooltip) {
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Insets screenInsets;
Point result = new Point();
double x, y, limit;
int yoff = 0;
if (OSFunction.isLinux()) {
screenInsets = Toolkit.getDefaultToolkit().getScreenInsets(gc);
int i = screenInsets.bottom + screenInsets.left + screenInsets.right
+ screenInsets.top;
// If all insets are zero then offset them all by 32, bit of a hack
// for desktops that allow intelligent hiding of tray panel
if (i == 0) {
screenInsets = new Insets(32, 32, 32, 32);
}
} else {
screenInsets = new Insets(0, 0, 0, 0);
}
// Calculate X axis positioning
x = coords.x;
if (x > (screenSize.getWidth() / 2)) {
limit = screenSize.width - screenInsets.right;
if (x + boxwidth > limit) {
if (screenInsets.right == 0) {
x -= boxwidth;
} else {
x = limit - boxwidth;
}
}
} else {
limit = screenInsets.left;
if (x < limit) {
x = limit;
}
}
// Calculate Y axis positioning
y = coords.y;
if (y > (screenSize.getHeight() / 2)) {
// Bottom
if (istooltip && screenInsets.bottom == 0) {
yoff = (int) ((ti.getSize().getHeight() + 1) / 2);
}
} else // Bottom
{
if (istooltip && screenInsets.top == 0) {
yoff = (int) ((ti.getSize().getHeight() + 1) / 2);
}
}
if (screenInsets.top != 0 && y < screenInsets.top) {
y += (screenInsets.top - y);
}
limit = screenSize.height - screenInsets.bottom;
if (y + yoff + boxheight > limit) {
if (yoff > 0) {
y -= (boxheight + yoff);
} else if (screenInsets.bottom == 0) {
y -= (boxheight + yoff);
} else {
y = limit - boxheight;
}
} else {
y += yoff;
}
result.setLocation(x, y);
return result;
}
/**
* Set info tip text
*
* @param text
*/
public void setInfoTip(String text) {
if (ti == null) {
return;
}
if (OSFunction.isLinux()) {
// Check to see if tay icon need reloaded
if (SystemTray.isSupported() && isLoaded() && st.getTrayIcons().length == 0) {
try {
st.add(ti);
} catch (Exception ex) {
}
}
// Update tooltip (Linux only)
if (infoToolTip != null) {
infoToolTip.setText(text);
if (infoToolTip.isVisible()) {
infoToolTip.setLocation(getPlacementPosition(mouseloc, infoToolTip.getWidth(), infoToolTip.getHeight(), true));
}
}
} else {
// Update tooltip (Windows Only)
ti.setToolTip(text);
}
}
/**
* Display desktop message (Windows only)
*
* @param title
* @param body
*/
public void displayMessage(String title, String body) {
if (ti != null) {
ti.displayMessage(title, body, TrayIcon.MessageType.INFO);
}
}
/**
* Load tray icon
*/
public void load() {
// I know this looks odd but it is required for onscreen positioning
// of the tray popup to work
if (trayPopupMenu != null) {
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
trayPopupMenu.setLocation(screenSize.height, screenSize.width);
trayPopupMenu.setVisible(true);
trayPopupMenu.setVisible(false);
}
// Add this tray icon to system tray
try {
if (st != null) {
st.add(ti);
loaded = true;
}
} catch (Exception ex) {
loaded = false;
}
}
/**
* Unload Tray icon
*/
public void unload() {
// Remove the tray icon from system tray
if (st != null) {
st.remove(ti);
}
loaded = false;
}
/**
* Add a mouse listener
*
* @param ml
*/
public void addMouseListener(MouseListener ml) {
if (ti != null) {
ti.addMouseListener(ml);
}
}
/**
* Is tray icon loaded
*
* @return ture if it is
*/
public boolean isLoaded() {
return loaded;
}
public boolean isSupported() {
return st != null;
}
/**
* Info tip object
*/
private static final class InfoTip extends JWindow {
JTextArea jta;
Pattern p = Pattern.compile("\n");
public InfoTip() {
initInfoTip();
}
private void initInfoTip() {
setType(Type.POPUP);
jta = new JTextArea();
add(jta);
JToolTip jtt = jta.createToolTip();
jta.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY));
jta.setBackground(new Color(jtt.getBackground().getRGB()));
jta.setForeground(new Color(jtt.getForeground().getRGB()));
setBackground(jta.getBackground());
jta.setOpaque(true);
jta.setEditable(false);
jta.setLineWrap(true);
jta.setWrapStyleWord(true);
jta.setVisible(true);
setEnabled(true);
}
/**
* Set info tip text
*
* @param text
*/
public void setText(String text) {
String[] strs = p.split(text);
String largest = "";
int longest = 0;
int width;
for (String s : strs) {
width = jta.getFontMetrics(jta.getFont()).stringWidth(s);
if (width > longest) {
largest = s;
longest = width;
}
}
jta.setText(" " + text.replace("\n", "\n "));
width = jta.getFontMetrics(jta.getFont()).stringWidth(largest + "XXX");
int lineheight = jta.getFontMetrics(jta.getFont()).getHeight() + 1;
int boxheight = jta.getLineCount() * (lineheight);
setSize(width, boxheight);
}
}
}

View file

@ -0,0 +1,93 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.5" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
<Properties>
<Property name="defaultCloseOperation" type="int" value="2"/>
<Property name="resizable" type="boolean" value="false"/>
</Properties>
<SyntheticProperties>
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
</SyntheticProperties>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane1" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<Component id="jButtonLaunchURL" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<Component id="jButtonClose" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="jScrollPane1" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jButtonClose" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jButtonLaunchURL" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTextArea" name="jTextArea">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="columns" type="int" value="40"/>
<Property name="lineWrap" type="boolean" value="true"/>
<Property name="rows" type="int" value="20"/>
<Property name="text" type="java.lang.String" value="&#xa;"/>
<Property name="wrapStyleWord" type="boolean" value="true"/>
</Properties>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JButton" name="jButtonClose">
<Properties>
<Property name="text" type="java.lang.String" value="Close"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButtonCloseActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="jButtonLaunchURL">
<Properties>
<Property name="text" type="java.lang.String" value="URL Desc"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButtonLaunchURLActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Form>

View file

@ -0,0 +1,169 @@
/*
* 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 lib;
/**
*
* @author Alistair Neil <info@dazzleships.net>
*/
public class TextResourceDialog extends javax.swing.JDialog {
private String strUrl;
/**
* Creates new License Dialog
*
* @param parent
* @param modal
*/
public TextResourceDialog(java.awt.Frame parent, boolean modal) {
super(parent, modal);
initComponents();
jTextArea.setCaretPosition(0);
jButtonLaunchURL.setVisible(false);
}
/**
* Set the browser url for unnoficial translation
*
* @param url
*/
public void setButtonURL(String url) {
strUrl = url;
jButtonLaunchURL.setVisible(url != null);
}
/**
* Get the license text
*
* @return Text
*/
public String getText() {
return jTextArea.getText();
}
/**
* Set the license text
*
* @param text
*/
public void setText(String text) {
jTextArea.setText(text);
jTextArea.setCaretPosition(0);
}
/**
* Set the text on the Close button
*
* @param text
*/
public void setCloseButtonText(String text) {
jButtonClose.setText(text);
}
/**
* Set the text on the Close button
*
* @param text
*/
public void setURLButtonText(String text) {
jButtonLaunchURL.setText(text);
}
/**
* 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() {
jScrollPane1 = new javax.swing.JScrollPane();
jTextArea = new javax.swing.JTextArea();
jButtonClose = new javax.swing.JButton();
jButtonLaunchURL = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
setResizable(false);
jTextArea.setEditable(false);
jTextArea.setColumns(40);
jTextArea.setLineWrap(true);
jTextArea.setRows(20);
jTextArea.setText("\n");
jTextArea.setWrapStyleWord(true);
jScrollPane1.setViewportView(jTextArea);
jButtonClose.setText("Close");
jButtonClose.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonCloseActionPerformed(evt);
}
});
jButtonLaunchURL.setText("URL Desc");
jButtonLaunchURL.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonLaunchURLActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1)
.addGroup(layout.createSequentialGroup()
.addComponent(jButtonLaunchURL)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jButtonClose)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jScrollPane1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jButtonClose)
.addComponent(jButtonLaunchURL))
.addContainerGap())
);
pack();
}// </editor-fold>//GEN-END:initComponents
private void jButtonCloseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonCloseActionPerformed
dispose();
}//GEN-LAST:event_jButtonCloseActionPerformed
private void jButtonLaunchURLActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonLaunchURLActionPerformed
Utilities.openFileExternally(strUrl);
}//GEN-LAST:event_jButtonLaunchURLActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton jButtonClose;
private javax.swing.JButton jButtonLaunchURL;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JTextArea jTextArea;
// End of variables declaration//GEN-END:variables
}

View file

@ -0,0 +1,63 @@
/*
* 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 lib;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.UIManager;
/**
*
* @author Alistair Neil <info@dazzleships.net>
*/
public class TrayPopupMenu extends JPopupMenu {
private Color bg;
public TrayPopupMenu() {
super();
bg = super.getBackground();
}
@Override
public JMenuItem add(JMenuItem mi) {
mi.setForeground(new Color(UIManager.getColor("MenuItem.foreground").getRGB()));
super.add(mi);
return mi;
}
@Override
public void setForeground(Color fg) {
super.setForeground(fg);
}
@Override
public void setBackground(Color bg) {
super.setBackground(bg);
this.bg = bg;
}
@Override
public void paintComponent(final Graphics g) {
g.setColor(new Color(bg.getRGB()));
g.fillRect(0, 0, getWidth(), getHeight());
}
}

497
src/lib/Utilities.java Normal file
View file

@ -0,0 +1,497 @@
/*
* 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 lib;
import java.awt.Desktop;
import java.awt.FontMetrics;
import java.awt.Frame;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Formatter;
import java.util.Random;
import java.util.regex.Pattern;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.filechooser.FileFilter;
/**
*
* @author Alistair Neil <info@dazzleships.net>
*/
public final class Utilities {
/**
* Constructor
*/
public Utilities() {
}
/**
* Covert list to csv
*
* @param al
* @return String of comma separated values
*/
public static String getListAsCSV(ArrayList<String> al) {
return al.toString().replace("[", "").replace("]", "").replace(" ", "");
}
/**
* Preloads filechooser in background so it will open instantly when
* requested
*/
public static void preloadFileChooser() {
Thread t = new Thread(new java.lang.Runnable() {
@Override
public void run() {
JFileChooser fileChooser = new JFileChooser();
}
});
t.start();
}
/**
* Opens java file chooser dialog, convenience method. Returns filepath if
* successful and null if not
*
* @param parent
* @param folder
* @param filter Extension filter
* @param mode Fileselection mode
* @return String Filepath
*/
public static String openFileChooser(Frame parent, String folder, FileFilter filter, int mode) {
JFileChooser fileChooser = new JFileChooser();
fileChooser.setFileSelectionMode(mode);
fileChooser.setCurrentDirectory(new File(folder));
if (filter != null) {
fileChooser.addChoosableFileFilter(filter);
}
int intReturn = fileChooser.showOpenDialog(parent);
if (intReturn == JFileChooser.APPROVE_OPTION) {
return fileChooser.getSelectedFile().getAbsolutePath();
} else {
return null;
}
}
/**
* Check for newer appversion
*
* @param localversion
* @param remoteversion
* @return True if newer
*/
public static boolean isNewerVersion(String localversion, String remoteversion) {
return convertBuildnumToFloat(remoteversion) > convertBuildnumToFloat(localversion);
}
/**
* Convert an debian build number into a floating point number
*
* @param version
* @return Float version
*/
private static float convertBuildnumToFloat(String version) {
float result;
Pattern p;
String[] parts;
try {
if (version.contains("-")) {
// Handling for old non-debian compatible version
p = Pattern.compile("-");
parts = p.split(version);
} else {
// Handling for new debian compatible version
p = Pattern.compile("\\.");
parts = p.split(version);
parts[0] = parts[0] + "." + parts[1];
parts[1] = parts[2];
parts[2] = "";
}
result = Float.parseFloat(parts[0]);
result += (Float.parseFloat(parts[1]) / 100000);
} catch (Exception ex) {
version = version.replaceAll("[^0-9.]", "");
result = convertVersionToFloat(version);
}
return result;
}
/**
* Convert a windows version number into a floating point number
*
* @param version
* @return Float version
*/
private static float convertVersionToFloat(String version) {
int c;
float f;
version = version.toLowerCase();
if (version.startsWith("v")) {
version = version.substring(1);
}
try {
c = version.charAt(version.length() - 1);
if (c > 96) {
version = version.substring(0, version.length() - 1);
Float fraction = (float) (c - 96) / 10000;
f = Float.parseFloat(version) + fraction;
} else {
f = Float.parseFloat(version);
}
} catch (Exception ex) {
f = 0;
}
return f;
}
/**
* Open the desktop default file editor
*
* @param path Path to file
*/
public static void editFile(String path) {
if (OSFunction.isLinux()) {
OSFunction.launchProcess("xdg-open", path);
return;
}
if (OSFunction.isWindows()) {
OSFunction.launchProcess("notepad", path);
}
}
/**
* Launch the desktops default file handling program
*
* @param strUrl
* @return Returns true if successful
*/
public static boolean openFileExternally(final String strUrl) {
String url = strUrl.replace("\\", "/");
try {
if (OSFunction.isLinux()) {
OSFunction.launchProcess("xdg-open", url);
} else {
if (Desktop.isDesktopSupported()) {
Desktop deskSupport = Desktop.getDesktop();
if (url.startsWith("http") || url.startsWith("ftp")) {
deskSupport.browse(new URI(url));
} else {
deskSupport.open(new File(url));
}
}
}
return true;
} catch (URISyntaxException | IOException ex) {
}
return false;
}
/**
* Initialises the UI Look and Feel
*
* @param theme
*/
public static void loadUIStyle(String theme) {
try {
if (theme == null) {
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
return;
}
if (theme.contentEquals("Metal")) {
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
return;
}
if (theme.contentEquals("Nimbus")) {
// Switch to Nimbus theme
UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
return;
}
if (theme.contentEquals("System")) {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
return;
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
return;
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
}
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
// If everything else fails use default cross platform metal
try {
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
}
/**
* Adjust specified column width based on the width of a test string
*
* @param table
* @param test
*/
public static void adjustTableColumnWidth(JTable table, String... test) {
FontMetrics ourFontMetrics = table.getFontMetrics(table.getFont());
int col = 0;
for (String s : test) {
table.getColumn(table.getColumnName(col++)).setPreferredWidth(ourFontMetrics.stringWidth(s));
}
}
/**
* Generate secret key.
*
* @param length
* @return String key
*/
public static String generateSecretKey(int length) {
StringBuilder buffer = new StringBuilder();
Random random = new Random();
String chars = "abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int x;
try {
for (int i = 0; i < length; i++) {
x = random.nextInt(chars.length() - 1);
buffer.append(chars.substring(x, x + 1));
}
} catch (Exception ex) {
}
return buffer.toString();
}
public static String getTorHashPassword(String secret) {
byte[] key = S2KRFC2440(secret);
return "16:" + byteToHex(key);
}
/**
* Secret to key, Algorithm info taken from
* http://sunsite.icm.edu.pl/gnupg/rfc2440-3.html
*
* @param secret
* @return hashed key for the given secret
*/
public static byte[] S2KRFC2440(String secret) {
// Create our message digest for SHA-1
MessageDigest md;
try {
md = MessageDigest.getInstance("SHA-1");
} catch (Exception ex) {
return null;
}
// Create our random S2K salt, the 9th byte is loaded with the code count which
// determines the amount of octet hashing used.
// This salt is eventually combined with the secret to prevent dictionary attacks
int codecount = 32;
byte[] s2ksalt = new byte[9];
SecureRandom sr = new SecureRandom();
sr.nextBytes(s2ksalt);
s2ksalt[8] = (byte) codecount;
// The octet hashing count is defined by the following formula where EXPBIAS is 6
int octethashcount = (16 + (codecount & 15)) << ((codecount >> 4) + 6);
// Merge our S2K salt and partialsecret arrays together into one array to
// create the full secret key.
byte[] partialsecret;
try {
partialsecret = secret.getBytes("UTF-8");
} catch (UnsupportedEncodingException ex) {
return null;
}
byte[] fullsecret = new byte[8 + partialsecret.length];
System.arraycopy(s2ksalt, 0, fullsecret, 0, 8);
System.arraycopy(partialsecret, 0, fullsecret, 8, partialsecret.length);
// Do the hashing based on the hashcount
while (true) {
if (octethashcount < fullsecret.length) {
md.update(fullsecret, 0, octethashcount);
break;
} else {
md.update(fullsecret);
}
octethashcount -= fullsecret.length;
}
// Create our final key by merging s2kspecifier and digest result
byte[] ourkey = new byte[20 + 9];
System.arraycopy(md.digest(), 0, ourkey, 9, 20);
System.arraycopy(s2ksalt, 0, ourkey, 0, 9);
return ourkey;
}
/**
* Get SHAHash using given password string
*
* @param password
* @return SHAhash string
*/
public static String getSHAHash(String password) {
String sha1 = "";
try {
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
crypt.reset();
crypt.update(password.getBytes("UTF-8"));
sha1 = byteToHex(crypt.digest());
} catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
}
return sha1;
}
/**
* Convert byte to a hex string
*
* @param hash
* @return byte as a hex string
*/
private static String byteToHex(final byte[] hash) {
String result;
try (Formatter formatter = new Formatter()) {
for (byte b : hash) {
formatter.format("%02x", b);
}
result = formatter.toString();
}
return result;
}
/**
* Retrieve text from a resource text file
*
* @param resourcepath
* @return String text
*/
public static String getTextFromResource(String resourcepath) {
SimpleFile sf = new SimpleFile(resourcepath);
sf.openBufferedResource();
String text = sf.readEntireFile();
sf.closeFile();
return text;
}
/**
* Retrieve text from a text file
*
* @param filepath
* @return String text
*/
public static String getTextFromFile(String filepath) {
SimpleFile sf = new SimpleFile(filepath);
String text = "";
if (sf.exists()) {
sf.openBufferedRead();
text = sf.readEntireFile();
sf.closeFile();
}
return text;
}
/**
* Calculate the sha1 checksum of a given file
*
* @param filepath
* @return Checksum as a hex string
*/
public static String getSha1Sum(String filepath) {
StringBuilder sb = new StringBuilder("");
try {
MessageDigest md = MessageDigest.getInstance("SHA1");
FileInputStream fis = new FileInputStream(filepath);
byte[] dataBytes = new byte[1024];
int nread;
while ((nread = fis.read(dataBytes)) != -1) {
md.update(dataBytes, 0, nread);
}
byte[] mdbytes = md.digest();
//convert the byte to hex format
for (int i = 0; i < mdbytes.length; i++) {
sb.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16).substring(1));
}
} catch (NoSuchAlgorithmException | IOException ex) {
}
return sb.toString();
}
/**
* Creates a hidden dummy window for registration to various docks/launchers
* Fixes the neverending launching indicator
*/
public static void registerWindow() {
final JFrame jf = new JFrame();
jf.addWindowListener(new java.awt.event.WindowListener() {
@Override
public void windowOpened(WindowEvent e) {
jf.dispose();
}
@Override
public void windowClosing(WindowEvent e) {
}
@Override
public void windowClosed(WindowEvent e) {
}
@Override
public void windowIconified(WindowEvent e) {
}
@Override
public void windowDeiconified(WindowEvent e) {
}
@Override
public void windowActivated(WindowEvent e) {
}
@Override
public void windowDeactivated(WindowEvent e) {
}
});
jf.setUndecorated(true);
jf.setBounds(0, 0, 0, 0);
jf.setVisible(true);
}
}

View file

@ -0,0 +1,263 @@
# English GB, Default language file
gpltransurl=https://www.gnu.org/licenses/translations.en.html
appdesc=$appname $appver, Tor Exit Nodes Made Simple.
text_yes=Yes
text_no=No
text_mode=Mode
wintitle_prefs = $appname Preferences
wintitle_about = About $appname
wintitle_patternedit = $appname Pattern Editor
wintitle_guardnodes=Guard node selection
wintitle_tormonitor=Tor Client Monitor
textfield_unknown=Unknown
progstatus_initial=Initialising...
progstatus_generate=Generating fresh node list, please wait.
progstatus_cachedated=Cached descriptors out of date, will renew them.
progstatus_nonet=Internet access un-available.
progstatus_checkrecommended=Checking for the latest recommended nodes.
progstatus_gotrecommended=Retrieved recommended node list.
progstatus_torfailretry=Tor failed to start, retrying.
progstatus_nodefail=Requested node activation failed.
progstatus_nodefailretry=Requested node activation failed, will try again please wait.
progstatus_nodefailtorchoose=Requested node not reachable, will let Tor choose please wait.
progstatus_nodeactive3hop=3 Hop Circuit to exit node $nodename is active.
progstatus_nodeactive2hop=2 Hop Circuit to exit node $nodename is active.
progstatus_autoswitch=Auto-Switching to node
progstatus_manswitch=Switching to manually selected node
progstatus_waitfortor=Waiting for Tor to activate a node.
progstatus_switchtonode=Switching to node $nodename.
progstatus_applychanges=Applying new preferences.
circuit_status_creating_2hop=Creating 2 hop circuit.
circuit_status_creating_3hop=Creating 3 hop circuit.
circuit_status_testing=Testing circuit.
circuit_status_aborted=Testing aborted.
circuit_status_built=$1 circuits built.
circuit_status_passed=Circuit passed.
circuit_status_failed=Circuit Failed.
circuit_status_none=No circuits available.
circuit_status_noroute=All routers down.
combo_proxymode1=Disabled
combo_proxymode2=Proxy by Pattern
combo_proxymode3=Proxy all Traffic
combo_loglev1=Debug
combo_loglev2=Info
combo_loglev3=Notice
traymenu_proxymode1=Mode : Proxy Disabled
traymenu_proxymode2=Mode : Proxy by Pattern
traymenu_proxymode3=Mode : Proxy all Traffic
traymenu_showgui=Hide/Show GUI
traytool_guardnode=GuardNode
traytool_exitnode=ExitNode
exittable_col1=ExitNode
exittable_col2=BW (MB\\s)
exittable_col3=Latency (ms)
exittable_col4=Status
exittable_col5=Favourite
guardtable_col1=GuardNode
guardtable_col2=Country
guardtable_col3=BW (MB\\s)
guardtable_col4=Trusted
patterntable_col1=Description
patterntable_col2=Pattern
patterntable_col3=Enabled
menu_menu=Menu
menu_prefs=Preferences
menu_quickadd=Quick Add Pattern
menu_patternedit=Proxy Pattern Editor
menu_export=Export Patterns
menu_import=Import Patterns
menu_quit=Quit
menu_defaultpatterns=Default Patterns
menu_userpatterns=User Patterns
menu_help=Help
menu_debuglog=View Debug Log
menu_helpcontents=Help Contents
menu_torcheck=Tor Routing Check
menu_about=About
menu_license=License
menu_tormanual=Official Tor Manual
menu_tormonitor=Tor Client Monitor
menu_close=Close Menu
menu_proxy=Proxy Mode
menu_leaktest=DNS Leak Test
menu_credits=Credits
label_latency_url=Tor Latency Checking URL :
label_guardnode=Guard :
label_bridgenode=Bridge :
label_activecountry=Exit Country :
label_proxymode=Proxy Mode :
label_exitnode=Exit Node:
label_torlatency=Latency
label_fingerprint=Fingerprint:
label_bandwidth=Bandwidth
label_streams=Streams
label_stable=Stable
label_status=Client Status:
label_listenport=Tor Listening Port :
label_defaultproxy=Default HTTP Proxy :
label_bridgeaddress=Tor Bridge Address :
label_portranges=Currently active port ranges, $portmin to $portmax
label_editcountry=Select Country To View its Patterns
label_quickadd_desc=Description :
label_quickadd_pattern=Pattern :
label_threshold=Threshold
label_exitip=Exit IP:
label_guardip=Guard IP:
label_guardcountry=Guard Country:
label_torlogging=Logging Level :
label_torargs=Startup Arguments :
label_torsocks=Socks Settings :
label_diskoptions=Disk Options :
label_guard_minimum=You can have either zero guard nodes selected in which case the tor client will choose or you can have 3 or more guard nodes selected.
label_nickname=Nickname
label_ip=IP
label_country=Country
label_exit=Exit :
label_middle=Middle :
label_donotproxy=Do not proxy :
button_details=Atlas Details
button_whois=WhoIs
button_close=Close
button_apply=Apply
button_delete=Delete
button_addnew=Add New
button_save=Save
button_cancel=Cancel
button_continue=Continue
button_getbridges=Get Bridges
button_mozillarestart=$browser Restart
button_visitus=Visit Us
button_contactus=Contact Us
button_translations=Unofficial Translations
button_prefdefaults=Reset to Defaults
button_setguards=Set Guard Nodes
button_clearfavs=Clear Favourites
button_clearguards=Clear Selected Guards
button_support=Support SelekTOR
button_patreon=Support SelekTOR with Patreon
panel_info=Active Circuit
panel_general=General Settings
panel_network=Network Settings
panel_management=Node Management Settings
panel_torclientset=Tor Client Settings
panel_startupargs=Startup Arguments
panel_stdout=StdOut Monitor
chkbox_autoselect=Auto Node Select
chkbox_autostart=Autostart SelekTOR
chkbox_checkforupdates=Check for updates on startup
chkbox_disabletray=Disable tray icon.
chkbox_autopatterns=Auto install latest patterns.
chkbox_mozillawarn=Disable Mozilla warning
chkbox_recnodesonly=Use recommended nodes in Pattern Mode
chkbox_hidetotray=Minimise at startup
chkbox_minonclose=Minimise instead of Exit on close
chkbox_twohop=Use 2 hop circuits to Exit Node in Pattern mode
chkbox_safesocks=Safe Socks
chkbox_warnunsafesocks=Warn Unsafe
chkbox_diskavoid=Avoid disk writes
chkbox_testsocks=Test Socks
chkbox_safelog=Safe Logging
chkbox_guardwarn1=Issue popup warning if unspecified guard node is used
chkbox_securedelete=Secure delete Tor caches on exit
chkbox_guardwarn2=Issue popup warning if less than 3 guard nodes selected
ttip_autostart=Will start SelekTOR automatically on boot/login.
ttip_hidetotray=SelekTOR will startup in system tray
ttip_checkforupdates=SelekTOR will check for a newer version on startup
ttip_autoinstall=Will fetch the latest patterns from Dazzleships.Net.
ttip_disabletray=Disable the system tray icon
ttip_mozillawarn=Disable the Mozilla browser warning
ttip_listenport=The Tor client listening port.
ttip_defaultproxy=Any traffic not routed through Tor will be redirected through this HTTP proxy.
ttip_donotproxy=Any URL that contains one of these comma separated entries will not be proxied and will be connected to directly.
ttip_bridgeaddress=To bypass ISP blocking add a valid bridge address here.
ttip_forcedns=Force DNS Lookup via Tor, requires browser restart.
ttip_forcenode=When checked node will be activated regardless of any current activity
ttip_enhanon=Will use 3 node hops instead of 2 hops.
ttip_recnodesonly=Will use the recommended nodes in pattern mode
ttip_minonclose=Application will minimise instead of exit when main window is closed
ttip_threshold=Threshold Latency
ttip_safesocks=When enabled, Tor will reject application connections that use unsafe variants of the socks protocol.
ttip_warnunsafe=When enabled, Tor will warn whenever a request is received that only contains an IP address instead of a hostname.
ttip_testsocks=When enabled, Tor will make a notice-level log entry for each connection indicating whether it used a safe socks protocol or an unsafe one.
ttip_safelogging=When enabled, Tor will scrub potentially sensitive strings from log messages.
ttip_avoiddisk=When enabled, Tor will try to write to disk less frequently than we would otherwise.
ttip_extraargs=Additional user specified arguments, see Tor Manual.
ttip_combo_loglevel=Tor logging level.
ttip_twohop=Use 2 hop circuits instead of Tor default of 3, reduces latency but lowers anonymity.
ttip_resetbasicprefs=Reset Basic preferences to their defaults.
ttip_resetadvprefs=Reset Advanced preferences to their defaults.
ttip_securedelete=When enabled, Tor caches will be overwritten by zero's then deleted
ttip_autonode=When enabled, SelekTOR will attempt to choose the best performing node
ttip_guardwarn=When enabled, a popup warning will be issued indicating an un-specified guard node is active.
ttip_clearguards=Clear selected guard nodes.
ttip_clearfavs=Clear Favourites
ttip_guardwarn2=When enabled, a popup warning will be issued indicating not enough guardnodes are selected.
dlg_update_title=Update Available.
dlg_update_body=$version is now available for download.
dlg_restoreproxy_title=Original Proxy Settings
dlg_restoreproxy_body=Select Continue to restore the proxy settings to their original settings prior to the installation of SelekTOR.
dlg_resetproxy_title=Default Proxy Settings
dlg_resetproxy_body=Select Continue to reset proxy settings to their system defaults.
dlg_gsetting_title=Gsettings not found
dlg_gsetting_body=$appname cannot function fully without the gsettings binary installed, on some distro's it can be found in the package libglib2.0-bin.
dlg_torclient_title=TOR Client not found
dlg_torclient_body=$appname cannot function without the Tor client installed please install the tor and the tor-geoipdb packages for your distro.
dlg_mozillarestart_title=Warning: $browser browser is active.
dlg_mozillarestart_body=$appname detected that the $browser browser is already running.\nA browser restart is required to enable $appname functionality.\n\nIf you elect to restart $browser all currently open tabs will be restored when $browser restarts, requires \"Show my Windows and tabs from last time\" option to be selected in $browser preferences/options.\n\nYou can disable this browser warning in $appname Preferences.
dlg_license_title=$appname License
dlg_credits_title=$appname Credits
dlg_credits_body=To have your name listed here and also earn my gratitude please consider supporting the further development of SelekTOR on the Linux platform via Patreon.
dlg_exportuser_title=Export User Patterns
dlg_exportuser_body=No user created patterns found.\n\nUse the pattern editor to add your own patterns
dlg_exportdefault_title=Export Default Patterns
dlg_exportdefault_body=No default patterns found.
dlg_saveuser_title=Save User patterns
dlg_savedefault_title=Save Default patterns
dlg_import_title=Import pattern file
dlg_import_success_title=Patterns Imported
dlg_import_success_body=Patterns were succesfully imported and are now active.
dlg_import_fail_title=Import Failed
dlg_import_fail_body=Failed to correctly import patterns.
dlg_whois_title=Whois $ipaddress
dlg_whois_body=Please wait while I try fetching Whois data...
dlg_whois_fail=Sorry unable to fetch Whois information.
dlg_toold_body=The currently installed Tor client is to old, Tor 0.2.7.6 or better is required.\n\nLinux users should visit the following page\nhttps://www.torproject.org/download/download-unix.html.en\nto obtain the latest Tor client.
dlg_error_title=Startup Error
dlg_error_body=This error is fatal and $appname will shut itself down.
dlg_quickadd_title=Add Pattern
dlg_nodelistfail_body=Nodelist generation failed due to GEOIP errors.
dlg_patterneditsave_title=Save Current Patterns
dlg_patterneditsave_body=Current patterns have been modified.\n\nIf you wish to save them, click Continue else click Cancel.
dlg_instancefail_title=Multiple instance failure
dlg_instancefail_body=An instance of $appname is already running, only one instance can be run at any time.\n\nEither shutdown the existing instance of $appname or in the event of a $appname crash restart X by logging out and in again.
dlg_guardwarn_title=Guard Node Warning
dlg_guardwarn_body=A guard node that is not in your specified guard nodes list has been used.\nThis is probably due to your selected guard nodes being no longer reachable and thus the tor client has assigned its own guard node.\n\nYou may want to check your currently set guard nodes to see if they are still available or select new ones.
dlg_notenoughguards_body=Their are not enough guard nodes set for Tor to operate efficiently or securely.\n\nEither clear all selected guards which will allow the Tor client to choose its own guards or select three or more guards manually.
dlg_bridgerr_title=Bridge address validation failure
dlg_bridgerr_body=The supplied bridge information contains validation errors and does not conform to a valid host:port ipv4 address format.\n\nBridge specification format examples are as follows:\n\nSingle bridge:\n127.0.0.1:8080\n\nMultiple bridges:\n127.0.0.1:8080,128.5.6.8:224\n\nBridges have been reset to their defaults.
table_popup_details=Details
table_popup_begintest=Begin Test Cycle
table_popup_whois=WhoIs
tab_basic=Basic
tab_advanced=Advanced
isoA1=Anonymous Proxy
isoA2=Satellite Provider
isoO1=Other Country
isoU1=Unknown
chkbox_disablenotify=Disable desktop notifications
ttip_disablenotify=Disable desktop notifications
dlg_libnotify_title=notify-send not found
dlg_libnotify_body=Desktop notifications will not function without the libnotify-bin package installed.\n\nTo prevent this popup appearing again either install the required package or disable desktop notifications in preferences.
ttip_hidemin=Application will hide instead of minimise
chkbox_hidemin=Hide instead of Minimise
label_autoselect=Auto Selection Mode :
menu_geoip=Update GEOIP
chkbox_geocheck=Do quarterly GEOIP update check
ttip_geocheck=SelekTOR will popup the "GEOIP Update dialog" if your GEOIP database is out of date.
dlg_geo_title=GEO Location Data Update
dlg_geo_body=The default geo-location data that comes with the Tor client is sometimes out of date, You can have SelekTOR download and use the latest geolocation data. These are maintained on a quarterly basis.\n\nPlease note, if you choose not to update, some nodes may be assigned to the wrong country.\n\nThe data in these files, like the data supplied by the Tor client, is provided by Maxmind.com.
dload_status_contact=Fetching latest GEOIP data
dload_status_failed=Download failed
chkbox_viator=Download via Tor
ttip_patterntable=Supports in-line editing, double left click a table cell to begin editing.
fileext_pattern=Zipped Pattern File

View file

@ -0,0 +1,10 @@
progstatus_initial=Initializing...
chkbox_hidetotray=Minimize at startup
chkbox_minonclose=Minimize instead of Exit on close
ttip_minonclose=Application will minimize instead of exit when window is closed.
ttip_hidemin=Application will hide instead of minimize
chkbox_hidemin=Hide instead of Minimize
button_clearfavs=Clear Favorites
ttip_clearfavs=Clear Favorites
exittable_col5=Favorite

View file

@ -0,0 +1,256 @@
# French CA, Default language file, provided by yahoe001
gpltransurl=https://fsffrance.org/gpl/gpl-fr.fr.html
appdesc=$appname $appver, Les n\u0153uds de sortie de Tor simplifi\u00e9s.
text_yes=Oui
text_no=Non
wintitle_prefs = Pr\u00e9f\u00e9rences de $appname
wintitle_about = \u00c0 propos de $appname
wintitle_patternedit = \u00c9diteur de mod\u00e8les $appname
wintitle_guardnodes=S\u00e9lection des n\u0153uds de garde
wintitle_tormonitor=Moniteur du client Tor
textfield_unknown=Inconnu
progstatus_initial=Initialisation...
progstatus_bridges=Mise en place du changement de ponts.
progstatus_generate=G\u00e9n\u00e9ration d'une nouvelle liste de n\u0153uds, veuillez patienter.
progstatus_cachedated=Les descripteurs en cache sont p\u00e9rim\u00e9s, ils seront renouvel\u00e9s.
progstatus_nonet=L'acc\u00e8s \u00e0 Internet n'est pas disponible.
progstatus_checkrecommended=Recherche des derniers n\u0153uds recommand\u00e9s.
progstatus_torfailretry=\u00c9chec lors du d\u00e9marrage de Tor, nouvel essai.
progstatus_nodefail=\u00c9chec lors de l'activation du n\u0153ud demand\u00e9.
progstatus_nodefailretry=\u00c9chec lors de l'activation du n\u0153ud demand\u00e9. Nouvel essai, veuillez patienter.
progstatus_nodefailtorchoose=Le n\u0153ud demand\u00e9 n'est pas joignable, Tor en choisira un, veuillez patienter.
progstatus_nodeactive3hop=Le circuit \u00e0 3 sauts vers le n\u0153ud de sortie $nodename est actif.
progstatus_nodeactive2hop=Le circuit \u00e0 2 sauts vers le n\u0153ud de sortie $nodename est actif.
progstatus_autoswitch=Auto-commutation vers le n\u0153ud
progstatus_manswitch=Commutation vers le n\u0153ud choisi manuellement
progstatus_waitfortor=Attente d'activation d'un n\u0153ud par Tor.
progstatus_switchtonode=Commutation vers le n\u0153ud $nodename.
progstatus_applychanges=Mise en place des nouvelles pr\u00e9f\u00e9rences.
circuit_status_creating_2hop=Cr\u00e9ation d'un circuit \u00e0 2 sauts.
circuit_status_creating_3hop=Cr\u00e9ation d'un circuit \u00e0 3 sauts.
circuit_status_testing=Test du circuit.
circuit_status_aborted=Test interrompu.
circuit_status_built=$1 circuit(s) construit(s).
circuit_status_passed=Circuit v\u00e9rifi\u00e9.
circuit_status_failed=\u00c9chec de circuit.
circuit_status_none=Aucun circuit n'est disponible.
circuit_status_noroute=Routeurs (tous) hors service.
combo_proxymode1=D\u00e9sactiv\u00e9
combo_proxymode2=Relais par mod\u00e8le
combo_proxymode3=Relayer tout le trafic
combo_loglev1=D\u00e9bogage
combo_loglev2=Infos
combo_loglev3=Avis
traymenu_proxymode1=Mode : pas de relais
traymenu_proxymode2=Mode : relais par mod\u00e8le
traymenu_proxymode3=Mode : relayer tout le trafic
traymenu_showgui=Cacher/Montrer l'IUG
traytool_guardnode=Noeud de garde
traytool_exitnode=Noeud de sortie
exittable_col1=N\u0153ud de sortie
exittable_col2=BP (MB\\s)
exittable_col3=D\u00e9lai (ms)
exittable_col4=\u00c9tat
exittable_col5=Favori
patterntable_col1=Description
patterntable_col2=Mod\u00e8le
patterntable_col3=Activ\u00e9
guardtable_col1=N\u0153ud de garde
guardtable_col2=Pays
guardtable_col3=BP (MB\\s)
guardtable_col4=De confiance
menu_menu=Menu
menu_prefs=Pr\u00e9f\u00e9rences
menu_quickadd=Ajout rapide d'un mod\u00e8le
menu_patternedit=\u00c9diteur de mod\u00e8les de relais
menu_export=Exporter les mod\u00e8les
menu_import=Import les mod\u00e8les
menu_quit=Quitter
menu_defaultpatterns=Mod\u00e8le par d\u00e9faut
menu_userpatterns=Mod\u00e8les de l'utilisateur
menu_help=Aide
menu_debuglog=Voir le journal de d\u00e9bogage
menu_helpcontents=Contenu de l'aide
menu_torcheck=V\u00e9rification de routine de Tor
menu_about=\u00c0 propos de
menu_license=Licence
menu_proxy=Mode de relais
menu_close=Fermer le menu
menu_tormanual=Manuel officiel de Tor
menu_tormonitor=Moniteur du client Tor
menu_leaktest=Test de fuite DNS
menu_credits=Cr\u00e9dits
label_activecountry=Pays actif :
label_proxymode=Mode de relais :
label_exitnode=N\u0153ud de sortie :
label_ip=IP :
label_torlatency=D\u00e9lai
label_fingerprint=Empreinte :
label_bandwidth=Bande passante
label_streams=Flux
label_stable=Stable
label_status=\u00c9tat :
label_listenport=Port d'\u00e9coute de Tor :
label_defaultproxy=Mandataire HTTP par d\u00e9faut :
label_bridgeaddress=Adresse de pont de Tor :
label_portranges=Plages de port pr\u00e9sentement actives, de $portmin \u00e0 $portmax
label_editcountry=Choisir un pays pour voir ses mod\u00e8les
label_quickadd_desc=Description :
label_quickadd_pattern=Mod\u00e8le :
label_threshold=D\u00e9lai seuil
label_middle=Milieu :
label_exit=Sortie :
label_nickname=Pseudonyme
label_ip=IP
label_country=Pays
label_guard_minimum=Vous pouvez soit ne choisir aucun n\u0153ud de garde au cas o\u00f9 le client Tor les choisit, soit choisir trois n\u0153uds de garde ou plus.
label_torlogging=Niveau de journalisation :
label_torargs=Arguments de d\u00e9marrage :
label_torsocks=Param\u00e8tres Socks :
label_diskoptions=Options du disque :
label_guardnode=Garde :
label_bridgenode=Pont :
label_donotproxy=Ne pas relayer :
button_details=D\u00e9tails
button_whois=Qui est
button_close=Fermer
button_apply=Appliquer
button_delete=Supprimer
button_addnew=Ajouter un nouveau
button_save=Enregistrer
button_cancel=Annuler
button_continue=Continuer
button_getbridges=Obtenir des ponts
button_mozillarestart=Red\u00e9marrer $browser
button_visitus=Rendez-nous visite
button_contactus=Contactez-nous
button_translations=Traductions non officielles
button_prefdefaults=R\u00e9initialiser aux leurs valeurs par d\u00e9faut.
button_setguards=D\u00e9finir les n\u0153uds de garde
button_details=D\u00e9tails de l'atlas
button_clearguards=Effacer les n\u0153uds de garde choisis
button_clearfavs=Effacer les favoris
button_support=Soutenir SelekTOR
button_patreon=Soutenir SelekTOR avec Patreon
panel_general=Param\u00e8tres g\u00e9n\u00e9raux
panel_network= Param\u00e8tres r\u00e9seau
panel_management=Param\u00e8tres de gestion des n\u0153uds
panel_info=Circuit actif
panel_torclientset=Param\u00e8tres du client Tor
panel_startupargs=Arguments de d\u00e9marrage
panel_stdout=Moniteur de sortie standard
chkbox_autoselect=Choix automatique du n\u0153ud
chkbox_autostart=D\u00e9marrage automatique de SelekTOR
chkbox_checkforupdates=V\u00e9rifier les mises \u00e0 jour au d\u00e9marrage
chkbox_disabletray=D\u00e9sactiver l'ic\u00f4ne de notification
chkbox_autopatterns=Installer automatiquement les derniers mod\u00e8les.
chkbox_mozillawarn=D\u00e9sactiver l'avertissement de Mozilla
chkbox_recnodesonly=Utiliser les n\u0153uds recommand\u00e9s en mode par mod\u00e8les
chkbox_hidetotray=Minimiser au d\u00e9marrage
chkbox_minonclose=Minimiser plut\u00f4t que de quitter lors de la fermeture
chkbox_safesocks=Socks s\u00e9curitaire
chkbox_twohop=Utiliser des circuits \u00e0 2 sauts vers le n\u0153ud de sortie en mode par mod\u00e8les
chkbox_warnunsafesocks=Avertir si \u00e0 risque
chkbox_diskavoid=\u00c9viter les \u00e9critures sur le disque
chkbox_testsocks=Tester Socks
chkbox_safelog=Journalisation s\u00e9curitaire
chkbox_guardwarn1=Afficher une fen\u00eatre d'avertissement si un n\u0153ud de garde non sp\u00e9cifi\u00e9 est utilis\u00e9
chkbox_guardwarn2=Afficher une fen\u00eatre d'avertissement si moins de trois n\u0153uds de garde sont choisis
chkbox_securedelete=Effacement s\u00e9curis\u00e9 des caches de Tor lors de la fermeture
ttip_autostart=D\u00e9marrage automatique de SelekTOR lors du d\u00e9marrage/de la connexion
ttip_hidetotray=Minimiser au d\u00e9marrage
ttip_checkforupdates=SelekTOR v\u00e9rifiera les mises \u00e0 jour au d\u00e9marage
ttip_autoinstall=Les derniers mod\u00e8les seront r\u00e9cup\u00e9r\u00e9s de Dazzleships.Net
ttip_disabletray=D\u00e9sactiver l'ic\u00f4ne de notification
ttip_mozillawarn=D\u00e9sactiver l'avertissement du navigateur Mozilla
ttip_listenport=Le port d'\u00e9coute du client Tor
ttip_defaultproxy=Tout trafic qui ne sera pas redirig\u00e9 par Tor sera redirig\u00e9 par ce mandataire HTTP
ttip_donotproxy=Toute URL contenant une de ces entr\u00e9es s\u00e9par\u00e9es par des virgules ne sera pas relay\u00e9e. L'on s'y connectera directement.
ttip_bridgeaddress=Pour contourner le blocage du FSI, ajouter une adresse de pont valide ici
ttip_forcedns=Forcer la recherche DNS par Tor, exige le red\u00e9marrage du navigateur
ttip_forcenode=Si coch\u00e9, le n\u0153ud sera activ\u00e9 quelque soit l'activit\u00e9 du n\u0153ud
ttip_recnodesonly=Les n\u0153uds recommand\u00e9s seront utilis\u00e9s en mode par mod\u00e8les
ttip_minonclose=L'application sera minimis\u00e9e au lieu de quitter \u00e0 la fermeture de la fermeture principale
ttip_threshold=D\u00e9lai seuil
ttip_safesocks=Activ\u00e9e, Tor rejettera les connexions logicielles qui utilisent des variantes dangereuses du protocole Socks.
ttip_warnunsafe=Activ\u00e9e, Tor avertira \u00e0 chaque fois qu'une requ\u00eate est re\u00e7ue contenant seulement une adresse IP au lieu d'un nom d'h\u00f4te.
ttip_testsocks=Activ\u00e9e Tor journalisera une entr\u00e9e de journal de niveau avis pour chaque connexion en indiquant si elle utilise un protocole Socks s\u00e9curitaire ou dangereux.
ttip_safelogging=Activ\u00e9e, Tor nettoiera les cha\u00eenes potentiellement sensibles des messages de journalisation.
ttip_avoiddisk=Activ\u00e9e, Tor essaiera d'\u00e9crire moins fr\u00e9quemment sur le disque que nous ne le ferions autrement.
ttip_extraargs= Arguments suppl\u00e9mentaires sp\u00e9cifi\u00e9s par l'utilisateur, voir le Manuel Tor.
ttip_combo_loglevel=Niveau de journalisation de Tor.
ttip_twohop=Utiliser des circuits \u00e0 2 sauts au lieu des 3 par d\u00e9faut de Tor. R\u00e9duit le d\u00e9lai de transit mais affaiblit l'anonymat.
ttip_resetbasicprefs=R\u00e9initialiser les pr\u00e9f\u00e9rences de base \u00e0 leurs valeurs par d\u00e9faut.
ttip_resetadvprefs=R\u00e9initialiser les pr\u00e9f\u00e9rences avanc\u00e9es \u00e0 leurs valeurs par d\u00e9faut.
ttip_guardwarn1=Activ\u00e9, une fen\u00eatre d'avertissement sera affich\u00e9e indiquant qu'un n\u0153ud de garde non sp\u00e9cifi\u00e9 est actif.
ttip_guardwarn2=Activ\u00e9, une fen\u00eatre d'avertissement sera affich\u00e9e indiquant que trop peu de n\u0153uds de garde sont choisis
ttip_clearguards=Effacer les n\u0153uds de garde choisis.
ttip_securedelete=Activ\u00e9, les caches de Tor seront \u00e9cras\u00e9es par des z\u00e9ros, puis supprim\u00e9es
dlg_update_title=Mise \u00e0 jour disponible.
dlg_update_body=$version est maintenant disponible au t\u00e9l\u00e9chargement.
dlg_restoreproxy_title=Param\u00e8tres originaux du mandataire
dlg_restoreproxy_body=Choisir Continuer pour restaurer les param\u00e8tres du mandataire aux valeurs par d\u00e9faut avant l'installation de SelekTOR.
dlg_resetproxy_title=Param\u00e8tres par d\u00e9faut du mandataire
dlg_resetproxy_body=Choisir Continuer pour r\u00e9initialiser les param\u00e8tres du serveur mandataire \u00e0 leurs valeurs syst\u00e8me par d\u00e9faut.
dlg_gsetting_title=Gsettings introuvable
dlg_gsetting_body=$appname ne peux pas fonctionner correctement sans que l'ex\u00e9cutable binary soit install\u00e9. Dans certaines distributions il peut \u00eatre trouv\u00e9 dans le paquet libglib2.0-bin.
dlg_torclient_title=Client TOR introuvable
dlg_torclient_body=$appname ne peux pas fonctionner sans que le client Tor ne soit Install\u00e9. Veuillez installer les paquets tor et tor-geoipdb pour votre distribution.
dlg_mozillarestart_title=Avertissement\u00a0: Le navigateur $browser est actif.
dlg_mozillarestart_body=$appname a d\u00e9tect\u00e9 que le navigateur $browser tourne d\u00e9j\u00e0.\nUn red\u00e9marrage du navigateur est exig\u00e9 pour permettre le fonctionnement de $appname.\n\nSi vous choisissez de red\u00e9marrer $browser, tous les onglets actuellement ouverts seront restaur\u00e9s au red\u00e9marrage de $browser, l'option \u00ab Afficher les dernier onglets et fen\u00eatres utilis\u00e9s \u00bb, doit \u00eatre choisie dans les options de $browser.\n\nVous pouvez d\u00e9sactiver cet avertissement du navigateur dans les Pr\u00e9f\u00e9rences de $appname.
dlg_license_title=Licence de $appname
dlg_exportuser_title=Exporter les mod\u00e8les d'utilisateur
dlg_exportuser_body=Aucun mod\u00e8le cr\u00e9\u00e9 par l'utilisateur n'a \u00e9t\u00e9 trouv\u00e9.\n\nUtilisez l'\u00e9diteur de mode pour ajouter vos propres mod\u00e8les
dlg_exportdefault_title=Exporter les mod\u00e8les par d\u00e9faut
dlg_exportdefault_body=Aucun mod\u00e8le par d\u00e9faut n'a \u00e9t\u00e9 trouv\u00e9.
dlg_saveuser_title=Enregistrer les modes de l'utilisateur
dlg_savedefault_title=Enregistrer les mod\u00e8les par d\u00e9faut
dlg_import_title=Importer le fichier des mod\u00e8les
dlg_import_success_title=Mod\u00e8les import\u00e9s
dlg_import_success_body=Les mod\u00e8les ont \u00e9t\u00e9 import\u00e9s avec succ\u00e8s et sont maintenant actifs.
dlg_import_fail_title=\u00c9chec lors l'importation
dlg_import_fail_body=Les mod\u00e8les n'ont pas \u00e9t\u00e9 import\u00e9s correctement.
dlg_whois_title=Qui est $ipaddress
dlg_whois_body=Veuillez patienter pendant que j'essaie de r\u00e9cup\u00e9rer les donn\u00e9s de WhoIs...
dlg_whois_fail=D\u00e9sol\u00e9, impossible de r\u00e9cup\u00e9rer les informations de Whois.
dlg_toold_body=Le client Tor actuellement install\u00e9 est trop ancien, Tor 0.2.7.6 ou ult\u00e9rieure est exig\u00e9e.\n\nLes utilisateurs de Linux devraient visiter la page suivante \nhttps://www.torproject.org/download/download-unix.html.en\npour obtenir le dernier client Tor.
dlg_error_title=Erreur de d\u00e9marrage
dlg_error_body=Cette erreur est fatale et $appname se fermera.
dlg_quickadd_title=Ajouter un mod\u00e8le
dlg_nodelistfail_body=La g\u00e9n\u00e9ration de la liste des n\u0153uds a \u00e9chou\u00e9 \u00e0 cause d'erreurs de GEOIP.
dlg_patterneditsave_title=Enregistrer les mod\u00e8les actuels
dlg_patterneditsave_body=Les mod\u00e8les actuels ont \u00e9t\u00e9 modifi\u00e9s.\n\nSi vous d\u00e9sirez les enregistrer, cliquez sur Continuer, autrement cliquez sur Annuler.
dlg_instancefail_title=\u00c9chec d\u00fb \u00e0 plusieurs instances
dlg_instancefail_body=Une instance de $appname est d\u00e9j\u00e0 en cours et une seule peut \u00eatre ex\u00e9cut\u00e9e \u00e0 la fois.\n\nQuittez l'instance existante de $appname ou dans le cas d'un plantage de $appname, red\u00e9marrez X en vous d\u00e9connectant et en vous connectant de nouveau.
dlg_guardwarn_title=Avertissement de n\u0153ud de garde
dlg_guardwarn_body=Un n\u0153ud de garde ne se trouvant pas dans votre liste de n\u0153uds de garde sp\u00e9cifi\u00e9e a \u00e9t\u00e9 utilis\u00e9.\nCeci provient probablement du fait que vos n\u0153uds de garde s\u00e9lectionn\u00e9s ne sont plus joignables et par cons\u00e9quent le client Tor a assign\u00e9 son propre n\u0153ud de garde.\n\nVous devriez v\u00e9rifier vos n\u0153uds de garde actuellement d\u00e9finis pour voir s'ils sont toujours disponibles, ou en choisir de nouveaux.
dlg_notenoughguards_body=Il n'y a pas assez de n\u0153uds de garde d\u00e9finis afin que Tor fonctionne efficacement et en toute s\u00e9curit\u00e9.\n\nSupprimez tous les n\u0153uds de garde s\u00e9lectionn\u00e9s, ce qui permettra au client Tor de choisir ses propres n\u0153uds de garde, ou choisissez manuellement trois n\u0153uds de garde ou plus.dlg_notenoughguards_body=Il n'y a pas assez de n\u0153uds de garde d\u00e9finis afin que Tor fonctionne efficacement et en toute s\u00e9curit\u00e9.\n\nSupprimez tous les n\u0153uds de garde s\u00e9lectionn\u00e9s, ce qui permettra au client Tor de choisir ses propres n\u0153uds de garde, ou choisissez manuellement trois n\u0153uds de garde ou plus.
dlg_bridgerr_title=\u00c9chec de validation de l'adresse de pont
dlg_bridgerr_body=Les informations de pont fournies contiennent des erreurs de validation et ne se conforment pas \u00e0 un format d'adresse IPv4 valide h\u00f4te:port\n\nVoici des exemples de format de sp\u00e9cification de ponts :\n\nPont simple : \n127.0.0.1:8080\n\nPonts multiples : \n127.0.0.1:8080,128.5.6.8:224\n\nLes ponts ont \u00e9t\u00e9 r\u00e9initialis\u00e9s \u00e0 leurs valeurs par d\u00e9faut.
dlg_credits_title=Cr\u00e9dits de $appname
dlg_credits_body=Afin que votre nom apparaissent ici et pour aussi m\u00e9riter ma gratitude, veuillez envisager de soutenir le d\u00e9veloppement futur de SelekTOR sous Linux avec Patreon.
table_popup_details=D\u00e9tails
table_popup_whois=Qui est
table_popup_begintest=Commencer le cycle de test
tab_basic=De base
tab_advanced=Avanc\u00e9
isoA1=Mandataire annonyme
isoO1=autre Pays
isoU1=Inconnu
chkbox_disablenotify=D\u00e9sactiver les notifications du bureau
ttip_disablenotify=D\u00e9sactiver les notifications du bureau
dlg_libnotify_title=notify-send est introuvable
dlg_libnotify_body=Les notifications de bureau ne fonctionneront pas sans que le paquet libnotify-bin ne soit install\u00e9.\n\nPour emp\u00eacher que cette fen\u00eatre apparaissent de nouveau installez le paquet exig\u00e9 ou d\u00e9sactivez les notifications de bureau dans les pr\u00e9f\u00e9rences.
ttip_hidemin=L'appli sera cach\u00e9e au lieu d'\u00eatre minimis\u00e9e.
chkbox_hidemin=Cacher au lieu de minimiser
label_autoselect= Mode de s\u00e9lection automatique :
menu_geoip=Mettre GEOIP \u00e0 jour
chkbox_geocheck=V\u00e9rification trimestrielle des mises \u00e0 jour GEOIP
ttip_geocheck=SelekTOR affichera la \u00abfen\u00eatre de mise \u00e0 jour GEOIP \u00bbsi votre base de donn\u00e9es GEOIP est p\u00e9rim\u00e9e.
dlg_geo_title=Mise \u00e0 jour des donn\u00e9es de g\u00e9olocalisation
dlg_geo_body=Les donn\u00e9es de g\u00e9olocalisation fournies par Tor sont parfois p\u00e9rim\u00e9es. Vous pouvez demander \u00e0 SelekTOR de t\u00e9l\u00e9charger ses propres fichiers de donn\u00e9es de g\u00e9olocalisation de Dazzleships.net et de les utiliser. Ils sont mis \u00e0 jour trimestriellement.\n\nVeuillez noter que si vous choisissez de ne pas mettre \u00e0 jour, certains n\u0153uds pourraient \u00eatre assign\u00e9s au mauvais pays.\n\nLes donn\u00e9es des ces fichiers, comme les donn\u00e9es fournies par le client Tor, sont fournies par Maxmind.com.
dload_status_contact=R\u00e9cup\u00e9ration des derni\u00e8res donn\u00e9es GEOIP
dload_status_failed=\u00c9chec de t\u00e9l\u00e9chargement
chkbox_viator=T\u00e9l\u00e9charger par Tor
ttip_patterntable=\u00c9dition en ligne prise en charge, un double-clic gauche lance l'\u00e9dition d'une cellule d'un tableau.
fileext_pattern=Fichiers de mod\u00e8les zipp\u00e9

View file

@ -0,0 +1,256 @@
# French CA, Default language file, provided by yahoe001
gpltransurl=https://fsffrance.org/gpl/gpl-fr.fr.html
appdesc=$appname $appver, Les n\u0153uds de sortie de Tor simplifi\u00e9s.
text_yes=Oui
text_no=Non
wintitle_prefs = Pr\u00e9f\u00e9rences de $appname
wintitle_about = \u00c0 propos de $appname
wintitle_patternedit = \u00c9diteur de mod\u00e8les $appname
wintitle_guardnodes=S\u00e9lection des n\u0153uds de garde
wintitle_tormonitor=Moniteur du client Tor
textfield_unknown=Inconnu
progstatus_initial=Initialisation...
progstatus_bridges=Mise en place du changement de ponts.
progstatus_generate=G\u00e9n\u00e9ration d'une nouvelle liste de n\u0153uds, veuillez patienter.
progstatus_cachedated=Les descripteurs en cache sont p\u00e9rim\u00e9s, ils seront renouvel\u00e9s.
progstatus_nonet=L'acc\u00e8s \u00e0 Internet n'est pas disponible.
progstatus_checkrecommended=Recherche des derniers n\u0153uds recommand\u00e9s.
progstatus_torfailretry=\u00c9chec lors du d\u00e9marrage de Tor, nouvel essai.
progstatus_nodefail=\u00c9chec lors de l'activation du n\u0153ud demand\u00e9.
progstatus_nodefailretry=\u00c9chec lors de l'activation du n\u0153ud demand\u00e9. Nouvel essai, veuillez patienter.
progstatus_nodefailtorchoose=Le n\u0153ud demand\u00e9 n'est pas joignable, Tor en choisira un, veuillez patienter.
progstatus_nodeactive3hop=Le circuit \u00e0 3 sauts vers le n\u0153ud de sortie $nodename est actif.
progstatus_nodeactive2hop=Le circuit \u00e0 2 sauts vers le n\u0153ud de sortie $nodename est actif.
progstatus_autoswitch=Auto-commutation vers le n\u0153ud
progstatus_manswitch=Commutation vers le n\u0153ud choisi manuellement
progstatus_waitfortor=Attente d'activation d'un n\u0153ud par Tor.
progstatus_switchtonode=Commutation vers le n\u0153ud $nodename.
progstatus_applychanges=Mise en place des nouvelles pr\u00e9f\u00e9rences.
circuit_status_creating_2hop=Cr\u00e9ation d'un circuit \u00e0 2 sauts.
circuit_status_creating_3hop=Cr\u00e9ation d'un circuit \u00e0 3 sauts.
circuit_status_testing=Test du circuit.
circuit_status_aborted=Test interrompu.
circuit_status_built=$1 circuit(s) construit(s).
circuit_status_passed=Circuit v\u00e9rifi\u00e9.
circuit_status_failed=\u00c9chec de circuit.
circuit_status_none=Aucun circuit n'est disponible.
circuit_status_noroute=Routeurs (tous) hors service.
combo_proxymode1=D\u00e9sactiv\u00e9
combo_proxymode2=Relais par mod\u00e8le
combo_proxymode3=Relayer tout le trafic
combo_loglev1=D\u00e9bogage
combo_loglev2=Infos
combo_loglev3=Avis
traymenu_proxymode1=Mode : pas de relais
traymenu_proxymode2=Mode : relais par mod\u00e8le
traymenu_proxymode3=Mode : relayer tout le trafic
traymenu_showgui=Cacher/Montrer l'IUG
traytool_guardnode=Noeud de garde
traytool_exitnode=Noeud de sortie
exittable_col1=N\u0153ud de sortie
exittable_col2=BP (MB\\s)
exittable_col3=D\u00e9lai (ms)
exittable_col4=\u00c9tat
exittable_col5=Favori
patterntable_col1=Description
patterntable_col2=Mod\u00e8le
patterntable_col3=Activ\u00e9
guardtable_col1=N\u0153ud de garde
guardtable_col2=Pays
guardtable_col3=BP (MB\\s)
guardtable_col4=De confiance
menu_menu=Menu
menu_prefs=Pr\u00e9f\u00e9rences
menu_quickadd=Ajout rapide d'un mod\u00e8le
menu_patternedit=\u00c9diteur de mod\u00e8les de relais
menu_export=Exporter les mod\u00e8les
menu_import=Import les mod\u00e8les
menu_quit=Quitter
menu_defaultpatterns=Mod\u00e8le par d\u00e9faut
menu_userpatterns=Mod\u00e8les de l'utilisateur
menu_help=Aide
menu_debuglog=Voir le journal de d\u00e9bogage
menu_helpcontents=Contenu de l'aide
menu_torcheck=V\u00e9rification de routine de Tor
menu_about=\u00c0 propos de
menu_license=Licence
menu_proxy=Mode de relais
menu_close=Fermer le menu
menu_tormanual=Manuel officiel de Tor
menu_tormonitor=Moniteur du client Tor
menu_leaktest=Test de fuite DNS
menu_credits=Cr\u00e9dits
label_activecountry=Pays actif :
label_proxymode=Mode de relais :
label_exitnode=N\u0153ud de sortie :
label_ip=IP :
label_torlatency=D\u00e9lai
label_fingerprint=Empreinte :
label_bandwidth=Bande passante
label_streams=Flux
label_stable=Stable
label_status=\u00c9tat :
label_listenport=Port d'\u00e9coute de Tor :
label_defaultproxy=Mandataire HTTP par d\u00e9faut :
label_bridgeaddress=Adresse de pont de Tor :
label_portranges=Plages de port pr\u00e9sentement actives, de $portmin \u00e0 $portmax
label_editcountry=Choisir un pays pour voir ses mod\u00e8les
label_quickadd_desc=Description :
label_quickadd_pattern=Mod\u00e8le :
label_threshold=D\u00e9lai seuil
label_middle=Milieu :
label_exit=Sortie :
label_nickname=Pseudonyme
label_ip=IP
label_country=Pays
label_guard_minimum=Vous pouvez soit ne choisir aucun n\u0153ud de garde au cas o\u00f9 le client Tor les choisit, soit choisir trois n\u0153uds de garde ou plus.
label_torlogging=Niveau de journalisation :
label_torargs=Arguments de d\u00e9marrage :
label_torsocks=Param\u00e8tres Socks :
label_diskoptions=Options du disque :
label_guardnode=Garde :
label_bridgenode=Pont :
label_donotproxy=Ne pas relayer :
button_details=D\u00e9tails
button_whois=Qui est
button_close=Fermer
button_apply=Appliquer
button_delete=Supprimer
button_addnew=Ajouter un nouveau
button_save=Enregistrer
button_cancel=Annuler
button_continue=Continuer
button_getbridges=Obtenir des ponts
button_mozillarestart=Red\u00e9marrer $browser
button_visitus=Rendez-nous visite
button_contactus=Contactez-nous
button_translations=Traductions non officielles
button_prefdefaults=R\u00e9initialiser aux leurs valeurs par d\u00e9faut.
button_setguards=D\u00e9finir les n\u0153uds de garde
button_details=D\u00e9tails de l'atlas
button_clearguards=Effacer les n\u0153uds de garde choisis
button_clearfavs=Effacer les favoris
button_support=Soutenir SelekTOR
button_patreon=Soutenir SelekTOR avec Patreon
panel_general=Param\u00e8tres g\u00e9n\u00e9raux
panel_network= Param\u00e8tres r\u00e9seau
panel_management=Param\u00e8tres de gestion des n\u0153uds
panel_info=Circuit actif
panel_torclientset=Param\u00e8tres du client Tor
panel_startupargs=Arguments de d\u00e9marrage
panel_stdout=Moniteur de sortie standard
chkbox_autoselect=Choix automatique du n\u0153ud
chkbox_autostart=D\u00e9marrage automatique de SelekTOR
chkbox_checkforupdates=V\u00e9rifier les mises \u00e0 jour au d\u00e9marrage
chkbox_disabletray=D\u00e9sactiver l'ic\u00f4ne de notification
chkbox_autopatterns=Installer automatiquement les derniers mod\u00e8les.
chkbox_mozillawarn=D\u00e9sactiver l'avertissement de Mozilla
chkbox_recnodesonly=Utiliser les n\u0153uds recommand\u00e9s en mode par mod\u00e8les
chkbox_hidetotray=Minimiser au d\u00e9marrage
chkbox_minonclose=Minimiser plut\u00f4t que de quitter lors de la fermeture
chkbox_safesocks=Socks s\u00e9curitaire
chkbox_twohop=Utiliser des circuits \u00e0 2 sauts vers le n\u0153ud de sortie en mode par mod\u00e8les
chkbox_warnunsafesocks=Avertir si \u00e0 risque
chkbox_diskavoid=\u00c9viter les \u00e9critures sur le disque
chkbox_testsocks=Tester Socks
chkbox_safelog=Journalisation s\u00e9curitaire
chkbox_guardwarn1=Afficher une fen\u00eatre d'avertissement si un n\u0153ud de garde non sp\u00e9cifi\u00e9 est utilis\u00e9
chkbox_guardwarn2=Afficher une fen\u00eatre d'avertissement si moins de trois n\u0153uds de garde sont choisis
chkbox_securedelete=Effacement s\u00e9curis\u00e9 des caches de Tor lors de la fermeture
ttip_autostart=D\u00e9marrage automatique de SelekTOR lors du d\u00e9marrage/de la connexion
ttip_hidetotray=Minimiser au d\u00e9marrage
ttip_checkforupdates=SelekTOR v\u00e9rifiera les mises \u00e0 jour au d\u00e9marage
ttip_autoinstall=Les derniers mod\u00e8les seront r\u00e9cup\u00e9r\u00e9s de Dazzleships.Net
ttip_disabletray=D\u00e9sactiver l'ic\u00f4ne de notification
ttip_mozillawarn=D\u00e9sactiver l'avertissement du navigateur Mozilla
ttip_listenport=Le port d'\u00e9coute du client Tor
ttip_defaultproxy=Tout trafic qui ne sera pas redirig\u00e9 par Tor sera redirig\u00e9 par ce mandataire HTTP
ttip_donotproxy=Toute URL contenant une de ces entr\u00e9es s\u00e9par\u00e9es par des virgules ne sera pas relay\u00e9e. L'on s'y connectera directement.
ttip_bridgeaddress=Pour contourner le blocage du FSI, ajouter une adresse de pont valide ici
ttip_forcedns=Forcer la recherche DNS par Tor, exige le red\u00e9marrage du navigateur
ttip_forcenode=Si coch\u00e9, le n\u0153ud sera activ\u00e9 quelque soit l'activit\u00e9 du n\u0153ud
ttip_recnodesonly=Les n\u0153uds recommand\u00e9s seront utilis\u00e9s en mode par mod\u00e8les
ttip_minonclose=L'application sera minimis\u00e9e au lieu de quitter \u00e0 la fermeture de la fermeture principale
ttip_threshold=D\u00e9lai seuil
ttip_safesocks=Activ\u00e9e, Tor rejettera les connexions logicielles qui utilisent des variantes dangereuses du protocole Socks.
ttip_warnunsafe=Activ\u00e9e, Tor avertira \u00e0 chaque fois qu'une requ\u00eate est re\u00e7ue contenant seulement une adresse IP au lieu d'un nom d'h\u00f4te.
ttip_testsocks=Activ\u00e9e Tor journalisera une entr\u00e9e de journal de niveau avis pour chaque connexion en indiquant si elle utilise un protocole Socks s\u00e9curitaire ou dangereux.
ttip_safelogging=Activ\u00e9e, Tor nettoiera les cha\u00eenes potentiellement sensibles des messages de journalisation.
ttip_avoiddisk=Activ\u00e9e, Tor essaiera d'\u00e9crire moins fr\u00e9quemment sur le disque que nous ne le ferions autrement.
ttip_extraargs= Arguments suppl\u00e9mentaires sp\u00e9cifi\u00e9s par l'utilisateur, voir le Manuel Tor.
ttip_combo_loglevel=Niveau de journalisation de Tor.
ttip_twohop=Utiliser des circuits \u00e0 2 sauts au lieu des 3 par d\u00e9faut de Tor. R\u00e9duit le d\u00e9lai de transit mais affaiblit l'anonymat.
ttip_resetbasicprefs=R\u00e9initialiser les pr\u00e9f\u00e9rences de base \u00e0 leurs valeurs par d\u00e9faut.
ttip_resetadvprefs=R\u00e9initialiser les pr\u00e9f\u00e9rences avanc\u00e9es \u00e0 leurs valeurs par d\u00e9faut.
ttip_guardwarn1=Activ\u00e9, une fen\u00eatre d'avertissement sera affich\u00e9e indiquant qu'un n\u0153ud de garde non sp\u00e9cifi\u00e9 est actif.
ttip_guardwarn2=Activ\u00e9, une fen\u00eatre d'avertissement sera affich\u00e9e indiquant que trop peu de n\u0153uds de garde sont choisis
ttip_clearguards=Effacer les n\u0153uds de garde choisis.
ttip_securedelete=Activ\u00e9, les caches de Tor seront \u00e9cras\u00e9es par des z\u00e9ros, puis supprim\u00e9es
dlg_update_title=Mise \u00e0 jour disponible.
dlg_update_body=$version est maintenant disponible au t\u00e9l\u00e9chargement.
dlg_restoreproxy_title=Param\u00e8tres originaux du mandataire
dlg_restoreproxy_body=Choisir Continuer pour restaurer les param\u00e8tres du mandataire aux valeurs par d\u00e9faut avant l'installation de SelekTOR.
dlg_resetproxy_title=Param\u00e8tres par d\u00e9faut du mandataire
dlg_resetproxy_body=Choisir Continuer pour r\u00e9initialiser les param\u00e8tres du serveur mandataire \u00e0 leurs valeurs syst\u00e8me par d\u00e9faut.
dlg_gsetting_title=Gsettings introuvable
dlg_gsetting_body=$appname ne peux pas fonctionner correctement sans que l'ex\u00e9cutable binary soit install\u00e9. Dans certaines distributions il peut \u00eatre trouv\u00e9 dans le paquet libglib2.0-bin.
dlg_torclient_title=Client TOR introuvable
dlg_torclient_body=$appname ne peux pas fonctionner sans que le client Tor ne soit Install\u00e9. Veuillez installer les paquets tor et tor-geoipdb pour votre distribution.
dlg_mozillarestart_title=Avertissement\u00a0: Le navigateur $browser est actif.
dlg_mozillarestart_body=$appname a d\u00e9tect\u00e9 que le navigateur $browser tourne d\u00e9j\u00e0.\nUn red\u00e9marrage du navigateur est exig\u00e9 pour permettre le fonctionnement de $appname.\n\nSi vous choisissez de red\u00e9marrer $browser, tous les onglets actuellement ouverts seront restaur\u00e9s au red\u00e9marrage de $browser, l'option \u00ab Afficher les dernier onglets et fen\u00eatres utilis\u00e9s \u00bb, doit \u00eatre choisie dans les options de $browser.\n\nVous pouvez d\u00e9sactiver cet avertissement du navigateur dans les Pr\u00e9f\u00e9rences de $appname.
dlg_license_title=Licence de $appname
dlg_exportuser_title=Exporter les mod\u00e8les d'utilisateur
dlg_exportuser_body=Aucun mod\u00e8le cr\u00e9\u00e9 par l'utilisateur n'a \u00e9t\u00e9 trouv\u00e9.\n\nUtilisez l'\u00e9diteur de mode pour ajouter vos propres mod\u00e8les
dlg_exportdefault_title=Exporter les mod\u00e8les par d\u00e9faut
dlg_exportdefault_body=Aucun mod\u00e8le par d\u00e9faut n'a \u00e9t\u00e9 trouv\u00e9.
dlg_saveuser_title=Enregistrer les modes de l'utilisateur
dlg_savedefault_title=Enregistrer les mod\u00e8les par d\u00e9faut
dlg_import_title=Importer le fichier des mod\u00e8les
dlg_import_success_title=Mod\u00e8les import\u00e9s
dlg_import_success_body=Les mod\u00e8les ont \u00e9t\u00e9 import\u00e9s avec succ\u00e8s et sont maintenant actifs.
dlg_import_fail_title=\u00c9chec lors l'importation
dlg_import_fail_body=Les mod\u00e8les n'ont pas \u00e9t\u00e9 import\u00e9s correctement.
dlg_whois_title=Qui est $ipaddress
dlg_whois_body=Veuillez patienter pendant que j'essaie de r\u00e9cup\u00e9rer les donn\u00e9s de WhoIs...
dlg_whois_fail=D\u00e9sol\u00e9, impossible de r\u00e9cup\u00e9rer les informations de Whois.
dlg_toold_body=Le client Tor actuellement install\u00e9 est trop ancien, Tor 0.2.7.6 ou ult\u00e9rieure est exig\u00e9e.\n\nLes utilisateurs de Linux devraient visiter la page suivante \nhttps://www.torproject.org/download/download-unix.html.en\npour obtenir le dernier client Tor.
dlg_error_title=Erreur de d\u00e9marrage
dlg_error_body=Cette erreur est fatale et $appname se fermera.
dlg_quickadd_title=Ajouter un mod\u00e8le
dlg_nodelistfail_body=La g\u00e9n\u00e9ration de la liste des n\u0153uds a \u00e9chou\u00e9 \u00e0 cause d'erreurs de GEOIP.
dlg_patterneditsave_title=Enregistrer les mod\u00e8les actuels
dlg_patterneditsave_body=Les mod\u00e8les actuels ont \u00e9t\u00e9 modifi\u00e9s.\n\nSi vous d\u00e9sirez les enregistrer, cliquez sur Continuer, autrement cliquez sur Annuler.
dlg_instancefail_title=\u00c9chec d\u00fb \u00e0 plusieurs instances
dlg_instancefail_body=Une instance de $appname est d\u00e9j\u00e0 en cours et une seule peut \u00eatre ex\u00e9cut\u00e9e \u00e0 la fois.\n\nQuittez l'instance existante de $appname ou dans le cas d'un plantage de $appname, red\u00e9marrez X en vous d\u00e9connectant et en vous connectant de nouveau.
dlg_guardwarn_title=Avertissement de n\u0153ud de garde
dlg_guardwarn_body=Un n\u0153ud de garde ne se trouvant pas dans votre liste de n\u0153uds de garde sp\u00e9cifi\u00e9e a \u00e9t\u00e9 utilis\u00e9.\nCeci provient probablement du fait que vos n\u0153uds de garde s\u00e9lectionn\u00e9s ne sont plus joignables et par cons\u00e9quent le client Tor a assign\u00e9 son propre n\u0153ud de garde.\n\nVous devriez v\u00e9rifier vos n\u0153uds de garde actuellement d\u00e9finis pour voir s'ils sont toujours disponibles, ou en choisir de nouveaux.
dlg_notenoughguards_body=Il n'y a pas assez de n\u0153uds de garde d\u00e9finis afin que Tor fonctionne efficacement et en toute s\u00e9curit\u00e9.\n\nSupprimez tous les n\u0153uds de garde s\u00e9lectionn\u00e9s, ce qui permettra au client Tor de choisir ses propres n\u0153uds de garde, ou choisissez manuellement trois n\u0153uds de garde ou plus.dlg_notenoughguards_body=Il n'y a pas assez de n\u0153uds de garde d\u00e9finis afin que Tor fonctionne efficacement et en toute s\u00e9curit\u00e9.\n\nSupprimez tous les n\u0153uds de garde s\u00e9lectionn\u00e9s, ce qui permettra au client Tor de choisir ses propres n\u0153uds de garde, ou choisissez manuellement trois n\u0153uds de garde ou plus.
dlg_bridgerr_title=\u00c9chec de validation de l'adresse de pont
dlg_bridgerr_body=Les informations de pont fournies contiennent des erreurs de validation et ne se conforment pas \u00e0 un format d'adresse IPv4 valide h\u00f4te:port\n\nVoici des exemples de format de sp\u00e9cification de ponts :\n\nPont simple : \n127.0.0.1:8080\n\nPonts multiples : \n127.0.0.1:8080,128.5.6.8:224\n\nLes ponts ont \u00e9t\u00e9 r\u00e9initialis\u00e9s \u00e0 leurs valeurs par d\u00e9faut.
dlg_credits_title=Cr\u00e9dits de $appname
dlg_credits_body=Afin que votre nom apparaissent ici et pour aussi m\u00e9riter ma gratitude, veuillez envisager de soutenir le d\u00e9veloppement futur de SelekTOR sous Linux avec Patreon.
table_popup_details=D\u00e9tails
table_popup_whois=Qui est
table_popup_begintest=Commencer le cycle de test
tab_basic=De base
tab_advanced=Avanc\u00e9
isoA1=Mandataire annonyme
isoO1=autre Pays
isoU1=Inconnu
chkbox_disablenotify=D\u00e9sactiver les notifications du bureau
ttip_disablenotify=D\u00e9sactiver les notifications du bureau
dlg_libnotify_title=notify-send est introuvable
dlg_libnotify_body=Les notifications de bureau ne fonctionneront pas sans que le paquet libnotify-bin ne soit install\u00e9.\n\nPour emp\u00eacher que cette fen\u00eatre apparaissent de nouveau installez le paquet exig\u00e9 ou d\u00e9sactivez les notifications de bureau dans les pr\u00e9f\u00e9rences.
ttip_hidemin=L'appli sera cach\u00e9e au lieu d'\u00eatre minimis\u00e9e.
chkbox_hidemin=Cacher au lieu de minimiser
label_autoselect= Mode de s\u00e9lection automatique :
menu_geoip=Mettre GEOIP \u00e0 jour
chkbox_geocheck=V\u00e9rification trimestrielle des mises \u00e0 jour GEOIP
ttip_geocheck=SelekTOR affichera la \u00abfen\u00eatre de mise \u00e0 jour GEOIP \u00bbsi votre base de donn\u00e9es GEOIP est p\u00e9rim\u00e9e.
dlg_geo_title=Mise \u00e0 jour des donn\u00e9es de g\u00e9olocalisation
dlg_geo_body=Les donn\u00e9es de g\u00e9olocalisation fournies par Tor sont parfois p\u00e9rim\u00e9es. Vous pouvez demander \u00e0 SelekTOR de t\u00e9l\u00e9charger ses propres fichiers de donn\u00e9es de g\u00e9olocalisation de Dazzleships.net et de les utiliser. Ils sont mis \u00e0 jour trimestriellement.\n\nVeuillez noter que si vous choisissez de ne pas mettre \u00e0 jour, certains n\u0153uds pourraient \u00eatre assign\u00e9s au mauvais pays.\n\nLes donn\u00e9es des ces fichiers, comme les donn\u00e9es fournies par le client Tor, sont fournies par Maxmind.com.
dload_status_contact=R\u00e9cup\u00e9ration des derni\u00e8res donn\u00e9es GEOIP
dload_status_failed=\u00c9chec de t\u00e9l\u00e9chargement
chkbox_viator=T\u00e9l\u00e9charger par Tor
ttip_patterntable=\u00c9dition en ligne prise en charge, un double-clic gauche lance l'\u00e9dition d'une cellule d'un tableau.
fileext_pattern=Fichiers de mod\u00e8les zipp\u00e9

View file

@ -0,0 +1,256 @@
# French CA, Default language file, provided by yahoe001
gpltransurl=https://fsffrance.org/gpl/gpl-fr.fr.html
appdesc=$appname $appver, Les n\u0153uds de sortie de Tor simplifi\u00e9s.
text_yes=Oui
text_no=Non
wintitle_prefs = Pr\u00e9f\u00e9rences de $appname
wintitle_about = \u00c0 propos de $appname
wintitle_patternedit = \u00c9diteur de mod\u00e8les $appname
wintitle_guardnodes=S\u00e9lection des n\u0153uds de garde
wintitle_tormonitor=Moniteur du client Tor
textfield_unknown=Inconnu
progstatus_initial=Initialisation...
progstatus_bridges=Mise en place du changement de ponts.
progstatus_generate=G\u00e9n\u00e9ration d'une nouvelle liste de n\u0153uds, veuillez patienter.
progstatus_cachedated=Les descripteurs en cache sont p\u00e9rim\u00e9s, ils seront renouvel\u00e9s.
progstatus_nonet=L'acc\u00e8s \u00e0 Internet n'est pas disponible.
progstatus_checkrecommended=Recherche des derniers n\u0153uds recommand\u00e9s.
progstatus_torfailretry=\u00c9chec lors du d\u00e9marrage de Tor, nouvel essai.
progstatus_nodefail=\u00c9chec lors de l'activation du n\u0153ud demand\u00e9.
progstatus_nodefailretry=\u00c9chec lors de l'activation du n\u0153ud demand\u00e9. Nouvel essai, veuillez patienter.
progstatus_nodefailtorchoose=Le n\u0153ud demand\u00e9 n'est pas joignable, Tor en choisira un, veuillez patienter.
progstatus_nodeactive3hop=Le circuit \u00e0 3 sauts vers le n\u0153ud de sortie $nodename est actif.
progstatus_nodeactive2hop=Le circuit \u00e0 2 sauts vers le n\u0153ud de sortie $nodename est actif.
progstatus_autoswitch=Auto-commutation vers le n\u0153ud
progstatus_manswitch=Commutation vers le n\u0153ud choisi manuellement
progstatus_waitfortor=Attente d'activation d'un n\u0153ud par Tor.
progstatus_switchtonode=Commutation vers le n\u0153ud $nodename.
progstatus_applychanges=Mise en place des nouvelles pr\u00e9f\u00e9rences.
circuit_status_creating_2hop=Cr\u00e9ation d'un circuit \u00e0 2 sauts.
circuit_status_creating_3hop=Cr\u00e9ation d'un circuit \u00e0 3 sauts.
circuit_status_testing=Test du circuit.
circuit_status_aborted=Test interrompu.
circuit_status_built=$1 circuit(s) construit(s).
circuit_status_passed=Circuit v\u00e9rifi\u00e9.
circuit_status_failed=\u00c9chec de circuit.
circuit_status_none=Aucun circuit n'est disponible.
circuit_status_noroute=Routeurs (tous) hors service.
combo_proxymode1=D\u00e9sactiv\u00e9
combo_proxymode2=Relais par mod\u00e8le
combo_proxymode3=Relayer tout le trafic
combo_loglev1=D\u00e9bogage
combo_loglev2=Infos
combo_loglev3=Avis
traymenu_proxymode1=Mode : pas de relais
traymenu_proxymode2=Mode : relais par mod\u00e8le
traymenu_proxymode3=Mode : relayer tout le trafic
traymenu_showgui=Cacher/Montrer l'IUG
traytool_guardnode=Noeud de garde
traytool_exitnode=Noeud de sortie
exittable_col1=N\u0153ud de sortie
exittable_col2=BP (MB\\s)
exittable_col3=D\u00e9lai (ms)
exittable_col4=\u00c9tat
exittable_col5=Favori
patterntable_col1=Description
patterntable_col2=Mod\u00e8le
patterntable_col3=Activ\u00e9
guardtable_col1=N\u0153ud de garde
guardtable_col2=Pays
guardtable_col3=BP (MB\\s)
guardtable_col4=De confiance
menu_menu=Menu
menu_prefs=Pr\u00e9f\u00e9rences
menu_quickadd=Ajout rapide d'un mod\u00e8le
menu_patternedit=\u00c9diteur de mod\u00e8les de relais
menu_export=Exporter les mod\u00e8les
menu_import=Import les mod\u00e8les
menu_quit=Quitter
menu_defaultpatterns=Mod\u00e8le par d\u00e9faut
menu_userpatterns=Mod\u00e8les de l'utilisateur
menu_help=Aide
menu_debuglog=Voir le journal de d\u00e9bogage
menu_helpcontents=Contenu de l'aide
menu_torcheck=V\u00e9rification de routine de Tor
menu_about=\u00c0 propos de
menu_license=Licence
menu_proxy=Mode de relais
menu_close=Fermer le menu
menu_tormanual=Manuel officiel de Tor
menu_tormonitor=Moniteur du client Tor
menu_leaktest=Test de fuite DNS
menu_credits=Cr\u00e9dits
label_activecountry=Pays actif :
label_proxymode=Mode de relais :
label_exitnode=N\u0153ud de sortie :
label_ip=IP :
label_torlatency=D\u00e9lai
label_fingerprint=Empreinte :
label_bandwidth=Bande passante
label_streams=Flux
label_stable=Stable
label_status=\u00c9tat :
label_listenport=Port d'\u00e9coute de Tor :
label_defaultproxy=Mandataire HTTP par d\u00e9faut :
label_bridgeaddress=Adresse de pont de Tor :
label_portranges=Plages de port pr\u00e9sentement actives, de $portmin \u00e0 $portmax
label_editcountry=Choisir un pays pour voir ses mod\u00e8les
label_quickadd_desc=Description :
label_quickadd_pattern=Mod\u00e8le :
label_threshold=D\u00e9lai seuil
label_middle=Milieu :
label_exit=Sortie :
label_nickname=Pseudonyme
label_ip=IP
label_country=Pays
label_guard_minimum=Vous pouvez soit ne choisir aucun n\u0153ud de garde au cas o\u00f9 le client Tor les choisit, soit choisir trois n\u0153uds de garde ou plus.
label_torlogging=Niveau de journalisation :
label_torargs=Arguments de d\u00e9marrage :
label_torsocks=Param\u00e8tres Socks :
label_diskoptions=Options du disque :
label_guardnode=Garde :
label_bridgenode=Pont :
label_donotproxy=Ne pas relayer :
button_details=D\u00e9tails
button_whois=Qui est
button_close=Fermer
button_apply=Appliquer
button_delete=Supprimer
button_addnew=Ajouter un nouveau
button_save=Enregistrer
button_cancel=Annuler
button_continue=Continuer
button_getbridges=Obtenir des ponts
button_mozillarestart=Red\u00e9marrer $browser
button_visitus=Rendez-nous visite
button_contactus=Contactez-nous
button_translations=Traductions non officielles
button_prefdefaults=R\u00e9initialiser aux leurs valeurs par d\u00e9faut.
button_setguards=D\u00e9finir les n\u0153uds de garde
button_details=D\u00e9tails de l'atlas
button_clearguards=Effacer les n\u0153uds de garde choisis
button_clearfavs=Effacer les favoris
button_support=Soutenir SelekTOR
button_patreon=Soutenir SelekTOR avec Patreon
panel_general=Param\u00e8tres g\u00e9n\u00e9raux
panel_network= Param\u00e8tres r\u00e9seau
panel_management=Param\u00e8tres de gestion des n\u0153uds
panel_info=Circuit actif
panel_torclientset=Param\u00e8tres du client Tor
panel_startupargs=Arguments de d\u00e9marrage
panel_stdout=Moniteur de sortie standard
chkbox_autoselect=Choix automatique du n\u0153ud
chkbox_autostart=D\u00e9marrage automatique de SelekTOR
chkbox_checkforupdates=V\u00e9rifier les mises \u00e0 jour au d\u00e9marrage
chkbox_disabletray=D\u00e9sactiver l'ic\u00f4ne de notification
chkbox_autopatterns=Installer automatiquement les derniers mod\u00e8les.
chkbox_mozillawarn=D\u00e9sactiver l'avertissement de Mozilla
chkbox_recnodesonly=Utiliser les n\u0153uds recommand\u00e9s en mode par mod\u00e8les
chkbox_hidetotray=Minimiser au d\u00e9marrage
chkbox_minonclose=Minimiser plut\u00f4t que de quitter lors de la fermeture
chkbox_safesocks=Socks s\u00e9curitaire
chkbox_twohop=Utiliser des circuits \u00e0 2 sauts vers le n\u0153ud de sortie en mode par mod\u00e8les
chkbox_warnunsafesocks=Avertir si \u00e0 risque
chkbox_diskavoid=\u00c9viter les \u00e9critures sur le disque
chkbox_testsocks=Tester Socks
chkbox_safelog=Journalisation s\u00e9curitaire
chkbox_guardwarn1=Afficher une fen\u00eatre d'avertissement si un n\u0153ud de garde non sp\u00e9cifi\u00e9 est utilis\u00e9
chkbox_guardwarn2=Afficher une fen\u00eatre d'avertissement si moins de trois n\u0153uds de garde sont choisis
chkbox_securedelete=Effacement s\u00e9curis\u00e9 des caches de Tor lors de la fermeture
ttip_autostart=D\u00e9marrage automatique de SelekTOR lors du d\u00e9marrage/de la connexion
ttip_hidetotray=Minimiser au d\u00e9marrage
ttip_checkforupdates=SelekTOR v\u00e9rifiera les mises \u00e0 jour au d\u00e9marage
ttip_autoinstall=Les derniers mod\u00e8les seront r\u00e9cup\u00e9r\u00e9s de Dazzleships.Net
ttip_disabletray=D\u00e9sactiver l'ic\u00f4ne de notification
ttip_mozillawarn=D\u00e9sactiver l'avertissement du navigateur Mozilla
ttip_listenport=Le port d'\u00e9coute du client Tor
ttip_defaultproxy=Tout trafic qui ne sera pas redirig\u00e9 par Tor sera redirig\u00e9 par ce mandataire HTTP
ttip_donotproxy=Toute URL contenant une de ces entr\u00e9es s\u00e9par\u00e9es par des virgules ne sera pas relay\u00e9e. L'on s'y connectera directement.
ttip_bridgeaddress=Pour contourner le blocage du FSI, ajouter une adresse de pont valide ici
ttip_forcedns=Forcer la recherche DNS par Tor, exige le red\u00e9marrage du navigateur
ttip_forcenode=Si coch\u00e9, le n\u0153ud sera activ\u00e9 quelque soit l'activit\u00e9 du n\u0153ud
ttip_recnodesonly=Les n\u0153uds recommand\u00e9s seront utilis\u00e9s en mode par mod\u00e8les
ttip_minonclose=L'application sera minimis\u00e9e au lieu de quitter \u00e0 la fermeture de la fermeture principale
ttip_threshold=D\u00e9lai seuil
ttip_safesocks=Activ\u00e9e, Tor rejettera les connexions logicielles qui utilisent des variantes dangereuses du protocole Socks.
ttip_warnunsafe=Activ\u00e9e, Tor avertira \u00e0 chaque fois qu'une requ\u00eate est re\u00e7ue contenant seulement une adresse IP au lieu d'un nom d'h\u00f4te.
ttip_testsocks=Activ\u00e9e Tor journalisera une entr\u00e9e de journal de niveau avis pour chaque connexion en indiquant si elle utilise un protocole Socks s\u00e9curitaire ou dangereux.
ttip_safelogging=Activ\u00e9e, Tor nettoiera les cha\u00eenes potentiellement sensibles des messages de journalisation.
ttip_avoiddisk=Activ\u00e9e, Tor essaiera d'\u00e9crire moins fr\u00e9quemment sur le disque que nous ne le ferions autrement.
ttip_extraargs= Arguments suppl\u00e9mentaires sp\u00e9cifi\u00e9s par l'utilisateur, voir le Manuel Tor.
ttip_combo_loglevel=Niveau de journalisation de Tor.
ttip_twohop=Utiliser des circuits \u00e0 2 sauts au lieu des 3 par d\u00e9faut de Tor. R\u00e9duit le d\u00e9lai de transit mais affaiblit l'anonymat.
ttip_resetbasicprefs=R\u00e9initialiser les pr\u00e9f\u00e9rences de base \u00e0 leurs valeurs par d\u00e9faut.
ttip_resetadvprefs=R\u00e9initialiser les pr\u00e9f\u00e9rences avanc\u00e9es \u00e0 leurs valeurs par d\u00e9faut.
ttip_guardwarn1=Activ\u00e9, une fen\u00eatre d'avertissement sera affich\u00e9e indiquant qu'un n\u0153ud de garde non sp\u00e9cifi\u00e9 est actif.
ttip_guardwarn2=Activ\u00e9, une fen\u00eatre d'avertissement sera affich\u00e9e indiquant que trop peu de n\u0153uds de garde sont choisis
ttip_clearguards=Effacer les n\u0153uds de garde choisis.
ttip_securedelete=Activ\u00e9, les caches de Tor seront \u00e9cras\u00e9es par des z\u00e9ros, puis supprim\u00e9es
dlg_update_title=Mise \u00e0 jour disponible.
dlg_update_body=$version est maintenant disponible au t\u00e9l\u00e9chargement.
dlg_restoreproxy_title=Param\u00e8tres originaux du mandataire
dlg_restoreproxy_body=Choisir Continuer pour restaurer les param\u00e8tres du mandataire aux valeurs par d\u00e9faut avant l'installation de SelekTOR.
dlg_resetproxy_title=Param\u00e8tres par d\u00e9faut du mandataire
dlg_resetproxy_body=Choisir Continuer pour r\u00e9initialiser les param\u00e8tres du serveur mandataire \u00e0 leurs valeurs syst\u00e8me par d\u00e9faut.
dlg_gsetting_title=Gsettings introuvable
dlg_gsetting_body=$appname ne peux pas fonctionner correctement sans que l'ex\u00e9cutable binary soit install\u00e9. Dans certaines distributions il peut \u00eatre trouv\u00e9 dans le paquet libglib2.0-bin.
dlg_torclient_title=Client TOR introuvable
dlg_torclient_body=$appname ne peux pas fonctionner sans que le client Tor ne soit Install\u00e9. Veuillez installer les paquets tor et tor-geoipdb pour votre distribution.
dlg_mozillarestart_title=Avertissement\u00a0: Le navigateur $browser est actif.
dlg_mozillarestart_body=$appname a d\u00e9tect\u00e9 que le navigateur $browser tourne d\u00e9j\u00e0.\nUn red\u00e9marrage du navigateur est exig\u00e9 pour permettre le fonctionnement de $appname.\n\nSi vous choisissez de red\u00e9marrer $browser, tous les onglets actuellement ouverts seront restaur\u00e9s au red\u00e9marrage de $browser, l'option \u00ab Afficher les dernier onglets et fen\u00eatres utilis\u00e9s \u00bb, doit \u00eatre choisie dans les options de $browser.\n\nVous pouvez d\u00e9sactiver cet avertissement du navigateur dans les Pr\u00e9f\u00e9rences de $appname.
dlg_license_title=Licence de $appname
dlg_exportuser_title=Exporter les mod\u00e8les d'utilisateur
dlg_exportuser_body=Aucun mod\u00e8le cr\u00e9\u00e9 par l'utilisateur n'a \u00e9t\u00e9 trouv\u00e9.\n\nUtilisez l'\u00e9diteur de mode pour ajouter vos propres mod\u00e8les
dlg_exportdefault_title=Exporter les mod\u00e8les par d\u00e9faut
dlg_exportdefault_body=Aucun mod\u00e8le par d\u00e9faut n'a \u00e9t\u00e9 trouv\u00e9.
dlg_saveuser_title=Enregistrer les modes de l'utilisateur
dlg_savedefault_title=Enregistrer les mod\u00e8les par d\u00e9faut
dlg_import_title=Importer le fichier des mod\u00e8les
dlg_import_success_title=Mod\u00e8les import\u00e9s
dlg_import_success_body=Les mod\u00e8les ont \u00e9t\u00e9 import\u00e9s avec succ\u00e8s et sont maintenant actifs.
dlg_import_fail_title=\u00c9chec lors l'importation
dlg_import_fail_body=Les mod\u00e8les n'ont pas \u00e9t\u00e9 import\u00e9s correctement.
dlg_whois_title=Qui est $ipaddress
dlg_whois_body=Veuillez patienter pendant que j'essaie de r\u00e9cup\u00e9rer les donn\u00e9s de WhoIs...
dlg_whois_fail=D\u00e9sol\u00e9, impossible de r\u00e9cup\u00e9rer les informations de Whois.
dlg_toold_body=Le client Tor actuellement install\u00e9 est trop ancien, Tor 0.2.7.6 ou ult\u00e9rieure est exig\u00e9e.\n\nLes utilisateurs de Linux devraient visiter la page suivante \nhttps://www.torproject.org/download/download-unix.html.en\npour obtenir le dernier client Tor.
dlg_error_title=Erreur de d\u00e9marrage
dlg_error_body=Cette erreur est fatale et $appname se fermera.
dlg_quickadd_title=Ajouter un mod\u00e8le
dlg_nodelistfail_body=La g\u00e9n\u00e9ration de la liste des n\u0153uds a \u00e9chou\u00e9 \u00e0 cause d'erreurs de GEOIP.
dlg_patterneditsave_title=Enregistrer les mod\u00e8les actuels
dlg_patterneditsave_body=Les mod\u00e8les actuels ont \u00e9t\u00e9 modifi\u00e9s.\n\nSi vous d\u00e9sirez les enregistrer, cliquez sur Continuer, autrement cliquez sur Annuler.
dlg_instancefail_title=\u00c9chec d\u00fb \u00e0 plusieurs instances
dlg_instancefail_body=Une instance de $appname est d\u00e9j\u00e0 en cours et une seule peut \u00eatre ex\u00e9cut\u00e9e \u00e0 la fois.\n\nQuittez l'instance existante de $appname ou dans le cas d'un plantage de $appname, red\u00e9marrez X en vous d\u00e9connectant et en vous connectant de nouveau.
dlg_guardwarn_title=Avertissement de n\u0153ud de garde
dlg_guardwarn_body=Un n\u0153ud de garde ne se trouvant pas dans votre liste de n\u0153uds de garde sp\u00e9cifi\u00e9e a \u00e9t\u00e9 utilis\u00e9.\nCeci provient probablement du fait que vos n\u0153uds de garde s\u00e9lectionn\u00e9s ne sont plus joignables et par cons\u00e9quent le client Tor a assign\u00e9 son propre n\u0153ud de garde.\n\nVous devriez v\u00e9rifier vos n\u0153uds de garde actuellement d\u00e9finis pour voir s'ils sont toujours disponibles, ou en choisir de nouveaux.
dlg_notenoughguards_body=Il n'y a pas assez de n\u0153uds de garde d\u00e9finis afin que Tor fonctionne efficacement et en toute s\u00e9curit\u00e9.\n\nSupprimez tous les n\u0153uds de garde s\u00e9lectionn\u00e9s, ce qui permettra au client Tor de choisir ses propres n\u0153uds de garde, ou choisissez manuellement trois n\u0153uds de garde ou plus.dlg_notenoughguards_body=Il n'y a pas assez de n\u0153uds de garde d\u00e9finis afin que Tor fonctionne efficacement et en toute s\u00e9curit\u00e9.\n\nSupprimez tous les n\u0153uds de garde s\u00e9lectionn\u00e9s, ce qui permettra au client Tor de choisir ses propres n\u0153uds de garde, ou choisissez manuellement trois n\u0153uds de garde ou plus.
dlg_bridgerr_title=\u00c9chec de validation de l'adresse de pont
dlg_bridgerr_body=Les informations de pont fournies contiennent des erreurs de validation et ne se conforment pas \u00e0 un format d'adresse IPv4 valide h\u00f4te:port\n\nVoici des exemples de format de sp\u00e9cification de ponts :\n\nPont simple : \n127.0.0.1:8080\n\nPonts multiples : \n127.0.0.1:8080,128.5.6.8:224\n\nLes ponts ont \u00e9t\u00e9 r\u00e9initialis\u00e9s \u00e0 leurs valeurs par d\u00e9faut.
dlg_credits_title=Cr\u00e9dits de $appname
dlg_credits_body=Afin que votre nom apparaissent ici et pour aussi m\u00e9riter ma gratitude, veuillez envisager de soutenir le d\u00e9veloppement futur de SelekTOR sous Linux avec Patreon.
table_popup_details=D\u00e9tails
table_popup_whois=Qui est
table_popup_begintest=Commencer le cycle de test
tab_basic=De base
tab_advanced=Avanc\u00e9
isoA1=Mandataire annonyme
isoO1=autre Pays
isoU1=Inconnu
chkbox_disablenotify=D\u00e9sactiver les notifications du bureau
ttip_disablenotify=D\u00e9sactiver les notifications du bureau
dlg_libnotify_title=notify-send est introuvable
dlg_libnotify_body=Les notifications de bureau ne fonctionneront pas sans que le paquet libnotify-bin ne soit install\u00e9.\n\nPour emp\u00eacher que cette fen\u00eatre apparaissent de nouveau installez le paquet exig\u00e9 ou d\u00e9sactivez les notifications de bureau dans les pr\u00e9f\u00e9rences.
ttip_hidemin=L'appli sera cach\u00e9e au lieu d'\u00eatre minimis\u00e9e.
chkbox_hidemin=Cacher au lieu de minimiser
label_autoselect= Mode de s\u00e9lection automatique :
menu_geoip=Mettre GEOIP \u00e0 jour
chkbox_geocheck=V\u00e9rification trimestrielle des mises \u00e0 jour GEOIP
ttip_geocheck=SelekTOR affichera la \u00abfen\u00eatre de mise \u00e0 jour GEOIP \u00bbsi votre base de donn\u00e9es GEOIP est p\u00e9rim\u00e9e.
dlg_geo_title=Mise \u00e0 jour des donn\u00e9es de g\u00e9olocalisation
dlg_geo_body=Les donn\u00e9es de g\u00e9olocalisation fournies par Tor sont parfois p\u00e9rim\u00e9es. Vous pouvez demander \u00e0 SelekTOR de t\u00e9l\u00e9charger ses propres fichiers de donn\u00e9es de g\u00e9olocalisation de Dazzleships.net et de les utiliser. Ils sont mis \u00e0 jour trimestriellement.\n\nVeuillez noter que si vous choisissez de ne pas mettre \u00e0 jour, certains n\u0153uds pourraient \u00eatre assign\u00e9s au mauvais pays.\n\nLes donn\u00e9es des ces fichiers, comme les donn\u00e9es fournies par le client Tor, sont fournies par Maxmind.com.
dload_status_contact=R\u00e9cup\u00e9ration des derni\u00e8res donn\u00e9es GEOIP
dload_status_failed=\u00c9chec de t\u00e9l\u00e9chargement
chkbox_viator=T\u00e9l\u00e9charger par Tor
ttip_patterntable=\u00c9dition en ligne prise en charge, un double-clic gauche lance l'\u00e9dition d'une cellule d'un tableau.
fileext_pattern=Fichiers de mod\u00e8les zipp\u00e9

View file

@ -0,0 +1,256 @@
# French CA, Default language file, provided by yahoe001
gpltransurl=https://fsffrance.org/gpl/gpl-fr.fr.html
appdesc=$appname $appver, Les n\u0153uds de sortie de Tor simplifi\u00e9s.
text_yes=Oui
text_no=Non
wintitle_prefs = Pr\u00e9f\u00e9rences de $appname
wintitle_about = \u00c0 propos de $appname
wintitle_patternedit = \u00c9diteur de mod\u00e8les $appname
wintitle_guardnodes=S\u00e9lection des n\u0153uds de garde
wintitle_tormonitor=Moniteur du client Tor
textfield_unknown=Inconnu
progstatus_initial=Initialisation...
progstatus_bridges=Mise en place du changement de ponts.
progstatus_generate=G\u00e9n\u00e9ration d'une nouvelle liste de n\u0153uds, veuillez patienter.
progstatus_cachedated=Les descripteurs en cache sont p\u00e9rim\u00e9s, ils seront renouvel\u00e9s.
progstatus_nonet=L'acc\u00e8s \u00e0 Internet n'est pas disponible.
progstatus_checkrecommended=Recherche des derniers n\u0153uds recommand\u00e9s.
progstatus_torfailretry=\u00c9chec lors du d\u00e9marrage de Tor, nouvel essai.
progstatus_nodefail=\u00c9chec lors de l'activation du n\u0153ud demand\u00e9.
progstatus_nodefailretry=\u00c9chec lors de l'activation du n\u0153ud demand\u00e9. Nouvel essai, veuillez patienter.
progstatus_nodefailtorchoose=Le n\u0153ud demand\u00e9 n'est pas joignable, Tor en choisira un, veuillez patienter.
progstatus_nodeactive3hop=Le circuit \u00e0 3 sauts vers le n\u0153ud de sortie $nodename est actif.
progstatus_nodeactive2hop=Le circuit \u00e0 2 sauts vers le n\u0153ud de sortie $nodename est actif.
progstatus_autoswitch=Auto-commutation vers le n\u0153ud
progstatus_manswitch=Commutation vers le n\u0153ud choisi manuellement
progstatus_waitfortor=Attente d'activation d'un n\u0153ud par Tor.
progstatus_switchtonode=Commutation vers le n\u0153ud $nodename.
progstatus_applychanges=Mise en place des nouvelles pr\u00e9f\u00e9rences.
circuit_status_creating_2hop=Cr\u00e9ation d'un circuit \u00e0 2 sauts.
circuit_status_creating_3hop=Cr\u00e9ation d'un circuit \u00e0 3 sauts.
circuit_status_testing=Test du circuit.
circuit_status_aborted=Test interrompu.
circuit_status_built=$1 circuit(s) construit(s).
circuit_status_passed=Circuit v\u00e9rifi\u00e9.
circuit_status_failed=\u00c9chec de circuit.
circuit_status_none=Aucun circuit n'est disponible.
circuit_status_noroute=Routeurs (tous) hors service.
combo_proxymode1=D\u00e9sactiv\u00e9
combo_proxymode2=Relais par mod\u00e8le
combo_proxymode3=Relayer tout le trafic
combo_loglev1=D\u00e9bogage
combo_loglev2=Infos
combo_loglev3=Avis
traymenu_proxymode1=Mode : pas de relais
traymenu_proxymode2=Mode : relais par mod\u00e8le
traymenu_proxymode3=Mode : relayer tout le trafic
traymenu_showgui=Cacher/Montrer l'IUG
traytool_guardnode=Noeud de garde
traytool_exitnode=Noeud de sortie
exittable_col1=N\u0153ud de sortie
exittable_col2=BP (MB\\s)
exittable_col3=D\u00e9lai (ms)
exittable_col4=\u00c9tat
exittable_col5=Favori
patterntable_col1=Description
patterntable_col2=Mod\u00e8le
patterntable_col3=Activ\u00e9
guardtable_col1=N\u0153ud de garde
guardtable_col2=Pays
guardtable_col3=BP (MB\\s)
guardtable_col4=De confiance
menu_menu=Menu
menu_prefs=Pr\u00e9f\u00e9rences
menu_quickadd=Ajout rapide d'un mod\u00e8le
menu_patternedit=\u00c9diteur de mod\u00e8les de relais
menu_export=Exporter les mod\u00e8les
menu_import=Import les mod\u00e8les
menu_quit=Quitter
menu_defaultpatterns=Mod\u00e8le par d\u00e9faut
menu_userpatterns=Mod\u00e8les de l'utilisateur
menu_help=Aide
menu_debuglog=Voir le journal de d\u00e9bogage
menu_helpcontents=Contenu de l'aide
menu_torcheck=V\u00e9rification de routine de Tor
menu_about=\u00c0 propos de
menu_license=Licence
menu_proxy=Mode de relais
menu_close=Fermer le menu
menu_tormanual=Manuel officiel de Tor
menu_tormonitor=Moniteur du client Tor
menu_leaktest=Test de fuite DNS
menu_credits=Cr\u00e9dits
label_activecountry=Pays actif :
label_proxymode=Mode de relais :
label_exitnode=N\u0153ud de sortie :
label_ip=IP :
label_torlatency=D\u00e9lai
label_fingerprint=Empreinte :
label_bandwidth=Bande passante
label_streams=Flux
label_stable=Stable
label_status=\u00c9tat :
label_listenport=Port d'\u00e9coute de Tor :
label_defaultproxy=Mandataire HTTP par d\u00e9faut :
label_bridgeaddress=Adresse de pont de Tor :
label_portranges=Plages de port pr\u00e9sentement actives, de $portmin \u00e0 $portmax
label_editcountry=Choisir un pays pour voir ses mod\u00e8les
label_quickadd_desc=Description :
label_quickadd_pattern=Mod\u00e8le :
label_threshold=D\u00e9lai seuil
label_middle=Milieu :
label_exit=Sortie :
label_nickname=Pseudonyme
label_ip=IP
label_country=Pays
label_guard_minimum=Vous pouvez soit ne choisir aucun n\u0153ud de garde au cas o\u00f9 le client Tor les choisit, soit choisir trois n\u0153uds de garde ou plus.
label_torlogging=Niveau de journalisation :
label_torargs=Arguments de d\u00e9marrage :
label_torsocks=Param\u00e8tres Socks :
label_diskoptions=Options du disque :
label_guardnode=Garde :
label_bridgenode=Pont :
label_donotproxy=Ne pas relayer :
button_details=D\u00e9tails
button_whois=Qui est
button_close=Fermer
button_apply=Appliquer
button_delete=Supprimer
button_addnew=Ajouter un nouveau
button_save=Enregistrer
button_cancel=Annuler
button_continue=Continuer
button_getbridges=Obtenir des ponts
button_mozillarestart=Red\u00e9marrer $browser
button_visitus=Rendez-nous visite
button_contactus=Contactez-nous
button_translations=Traductions non officielles
button_prefdefaults=R\u00e9initialiser aux leurs valeurs par d\u00e9faut.
button_setguards=D\u00e9finir les n\u0153uds de garde
button_details=D\u00e9tails de l'atlas
button_clearguards=Effacer les n\u0153uds de garde choisis
button_clearfavs=Effacer les favoris
button_support=Soutenir SelekTOR
button_patreon=Soutenir SelekTOR avec Patreon
panel_general=Param\u00e8tres g\u00e9n\u00e9raux
panel_network= Param\u00e8tres r\u00e9seau
panel_management=Param\u00e8tres de gestion des n\u0153uds
panel_info=Circuit actif
panel_torclientset=Param\u00e8tres du client Tor
panel_startupargs=Arguments de d\u00e9marrage
panel_stdout=Moniteur de sortie standard
chkbox_autoselect=Choix automatique du n\u0153ud
chkbox_autostart=D\u00e9marrage automatique de SelekTOR
chkbox_checkforupdates=V\u00e9rifier les mises \u00e0 jour au d\u00e9marrage
chkbox_disabletray=D\u00e9sactiver l'ic\u00f4ne de notification
chkbox_autopatterns=Installer automatiquement les derniers mod\u00e8les.
chkbox_mozillawarn=D\u00e9sactiver l'avertissement de Mozilla
chkbox_recnodesonly=Utiliser les n\u0153uds recommand\u00e9s en mode par mod\u00e8les
chkbox_hidetotray=Minimiser au d\u00e9marrage
chkbox_minonclose=Minimiser plut\u00f4t que de quitter lors de la fermeture
chkbox_safesocks=Socks s\u00e9curitaire
chkbox_twohop=Utiliser des circuits \u00e0 2 sauts vers le n\u0153ud de sortie en mode par mod\u00e8les
chkbox_warnunsafesocks=Avertir si \u00e0 risque
chkbox_diskavoid=\u00c9viter les \u00e9critures sur le disque
chkbox_testsocks=Tester Socks
chkbox_safelog=Journalisation s\u00e9curitaire
chkbox_guardwarn1=Afficher une fen\u00eatre d'avertissement si un n\u0153ud de garde non sp\u00e9cifi\u00e9 est utilis\u00e9
chkbox_guardwarn2=Afficher une fen\u00eatre d'avertissement si moins de trois n\u0153uds de garde sont choisis
chkbox_securedelete=Effacement s\u00e9curis\u00e9 des caches de Tor lors de la fermeture
ttip_autostart=D\u00e9marrage automatique de SelekTOR lors du d\u00e9marrage/de la connexion
ttip_hidetotray=Minimiser au d\u00e9marrage
ttip_checkforupdates=SelekTOR v\u00e9rifiera les mises \u00e0 jour au d\u00e9marage
ttip_autoinstall=Les derniers mod\u00e8les seront r\u00e9cup\u00e9r\u00e9s de Dazzleships.Net
ttip_disabletray=D\u00e9sactiver l'ic\u00f4ne de notification
ttip_mozillawarn=D\u00e9sactiver l'avertissement du navigateur Mozilla
ttip_listenport=Le port d'\u00e9coute du client Tor
ttip_defaultproxy=Tout trafic qui ne sera pas redirig\u00e9 par Tor sera redirig\u00e9 par ce mandataire HTTP
ttip_donotproxy=Toute URL contenant une de ces entr\u00e9es s\u00e9par\u00e9es par des virgules ne sera pas relay\u00e9e. L'on s'y connectera directement.
ttip_bridgeaddress=Pour contourner le blocage du FSI, ajouter une adresse de pont valide ici
ttip_forcedns=Forcer la recherche DNS par Tor, exige le red\u00e9marrage du navigateur
ttip_forcenode=Si coch\u00e9, le n\u0153ud sera activ\u00e9 quelque soit l'activit\u00e9 du n\u0153ud
ttip_recnodesonly=Les n\u0153uds recommand\u00e9s seront utilis\u00e9s en mode par mod\u00e8les
ttip_minonclose=L'application sera minimis\u00e9e au lieu de quitter \u00e0 la fermeture de la fermeture principale
ttip_threshold=D\u00e9lai seuil
ttip_safesocks=Activ\u00e9e, Tor rejettera les connexions logicielles qui utilisent des variantes dangereuses du protocole Socks.
ttip_warnunsafe=Activ\u00e9e, Tor avertira \u00e0 chaque fois qu'une requ\u00eate est re\u00e7ue contenant seulement une adresse IP au lieu d'un nom d'h\u00f4te.
ttip_testsocks=Activ\u00e9e Tor journalisera une entr\u00e9e de journal de niveau avis pour chaque connexion en indiquant si elle utilise un protocole Socks s\u00e9curitaire ou dangereux.
ttip_safelogging=Activ\u00e9e, Tor nettoiera les cha\u00eenes potentiellement sensibles des messages de journalisation.
ttip_avoiddisk=Activ\u00e9e, Tor essaiera d'\u00e9crire moins fr\u00e9quemment sur le disque que nous ne le ferions autrement.
ttip_extraargs= Arguments suppl\u00e9mentaires sp\u00e9cifi\u00e9s par l'utilisateur, voir le Manuel Tor.
ttip_combo_loglevel=Niveau de journalisation de Tor.
ttip_twohop=Utiliser des circuits \u00e0 2 sauts au lieu des 3 par d\u00e9faut de Tor. R\u00e9duit le d\u00e9lai de transit mais affaiblit l'anonymat.
ttip_resetbasicprefs=R\u00e9initialiser les pr\u00e9f\u00e9rences de base \u00e0 leurs valeurs par d\u00e9faut.
ttip_resetadvprefs=R\u00e9initialiser les pr\u00e9f\u00e9rences avanc\u00e9es \u00e0 leurs valeurs par d\u00e9faut.
ttip_guardwarn1=Activ\u00e9, une fen\u00eatre d'avertissement sera affich\u00e9e indiquant qu'un n\u0153ud de garde non sp\u00e9cifi\u00e9 est actif.
ttip_guardwarn2=Activ\u00e9, une fen\u00eatre d'avertissement sera affich\u00e9e indiquant que trop peu de n\u0153uds de garde sont choisis
ttip_clearguards=Effacer les n\u0153uds de garde choisis.
ttip_securedelete=Activ\u00e9, les caches de Tor seront \u00e9cras\u00e9es par des z\u00e9ros, puis supprim\u00e9es
dlg_update_title=Mise \u00e0 jour disponible.
dlg_update_body=$version est maintenant disponible au t\u00e9l\u00e9chargement.
dlg_restoreproxy_title=Param\u00e8tres originaux du mandataire
dlg_restoreproxy_body=Choisir Continuer pour restaurer les param\u00e8tres du mandataire aux valeurs par d\u00e9faut avant l'installation de SelekTOR.
dlg_resetproxy_title=Param\u00e8tres par d\u00e9faut du mandataire
dlg_resetproxy_body=Choisir Continuer pour r\u00e9initialiser les param\u00e8tres du serveur mandataire \u00e0 leurs valeurs syst\u00e8me par d\u00e9faut.
dlg_gsetting_title=Gsettings introuvable
dlg_gsetting_body=$appname ne peux pas fonctionner correctement sans que l'ex\u00e9cutable binary soit install\u00e9. Dans certaines distributions il peut \u00eatre trouv\u00e9 dans le paquet libglib2.0-bin.
dlg_torclient_title=Client TOR introuvable
dlg_torclient_body=$appname ne peux pas fonctionner sans que le client Tor ne soit Install\u00e9. Veuillez installer les paquets tor et tor-geoipdb pour votre distribution.
dlg_mozillarestart_title=Avertissement\u00a0: Le navigateur $browser est actif.
dlg_mozillarestart_body=$appname a d\u00e9tect\u00e9 que le navigateur $browser tourne d\u00e9j\u00e0.\nUn red\u00e9marrage du navigateur est exig\u00e9 pour permettre le fonctionnement de $appname.\n\nSi vous choisissez de red\u00e9marrer $browser, tous les onglets actuellement ouverts seront restaur\u00e9s au red\u00e9marrage de $browser, l'option \u00ab Afficher les dernier onglets et fen\u00eatres utilis\u00e9s \u00bb, doit \u00eatre choisie dans les options de $browser.\n\nVous pouvez d\u00e9sactiver cet avertissement du navigateur dans les Pr\u00e9f\u00e9rences de $appname.
dlg_license_title=Licence de $appname
dlg_exportuser_title=Exporter les mod\u00e8les d'utilisateur
dlg_exportuser_body=Aucun mod\u00e8le cr\u00e9\u00e9 par l'utilisateur n'a \u00e9t\u00e9 trouv\u00e9.\n\nUtilisez l'\u00e9diteur de mode pour ajouter vos propres mod\u00e8les
dlg_exportdefault_title=Exporter les mod\u00e8les par d\u00e9faut
dlg_exportdefault_body=Aucun mod\u00e8le par d\u00e9faut n'a \u00e9t\u00e9 trouv\u00e9.
dlg_saveuser_title=Enregistrer les modes de l'utilisateur
dlg_savedefault_title=Enregistrer les mod\u00e8les par d\u00e9faut
dlg_import_title=Importer le fichier des mod\u00e8les
dlg_import_success_title=Mod\u00e8les import\u00e9s
dlg_import_success_body=Les mod\u00e8les ont \u00e9t\u00e9 import\u00e9s avec succ\u00e8s et sont maintenant actifs.
dlg_import_fail_title=\u00c9chec lors l'importation
dlg_import_fail_body=Les mod\u00e8les n'ont pas \u00e9t\u00e9 import\u00e9s correctement.
dlg_whois_title=Qui est $ipaddress
dlg_whois_body=Veuillez patienter pendant que j'essaie de r\u00e9cup\u00e9rer les donn\u00e9s de WhoIs...
dlg_whois_fail=D\u00e9sol\u00e9, impossible de r\u00e9cup\u00e9rer les informations de Whois.
dlg_toold_body=Le client Tor actuellement install\u00e9 est trop ancien, Tor 0.2.7.6 ou ult\u00e9rieure est exig\u00e9e.\n\nLes utilisateurs de Linux devraient visiter la page suivante \nhttps://www.torproject.org/download/download-unix.html.en\npour obtenir le dernier client Tor.
dlg_error_title=Erreur de d\u00e9marrage
dlg_error_body=Cette erreur est fatale et $appname se fermera.
dlg_quickadd_title=Ajouter un mod\u00e8le
dlg_nodelistfail_body=La g\u00e9n\u00e9ration de la liste des n\u0153uds a \u00e9chou\u00e9 \u00e0 cause d'erreurs de GEOIP.
dlg_patterneditsave_title=Enregistrer les mod\u00e8les actuels
dlg_patterneditsave_body=Les mod\u00e8les actuels ont \u00e9t\u00e9 modifi\u00e9s.\n\nSi vous d\u00e9sirez les enregistrer, cliquez sur Continuer, autrement cliquez sur Annuler.
dlg_instancefail_title=\u00c9chec d\u00fb \u00e0 plusieurs instances
dlg_instancefail_body=Une instance de $appname est d\u00e9j\u00e0 en cours et une seule peut \u00eatre ex\u00e9cut\u00e9e \u00e0 la fois.\n\nQuittez l'instance existante de $appname ou dans le cas d'un plantage de $appname, red\u00e9marrez X en vous d\u00e9connectant et en vous connectant de nouveau.
dlg_guardwarn_title=Avertissement de n\u0153ud de garde
dlg_guardwarn_body=Un n\u0153ud de garde ne se trouvant pas dans votre liste de n\u0153uds de garde sp\u00e9cifi\u00e9e a \u00e9t\u00e9 utilis\u00e9.\nCeci provient probablement du fait que vos n\u0153uds de garde s\u00e9lectionn\u00e9s ne sont plus joignables et par cons\u00e9quent le client Tor a assign\u00e9 son propre n\u0153ud de garde.\n\nVous devriez v\u00e9rifier vos n\u0153uds de garde actuellement d\u00e9finis pour voir s'ils sont toujours disponibles, ou en choisir de nouveaux.
dlg_notenoughguards_body=Il n'y a pas assez de n\u0153uds de garde d\u00e9finis afin que Tor fonctionne efficacement et en toute s\u00e9curit\u00e9.\n\nSupprimez tous les n\u0153uds de garde s\u00e9lectionn\u00e9s, ce qui permettra au client Tor de choisir ses propres n\u0153uds de garde, ou choisissez manuellement trois n\u0153uds de garde ou plus.dlg_notenoughguards_body=Il n'y a pas assez de n\u0153uds de garde d\u00e9finis afin que Tor fonctionne efficacement et en toute s\u00e9curit\u00e9.\n\nSupprimez tous les n\u0153uds de garde s\u00e9lectionn\u00e9s, ce qui permettra au client Tor de choisir ses propres n\u0153uds de garde, ou choisissez manuellement trois n\u0153uds de garde ou plus.
dlg_bridgerr_title=\u00c9chec de validation de l'adresse de pont
dlg_bridgerr_body=Les informations de pont fournies contiennent des erreurs de validation et ne se conforment pas \u00e0 un format d'adresse IPv4 valide h\u00f4te:port\n\nVoici des exemples de format de sp\u00e9cification de ponts :\n\nPont simple : \n127.0.0.1:8080\n\nPonts multiples : \n127.0.0.1:8080,128.5.6.8:224\n\nLes ponts ont \u00e9t\u00e9 r\u00e9initialis\u00e9s \u00e0 leurs valeurs par d\u00e9faut.
dlg_credits_title=Cr\u00e9dits de $appname
dlg_credits_body=Afin que votre nom apparaissent ici et pour aussi m\u00e9riter ma gratitude, veuillez envisager de soutenir le d\u00e9veloppement futur de SelekTOR sous Linux avec Patreon.
table_popup_details=D\u00e9tails
table_popup_whois=Qui est
table_popup_begintest=Commencer le cycle de test
tab_basic=De base
tab_advanced=Avanc\u00e9
isoA1=Mandataire annonyme
isoO1=autre Pays
isoU1=Inconnu
chkbox_disablenotify=D\u00e9sactiver les notifications du bureau
ttip_disablenotify=D\u00e9sactiver les notifications du bureau
dlg_libnotify_title=notify-send est introuvable
dlg_libnotify_body=Les notifications de bureau ne fonctionneront pas sans que le paquet libnotify-bin ne soit install\u00e9.\n\nPour emp\u00eacher que cette fen\u00eatre apparaissent de nouveau installez le paquet exig\u00e9 ou d\u00e9sactivez les notifications de bureau dans les pr\u00e9f\u00e9rences.
ttip_hidemin=L'appli sera cach\u00e9e au lieu d'\u00eatre minimis\u00e9e.
chkbox_hidemin=Cacher au lieu de minimiser
label_autoselect= Mode de s\u00e9lection automatique :
menu_geoip=Mettre GEOIP \u00e0 jour
chkbox_geocheck=V\u00e9rification trimestrielle des mises \u00e0 jour GEOIP
ttip_geocheck=SelekTOR affichera la \u00abfen\u00eatre de mise \u00e0 jour GEOIP \u00bbsi votre base de donn\u00e9es GEOIP est p\u00e9rim\u00e9e.
dlg_geo_title=Mise \u00e0 jour des donn\u00e9es de g\u00e9olocalisation
dlg_geo_body=Les donn\u00e9es de g\u00e9olocalisation fournies par Tor sont parfois p\u00e9rim\u00e9es. Vous pouvez demander \u00e0 SelekTOR de t\u00e9l\u00e9charger ses propres fichiers de donn\u00e9es de g\u00e9olocalisation de Dazzleships.net et de les utiliser. Ils sont mis \u00e0 jour trimestriellement.\n\nVeuillez noter que si vous choisissez de ne pas mettre \u00e0 jour, certains n\u0153uds pourraient \u00eatre assign\u00e9s au mauvais pays.\n\nLes donn\u00e9es des ces fichiers, comme les donn\u00e9es fournies par le client Tor, sont fournies par Maxmind.com.
dload_status_contact=R\u00e9cup\u00e9ration des derni\u00e8res donn\u00e9es GEOIP
dload_status_failed=\u00c9chec de t\u00e9l\u00e9chargement
chkbox_viator=T\u00e9l\u00e9charger par Tor
ttip_patterntable=\u00c9dition en ligne prise en charge, un double-clic gauche lance l'\u00e9dition d'une cellule d'un tableau.
fileext_pattern=Fichiers de mod\u00e8les zipp\u00e9

View file

@ -0,0 +1,261 @@
# Portuguese BR, Default language file, provide by Paulo Roberto Alves de Oliveira (aka kretcheu) <kretcheu@gmail.com> Licensed by GPL-2+
appdesc=$appname $appver, N\u00f3s de sa\u00edda Tor com simplicidade.
text_yes=Sim
text_no=N\u00e3o
text_mode=N\u00f3
wintitle_prefs = Prefer\u00eancias $appname
wintitle_about = Sobre $appname
wintitle_patternedit = Editor de modelos $appname
wintitle_guardnodes=Sele\u00e7\u00e3o de n\u00f3s guarda
wintitle_tormonitor=Monitor do cliente Tor
textfield_unknown=Desconhecido
progstatus_initial=Iniciando...
progstatus_generate=Gerando lista de n\u00f3s, por favor aguarde.
progstatus_cachedated=Descri\u00e7\u00f5es armazenadas desatualizadas, iremos atualiz\u00e1-las.
progstatus_nonet=Acesso a Internet n\u00e3o dispon\u00edvel.
progstatus_checkrecommended=Verificando os \u00faltimos n\u00f3s recomendados.
progstatus_gotrecommended=Lista de n\u00f3s recomendados recuperados.
progstatus_torfailretry=O Tor falhou ao iniciar, tentando novamente.
progstatus_nodefail=Ativa\u00e7\u00e3o requisitada do n\u00f3 falhou.
progstatus_nodefailretry=Ativa\u00e7\u00e3o requisitada do n\u00f3 falhou, tentaremos novamente, por favor aguarde.
progstatus_nodefailtorchoose=N\u00f3 requisitado fora de alcance, deixaremos o Tor escolher.
progstatus_nodeactive3hop=Circuito de 3 saltos do n\u00f3 de sa\u00edda $nodename est\u00e1 ativo.
progstatus_nodeactive2hop=Cirtuito de 2 saltos do n\u00f3 de sa\u00edda $nodename est\u00e1 ativo.
progstatus_autoswitch=Troca autom\u00e1tica de n\u00f3
progstatus_manswitch=Trocando para n\u00f3 manualmente selecionado.
progstatus_waitfortor=Aguardando ativa\u00e7\u00e3o do n\u00f3 pelo Tor.
progstatus_switchtonode=Trocando para o n\u00f3 $nodename.
progstatus_applychanges=Aplicando novas prefer\u00eancias.
circuit_status_creating_2hop=Criando circuito de 2 saltos.
circuit_status_creating_3hop=Criando circuito de 3 saltos.
circuit_status_testing=Testanto circuito.
circuit_status_aborted=Teste cancelado.
circuit_status_built=Circuito $1 constru\u00eddo.
circuit_status_passed=Circuito passou.
circuit_status_failed=Circuito falhou.
circuit_status_none=Nenhum circuito dispon\u00edvel.
circuit_status_noroute=Todos roteadores fora.
combo_proxymode1=Desabilitado
combo_proxymode2=Proxy por modelo
combo_proxymode3=Proxy para todo tr\u00e1fego
combo_loglev1=Depura\u00e7\u00e3o
combo_loglev2=Informa\u00e7\u00e3o
combo_loglev3=Aviso
traymenu_proxymode1=Modo: Proxy Desabilitado
traymenu_proxymode2=Modo: Proxy por modelo
traymenu_proxymode3=Modo: Proxy para todo tr\u00e1fego
traymenu_showgui=Esconde/Mostra GUI
traytool_guardnode=N\u00f3 guarda
traytool_exitnode=N\u00f3 de sa\u00edda
exittable_col1=N\u00f3 de sa\u00edda
exittable_col2=Largura de Banda (MB\/s)
exittable_col3=Lat\u00eancia (ms)
exittable_col4=Estado
exittable_col5=Favorito
guardtable_col1=N\u00f3 guarda
guardtable_col2=Pa\u00eds
guardtable_col3=Largura de Banda (MB\/s)
guardtable_col4=Confi\u00e1vel
patterntable_col1=Descri\u00e7\u00e3o
patterntable_col2=Modelo
patterntable_col3=Habilitado
menu_menu=Menu
menu_prefs=Prefer\u00eancias
menu_quickadd=Adicione modelo rapidamente
menu_patternedit=Editor de modelo de proxy
menu_export=Exporta\u00e7\u00e3o de modelos
menu_import=Importa\u00e7\u00e3o de modelos
menu_quit=Sair
menu_defaultpatterns=Modelos padr\u00e3o
menu_userpatterns=Modelos de usu\u00e1rio
menu_help=Ajuda
menu_debuglog=Ver log de depura\u00e7\u00e3o
menu_helpcontents=Conte\u00fado de ajuda
menu_torcheck=Verificar roteamento Tor
menu_about=Sobre
menu_license=Licen\u00e7a
menu_tormanual=Manual oficial do Tor
menu_tormonitor=Monitor de cliente Tor
menu_close=Menu fechar
menu_proxy=Modo Proxy
menu_leaktest=Testar vazamento de DNS
menu_credits=Cr\u00e9ditos
label_latency_url=URL de verifica\u00e7\u00e3o de lat\u00eancia do Tor:
label_guardnode=Guarda:
label_bridgenode=Ponte:
label_activecountry=Pa\u00eds de sa\u00edda:
label_proxymode=Modo do proxy:
label_exitnode=N\u00f3 de sa\u00edda:
label_torlatency=Lat\u00eancia
label_fingerprint=Impress\u00e3o digital:
label_bandwidth=Largura de banda
label_streams=Fluxos
label_stable=Est\u00e1vel
label_status=Estado do cliente:
label_listenport=Porta de escuta do Tor:
label_defaultproxy=Proxy HTTP padr\u00e3o:
label_bridgeaddress=Endere\u00e7o de ponte Tor:
label_portranges=Intervalo atual de portas, $portmin at\u00e9 $portmax
label_editcountry=Selecione o pa\u00eds para ver seu modelo
label_quickadd_desc=Descri\u00e7\u00e3o:
label_quickadd_pattern=Modelo:
label_threshold=Limite
label_exitip=IP de sa\u00edda:
label_guardip=IP do n\u00f3 guarda:
label_guardcountry=Pa\u00eds do n\u00f3 guarda:
label_torlogging=N\u00edvel de log:
label_torargs=Par\u00e2metros iniciais:
label_torsocks=Configura\u00e7\u00e3o do Socks:
label_diskoptions=Op\u00e7\u00f5es de disco:
label_guard_minimum=Voc\u00ea pode tanto n\u00e3o ter n\u00f3s guarda selecionados, nesse caso o cliente Tor ir\u00e1 escolher ou ter 3 ou mais n\u00f3s guarda selecionados.
label_nickname=Apelido
label_ip=IP
label_country=Pa\u00eds
label_exit=Sa\u00edda:
label_middle=Meio:
label_donotproxy=Sem proxy:
button_details=Detalhes do atlas
button_whois=WhoIs
button_close=Fechar
button_apply=Aplicar
button_delete=Apagar
button_addnew=Adicionar novo
button_save=Salvar
button_cancel=Cancelar
button_continue=Continuar
button_getbridges=Obter pontes
button_mozillarestart=Reiniciar $browser
button_visitus=Visite-nos
button_contactus=Contacte-nos
button_translations=Tradu\u00e7\u00f5es n\u00e3o oficiais
button_prefdefaults=Restaurar padr\u00f5es
button_setguards=Definir n\u00f3s guarda
button_clearguards=Limpar n\u00f3s guarda selecionados
button_clearfavs=Limpar Favoritos
button_support=Apoie o SelekTOR
button_patreon=Apoie o SelekTOR com Patreon
panel_info=Circuito ativo
panel_general=Configura\u00e7\u00f5es gerais
panel_network=Configura\u00e7\u00f5es de rede
panel_management=Configura\u00e7\u00f5es de gest\u00e3o de n\u00f3s
panel_torclientset=Configura\u00e7\u00f5es do cliente Tor
panel_startupargs=Par\u00e2metros iniciais
panel_stdout=Monitor de sa\u00edda
chkbox_autoselect=Sele\u00e7\u00e3o autom\u00e1tica de n\u00f3s
chkbox_autostart=Iniciar automaticamente o SelekTOR
chkbox_checkforupdates=Verificar por atualiza\u00e7\u00f5es ao iniciar
chkbox_disabletray=Desabilitar \u00edcone da bandeja.
chkbox_autopatterns=Instalar automaticamente os \u00faltimos modelos.
chkbox_mozillawarn=Desabilitar alerta Mozilla
chkbox_recnodesonly=Usar n\u00f3s recomendados no modelo
chkbox_hidetotray=Minimizar ao iniciar
chkbox_minonclose=Minimizar ao inv\u00e9s de sair ao fechar
chkbox_twohop=Usar circuitos de 2 saltos para n\u00f3 de sa\u00edda no modelo
chkbox_safesocks=Socks seguro
chkbox_warnunsafesocks=Avisar se inseguro
chkbox_diskavoid=Evitar escrita no disco
chkbox_testsocks=Testar Socks
chkbox_safelog=Logging seguro
chkbox_guardwarn1=Alertar se um n\u00f3 guarda n\u00e3o especificado for usado
chkbox_securedelete=Apagar dados armazenados do Tor ao sair
chkbox_guardwarn2=Alertar se menos de 3 n\u00f3s guardas forem selecionados
ttip_autostart=Ir\u00e1 iniciar o SelekTOR automaticamente no boot/login.
ttip_hidetotray=SelekTOR iniciar\u00e1 na bandeja do sistema
ttip_checkforupdates=SelekTOR verificar\u00e1 por nova vers\u00e3o ao iniciar
ttip_autoinstall=Buscar\u00e1 \u00faltimos modelos de Dazzleships.Net.
ttip_disabletray=Desabilitar \u00edcone na bandeja do sistema
ttip_mozillawarn=Desabilitar alerta do navegador Mozilla
ttip_listenport=Cliente Tor escutando na porta.
ttip_defaultproxy=Todo tr\u00e1fego n\u00e3o roteado pelo Tor ir\u00e1 ser redirecionado por esse proxy HTTP.
ttip_donotproxy=Qualquer URL que contenha uma ou mais dessas entradas, separadas por v\u00edrgula, ser\u00e1 conectada diretamente.
ttip_bridgeaddress=Para evitar bloqueio do provedor adicione um endere\u00e7o v\u00e1lido de ponte aqui.
ttip_forcedns=Force pesquisa de DNS via Tor, precisa reiniciar o navegador.
ttip_forcenode=Quando marcado o n\u00f3 \u00e9 ativado independente de atividade atual
ttip_enhanon=Usar\u00e1 3 saltos de n\u00f3s ao inv\u00e9s de 2 saltos.
ttip_recnodesonly=Usuar\u00e1 n\u00f3s recomendados do modelo
ttip_minonclose=A aplica\u00e7\u00e3o ir\u00e1 minimizar ao inv\u00e9s de sair ao fechar a janela principal
ttip_threshold=Limite de lat\u00eancia
ttip_safesocks=Quando habilitado, o Tor ir\u00e1 rejeitar conex\u00f5es que usam varia\u00e7\u00f5es inseguras do protocolo socks.
ttip_warnunsafe=Quando habilitado, o Tor ir\u00e1 avisar sempre que uma requisi\u00e7\u00e3o recebida contiver apenas IP ao inv\u00e9s de um nome de m\u00e1quina.
ttip_testsocks=Quando habilitado, o Tor ir\u00e1 gerar um log de n\u00edvel aviso para cada conex\u00e3o, indicando se foi usado o protocolo socks seguro ou inseguro.
ttip_safelogging=Quando habilitado, o Tor ir\u00e1 limpar o texto potencialmente cr\u00edtico das mensagens de log.
ttip_avoiddisk=Quando habilitado, o Tor tentar\u00e1 escrever no disco com menos frequ\u00eancia.
ttip_extraargs=Especifique par\u00e2metros adicionais, veja o manual do Tor.
ttip_combo_loglevel=N\u00edvel de log do Tor.
ttip_twohop=Usar circuitos de 2 saltos ao inv\u00e9s de 3 saltos, padr\u00e3o do Tor, reduz a lat\u00eancia mas diminui o anonimato.
ttip_resetbasicprefs=Restaurar as prefer\u00eancias b\u00e1sicas para seus padr\u00f5es.
ttip_resetadvprefs=Restaurar as prefer\u00eancias avan\u00e7adas para seus padr\u00f5es.
ttip_securedelete=Quando habilitado, o armazenamento do Tor ser\u00e1 sobrescrito por zeros quanto apagado.
ttip_autonode=Quando habilitado, o SelekTOR tentar\u00e1 escolher o n\u00f3 de melhor performance.
ttip_guardwarn=Quando habilitado, um alerta ser\u00e1 usado para indicar que um n\u00f3 guarda n\u00e3o especificado est\u00e1 ativo.
ttip_clearguards=Limpar n\u00f3s guarda selecionados.
ttip_guardwarn2=Quando habilitado, um alerta ser\u00e1 usado para indicar insufici\u00eancia de n\u00f3s guarda selecionados.
dlg_update_title=Atualiza\u00e7\u00e3o dispon\u00edvel.
dlg_update_body=Vers\u00e3o $version est\u00e1 dispon\u00edvel para download.
dlg_restoreproxy_title=Configura\u00e7\u00e3o original do proxy
dlg_restoreproxy_body=Selecione continue para restaurar as configura\u00e7\u00f5es originais do proxy antes da instala\u00e7\u00e3o do SelekTOR.
dlg_resetproxy_title=Configura\u00e7\u00e3o padr\u00e3o do proxy
dlg_resetproxy_body=Selecione continuar para limpar as configura\u00e7\u00f5es de proxy para o padr\u00e3o do sistema.
dlg_gsetting_title=Gsettings n\u00e3o encontrado
dlg_gsetting_body=$appname n\u00e3o funciona sem o bin\u00e1rio gsettings instalado, em algumas distribui\u00e7\u00f5es pode ser encontrado no pacote libglib2.0-bin.
dlg_torclient_title=Cliente TOR n\u00e3o encontrado
dlg_torclient_body=$appname n\u00e3o funciona sem um cliente Tor instalado, por favor instale os pacotes tor e tor-geoipdb da sua distribui\u00e7\u00e3o.
dlg_mozillarestart_title=Alerta: O navegador $browser est\u00e1 ativo.
dlg_mozillarestart_body=O $appname detectou que o navegador $browser j\u00e1 est\u00e1 em execu\u00e7\u00e3o.\nReiniciar o navegador \u00e9 necess\u00e1rio para habilitar $appname.\n\nSe escolher reiniciar o $browser todas as abas abertas ser\u00e3o restauradas quando o $browser reiniciar, requer que a op\u00e7\u00e3o \"Restaurar janelas e abas anteriores\" seja selecionada no menu prefer\u00eancias no $browser.\n\nVoc\u00ea pode desabilitar o aviso do navegador em prefer\u00eancias de $appname.
dlg_license_title=Licen\u00e7a $appname
dlg_exportuser_title=Exportar modelo de usu\u00e1rio
dlg_exportuser_body=Nenhum modelo de usu\u00e1rio encontrado.\n\nUse o editor de modelos para adicionar seus pr\u00f3rios modelos
dlg_exportdefault_title=Exporte os modelos padr\u00e3o
dlg_exportdefault_body=Nenhum modelo padr\u00e3o encontrado.
dlg_saveuser_title=Salvar o modelo de usu\u00e1rio
dlg_savedefault_title=Salvar os modelos padr\u00e3o
dlg_import_title=Importar um arquivo de modelo
dlg_import_success_title=Modelo importado
dlg_import_success_body=Modelos importados com susesso e agora ativos.
dlg_import_fail_title=Importa\u00e7\u00e3o falhou
dlg_import_fail_body=Falhou ao importar modelos.
dlg_whois_title=Whois $ipaddress
dlg_whois_body=Por favor aguarde enquanto buscando dados Whois...
dlg_whois_fail=Desculpe, n\u00e3o foi poss\u00edvel encontrar informa\u00e7\u00f5es de Whois.
dlg_toold_body=O cliente Tor atualmente instalado \u00e9 antigo, o Tor 0.2.7.6 ou mais novo \u00e9 requerido.\n\nUsu\u00e1rios de GNU/Linux podem acessar a p\u00e1gina \nhttps://www.torproject.org/download/download-unix.html.en\n para obter o cliente Tor mais recente, ou diretamente dos reposit\u00f3rios.
dlg_error_title=Erro de inicia\u00e7\u00e3o
dlg_error_body=Esse erro \u00e9 fatal e $appname ir\u00e1 fechar.
dlg_quickadd_title=Adicionar modelo
dlg_nodelistfail_body=A gera\u00e7\u00e3o da lista de n\u00f3s falhou devido a erros do GEOIP.
dlg_patterneditsave_title=Salvar os modelos atuais
dlg_patterneditsave_body=Modelos atuais foram modificados.\n\nSe voc\u00ea deseja salv\u00e1-los clique em continuar sen\u00e3o clique em cancelar.
dlg_instancefail_title=Falha de inst\u00e2ncia multipla
dlg_instancefail_body=Uma inst\u00e2ncia de $appname j\u00e1 est\u00e1 em execu\u00e7\u00e3o, somente uma inst\u00e2ncia pode ser executada por vez.\n\nFechar a inst\u00e2ncia existente de $appname ou no caso de $appname congelar reinicie o X deslogando e logando novamente.
dlg_guardwarn_title=Alerta de n\u00f3 guarda
dlg_guardwarn_body=Um n\u00f3 guarda que n\u00e3o est\u00e1 na lista de n\u00f3s guarda especificados foi usado.\nProvavelmente porque seus n\u00f3s guarda selecionados n\u00e3o s\u00e3o mais alcan\u00e7\u00e1veis e o cliente Tor escolheu seus pr\u00f3prios n\u00f3s guarda. Talvez queira verificar sua lista de n\u00f3s guarda para ver se ainda est\u00e3o dispon\u00edveis ou selecionar novos.
dlg_notenoughguards_body=N\u00e3o h\u00e1 n\u00f3s guarda suficientes para o Tor operar com seguran\u00e7a e efici\u00eancia.\n\nLimpe todos os n\u00f3s guarda selecionados e deixe o cliente Tor escolher seus pr\u00f3prios n\u00f3s guarda ou escolha 3 n\u00f3s guarda manualmente.
dlg_bridgerr_title=Falha na valida\u00e7\u00e3o do endere\u00e7o da ponte.
dlg_bridgerr_body=A informa\u00e7\u00e3o da ponte fornecida cont\u00e9m erros de valida\u00e7\u00e3o e n\u00e3o est\u00e1 em conformidade com um formato v\u00e1lido host:port endere\u00e7o ipv4.\n\nExemplos do formato de especifica\u00e7\u00e3o de pontes s\u00e3o:\n\nPonte \u00fanica:\n127.0.0.1:8080\n\nPontes m\u00faltiplas:\n127.0.0.1:8080,128.5.6.8:224\n\nAs pontes foram restauradas para os padr\u00f5es.
dlg_credits_title=Cr\u00e9ditos $appname
dlg_credits_body=Para ter seu nome listado aqui e tamb\u00e9m merecer minha gratid\u00e3o por favor apoie o desenvolvimento do SelekTOR na plataforma GNU/Linux atrav\u00e9s do Patreon
table_popup_details=Detalhes
table_popup_begintest=Inicia ciclo de teste
table_popup_whois=WhoIs
tab_basic=B\u00e1sico
tab_advanced=Avan\u00e7ado
isoA1=Proxy an\u00f4nimo
isoA2=Provedor de sat\u00e9lite
isoO1=Outro pa\u00eds
isoU1=Desconhecido
chkbox_disablenotify=Desabilitar notifica\u00e7\u00f5es
ttip_disablenotify=Desabilita notifica\u00e7\u00f5es
dlg_libnotify_title=notify-send n\u00e3o encontrado
dlg_libnotify_body=Notifica\u00e7\u00f5es n\u00e3o funcionam sem o pacote libnotify-bin instalado.\n\nPara previnir que esse alerta apare\u00e7a novamente, instale o pacote requerido ou desabilite as notifica\u00e7\u00f5es em prefer\u00eancias.
ttip_hidemin=Aplica\u00e7\u00e3o ser\u00e1 oculta ao inv\u00e9s de minimizar
chkbox_hidemin=Ocultar ao inv\u00e9s de minimizar
label_autoselect=Modo de auto sele\u00e7\u00e3o:
menu_geoip=Atualizar GEOIP
chkbox_geocheck=Fazer verifica\u00e7\u00e3o trimestral de atualiza\u00e7\u00e3o do GEOIP
ttip_geocheck=SelekTOR ir\u00e1 mostrar o "Di\u00e1logo de atualiza\u00e7\u00e3o GEOIP" se sua base de dados GEOIP estiver desatualizada.
dlg_geo_title=Atualiza\u00e7\u00e3o de dados de geolocaliza\u00e7\u00e3o
dlg_geo_body=Os dados de geolocaliza\u00e7\u00e3o padr\u00e3o vindos do cliente Tor algumas vezes est\u00e3o desatualizados, voc\u00ea pode baixar os dados de geolocaliza\u00e7\u00e3o de Dazzleships.net. Eles s\u00e3o atualizados trimestralmente.\n\nVeja, se escolher n\u00e3o atualizar, alguns n\u00f3s podem estar atribu\u00eddos a pa\u00edses errados.\n\nOs dados nesses arquivos, assim como os do cliente Tor s\u00e3o fornecidos por Maxmind.com.
dload_status_contact=Obtendo dados GEOIP mais recentes
dload_status_failed=Download falhou
chkbox_viator=Download via Tor
ttip_patterntable=Para editar, d\u00ea um duplo click na c\u00e9lula da tabela que deseja modificar.
fileext_pattern=Arquivo zip do modelo

View file

@ -0,0 +1 @@
Alistair Neil (Developer)

339
src/resources/license.txt Normal file
View file

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

BIN
src/resources/trayicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9 KiB