Ticket #3112: npm_patch

File npm_patch, 16.5 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 1859)
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 1859)
64+++ src/org/openstreetmap/josm/gui/preferences/PreferenceDialog.java (working copy)
65@@ -39,7 +39,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 1859)
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,20 +64,93 @@
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+ public boolean authCancelled = false;
179+ @Override protected PasswordAuthentication getPasswordAuthentication() {
180+ return credentialsManager.getPasswordAuthentication(this);
181+ }
182+ }
183
184- @Override protected PasswordAuthentication getPasswordAuthentication() {
185- String username = Main.pref.get("osm-server.username");
186+ /**
187+ * Must be called before each connection attemp to initialize the authentication.
188+ */
189+ protected final void initAuthentication() {
190+ authentication.authCancelled = false;
191+ authentication.passwordtried = false;
192+ }
193+
194+ /**
195+ * @return Whether the connection was cancelled.
196+ */
197+ protected final boolean isAuthCancelled() {
198+ return authentication.authCancelled;
199+ }
200+
201+ public void cancel() {
202+ //TODO
203+ //Main.pleaseWaitDlg.currentAction.setText(tr("Aborting..."));
204+ cancel = true;
205+ if (activeConnection != null) {
206+ activeConnection.setConnectTimeout(100);
207+ activeConnection.setReadTimeout(100);
208+ try {
209+ Thread.sleep(100);
210+ } catch (InterruptedException ex) {}
211+ activeConnection.disconnect();
212+ }
213+ }
214+
215+ protected void addAuth(HttpURLConnection con) throws CharacterCodingException {
216+ CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder();
217+ String auth;
218+ try {
219+ synchronized (credentialsManager) {
220+ auth = credentialsManager.lookupUsername() + ":" + credentialsManager.lookupPassword();
221+ }
222+ } catch (CMException e) {
223+ auth = ":";
224+ }
225+ ByteBuffer bytes = encoder.encode(CharBuffer.wrap(auth));
226+ con.addRequestProperty("Authorization", "Basic "+Base64.encode(bytes));
227+ }
228+
229+ public static class PlainCredentialsManager implements CredentialsManager {
230+ public String lookupUsername() throws CMException {
231+ String username = Main.pref.get("osm-server.username", null);
232+ if (username == null) throw new CredentialsManager.NoContentException();
233+ return username;
234+ }
235+ public String lookupPassword() throws CMException {
236 String password = Main.pref.get("osm-server.password");
237- if (passwordtried || username.equals("") || password.equals("")) {
238+ if (password == null) throw new CredentialsManager.NoContentException();
239+ return password;
240+ }
241+ public void storeUsername(String username) {
242+ Main.pref.put("osm-server.username", username);
243+ }
244+ public void storePassword(String password) {
245+ Main.pref.put("osm-server.password", password);
246+ }
247+ public PasswordAuthentication getPasswordAuthentication(OsmAuth caller) {
248+ String username, password;
249+ try {
250+ username = lookupUsername();
251+ } catch (CMException e) {
252+ username = "";
253+ }
254+ try {
255+ password = lookupPassword();
256+ } catch (CMException e) {
257+ password = "";
258+ }
259+ if (caller.passwordtried || username.equals("") || password.equals("")) {
260 JPanel p = new JPanel(new GridBagLayout());
261 if (!username.equals("") && !password.equals("")) {
262 p.add(new JLabel(tr("Incorrect password or username.")), GBC.eop());
263@@ -92,56 +175,71 @@
264 new String[] {"ok.png", "cancel.png"}).getValue();
265
266 if (choice != 1) {
267- authCancelled = true;
268+ caller.authCancelled = true;
269 return null;
270 }
271 username = usernameField.getText();
272 password = String.valueOf(passwordField.getPassword());
273 if (savePassword.isSelected()) {
274- Main.pref.put("osm-server.username", username);
275- Main.pref.put("osm-server.password", password);
276+ storeUsername(username);
277+ storePassword(password);
278 }
279 if (username.equals(""))
280 return null;
281 }
282- passwordtried = true;
283+ caller.passwordtried = true;
284 return new PasswordAuthentication(username, password.toCharArray());
285 }
286- }
287+ public PreferenceAdditions newPreferenceAdditions() {
288+ return new PreferenceAdditions() {
289+ /**
290+ * Editfield for the username to the OSM account.
291+ */
292+ private JTextField osmDataUsername = new JTextField(20);
293+ /**
294+ * Passwordfield for the userpassword of the REST API.
295+ */
296+ private JPasswordField osmDataPassword = new JPasswordField(20);
297
298- /**
299- * Must be called before each connection attemp to initialize the authentication.
300- */
301- protected final void initAuthentication() {
302- authentication.authCancelled = false;
303- authentication.passwordtried = false;
304- }
305+ private String oldUsername = "";
306+ private String oldPassword = "";
307
308- /**
309- * @return Whether the connection was cancelled.
310- */
311- protected final boolean isAuthCancelled() {
312- return authentication.authCancelled;
313- }
314-
315- public void cancel() {
316- //TODO
317- //Main.pleaseWaitDlg.currentAction.setText(tr("Aborting..."));
318- cancel = true;
319- if (activeConnection != null) {
320- activeConnection.setConnectTimeout(100);
321- activeConnection.setReadTimeout(100);
322- try {
323- Thread.sleep(100);
324- } catch (InterruptedException ex) {}
325- activeConnection.disconnect();
326+ public void addPreferenceOptions(JPanel panel) {
327+ try {
328+ oldUsername = lookupUsername();
329+ } catch (CMException e) {
330+ oldUsername = "";
331+ }
332+ try {
333+ oldPassword = lookupPassword();
334+ } catch (CMException e) {
335+ oldPassword = "";
336+ }
337+ osmDataUsername.setText(oldUsername);
338+ osmDataPassword.setText(oldPassword);
339+ osmDataUsername.setToolTipText(tr("Login name (e-mail) to the OSM account."));
340+ osmDataPassword.setToolTipText(tr("Login password to the OSM account. Leave blank to not store any password."));
341+ panel.add(new JLabel(tr("OSM username (e-mail)")), GBC.std());
342+ panel.add(osmDataUsername, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,5));
343+ panel.add(new JLabel(tr("OSM password")), GBC.std());
344+ panel.add(osmDataPassword, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,0));
345+ JLabel warning = new JLabel(tr("<html>" +
346+ "WARNING: The password is stored in plain text in the preferences file.<br>" +
347+ "The password is transferred in plain text to the server, encoded in the URL.<br>" +
348+ "<b>Do not use a valuable Password.</b></html>"));
349+ warning.setFont(warning.getFont().deriveFont(Font.ITALIC));
350+ panel.add(warning, GBC.eop().fill(GBC.HORIZONTAL));
351+ }
352+ public void preferencesChanged() {
353+ String newUsername = osmDataUsername.getText();
354+ String newPassword = String.valueOf(osmDataPassword.getPassword());
355+ if (!oldUsername.equals(newUsername))
356+ storeUsername(newUsername);
357+ if (!oldPassword.equals(newPassword))
358+ storePassword(newPassword);
359+ }
360+ };
361 }
362 }
363+}
364
365- protected void addAuth(HttpURLConnection con) throws CharacterCodingException {
366- CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder();
367- String auth = Main.pref.get("osm-server.username") + ":" + Main.pref.get("osm-server.password");
368- ByteBuffer bytes = encoder.encode(CharBuffer.wrap(auth));
369- con.addRequestProperty("Authorization", "Basic "+Base64.encode(bytes));
370- }
371-}