Index: src/org/openstreetmap/josm/data/Preferences.java
===================================================================
--- src/org/openstreetmap/josm/data/Preferences.java	(revision 194)
+++ src/org/openstreetmap/josm/data/Preferences.java	(revision 195)
@@ -55,5 +55,5 @@
 	 * Map the property name to the property object.
 	 */
-	private final SortedMap<String, String> properties = new TreeMap<String, String>();
+	protected final SortedMap<String, String> properties = new TreeMap<String, String>();
 
 	/**
Index: src/org/openstreetmap/josm/data/ServerSidePreferences.java
===================================================================
--- src/org/openstreetmap/josm/data/ServerSidePreferences.java	(revision 194)
+++ src/org/openstreetmap/josm/data/ServerSidePreferences.java	(revision 195)
@@ -1,7 +1,27 @@
 package org.openstreetmap.josm.data;
 
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.io.Reader;
+import java.io.StringReader;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Map.Entry;
+
+import javax.swing.JOptionPane;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.io.OsmConnection;
+import org.openstreetmap.josm.io.XmlWriter;
+import org.openstreetmap.josm.tools.Base64;
+import org.openstreetmap.josm.tools.XmlObjectParser;
 
 /**
@@ -13,29 +33,124 @@
 public class ServerSidePreferences extends Preferences {
 
-	private final URL serverUrl;
-	private final String userName;
+	private final Connection connection;
 
-	public ServerSidePreferences(URL serverUrl, String userName) {
-		this.serverUrl = serverUrl;
-		this.userName = userName;
-		load();
-    }
-	
+	private class Connection extends OsmConnection {
+		URL serverUrl;
+		public Connection(URL serverUrl) {
+			this.serverUrl = serverUrl;
+		}
+		public String download() {
+			try {
+				System.out.println("reading preferenced from "+serverUrl);
+				HttpURLConnection con = (HttpURLConnection)serverUrl.openConnection();
+				addAuth(con);
+				con.connect();
+				BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
+				StringBuilder b = new StringBuilder();
+				for (String line = reader.readLine(); line != null; line = reader.readLine()) {
+					b.append(line);
+					b.append("\n");
+				}
+				con.disconnect();
+				return b.toString();
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+			return null;
+		}
+		public void upload(String s) {
+			try {
+				URL u = new URL(getPreferencesDir());
+				System.out.println("uplaoding preferences to "+u);
+				HttpURLConnection con = (HttpURLConnection)u.openConnection();
+				con.addRequestProperty("Authorization", "Basic "+Base64.encode(get("osm-server.username")+":"+get("osm-server.password")));
+				con.setRequestMethod("POST");
+				con.setDoOutput(true);
+				con.connect();
+				PrintWriter out = new PrintWriter(new OutputStreamWriter(con.getOutputStream()));
+				out.println(s);
+				out.close();
+				con.getInputStream().close();
+				con.disconnect();
+				JOptionPane.showMessageDialog(Main.parent, tr("Preferences stored on {0}", u.getHost()));
+			} catch (Exception e) {
+				e.printStackTrace();
+				JOptionPane.showMessageDialog(Main.parent, tr("Could not upload preferences. Reason: {0}", e.getMessage()));
+			}
+		}
+	}
+
+	public ServerSidePreferences(URL serverUrl) {
+		Connection connection = null;
+		try {
+			connection = new Connection(new URL(serverUrl+"/user/preferences"));
+		} catch (MalformedURLException e) {
+			e.printStackTrace();
+			JOptionPane.showMessageDialog(Main.parent, tr("Could not load preferenced from server."));
+		}
+		this.connection = connection;
+	}
+
 	@Override public String getPreferencesDir() {
-	    return serverUrl+"/user/"+userName+"/preferences";
-    }
+		return connection.serverUrl.toString();
+	}
 
-	@Override public void load() {
+	/**
+	 * Do nothing on load. Preferences are loaded with download().
+	 */
+	@Override public void load() throws IOException {
+	}
+
+	/**
+	 * Do nothing on save. Preferences are uploaded using upload().
+	 */
+	@Override protected void save() {
+	}
+
+	public static class Prop {
+		public String key;
+		public String value;
+	}
+
+	public void download(String userName, String password) {
 		resetToDefault();
-    }
+		if (!properties.containsKey("osm-server.username") && userName != null)
+			properties.put("osm-server.username", userName);
+		if (!properties.containsKey("osm-server.password") && password != null)
+			properties.put("osm-server.password", password);
+        Reader in = new StringReader(connection.download());
+		try {
+	        XmlObjectParser.Uniform<Prop> parser = new XmlObjectParser.Uniform<Prop>(in, "tag", Prop.class);
+	        for (Prop p : parser)
+	        	properties.put(p.key, p.value);
+        } catch (RuntimeException e) {
+	        e.printStackTrace();
+        }
+	}
 
-	@Override protected void save() {
-    }
+	/**
+	 * Use this instead of save() for the ServerSidePreferences, since uploads
+	 * are costly while save is called often.
+	 * 
+	 * This is triggered by an explicit menu option.
+	 */
+	public void upload() {
+		StringBuilder b = new StringBuilder("<preferences>\n");
+		for (Entry<String, String> p : properties.entrySet()) {
+			b.append("<tag key='");
+			b.append(XmlWriter.encode(p.getKey()));
+			b.append("' value='");
+			b.append(XmlWriter.encode(p.getValue()));
+			b.append("' />\n");
+		}
+		b.append("</preferences>");
+		connection.upload(b.toString());
+	}
 
 	@Override public Collection<Bookmark> loadBookmarks() {
 		return Collections.<Bookmark>emptyList();
-    }
+	}
 
 	@Override public void saveBookmarks(Collection<Bookmark> bookmarks) {
-    }
+	}
 }
Index: src/org/openstreetmap/josm/gui/MainApplet.java
===================================================================
--- src/org/openstreetmap/josm/gui/MainApplet.java	(revision 194)
+++ src/org/openstreetmap/josm/gui/MainApplet.java	(revision 195)
@@ -4,4 +4,6 @@
 
 import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyEvent;
 import java.util.Arrays;
 import java.util.Collection;
@@ -18,4 +20,5 @@
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.JosmAction;
 import org.openstreetmap.josm.data.ServerSidePreferences;
 import org.openstreetmap.josm.tools.GBC;
@@ -23,5 +26,14 @@
 public class MainApplet extends JApplet {
 
-	private final class MainCaller extends Main {
+	public static final class UploadPreferencesAction extends JosmAction {
+		public UploadPreferencesAction() {
+			super(tr("Upload Preferences"), "upload-preferences", tr("Upload the current preferences to the server"), KeyEvent.VK_U, KeyEvent.CTRL_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK, true);
+        }
+	    public void actionPerformed(ActionEvent e) {
+	    	((ServerSidePreferences)Main.pref).upload();
+	    }
+    }
+
+    private final class MainCaller extends Main {
 		private MainCaller() {
 			setContentPane(contentPane);
@@ -76,5 +88,6 @@
 
 		Main.applet = true;
-		Main.pref = new ServerSidePreferences(getCodeBase(), username);
+		Main.pref = new ServerSidePreferences(getCodeBase());
+		((ServerSidePreferences)Main.pref).download(username, password);
 
 		Main.preConstructorInit(args);
@@ -86,4 +99,5 @@
 		// remove offending stuff from JOSM (that would break the SecurityManager)
 		m.remove(m.fileMenu);
+		m.editMenu.add(new UploadPreferencesAction());
 		m.open.setEnabled(false);
 		m.exit.setEnabled(false);
Index: src/org/openstreetmap/josm/io/OsmConnection.java
===================================================================
--- src/org/openstreetmap/josm/io/OsmConnection.java	(revision 194)
+++ src/org/openstreetmap/josm/io/OsmConnection.java	(revision 195)
@@ -17,4 +17,5 @@
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.tools.Base64;
 import org.openstreetmap.josm.tools.GBC;
 
@@ -126,3 +127,7 @@
 		}
 	}
+
+	protected void addAuth(HttpURLConnection con) {
+        con.addRequestProperty("Authorization", "Basic "+Base64.encode(Main.pref.get("osm-server.username")+":"+Main.pref.get("osm-server.password")));
+    }
 }
Index: src/org/openstreetmap/josm/tools/Base64.java
===================================================================
--- src/org/openstreetmap/josm/tools/Base64.java	(revision 195)
+++ src/org/openstreetmap/josm/tools/Base64.java	(revision 195)
@@ -0,0 +1,19 @@
+package org.openstreetmap.josm.tools;
+
+public class Base64 {
+
+	private static String enc = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+	public static String encode(String s) {
+		StringBuilder out = new StringBuilder();
+		for (int i = 0; i < (s.length()+2)/3; ++i) {
+			int l = Math.min(3, s.length()-i*3);
+			String buf = s.substring(i*3, i*3+l);
+            out.append(enc.charAt(buf.charAt(0)>>2));
+            out.append(enc.charAt((buf.charAt(0) & 0x03) << 4 | (l==1?0:(buf.charAt(1) & 0xf0) >> 4)));
+            out.append(l>1?enc.charAt((buf.charAt(1) & 0x0f) << 2 | (buf.charAt(2) & 0xc0) >> 6):'=');
+            out.append(l>2?enc.charAt(buf.charAt(2) & 0x3f):'=');
+		}
+		return out.toString();
+	}
+}
Index: src/org/openstreetmap/josm/tools/XmlObjectParser.java
===================================================================
--- src/org/openstreetmap/josm/tools/XmlObjectParser.java	(revision 194)
+++ src/org/openstreetmap/josm/tools/XmlObjectParser.java	(revision 195)
@@ -230,4 +230,5 @@
 					return XmlObjectParser.this.hasNext();
 				} catch (SAXException e) {
+					e.printStackTrace();
 					throw new RuntimeException(e);
 				}
@@ -237,4 +238,5 @@
 					return XmlObjectParser.this.next();
 				} catch (SAXException e) {
+					e.printStackTrace();
 					throw new RuntimeException(e);
 				}
