Index: src/org/openstreetmap/josm/data/osm/OsmPrimitive.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/OsmPrimitive.java	(revision 226)
+++ src/org/openstreetmap/josm/data/osm/OsmPrimitive.java	(revision 227)
@@ -56,4 +56,18 @@
 
 	/**
+	 * Visibility status as specified by the server. The visible attribute was
+	 * introduced with the 0.4 API to be able to communicate deleted objects
+	 * (they will have visible=false). Currently JOSM does never deal with
+	 * these, so this is really for future use only.
+	 */
+	public boolean visible = true;
+	
+	/** 
+	 * User that last modified this primitive, as specified by the server.
+	 * Never changed by JOSM.
+	 */
+	public User user = null;
+	
+	/**
 	 * <code>true</code>, if the object has been shown. This property is not used
 	 * internally by JOSM, but can be used by plugins that take over the object
@@ -182,4 +196,6 @@
 			deleted == osm.deleted &&
 			(semanticOnly || (timestamp == null ? osm.timestamp==null : timestamp.equals(osm.timestamp))) &&
+			(semanticOnly || (user == null ? osm.user==null : user==osm.user)) &&
+			(semanticOnly || (visible == osm.visible)) &&
 			(keys == null ? osm.keys==null : keys.equals(osm.keys));
 	}
Index: src/org/openstreetmap/josm/data/osm/User.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/User.java	(revision 227)
+++ src/org/openstreetmap/josm/data/osm/User.java	(revision 227)
@@ -0,0 +1,37 @@
+package org.openstreetmap.josm.data.osm;
+
+import java.util.HashMap;
+
+/** 
+ * A simple class to keep a list of user names.
+ * 
+ * Instead of storing user names as strings with every OSM primtive, we store
+ * a reference to an user object, and make sure that for each username there
+ * is only one user object.
+ * 
+ * @author fred
+ *
+ */
+public class User {
+
+	/** storage for existing User objects. */
+	private static HashMap<String,User> userMap = new HashMap<String,User>();
+	
+	/** the username. */
+	public String name;
+	
+	/** private constructor, only called from get method. */
+	private User(String name) {
+		this.name = name;
+	}
+	
+	/** returns a new or existing User object that represents the given name. */
+	public static User get(String name) {
+		User user = userMap.get(name);
+		if (user == null) {
+			user = new User(name);
+			userMap.put(name, user);
+		}
+		return user;
+	}
+}
Index: src/org/openstreetmap/josm/io/OsmReader.java
===================================================================
--- src/org/openstreetmap/josm/io/OsmReader.java	(revision 226)
+++ src/org/openstreetmap/josm/io/OsmReader.java	(revision 227)
@@ -6,7 +6,10 @@
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.lang.reflect.Array;
 import java.text.ParseException;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.Map;
@@ -20,4 +23,5 @@
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.Segment;
+import org.openstreetmap.josm.data.osm.User;
 import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.data.osm.visitor.AddVisitor;
@@ -76,4 +80,6 @@
 			osm.deleted = deleted;
 			osm.timestamp = timestamp;
+			osm.user = user;
+			osm.visible = visible;
 		}
 	}
@@ -84,4 +90,5 @@
 	 */
 	private Map<OsmPrimitiveData, long[]> segs = new HashMap<OsmPrimitiveData, long[]>();
+
 	/**
 	 * Data structure for the remaining way objects
@@ -89,4 +96,8 @@
 	private Map<OsmPrimitiveData, Collection<Long>> ways = new HashMap<OsmPrimitiveData, Collection<Long>>();
 
+	/** 
+	 * List of protocol versions that will be accepted on reading
+	 */
+	private HashSet<String> allowedVersions = new HashSet<String>();
 
 	private class Parser extends MinML2 {
@@ -101,5 +112,5 @@
 					if (atts == null)
 						throw new SAXException(tr("Unknown version"));
-					if (!Main.pref.get("osm-server.version", "0.4").equals(atts.getValue("version")))
+					if (!allowedVersions.contains(atts.getValue("version")))
 						throw new SAXException(tr("Unknown version")+": "+atts.getValue("version"));
 				} else if (qName.equals("node")) {
@@ -138,4 +149,16 @@
 		}
 	}
+	
+	/** 
+	 * Constructor initializes list of allowed protocol versions.
+	 */
+	public OsmReader() {
+		// first add the main server version
+		allowedVersions.add(Main.pref.get("osm-server.version", "0.4"));
+		// now also add all compatible versions
+		String[] additionalVersions = 
+			Main.pref.get("osm-server.additional-versions", "0.3").split("/,/");
+		allowedVersions.addAll(Arrays.asList(additionalVersions));	
+	}
 
 	/**
@@ -155,4 +178,17 @@
 				throw new SAXException(tr("Couldn''t read time format \"{0}\".",time));
 			}
+		}
+		
+		// user attribute added in 0.4 API
+		String user = atts.getValue("user");
+		if (user != null) {
+			// do not store literally; get object reference for string
+			current.user = User.get(user);
+		}
+		
+		// visible attribute added in 0.4 API
+		String visible = atts.getValue("visible");
+		if (visible != null) {
+			current.visible = Boolean.parseBoolean(visible);
 		}
 
Index: src/org/openstreetmap/josm/io/OsmWriter.java
===================================================================
--- src/org/openstreetmap/josm/io/OsmWriter.java	(revision 226)
+++ src/org/openstreetmap/josm/io/OsmWriter.java	(revision 227)
@@ -153,5 +153,6 @@
 
 	/**
-	 * Add the common part as the from of the tag as well as the id or the action tag.
+	 * Add the common part as the form of the tag as well as the XML attributes
+	 * id, action, user, and visible.
 	 */
 	private void addCommon(OsmPrimitive osm, String tagname) {
@@ -170,4 +171,10 @@
 			out.print(" timestamp='"+time+"'");
 		}
+		// user and visible added with 0.4 API
+		if (osm.user != null) {
+			out.print(" user='"+XmlWriter.encode(osm.user.name)+"'");
+		}
+		out.print(" visible='"+osm.visible+"'");
+		
 	}
 }
