diff --git a/src/net/i2p/itoopie/Main.java b/src/net/i2p/itoopie/Main.java index 3d93bfbdf..515b2a903 100644 --- a/src/net/i2p/itoopie/Main.java +++ b/src/net/i2p/itoopie/Main.java @@ -128,7 +128,7 @@ public class Main { private static void testStuff(){ _conf.parseConfigStr("server.hostname=127.0.0.1"); - _conf.parseConfigStr("server.port=7888"); + _conf.parseConfigStr("server.port=5555"); _conf.parseConfigStr("server.target=jsonrpc"); diff --git a/src/net/i2p/itoopie/gui/Main.java b/src/net/i2p/itoopie/gui/Main.java index a3e3d999a..0f259d346 100644 --- a/src/net/i2p/itoopie/gui/Main.java +++ b/src/net/i2p/itoopie/gui/Main.java @@ -28,6 +28,8 @@ import net.i2p.itoopie.gui.component.util.TabChangeListener; import net.i2p.itoopie.util.IconLoader; import javax.swing.UIManager; import javax.swing.border.Border; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; import java.awt.Color; import java.awt.event.ActionEvent; @@ -36,7 +38,8 @@ import java.awt.FlowLayout; public class Main { - private JFrame frame; + private static JFrame frame; + private static JTabbedPane tabbedPane; private final static Color VERY_LIGHT = new Color(230,230,230); private final static Color LIGHT = new Color(215,215,215); private final static Color MEDIUM = new Color (175,175,175); @@ -79,7 +82,7 @@ public class Main { frame.setResizable(false); WindowHandler.registerMain(frame); - JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP); + tabbedPane = new JTabbedPane(JTabbedPane.TOP); frame.getContentPane().add(tabbedPane, BorderLayout.CENTER); TabLogoPanel overviewPanel = new OverviewTab("itoopie-opaque12"); @@ -126,4 +129,14 @@ public class Main { frame.setVisible(true); } + + /** + * Used to manually trigger updates for the tab being shown. + */ + public static void fireNewChange(){ + for (ChangeListener ch : tabbedPane.getChangeListeners()){ + ch.stateChanged(new ChangeEvent(tabbedPane)); + } + } + } diff --git a/src/net/i2p/itoopie/gui/SettingsFrame.java b/src/net/i2p/itoopie/gui/SettingsFrame.java index 625d945cb..b2da4c53d 100644 --- a/src/net/i2p/itoopie/gui/SettingsFrame.java +++ b/src/net/i2p/itoopie/gui/SettingsFrame.java @@ -12,6 +12,7 @@ import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.net.InetAddress; import java.net.UnknownHostException; +import java.util.HashMap; import javax.swing.JOptionPane; import javax.swing.JPanel; @@ -22,10 +23,14 @@ import javax.swing.JSeparator; import com.thetransactioncompany.jsonrpc2.client.JSONRPC2SessionException; import net.i2p.itoopie.configuration.ConfigurationManager; +import net.i2p.itoopie.gui.StatusHandler.DEFAULT_STATUS; import net.i2p.itoopie.gui.component.RegisteredFrame; import net.i2p.itoopie.i18n.Transl; +import net.i2p.itoopie.i2pcontrol.InvalidParametersException; import net.i2p.itoopie.i2pcontrol.InvalidPasswordException; import net.i2p.itoopie.i2pcontrol.JSONRPC2Interface; +import net.i2p.itoopie.i2pcontrol.methods.I2PControl.I2P_CONTROL; +import net.i2p.itoopie.i2pcontrol.methods.SetI2PControl; import net.i2p.itoopie.security.ItoopieHostnameVerifier; import javax.swing.BoxLayout; @@ -38,13 +43,32 @@ import java.awt.Component; public class SettingsFrame extends RegisteredFrame{ private static final Log _log = LogFactory.getLog(SettingsFrame.class); - private final static int SAVE_OK = 0; - private final static int SAVE_ERROR = 1; + private enum LOCAL_SAVE_STATUS { + SAVE_OK, + SAVE_ERROR, + NO_CHANGES, + }; + + private static enum REMOTE_SAVE_STATUS{ + SAVE_FAILED_LOCALLY { public String toString(){return Transl._("Settings aren't valid, not saving.");} }, + SAVE_FAILED_REMOTELY { public String toString(){return Transl._("I2P router rejected settings.");} }, + SAVED_OK { public String toString(){return Transl._("Saved settings on I2P router.");} }, + SAVED_RESTART_NEEDED { public String toString(){return Transl._("Saved settings on I2P router. I2P router needs to be restarted.");} }, + NO_CHANGES { public String toString(){return Transl._("No changes found, settings not saved.");} } + }; + private static Boolean instanceShown = false; - private JTextField textFieldRouterIP; - private JTextField textFieldRouterPort; + // NetworkPanel + private JTextField txtRouterIP; + private JTextField txtRouterPort; private JPasswordField passwordField; + // PasswordPanel + private JPasswordField txtNewPassword; + private JPasswordField txtRetypeNewPassword; + // PortPanel + private JTextField txtNewPort; + private ConfigurationManager _conf; /** @@ -95,57 +119,41 @@ public class SettingsFrame extends RegisteredFrame{ GUIHelper.setDefaultStyle(); setTitle("itoopie Settings"); - setBounds(100, 100, 450, 150); + setBounds(0, 0, 450, 260); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS)); + getContentPane().setLayout(null); JPanel networkPanel = new JPanel(); - getContentPane().add(networkPanel); networkPanel.setLayout(null); + networkPanel.setBounds(0, 0, 426, 89); + getContentPane().add(networkPanel); + setupNetworkPanel(networkPanel); - JLabel lblI2PControl = new JLabel("Network:"); - lblI2PControl.setBounds(10, 10, 120, 15); - networkPanel.add(lblI2PControl); - lblI2PControl.setHorizontalAlignment(SwingConstants.RIGHT); + + JSeparator separator = new JSeparator(SwingConstants.HORIZONTAL); + separator.setBounds((96)/2, 90, (getWidth()-96), 1); + getContentPane().add(separator); - - JLabel lblRouterIP = new JLabel("IP address:"); - lblRouterIP.setBounds(138, 10, 100, 15); - networkPanel.add(lblRouterIP); - lblRouterIP.setHorizontalAlignment(SwingConstants.LEFT); - - textFieldRouterIP = new JTextField(); - textFieldRouterIP.setBounds(240, 10, 90, 19); - networkPanel.add(textFieldRouterIP); - textFieldRouterIP.setText("255.255.255"); - textFieldRouterIP.setColumns(10); - - - JLabel lblRouterPort = new JLabel("Port:"); - lblRouterPort.setBounds(138, 35, 100, 15); - networkPanel.add(lblRouterPort); - lblRouterPort.setHorizontalAlignment(SwingConstants.LEFT); - - textFieldRouterPort = new JTextField(); - textFieldRouterPort.setBounds(240, 35, 45, 19); - networkPanel.add(textFieldRouterPort); - textFieldRouterPort.setText("65555"); - textFieldRouterPort.setColumns(10); - - - JLabel lblRouterPassword = new JLabel("Password:"); - lblRouterPassword.setBounds(138, 60, 100, 15); - networkPanel.add(lblRouterPassword); - lblRouterPassword.setHorizontalAlignment(SwingConstants.LEFT); - - passwordField = new JPasswordField(); - passwordField.setBounds(240, 60, 100, 19); - networkPanel.add(passwordField); + JPanel newPasswordPanel = new JPanel(); + newPasswordPanel.setLayout(null); + newPasswordPanel.setBounds(0, 90, 426, 64); + getContentPane().add(newPasswordPanel); + setupNewPasswordPanel(newPasswordPanel); + separator = new JSeparator(SwingConstants.HORIZONTAL); + separator.setBounds((96)/2, 155, (getWidth()-96), 1); + getContentPane().add(separator); + + + JPanel newPortPanel = new JPanel(); + newPortPanel.setLayout(null); + newPortPanel.setBounds(0, 155, 426, 35); + getContentPane().add(newPortPanel); + setupNewPortPanel(newPortPanel); + JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); - buttonPanel.setAlignmentY(BOTTOM_ALIGNMENT); - buttonPanel.setMaximumSize(new Dimension(2000, 24)); + buttonPanel.setBounds(0, 200, getWidth()-10, 35); getContentPane().add(buttonPanel); @@ -154,10 +162,47 @@ public class SettingsFrame extends RegisteredFrame{ btnDone.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent arg0) { - if (SAVE_OK == saveSettings()){ - dispose(); - } else { + LOCAL_SAVE_STATUS localSettingStatus = saveRemoteHostSettings(); + if (LOCAL_SAVE_STATUS.SAVE_OK == localSettingStatus){ + + StatusHandler.setStatus(Transl._("Settings saved.")); + } else if (LOCAL_SAVE_STATUS.SAVE_ERROR == localSettingStatus){ populateSettings(); + } else if (LOCAL_SAVE_STATUS.NO_CHANGES == localSettingStatus){ + StatusHandler.setStatus(Transl._("Settings not saved, no changes found.")); + } + + REMOTE_SAVE_STATUS newPortStatus = saveNewPort(); + switch (newPortStatus){ + case SAVED_OK: + StatusHandler.setStatus("New remote port: " + REMOTE_SAVE_STATUS.SAVED_OK); + break; + case SAVE_FAILED_LOCALLY: + StatusHandler.setStatus("New remote port: " + REMOTE_SAVE_STATUS.SAVE_FAILED_LOCALLY); + break; + case SAVE_FAILED_REMOTELY: + StatusHandler.setStatus("New remote port: " + REMOTE_SAVE_STATUS.SAVE_FAILED_REMOTELY); + break; + } + + REMOTE_SAVE_STATUS newPasswordStatus = saveNewPassword(); + switch (newPasswordStatus){ + case SAVED_OK: + StatusHandler.setStatus("New remote password: " + REMOTE_SAVE_STATUS.SAVED_OK); + break; + case SAVE_FAILED_LOCALLY: + StatusHandler.setStatus("New remote password: " + REMOTE_SAVE_STATUS.SAVE_FAILED_LOCALLY); + break; + case SAVE_FAILED_REMOTELY: + StatusHandler.setStatus("New remote password: " + REMOTE_SAVE_STATUS.SAVE_FAILED_REMOTELY); + break; + } + + if (localSettingStatus != LOCAL_SAVE_STATUS.SAVE_ERROR && + newPortStatus != REMOTE_SAVE_STATUS.SAVE_FAILED_LOCALLY && newPortStatus != REMOTE_SAVE_STATUS.SAVE_FAILED_REMOTELY && + newPasswordStatus != REMOTE_SAVE_STATUS.SAVE_FAILED_LOCALLY && newPasswordStatus != REMOTE_SAVE_STATUS.SAVE_FAILED_REMOTELY){ + Main.fireNewChange(); + dispose(); } } }); @@ -179,29 +224,110 @@ public class SettingsFrame extends RegisteredFrame{ validate(); } - @Override - public void setVisible(boolean isVisible){ - if (isVisible){ - populateSettings(); - } - super.setVisible(isVisible); + private void setupNetworkPanel(JPanel networkPanel){ + JLabel lblI2PControl = new JLabel("Network:"); + lblI2PControl.setBounds(10, 10, 120, 15); + networkPanel.add(lblI2PControl); + lblI2PControl.setHorizontalAlignment(SwingConstants.RIGHT); + + + JLabel lblRouterIP = new JLabel("IP address:"); + lblRouterIP.setBounds(138, 10, 100, 15); + networkPanel.add(lblRouterIP); + lblRouterIP.setHorizontalAlignment(SwingConstants.LEFT); + + txtRouterIP = new JTextField(); + txtRouterIP.setBounds(240, 10, 90, 19); + networkPanel.add(txtRouterIP); + + + JLabel lblRouterPort = new JLabel("Port:"); + lblRouterPort.setBounds(138, 35, 100, 15); + networkPanel.add(lblRouterPort); + lblRouterPort.setHorizontalAlignment(SwingConstants.LEFT); + + txtRouterPort = new JTextField(); + txtRouterPort.setBounds(240, 35, 45, 19); + networkPanel.add(txtRouterPort); + + + JLabel lblRouterPassword = new JLabel("Password:"); + lblRouterPassword.setBounds(138, 60, 100, 15); + networkPanel.add(lblRouterPassword); + lblRouterPassword.setHorizontalAlignment(SwingConstants.LEFT); + + passwordField = new JPasswordField(); + passwordField.setBounds(240, 60, 90, 19); + networkPanel.add(passwordField); + } + + + private void setupNewPasswordPanel(JPanel pwdPanel){ + JLabel lblNewPassword = new JLabel(Transl._("New password:")); + lblNewPassword.setBounds(10, 10, 120, 15); + pwdPanel.add(lblNewPassword); + lblNewPassword.setHorizontalAlignment(SwingConstants.RIGHT); + + + JLabel lblNewPassword2 = new JLabel(Transl._("Password:")); + lblNewPassword2.setBounds(138, 10, 100, 15); + pwdPanel.add(lblNewPassword2); + lblNewPassword2.setHorizontalAlignment(SwingConstants.LEFT); + + txtNewPassword = new JPasswordField(); + txtNewPassword.setBounds(240, 10, 90, 19); + pwdPanel.add(txtNewPassword); + + + JLabel lblRetypeNewPassword = new JLabel(Transl._("Repeat:")); + lblRetypeNewPassword.setBounds(138, 35, 100, 15); + pwdPanel.add(lblRetypeNewPassword); + lblRetypeNewPassword.setHorizontalAlignment(SwingConstants.LEFT); + + txtRetypeNewPassword = new JPasswordField(); + txtRetypeNewPassword.setBounds(240, 35, 90, 19); + pwdPanel.add(txtRetypeNewPassword); } + private void setupNewPortPanel(JPanel portPanel){ + JLabel lblPort = new JLabel(Transl._("New port:")); + lblPort.setBounds(10, 10, 120, 15); + portPanel.add(lblPort); + lblPort.setHorizontalAlignment(SwingConstants.RIGHT); + + + JLabel lblPort2 = new JLabel(Transl._("Port:")); + lblPort2.setBounds(138, 10, 100, 15); + portPanel.add(lblPort2); + lblPort2.setHorizontalAlignment(SwingConstants.LEFT); + + txtNewPort = new JTextField(); + txtNewPort.setBounds(240, 10, 45, 19); + portPanel.add(txtNewPort); + } + + private void populateSettings(){ - textFieldRouterIP.setText(_conf.getConf("server.hostname", "127.0.0.1")); - textFieldRouterPort.setText(_conf.getConf("server.port", 7650)+""); + txtRouterIP.setText(_conf.getConf("server.hostname", "127.0.0.1")); + txtRouterPort.setText(_conf.getConf("server.port", 7650)+""); passwordField.setText(_conf.getConf("server.password", "itoopie")); } @SuppressWarnings("static-access") - private int saveSettings(){ + private LOCAL_SAVE_STATUS saveRemoteHostSettings(){ ItoopieHostnameVerifier.clearRecentlyDenied(); String oldIP = _conf.getConf("server.hostname", "127.0.0.1"); int oldPort = _conf.getConf("server.port", 7650); String oldPW = _conf.getConf("server.password", "itoopie"); - - String ipText = textFieldRouterIP.getText(); + String ipText = txtRouterIP.getText(); + String portText = txtRouterPort.getText(); + String pwText = new String(passwordField.getPassword()); + +// // Exit SAVE_STATUS.NO_CHANGES if no changes are found. Possibly just a annoying check. +// if (ipText.equals(oldIP) && portText.equals(oldPort+"") && pwText.equals(oldPW)) +// return LOCAL_SAVE_STATUS.NO_CHANGES; + try { InetAddress.getByName(ipText); } catch (UnknownHostException e) { @@ -212,10 +338,9 @@ public class SettingsFrame extends RegisteredFrame{ Transl._("Invalid ip address."), JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE); - return SAVE_ERROR; + return LOCAL_SAVE_STATUS.SAVE_ERROR; } - String portText = textFieldRouterPort.getText(); int port = 0; try { port = Integer.parseInt(portText); @@ -229,10 +354,9 @@ public class SettingsFrame extends RegisteredFrame{ Transl._("Invalid port."), JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE); - return SAVE_ERROR; + return LOCAL_SAVE_STATUS.SAVE_ERROR; } - String pwText = new String(passwordField.getPassword()); try { _conf.setConf("server.hostname", ipText); _conf.setConf("server.port", port); @@ -247,7 +371,7 @@ public class SettingsFrame extends RegisteredFrame{ Transl._("Rejected password."), JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE); - return SAVE_ERROR; + return LOCAL_SAVE_STATUS.SAVE_ERROR; } catch (JSONRPC2SessionException e) { _conf.setConf("server.hostname", oldIP); _conf.setConf("server.port", oldPort); @@ -260,7 +384,7 @@ public class SettingsFrame extends RegisteredFrame{ Transl._("Connection failed."), JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE); - return SAVE_ERROR; + return LOCAL_SAVE_STATUS.SAVE_ERROR; } _conf.setConf("server.hostname", ipText); @@ -271,7 +395,6 @@ public class SettingsFrame extends RegisteredFrame{ _log.debug("Port old->new: \""+_conf.getConf("server.port",7650)+"\"->\"" + portText + "\""); _log.debug("Password old->new: \""+oldPW+"\"->\"" + pwText + "\""); - StatusHandler.setStatus("Settings saved"); (new Thread() { @Override @@ -279,7 +402,100 @@ public class SettingsFrame extends RegisteredFrame{ _conf.writeConfFile(); } }).start(); - return SAVE_OK; + return LOCAL_SAVE_STATUS.SAVE_OK; } + private REMOTE_SAVE_STATUS saveNewPassword(){ + String oldPW = _conf.getConf("server.password", "itoopie"); + String pw = new String(txtNewPassword.getPassword()); + String pwRepeat = new String(txtRetypeNewPassword.getPassword()); + + if ((pw.length() < 1) && (pwRepeat.length() < 1)){ + return REMOTE_SAVE_STATUS.NO_CHANGES; + } + + if (!pw.equals(pwRepeat)){ + JOptionPane.showConfirmDialog( + this, + Transl._("The new password and the repeated new password do not match.\r\n"), + Transl._("Mistyped password."), + JOptionPane.OK_OPTION, + JOptionPane.ERROR_MESSAGE); + return REMOTE_SAVE_STATUS.SAVE_FAILED_LOCALLY; + } + + if (pw.equals(oldPW)){ + JOptionPane.showConfirmDialog( + this, + Transl._("The new password is the same as the old password.\r\n"), + Transl._("No new password."), + JOptionPane.OK_CANCEL_OPTION, + JOptionPane.ERROR_MESSAGE); + return REMOTE_SAVE_STATUS.NO_CHANGES; + } + + HashMap hm = new HashMap(); + hm.put(I2P_CONTROL.PASSWORD, pw); + try { + SetI2PControl.execute(hm); + _conf.setConf("server.password", pw); // Reflect remote changes in local settings. + passwordField.setText(pw); + return REMOTE_SAVE_STATUS.SAVED_OK; + } catch (InvalidPasswordException e) { + StatusHandler.setDefaultStatus(DEFAULT_STATUS.INVALID_PASSWORD); + return REMOTE_SAVE_STATUS.SAVE_FAILED_LOCALLY; + } catch (JSONRPC2SessionException e) { + StatusHandler.setDefaultStatus(DEFAULT_STATUS.NOT_CONNECTED); + return REMOTE_SAVE_STATUS.SAVE_FAILED_LOCALLY; + } catch (InvalidParametersException e) { + return REMOTE_SAVE_STATUS.SAVE_FAILED_REMOTELY; + } + } + + + private REMOTE_SAVE_STATUS saveNewPort(){ + String oldPort = _conf.getConf("server.port", 7650) + ""; + String port = txtNewPort.getText(); + + if (port.length() < 1){ + return REMOTE_SAVE_STATUS.NO_CHANGES; + } + + if (port.equals(oldPort)){ + return REMOTE_SAVE_STATUS.NO_CHANGES; + } + + int nbrPort = 0; + try { + nbrPort = Integer.parseInt(port); + if (nbrPort > 65535 || nbrPort < 1) + throw new NumberFormatException(); + } catch (NumberFormatException e){ + JOptionPane.showConfirmDialog( + this, + Transl._(port + " can not be interpreted as a port.\r\n" + + "\r\nA port has to be a number in the range 1-65535."), + Transl._("Invalid port."), + JOptionPane.OK_CANCEL_OPTION, + JOptionPane.ERROR_MESSAGE); + return REMOTE_SAVE_STATUS.SAVE_FAILED_LOCALLY; + } + + HashMap hm = new HashMap(); + hm.put(I2P_CONTROL.PORT, nbrPort + ""); + try { + SetI2PControl.execute(hm); + _conf.setConf("server.port", nbrPort); // Reflect remote changes in local settings. + txtRouterPort.setText(port+""); + return REMOTE_SAVE_STATUS.SAVED_OK; + } catch (InvalidPasswordException e) { + StatusHandler.setDefaultStatus(DEFAULT_STATUS.INVALID_PASSWORD); + return REMOTE_SAVE_STATUS.SAVE_FAILED_LOCALLY; + } catch (JSONRPC2SessionException e) { + StatusHandler.setDefaultStatus(DEFAULT_STATUS.NOT_CONNECTED); + return REMOTE_SAVE_STATUS.SAVE_FAILED_LOCALLY; + } catch (InvalidParametersException e) { + return REMOTE_SAVE_STATUS.SAVE_FAILED_REMOTELY; + } + } } diff --git a/src/net/i2p/itoopie/gui/component/util/TabChangeListener.java b/src/net/i2p/itoopie/gui/component/util/TabChangeListener.java index 07e7afca6..e3c5205bc 100644 --- a/src/net/i2p/itoopie/gui/component/util/TabChangeListener.java +++ b/src/net/i2p/itoopie/gui/component/util/TabChangeListener.java @@ -26,9 +26,14 @@ public class TabChangeListener implements ChangeListener { /** * Fire onTabFocus for visible tabs when stateChanged. */ - public void stateChanged(ChangeEvent e) { + public void stateChanged(final ChangeEvent e) { if (adaptee.isVisible()){ - adaptee.onTabFocus(e); + (new Thread(){ + @Override + public void run(){ + adaptee.onTabFocus(e); + } + }).start(); } } }