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

Last change on this file since 2474 was 2322, checked in by Gubaer, 14 years ago

Added canceling of DownloadOsmTaskLists
Removed error remembering in the progress dialog

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