Ticket #3112: npm_patch_r1953

File npm_patch_r1953, 17.4 KB (added by bastiK, 16 years ago)
Line 
1Index: src/org/openstreetmap/josm/gui/preferences/ServerAccessPreference.java
2===================================================================
3--- src/org/openstreetmap/josm/gui/preferences/ServerAccessPreference.java (revision 1953)
4+++ src/org/openstreetmap/josm/gui/preferences/ServerAccessPreference.java (working copy)
5@@ -11,6 +11,8 @@
6
7 import org.openstreetmap.josm.Main;
8 import org.openstreetmap.josm.tools.GBC;
9+import org.openstreetmap.josm.io.OsmConnection;
10+import org.openstreetmap.josm.io.CredentialsManager.PreferenceAdditions;
11
12 public class ServerAccessPreference implements PreferenceSetting {
13
14@@ -25,41 +27,22 @@
15 */
16 private JTextField osmDataServer = new JTextField(20);
17 /**
18- * Editfield for the username to the OSM account.
19+ * Provide username and password input editfields.
20+ * Store the values if user hits OK.
21 */
22- private JTextField osmDataUsername = new JTextField(20);
23- /**
24- * Passwordfield for the userpassword of the REST API.
25- */
26- private JPasswordField osmDataPassword = new JPasswordField(20);
27+ private PreferenceAdditions credentialsPA = OsmConnection.credentialsManager.newPreferenceAdditions();
28
29 public void addGui(PreferenceDialog gui) {
30 osmDataServer.setText(Main.pref.get("osm-server.url", "http://api.openstreetmap.org/api"));
31- osmDataUsername.setText(Main.pref.get("osm-server.username"));
32- osmDataPassword.setText(Main.pref.get("osm-server.password"));
33-
34 osmDataServer.setToolTipText(tr("The base URL for the OSM server (REST API)"));
35- osmDataUsername.setToolTipText(tr("Login name (e-mail) to the OSM account."));
36- osmDataPassword.setToolTipText(tr("Login password to the OSM account. Leave blank to not store any password."));
37-
38 gui.connection.add(new JLabel(tr("Base Server URL")), GBC.std());
39 gui.connection.add(osmDataServer, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,5));
40- gui.connection.add(new JLabel(tr("OSM username (e-mail)")), GBC.std());
41- gui.connection.add(osmDataUsername, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,5));
42- gui.connection.add(new JLabel(tr("OSM password")), GBC.std());
43- gui.connection.add(osmDataPassword, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,0));
44- JLabel warning = new JLabel(tr("<html>" +
45- "WARNING: The password is stored in plain text in the preferences file.<br>" +
46- "The password is transferred in plain text to the server, encoded in the URL.<br>" +
47- "<b>Do not use a valuable Password.</b></html>"));
48- warning.setFont(warning.getFont().deriveFont(Font.ITALIC));
49- gui.connection.add(warning, GBC.eop().fill(GBC.HORIZONTAL));
50+ credentialsPA.addPreferenceOptions(gui.connection);
51 }
52
53 public boolean ok() {
54 Main.pref.put("osm-server.url", osmDataServer.getText());
55- Main.pref.put("osm-server.username", osmDataUsername.getText());
56- Main.pref.put("osm-server.password", String.valueOf(osmDataPassword.getPassword()));
57+ credentialsPA.preferencesChanged();
58 return false;
59 }
60 }
61Index: src/org/openstreetmap/josm/gui/preferences/PreferenceDialog.java
62===================================================================
63--- src/org/openstreetmap/josm/gui/preferences/PreferenceDialog.java (revision 1953)
64+++ src/org/openstreetmap/josm/gui/preferences/PreferenceDialog.java (working copy)
65@@ -40,7 +40,7 @@
66
67 // some common tabs
68 public final JPanel display = createPreferenceTab("display", tr("Display Settings"), tr("Various settings that influence the visual representation of the whole program."));
69- public final JPanel connection = createPreferenceTab("connection", I18n.tr("Connection Settings"), I18n.tr("Connection Settings for the OSM server."));
70+ public final JPanel connection = createPreferenceTab("connection", I18n.tr("Connection Settings"), I18n.tr("Connection Settings for the OSM server."),true);
71 public final JPanel map = createPreferenceTab("map", I18n.tr("Map Settings"), I18n.tr("Settings for the map projection and data interpretation."));
72 public final JPanel audio = createPreferenceTab("audio", I18n.tr("Audio Settings"), I18n.tr("Settings for the audio player and audio markers."));
73
74Index: src/org/openstreetmap/josm/io/CredentialsManager.java
75===================================================================
76--- src/org/openstreetmap/josm/io/CredentialsManager.java (revision 0)
77+++ src/org/openstreetmap/josm/io/CredentialsManager.java (revision 0)
78@@ -0,0 +1,54 @@
79+// License: GPL. For details, see LICENSE file.
80+package org.openstreetmap.josm.io;
81+
82+import org.openstreetmap.josm.io.OsmConnection.OsmAuth;
83+
84+/**
85+ * Manages how username and password are stored. In addition all
86+ * username/password-related user interaction is encapsulated here.
87+ */
88+public interface CredentialsManager {
89+ /**
90+ * lookupUsername, lookupPassword:
91+ *
92+ * Should throw or return non-null, possibly empty String.
93+ */
94+ public String lookupUsername() throws CMException;
95+ public String lookupPassword() throws CMException;
96+
97+ /**
98+ * storeUsername, storePassword:
99+ *
100+ * May silently fail to store.
101+ */
102+ public void storeUsername(String username) throws CMException;
103+ public void storePassword(String password) throws CMException;
104+
105+ /**
106+ * If authentication using the stored credentials fails, this method is
107+ * called to promt for new username/password.
108+ */
109+ public java.net.PasswordAuthentication getPasswordAuthentication(OsmAuth caller);
110+
111+ /**
112+ * Credentials-related preference gui.
113+ */
114+ public interface PreferenceAdditions {
115+ public void addPreferenceOptions(javax.swing.JPanel panel);
116+ public void preferencesChanged();
117+ }
118+ public PreferenceAdditions newPreferenceAdditions();
119+
120+ public class CMException extends Exception {
121+ public CMException() {super();}
122+ public CMException(String message, Throwable cause) {super(message, cause);}
123+ public CMException(String message) {super(message);}
124+ public CMException(Throwable cause) {super(cause);}
125+ }
126+ public class NoContentException extends CMException {
127+ public NoContentException() {super();}
128+ public NoContentException(String message, Throwable cause) {super(message, cause);}
129+ public NoContentException(String message) {super(message);}
130+ public NoContentException(Throwable cause) {super(cause);}
131+ }
132+}
133Index: src/org/openstreetmap/josm/io/OsmConnection.java
134===================================================================
135--- src/org/openstreetmap/josm/io/OsmConnection.java (revision 1953)
136+++ src/org/openstreetmap/josm/io/OsmConnection.java (working copy)
137@@ -24,6 +24,7 @@
138 import org.openstreetmap.josm.gui.ExtendedDialog;
139 import org.openstreetmap.josm.tools.Base64;
140 import org.openstreetmap.josm.tools.GBC;
141+import org.openstreetmap.josm.io.CredentialsManager.CMException;
142
143 /**
144 * Base class that handles common things like authentication for the reader and writer
145@@ -35,8 +36,17 @@
146
147 protected boolean cancel = false;
148 protected HttpURLConnection activeConnection;
149+ /**
150+ * Handles password storage and some related gui-components.
151+ * It can be set by a plugin. This may happen at startup and
152+ * by changing the preferences.
153+ * Syncronize on this object to get or set a consistent
154+ * username/password pair.
155+ */
156+ public static CredentialsManager credentialsManager = new PlainCredentialsManager();
157
158 private static OsmAuth authentication = new OsmAuth();
159+
160 /**
161 * Initialize the http defaults and the authenticator.
162 */
163@@ -54,58 +64,17 @@
164 /**
165 * The authentication class handling the login requests.
166 */
167- private static class OsmAuth extends Authenticator {
168+ public static class OsmAuth extends Authenticator {
169 /**
170 * Set to true, when the autenticator tried the password once.
171 */
172- boolean passwordtried = false;
173+ public boolean passwordtried = false;
174 /**
175 * Whether the user cancelled the password dialog
176 */
177- boolean authCancelled = false;
178-
179+ public boolean authCancelled = false;
180 @Override protected PasswordAuthentication getPasswordAuthentication() {
181- String username = Main.pref.get("osm-server.username");
182- String password = Main.pref.get("osm-server.password");
183- if (passwordtried || username.equals("") || password.equals("")) {
184- JPanel p = new JPanel(new GridBagLayout());
185- if (!username.equals("") && !password.equals("")) {
186- p.add(new JLabel(tr("Incorrect password or username.")), GBC.eop());
187- }
188- p.add(new JLabel(tr("Username")), GBC.std().insets(0,0,10,0));
189- JTextField usernameField = new JTextField(username, 20);
190- p.add(usernameField, GBC.eol());
191- p.add(new JLabel(tr("Password")), GBC.std().insets(0,0,10,0));
192- JPasswordField passwordField = new JPasswordField(password, 20);
193- p.add(passwordField, GBC.eol());
194- JLabel warning = new JLabel(tr("Warning: The password is transferred unencrypted."));
195- warning.setFont(warning.getFont().deriveFont(Font.ITALIC));
196- p.add(warning, GBC.eop());
197-
198- JCheckBox savePassword = new JCheckBox(tr("Save user and password (unencrypted)"), !username.equals("") && !password.equals(""));
199- p.add(savePassword, GBC.eop());
200-
201- int choice = new ExtendedDialog(Main.parent,
202- tr("Enter Password"),
203- p,
204- new String[] {tr("Login"), tr("Cancel")},
205- new String[] {"ok.png", "cancel.png"}).getValue();
206-
207- if (choice != 1) {
208- authCancelled = true;
209- return null;
210- }
211- username = usernameField.getText();
212- password = String.valueOf(passwordField.getPassword());
213- if (savePassword.isSelected()) {
214- Main.pref.put("osm-server.username", username);
215- Main.pref.put("osm-server.password", password);
216- }
217- if (username.equals(""))
218- return null;
219- }
220- passwordtried = true;
221- return new PasswordAuthentication(username, password.toCharArray());
222+ return credentialsManager.getPasswordAuthentication(this);
223 }
224 }
225
226@@ -140,7 +109,14 @@
227
228 protected void addAuth(HttpURLConnection con) throws CharacterCodingException {
229 CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder();
230- String auth = Main.pref.get("osm-server.username") + ":" + Main.pref.get("osm-server.password");
231+ String auth;
232+ try {
233+ synchronized (credentialsManager) {
234+ auth = credentialsManager.lookupUsername() + ":" + credentialsManager.lookupPassword();
235+ }
236+ } catch (CMException e) {
237+ auth = ":";
238+ }
239 ByteBuffer bytes = encoder.encode(CharBuffer.wrap(auth));
240 con.addRequestProperty("Authorization", "Basic "+Base64.encode(bytes));
241 }
242@@ -154,4 +130,125 @@
243 public boolean isCanceled() {
244 return cancel;
245 }
246+
247+ public static class PlainCredentialsManager implements CredentialsManager {
248+ public String lookupUsername() throws CMException {
249+ String username = Main.pref.get("osm-server.username", null);
250+ if (username == null) throw new CredentialsManager.NoContentException();
251+ return username;
252+ }
253+ public String lookupPassword() throws CMException {
254+ String password = Main.pref.get("osm-server.password");
255+ if (password == null) throw new CredentialsManager.NoContentException();
256+ return password;
257+ }
258+ public void storeUsername(String username) {
259+ Main.pref.put("osm-server.username", username);
260+ }
261+ public void storePassword(String password) {
262+ Main.pref.put("osm-server.password", password);
263+ }
264+ public PasswordAuthentication getPasswordAuthentication(OsmAuth caller) {
265+ String username, password;
266+ try {
267+ username = lookupUsername();
268+ } catch (CMException e) {
269+ username = "";
270+ }
271+ try {
272+ password = lookupPassword();
273+ } catch (CMException e) {
274+ password = "";
275+ }
276+ if (caller.passwordtried || username.equals("") || password.equals("")) {
277+ JPanel p = new JPanel(new GridBagLayout());
278+ if (!username.equals("") && !password.equals("")) {
279+ p.add(new JLabel(tr("Incorrect password or username.")), GBC.eop());
280+ }
281+ p.add(new JLabel(tr("Username")), GBC.std().insets(0,0,10,0));
282+ JTextField usernameField = new JTextField(username, 20);
283+ p.add(usernameField, GBC.eol());
284+ p.add(new JLabel(tr("Password")), GBC.std().insets(0,0,10,0));
285+ JPasswordField passwordField = new JPasswordField(password, 20);
286+ p.add(passwordField, GBC.eol());
287+ JLabel warning = new JLabel(tr("Warning: The password is transferred unencrypted."));
288+ warning.setFont(warning.getFont().deriveFont(Font.ITALIC));
289+ p.add(warning, GBC.eop());
290+
291+ JCheckBox savePassword = new JCheckBox(tr("Save user and password (unencrypted)"), !username.equals("") && !password.equals(""));
292+ p.add(savePassword, GBC.eop());
293+
294+ int choice = new ExtendedDialog(Main.parent,
295+ tr("Enter Password"),
296+ p,
297+ new String[] {tr("Login"), tr("Cancel")},
298+ new String[] {"ok.png", "cancel.png"}).getValue();
299+
300+ if (choice != 1) {
301+ caller.authCancelled = true;
302+ return null;
303+ }
304+ username = usernameField.getText();
305+ password = String.valueOf(passwordField.getPassword());
306+ if (savePassword.isSelected()) {
307+ storeUsername(username);
308+ storePassword(password);
309+ }
310+ if (username.equals(""))
311+ return null;
312+ }
313+ caller.passwordtried = true;
314+ return new PasswordAuthentication(username, password.toCharArray());
315+ }
316+ public PreferenceAdditions newPreferenceAdditions() {
317+ return new PreferenceAdditions() {
318+ /**
319+ * Editfield for the username to the OSM account.
320+ */
321+ private JTextField osmDataUsername = new JTextField(20);
322+ /**
323+ * Passwordfield for the userpassword of the REST API.
324+ */
325+ private JPasswordField osmDataPassword = new JPasswordField(20);
326+
327+ private String oldUsername = "";
328+ private String oldPassword = "";
329+
330+ public void addPreferenceOptions(JPanel panel) {
331+ try {
332+ oldUsername = lookupUsername();
333+ } catch (CMException e) {
334+ oldUsername = "";
335+ }
336+ try {
337+ oldPassword = lookupPassword();
338+ } catch (CMException e) {
339+ oldPassword = "";
340+ }
341+ osmDataUsername.setText(oldUsername);
342+ osmDataPassword.setText(oldPassword);
343+ osmDataUsername.setToolTipText(tr("Login name (e-mail) to the OSM account."));
344+ osmDataPassword.setToolTipText(tr("Login password to the OSM account. Leave blank to not store any password."));
345+ panel.add(new JLabel(tr("OSM username (e-mail)")), GBC.std());
346+ panel.add(osmDataUsername, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,5));
347+ panel.add(new JLabel(tr("OSM password")), GBC.std());
348+ panel.add(osmDataPassword, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,0));
349+ JLabel warning = new JLabel(tr("<html>" +
350+ "WARNING: The password is stored in plain text in the preferences file.<br>" +
351+ "The password is transferred in plain text to the server, encoded in the URL.<br>" +
352+ "<b>Do not use a valuable Password.</b></html>"));
353+ warning.setFont(warning.getFont().deriveFont(Font.ITALIC));
354+ panel.add(warning, GBC.eop().fill(GBC.HORIZONTAL));
355+ }
356+ public void preferencesChanged() {
357+ String newUsername = osmDataUsername.getText();
358+ String newPassword = String.valueOf(osmDataPassword.getPassword());
359+ if (!oldUsername.equals(newUsername))
360+ storeUsername(newUsername);
361+ if (!oldPassword.equals(newPassword))
362+ storePassword(newPassword);
363+ }
364+ };
365+ }
366+ }
367 }