Index: src/org/openstreetmap/josm/gui/preferences/ServerAccessPreference.java
===================================================================
--- src/org/openstreetmap/josm/gui/preferences/ServerAccessPreference.java (revision 1953)
+++ src/org/openstreetmap/josm/gui/preferences/ServerAccessPreference.java (working copy)
@@ -11,6 +11,8 @@
import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.tools.GBC;
+import org.openstreetmap.josm.io.OsmConnection;
+import org.openstreetmap.josm.io.CredentialsManager.PreferenceAdditions;
public class ServerAccessPreference implements PreferenceSetting {
@@ -25,41 +27,22 @@
*/
private JTextField osmDataServer = new JTextField(20);
/**
- * Editfield for the username to the OSM account.
+ * Provide username and password input editfields.
+ * Store the values if user hits OK.
*/
- private JTextField osmDataUsername = new JTextField(20);
- /**
- * Passwordfield for the userpassword of the REST API.
- */
- private JPasswordField osmDataPassword = new JPasswordField(20);
+ private PreferenceAdditions credentialsPA = OsmConnection.credentialsManager.newPreferenceAdditions();
public void addGui(PreferenceDialog gui) {
osmDataServer.setText(Main.pref.get("osm-server.url", "http://api.openstreetmap.org/api"));
- osmDataUsername.setText(Main.pref.get("osm-server.username"));
- osmDataPassword.setText(Main.pref.get("osm-server.password"));
-
osmDataServer.setToolTipText(tr("The base URL for the OSM server (REST API)"));
- osmDataUsername.setToolTipText(tr("Login name (e-mail) to the OSM account."));
- osmDataPassword.setToolTipText(tr("Login password to the OSM account. Leave blank to not store any password."));
-
gui.connection.add(new JLabel(tr("Base Server URL")), GBC.std());
gui.connection.add(osmDataServer, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,5));
- gui.connection.add(new JLabel(tr("OSM username (e-mail)")), GBC.std());
- gui.connection.add(osmDataUsername, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,5));
- gui.connection.add(new JLabel(tr("OSM password")), GBC.std());
- gui.connection.add(osmDataPassword, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,0));
- JLabel warning = new JLabel(tr("" +
- "WARNING: The password is stored in plain text in the preferences file.
" +
- "The password is transferred in plain text to the server, encoded in the URL.
" +
- "Do not use a valuable Password."));
- warning.setFont(warning.getFont().deriveFont(Font.ITALIC));
- gui.connection.add(warning, GBC.eop().fill(GBC.HORIZONTAL));
+ credentialsPA.addPreferenceOptions(gui.connection);
}
public boolean ok() {
Main.pref.put("osm-server.url", osmDataServer.getText());
- Main.pref.put("osm-server.username", osmDataUsername.getText());
- Main.pref.put("osm-server.password", String.valueOf(osmDataPassword.getPassword()));
+ credentialsPA.preferencesChanged();
return false;
}
}
Index: src/org/openstreetmap/josm/gui/preferences/PreferenceDialog.java
===================================================================
--- src/org/openstreetmap/josm/gui/preferences/PreferenceDialog.java (revision 1953)
+++ src/org/openstreetmap/josm/gui/preferences/PreferenceDialog.java (working copy)
@@ -40,7 +40,7 @@
// some common tabs
public final JPanel display = createPreferenceTab("display", tr("Display Settings"), tr("Various settings that influence the visual representation of the whole program."));
- public final JPanel connection = createPreferenceTab("connection", I18n.tr("Connection Settings"), I18n.tr("Connection Settings for the OSM server."));
+ public final JPanel connection = createPreferenceTab("connection", I18n.tr("Connection Settings"), I18n.tr("Connection Settings for the OSM server."),true);
public final JPanel map = createPreferenceTab("map", I18n.tr("Map Settings"), I18n.tr("Settings for the map projection and data interpretation."));
public final JPanel audio = createPreferenceTab("audio", I18n.tr("Audio Settings"), I18n.tr("Settings for the audio player and audio markers."));
Index: src/org/openstreetmap/josm/io/CredentialsManager.java
===================================================================
--- src/org/openstreetmap/josm/io/CredentialsManager.java (revision 0)
+++ src/org/openstreetmap/josm/io/CredentialsManager.java (revision 0)
@@ -0,0 +1,54 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io;
+
+import org.openstreetmap.josm.io.OsmConnection.OsmAuth;
+
+/**
+ * Manages how username and password are stored. In addition all
+ * username/password-related user interaction is encapsulated here.
+ */
+public interface CredentialsManager {
+ /**
+ * lookupUsername, lookupPassword:
+ *
+ * Should throw or return non-null, possibly empty String.
+ */
+ public String lookupUsername() throws CMException;
+ public String lookupPassword() throws CMException;
+
+ /**
+ * storeUsername, storePassword:
+ *
+ * May silently fail to store.
+ */
+ public void storeUsername(String username) throws CMException;
+ public void storePassword(String password) throws CMException;
+
+ /**
+ * If authentication using the stored credentials fails, this method is
+ * called to promt for new username/password.
+ */
+ public java.net.PasswordAuthentication getPasswordAuthentication(OsmAuth caller);
+
+ /**
+ * Credentials-related preference gui.
+ */
+ public interface PreferenceAdditions {
+ public void addPreferenceOptions(javax.swing.JPanel panel);
+ public void preferencesChanged();
+ }
+ public PreferenceAdditions newPreferenceAdditions();
+
+ public class CMException extends Exception {
+ public CMException() {super();}
+ public CMException(String message, Throwable cause) {super(message, cause);}
+ public CMException(String message) {super(message);}
+ public CMException(Throwable cause) {super(cause);}
+ }
+ public class NoContentException extends CMException {
+ public NoContentException() {super();}
+ public NoContentException(String message, Throwable cause) {super(message, cause);}
+ public NoContentException(String message) {super(message);}
+ public NoContentException(Throwable cause) {super(cause);}
+ }
+}
Index: src/org/openstreetmap/josm/io/OsmConnection.java
===================================================================
--- src/org/openstreetmap/josm/io/OsmConnection.java (revision 1953)
+++ src/org/openstreetmap/josm/io/OsmConnection.java (working copy)
@@ -24,6 +24,7 @@
import org.openstreetmap.josm.gui.ExtendedDialog;
import org.openstreetmap.josm.tools.Base64;
import org.openstreetmap.josm.tools.GBC;
+import org.openstreetmap.josm.io.CredentialsManager.CMException;
/**
* Base class that handles common things like authentication for the reader and writer
@@ -35,8 +36,17 @@
protected boolean cancel = false;
protected HttpURLConnection activeConnection;
+ /**
+ * Handles password storage and some related gui-components.
+ * It can be set by a plugin. This may happen at startup and
+ * by changing the preferences.
+ * Syncronize on this object to get or set a consistent
+ * username/password pair.
+ */
+ public static CredentialsManager credentialsManager = new PlainCredentialsManager();
private static OsmAuth authentication = new OsmAuth();
+
/**
* Initialize the http defaults and the authenticator.
*/
@@ -54,58 +64,17 @@
/**
* The authentication class handling the login requests.
*/
- private static class OsmAuth extends Authenticator {
+ public static class OsmAuth extends Authenticator {
/**
* Set to true, when the autenticator tried the password once.
*/
- boolean passwordtried = false;
+ public boolean passwordtried = false;
/**
* Whether the user cancelled the password dialog
*/
- boolean authCancelled = false;
-
+ public boolean authCancelled = false;
@Override protected PasswordAuthentication getPasswordAuthentication() {
- String username = Main.pref.get("osm-server.username");
- String password = Main.pref.get("osm-server.password");
- if (passwordtried || username.equals("") || password.equals("")) {
- JPanel p = new JPanel(new GridBagLayout());
- if (!username.equals("") && !password.equals("")) {
- p.add(new JLabel(tr("Incorrect password or username.")), GBC.eop());
- }
- p.add(new JLabel(tr("Username")), GBC.std().insets(0,0,10,0));
- JTextField usernameField = new JTextField(username, 20);
- p.add(usernameField, GBC.eol());
- p.add(new JLabel(tr("Password")), GBC.std().insets(0,0,10,0));
- JPasswordField passwordField = new JPasswordField(password, 20);
- p.add(passwordField, GBC.eol());
- JLabel warning = new JLabel(tr("Warning: The password is transferred unencrypted."));
- warning.setFont(warning.getFont().deriveFont(Font.ITALIC));
- p.add(warning, GBC.eop());
-
- JCheckBox savePassword = new JCheckBox(tr("Save user and password (unencrypted)"), !username.equals("") && !password.equals(""));
- p.add(savePassword, GBC.eop());
-
- int choice = new ExtendedDialog(Main.parent,
- tr("Enter Password"),
- p,
- new String[] {tr("Login"), tr("Cancel")},
- new String[] {"ok.png", "cancel.png"}).getValue();
-
- if (choice != 1) {
- authCancelled = true;
- return null;
- }
- username = usernameField.getText();
- password = String.valueOf(passwordField.getPassword());
- if (savePassword.isSelected()) {
- Main.pref.put("osm-server.username", username);
- Main.pref.put("osm-server.password", password);
- }
- if (username.equals(""))
- return null;
- }
- passwordtried = true;
- return new PasswordAuthentication(username, password.toCharArray());
+ return credentialsManager.getPasswordAuthentication(this);
}
}
@@ -140,7 +109,14 @@
protected void addAuth(HttpURLConnection con) throws CharacterCodingException {
CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder();
- String auth = Main.pref.get("osm-server.username") + ":" + Main.pref.get("osm-server.password");
+ String auth;
+ try {
+ synchronized (credentialsManager) {
+ auth = credentialsManager.lookupUsername() + ":" + credentialsManager.lookupPassword();
+ }
+ } catch (CMException e) {
+ auth = ":";
+ }
ByteBuffer bytes = encoder.encode(CharBuffer.wrap(auth));
con.addRequestProperty("Authorization", "Basic "+Base64.encode(bytes));
}
@@ -154,4 +130,125 @@
public boolean isCanceled() {
return cancel;
}
+
+ public static class PlainCredentialsManager implements CredentialsManager {
+ public String lookupUsername() throws CMException {
+ String username = Main.pref.get("osm-server.username", null);
+ if (username == null) throw new CredentialsManager.NoContentException();
+ return username;
+ }
+ public String lookupPassword() throws CMException {
+ String password = Main.pref.get("osm-server.password");
+ if (password == null) throw new CredentialsManager.NoContentException();
+ return password;
+ }
+ public void storeUsername(String username) {
+ Main.pref.put("osm-server.username", username);
+ }
+ public void storePassword(String password) {
+ Main.pref.put("osm-server.password", password);
+ }
+ public PasswordAuthentication getPasswordAuthentication(OsmAuth caller) {
+ String username, password;
+ try {
+ username = lookupUsername();
+ } catch (CMException e) {
+ username = "";
+ }
+ try {
+ password = lookupPassword();
+ } catch (CMException e) {
+ password = "";
+ }
+ if (caller.passwordtried || username.equals("") || password.equals("")) {
+ JPanel p = new JPanel(new GridBagLayout());
+ if (!username.equals("") && !password.equals("")) {
+ p.add(new JLabel(tr("Incorrect password or username.")), GBC.eop());
+ }
+ p.add(new JLabel(tr("Username")), GBC.std().insets(0,0,10,0));
+ JTextField usernameField = new JTextField(username, 20);
+ p.add(usernameField, GBC.eol());
+ p.add(new JLabel(tr("Password")), GBC.std().insets(0,0,10,0));
+ JPasswordField passwordField = new JPasswordField(password, 20);
+ p.add(passwordField, GBC.eol());
+ JLabel warning = new JLabel(tr("Warning: The password is transferred unencrypted."));
+ warning.setFont(warning.getFont().deriveFont(Font.ITALIC));
+ p.add(warning, GBC.eop());
+
+ JCheckBox savePassword = new JCheckBox(tr("Save user and password (unencrypted)"), !username.equals("") && !password.equals(""));
+ p.add(savePassword, GBC.eop());
+
+ int choice = new ExtendedDialog(Main.parent,
+ tr("Enter Password"),
+ p,
+ new String[] {tr("Login"), tr("Cancel")},
+ new String[] {"ok.png", "cancel.png"}).getValue();
+
+ if (choice != 1) {
+ caller.authCancelled = true;
+ return null;
+ }
+ username = usernameField.getText();
+ password = String.valueOf(passwordField.getPassword());
+ if (savePassword.isSelected()) {
+ storeUsername(username);
+ storePassword(password);
+ }
+ if (username.equals(""))
+ return null;
+ }
+ caller.passwordtried = true;
+ return new PasswordAuthentication(username, password.toCharArray());
+ }
+ public PreferenceAdditions newPreferenceAdditions() {
+ return new PreferenceAdditions() {
+ /**
+ * Editfield for the username to the OSM account.
+ */
+ private JTextField osmDataUsername = new JTextField(20);
+ /**
+ * Passwordfield for the userpassword of the REST API.
+ */
+ private JPasswordField osmDataPassword = new JPasswordField(20);
+
+ private String oldUsername = "";
+ private String oldPassword = "";
+
+ public void addPreferenceOptions(JPanel panel) {
+ try {
+ oldUsername = lookupUsername();
+ } catch (CMException e) {
+ oldUsername = "";
+ }
+ try {
+ oldPassword = lookupPassword();
+ } catch (CMException e) {
+ oldPassword = "";
+ }
+ osmDataUsername.setText(oldUsername);
+ osmDataPassword.setText(oldPassword);
+ osmDataUsername.setToolTipText(tr("Login name (e-mail) to the OSM account."));
+ osmDataPassword.setToolTipText(tr("Login password to the OSM account. Leave blank to not store any password."));
+ panel.add(new JLabel(tr("OSM username (e-mail)")), GBC.std());
+ panel.add(osmDataUsername, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,5));
+ panel.add(new JLabel(tr("OSM password")), GBC.std());
+ panel.add(osmDataPassword, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,0));
+ JLabel warning = new JLabel(tr("" +
+ "WARNING: The password is stored in plain text in the preferences file.
" +
+ "The password is transferred in plain text to the server, encoded in the URL.
" +
+ "Do not use a valuable Password."));
+ warning.setFont(warning.getFont().deriveFont(Font.ITALIC));
+ panel.add(warning, GBC.eop().fill(GBC.HORIZONTAL));
+ }
+ public void preferencesChanged() {
+ String newUsername = osmDataUsername.getText();
+ String newPassword = String.valueOf(osmDataPassword.getPassword());
+ if (!oldUsername.equals(newUsername))
+ storeUsername(newUsername);
+ if (!oldPassword.equals(newPassword))
+ storePassword(newPassword);
+ }
+ };
+ }
+ }
}