source: josm/trunk/src/org/openstreetmap/josm/io/OsmConnection.java@ 2037

Last change on this file since 2037 was 2037, checked in by Gubaer, 15 years ago

Improved cancellation of upload tasks
Refactored upload dialog
fixed #2597: Size of upload dialog - now restores dialog size from preferences
fixed #2913: Upload dialog enters scrolling-mode when JOSM isn't maximized - no scroling anymore in ExtendeDialog for UploadDialog
fixed #2518: focus & select comment editing field

  • Property svn:eol-style set to native
File size: 11.3 KB
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.io;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Font;
7import java.awt.GridBagLayout;
8import java.net.Authenticator;
9import java.net.HttpURLConnection;
10import java.net.PasswordAuthentication;
11import java.nio.ByteBuffer;
12import java.nio.CharBuffer;
13import java.nio.charset.CharacterCodingException;
14import java.nio.charset.Charset;
15import java.nio.charset.CharsetEncoder;
16
17import javax.swing.JCheckBox;
18import javax.swing.JLabel;
19import javax.swing.JPanel;
20import javax.swing.JPasswordField;
21import javax.swing.JTextField;
22
23import org.openstreetmap.josm.Main;
24import org.openstreetmap.josm.gui.ExtendedDialog;
25import org.openstreetmap.josm.gui.progress.ProgressMonitor;
26import org.openstreetmap.josm.tools.Base64;
27import org.openstreetmap.josm.tools.GBC;
28
29/**
30 * Base class that handles common things like authentication for the reader and writer
31 * to the osm server.
32 *
33 * @author imi
34 */
35public class OsmConnection {
36
37 protected boolean cancel = false;
38 protected HttpURLConnection activeConnection;
39 /**
40 * Handles password storage and some related gui-components.
41 * It can be set by a plugin. This may happen at startup and
42 * by changing the preferences.
43 * Syncronize on this object to get or set a consistent
44 * username/password pair.
45 */
46 public static CredentialsManager credentialsManager = new PlainCredentialsManager();
47
48 private static OsmAuth authentication = new OsmAuth();
49
50 /**
51 * Initialize the http defaults and the authenticator.
52 */
53 static {
54 // TODO: current authentication handling is sub-optimal in that it seems to use the same authenticator for
55 // any kind of request. HTTP requests executed by plugins, e.g. to password-protected WMS servers,
56 // will use the same username/password which is undesirable.
57 try {
58 HttpURLConnection.setFollowRedirects(true);
59 Authenticator.setDefault(authentication);
60 } catch (SecurityException e) {
61 }
62 }
63
64 /**
65 * The authentication class handling the login requests.
66 */
67 public static class OsmAuth extends Authenticator {
68 /**
69 * Set to true, when the autenticator tried the password once.
70 */
71 public boolean passwordtried = false;
72 /**
73 * Whether the user cancelled the password dialog
74 */
75 public boolean authCancelled = false;
76 @Override protected PasswordAuthentication getPasswordAuthentication() {
77 return credentialsManager.getPasswordAuthentication(this);
78 }
79 }
80
81 /**
82 * Must be called before each connection attemp to initialize the authentication.
83 */
84 protected final void initAuthentication() {
85 authentication.authCancelled = false;
86 authentication.passwordtried = false;
87 }
88
89 /**
90 * @return Whether the connection was cancelled.
91 */
92 protected final boolean isAuthCancelled() {
93 return authentication.authCancelled;
94 }
95
96 public void cancel() {
97 cancel = true;
98 if (activeConnection != null) {
99 activeConnection.setConnectTimeout(100);
100 activeConnection.setReadTimeout(100);
101 try {
102 Thread.sleep(100);
103 } catch (InterruptedException ex) {}
104 activeConnection.disconnect();
105 }
106 }
107
108 protected void addAuth(HttpURLConnection con) throws CharacterCodingException {
109 CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder();
110 String auth;
111 try {
112 synchronized (credentialsManager) {
113 auth = credentialsManager.lookup(CredentialsManager.Key.USERNAME) + ":" +
114 credentialsManager.lookup(CredentialsManager.Key.PASSWORD);
115 }
116 } catch (CredentialsManager.CMException e) {
117 auth = ":";
118 }
119 ByteBuffer bytes = encoder.encode(CharBuffer.wrap(auth));
120 con.addRequestProperty("Authorization", "Basic "+Base64.encode(bytes));
121 }
122
123 /**
124 * Replies true if this connection is canceled
125 *
126 * @return true if this connection is canceled
127 * @return
128 */
129 public boolean isCanceled() {
130 return cancel;
131 }
132 /**
133 * Default implementation of the CredentialsManager interface.
134 * Saves passwords in plain text file.
135 */
136 public static class PlainCredentialsManager implements CredentialsManager {
137 public String lookup(CredentialsManager.Key key) throws CMException {
138 String secret = Main.pref.get("osm-server." + key.toString(), null);
139 if (secret == null) throw new CredentialsManager.NoContentException();
140 return secret;
141 }
142 public void store(CredentialsManager.Key key, String secret) {
143 Main.pref.put("osm-server." + key.toString(), secret);
144 }
145 public PasswordAuthentication getPasswordAuthentication(OsmAuth caller) {
146 String username, password;
147 try {
148 username = lookup(Key.USERNAME);
149 } catch (CMException e) {
150 username = "";
151 }
152 try {
153 password = lookup(Key.PASSWORD);
154 } catch (CMException e) {
155 password = "";
156 }
157 if (caller.passwordtried || username.equals("") || password.equals("")) {
158 JPanel p = new JPanel(new GridBagLayout());
159 if (!username.equals("") && !password.equals("")) {
160 p.add(new JLabel(tr("Incorrect password or username.")), GBC.eop());
161 }
162 p.add(new JLabel(tr("Username")), GBC.std().insets(0,0,10,0));
163 JTextField usernameField = new JTextField(username, 20);
164 p.add(usernameField, GBC.eol());
165 p.add(new JLabel(tr("Password")), GBC.std().insets(0,0,10,0));
166 JPasswordField passwordField = new JPasswordField(password, 20);
167 p.add(passwordField, GBC.eol());
168 JLabel warning = new JLabel(tr("Warning: The password is transferred unencrypted."));
169 warning.setFont(warning.getFont().deriveFont(Font.ITALIC));
170 p.add(warning, GBC.eop());
171
172 JCheckBox savePassword = new JCheckBox(tr("Save user and password (unencrypted)"),
173 !username.equals("") && !password.equals(""));
174 p.add(savePassword, GBC.eop());
175
176 ExtendedDialog dialog = new ExtendedDialog(
177 Main.parent,
178 tr("Enter Password"),
179 new String[] {tr("Login"), tr("Cancel")}
180 );
181 dialog.setContent(p);
182 dialog.setButtonIcons( new String[] {"ok.png", "cancel.png"});
183 dialog.showDialog();
184
185 if (dialog.getValue() != 1) {
186 caller.authCancelled = true;
187 return null;
188 }
189 username = usernameField.getText();
190 password = String.valueOf(passwordField.getPassword());
191 if (savePassword.isSelected()) {
192 store(Key.USERNAME, username);
193 store(Key.PASSWORD, password);
194 }
195 if (username.equals(""))
196 return null;
197 }
198 caller.passwordtried = true;
199 return new PasswordAuthentication(username, password.toCharArray());
200 }
201 public PreferenceAdditions newPreferenceAdditions() {
202 return new PreferenceAdditions() {
203 /**
204 * Editfield for the Base url to the REST API from OSM.
205 */
206 final private JTextField osmDataServerURL = new JTextField(20);
207 /**
208 * Editfield for the username to the OSM account.
209 */
210 final private JTextField osmDataUsername = new JTextField(20);
211 /**
212 * Passwordfield for the userpassword of the REST API.
213 */
214 final private JPasswordField osmDataPassword = new JPasswordField(20);
215
216 private String oldServerURL = "";
217 private String oldUsername = "";
218 private String oldPassword = "";
219
220 public void addPreferenceOptions(JPanel panel) {
221 try {
222 oldServerURL = lookup(Key.OSM_SERVER_URL); // result is not null (see CredentialsManager)
223 } catch (CMException e) {
224 oldServerURL = "";
225 }
226 if (oldServerURL.equals("")) {
227 oldServerURL = "http://api.openstreetmap.org/api";
228 }
229 try {
230 oldUsername = lookup(Key.USERNAME);
231 } catch (CMException e) {
232 oldUsername = "";
233 }
234 try {
235 oldPassword = lookup(Key.PASSWORD);
236 } catch (CMException e) {
237 oldPassword = "";
238 }
239 osmDataServerURL.setText(oldServerURL);
240 osmDataUsername.setText(oldUsername);
241 osmDataPassword.setText(oldPassword);
242 osmDataServerURL.setToolTipText(tr("The base URL for the OSM server (REST API)"));
243 osmDataUsername.setToolTipText(tr("Login name (e-mail) to the OSM account."));
244 osmDataPassword.setToolTipText(tr("Login password to the OSM account. Leave blank to not store any password."));
245 panel.add(new JLabel(tr("Base Server URL")), GBC.std());
246 panel.add(osmDataServerURL, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,5));
247 panel.add(new JLabel(tr("OSM username (e-mail)")), GBC.std());
248 panel.add(osmDataUsername, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,5));
249 panel.add(new JLabel(tr("OSM password")), GBC.std());
250 panel.add(osmDataPassword, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,0));
251 JLabel warning = new JLabel(tr("<html>" +
252 "WARNING: The password is stored in plain text in the preferences file.<br>" +
253 "The password is transferred in plain text to the server, encoded in the URL.<br>" +
254 "<b>Do not use a valuable Password.</b></html>"));
255 warning.setFont(warning.getFont().deriveFont(Font.ITALIC));
256 panel.add(warning, GBC.eop().fill(GBC.HORIZONTAL));
257 }
258 public void preferencesChanged() {
259 String newServerURL = osmDataServerURL.getText();
260 String newUsername = osmDataUsername.getText();
261 String newPassword = String.valueOf(osmDataPassword.getPassword());
262 if (!oldServerURL.equals(newServerURL)) {
263 store(Key.OSM_SERVER_URL, newServerURL);
264 }
265 if (!oldUsername.equals(newUsername)) {
266 store(Key.USERNAME, newUsername);
267 }
268 if (!oldPassword.equals(newPassword)) {
269 store(Key.PASSWORD, newPassword);
270 }
271 }
272 };
273 }
274 }
275}
Note: See TracBrowser for help on using the repository browser.