Index: /src/org/openstreetmap/josm/Main.java
===================================================================
--- /src/org/openstreetmap/josm/Main.java	(revision 50)
+++ /src/org/openstreetmap/josm/Main.java	(revision 51)
@@ -149,14 +149,17 @@
 			public void windowClosing(WindowEvent arg0) {
 				if (mapFrame != null) {
-					boolean changed = false;
+					boolean modified = false;
+					boolean uploadedModified = false;
 					for (Layer l : mapFrame.mapView.getAllLayers()) {
 						if (l instanceof OsmDataLayer && ((OsmDataLayer)l).isModified()) {
-							changed = true;
+							modified = true;
+							uploadedModified = ((OsmDataLayer)l).uploadedModified;
 							break;
 						}
 					}
-					if (changed) {
+					if (modified) {
+						String msg = uploadedModified ? "\nHint: Some changes came from uploading new data to the server." : "";
 						int answer = JOptionPane.showConfirmDialog(
-								Main.this, "There are unsaved changes. Really quit?",
+								Main.this, "There are unsaved changes. Really quit?"+msg,
 								"Unsaved Changes", JOptionPane.YES_NO_OPTION);
 						if (answer != JOptionPane.YES_OPTION)
Index: /src/org/openstreetmap/josm/actions/DownloadAction.java
===================================================================
--- /src/org/openstreetmap/josm/actions/DownloadAction.java	(revision 50)
+++ /src/org/openstreetmap/josm/actions/DownloadAction.java	(revision 51)
@@ -183,5 +183,5 @@
 						}
 
-						layer = new OsmDataLayer(dataSet, "Data Layer");
+						layer = new OsmDataLayer(dataSet, "Data Layer", false);
 					}
 
Index: /src/org/openstreetmap/josm/actions/ExtensionFileFilter.java
===================================================================
--- /src/org/openstreetmap/josm/actions/ExtensionFileFilter.java	(revision 50)
+++ /src/org/openstreetmap/josm/actions/ExtensionFileFilter.java	(revision 51)
@@ -15,9 +15,14 @@
 	private final String extension;
 	private final String description;
+	public final String defaultExtension;
 
+	public static final int OSM = 0;
+	public static final int GPX = 1;
+	public static final int CSV = 2;
+	
 	public static ExtensionFileFilter[] filters = {
-		new ExtensionFileFilter(".xml", "OSM Server Version 0.2 (.xml)"),
-		new ExtensionFileFilter(".gpx", "GPX Files Version 0.1 (.gpx)"),
-		//new ExtensionFileFilter(".josm", "JOSM Savefiles (.josm)")
+		new ExtensionFileFilter("osm,xml", "osm", "OSM Server Version 0.2 (.osm .xml)"),
+		new ExtensionFileFilter("gpx", "gpx", "GPX Files Version 0.1 (.gpx)"),
+		new ExtensionFileFilter("csv,txt", "csv", "CSV Files Version 0.1 (.csv .txt)"),
 	};
 
@@ -26,13 +31,23 @@
 	 *
 	 */
-	private ExtensionFileFilter(String extension, String description) {
+	private ExtensionFileFilter(String extension, String defExt, String description) {
 		this.extension = extension;
+		defaultExtension = defExt;
 		this.description = description;
+	}
+
+	public boolean acceptName(String filename) {
+		String name = filename.toLowerCase();
+		for (String ext : extension.split(","))
+			if (name.endsWith("."+ext))
+				return true;
+		return false;
 	}
 
 	@Override
 	public boolean accept(File pathname) {
-		String name = pathname.getName().toLowerCase();
-		return pathname.isDirectory() || name.endsWith(extension);
+		if (pathname.isDirectory())
+			return true;
+		return acceptName(pathname.getName());
 	}
 
Index: /src/org/openstreetmap/josm/actions/OpenAction.java
===================================================================
--- /src/org/openstreetmap/josm/actions/OpenAction.java	(revision 50)
+++ /src/org/openstreetmap/josm/actions/OpenAction.java	(revision 51)
@@ -36,5 +36,5 @@
 
 	/**
-	 * Create an open action. The name is "Open GPX".
+	 * Create an open action. The name is "Open a file".
 	 */
 	public OpenAction() {
@@ -47,5 +47,5 @@
 			fc.addChoosableFileFilter(ExtensionFileFilter.filters[i]);
 		fc.setAcceptAllFileFilterUsed(true);
-		
+
 		if (fc.showOpenDialog(Main.main) != JFileChooser.APPROVE_OPTION)
 			return;
@@ -54,14 +54,14 @@
 		if (filename == null)
 			return;
+		String fn = filename.getName();
 
 		try {
 			Layer layer;
-			String extension = filename.getName().toLowerCase().substring(filename.getName().lastIndexOf('.')+1);
 
-			if (asRawData(extension)) {
+			if (asRawData(fn)) {
 				Collection<Collection<GeoPoint>> data;
-				if (extension.equals("gpx")) {
+				if (ExtensionFileFilter.filters[ExtensionFileFilter.GPX].acceptName(fn)) {
 					data = new RawGpsReader(new FileReader(filename)).parse();
-				} else if (extension.equals("csv") || extension.equals("txt")) {
+				} else if (ExtensionFileFilter.filters[ExtensionFileFilter.CSV].acceptName(fn)) {
 					data = new LinkedList<Collection<GeoPoint>>();
 					data.add(new RawCsvReader(new FileReader(filename)).parse());
@@ -71,16 +71,16 @@
 			} else {
 				DataSet dataSet;
-				if (extension.equals("gpx"))
+				if (ExtensionFileFilter.filters[ExtensionFileFilter.GPX].acceptName(fn))
 					dataSet = new GpxReader(new FileReader(filename)).parse();
-				else if (extension.equals("xml") || extension.equals("osm"))
+				else if (ExtensionFileFilter.filters[ExtensionFileFilter.OSM].acceptName(fn))
 					dataSet = new OsmReader(new FileReader(filename)).parse();
-				else if (extension.equals("csv") || extension.equals("txt")) {
+				else if (ExtensionFileFilter.filters[ExtensionFileFilter.CSV].acceptName(fn)) {
 					JOptionPane.showMessageDialog(Main.main, "CSV Data import for non-GPS data is not implemented yet.");
 					return;
 				} else {
-					JOptionPane.showMessageDialog(Main.main, "Unknown file extension: "+extension);
+					JOptionPane.showMessageDialog(Main.main, "Unknown file extension: "+fn.substring(filename.getName().lastIndexOf('.')+1));
 					return;
 				}
-				layer = new OsmDataLayer(dataSet, "Data Layer");
+				layer = new OsmDataLayer(dataSet, "Data Layer", true);
 			}
 			
@@ -95,5 +95,5 @@
 		} catch (IOException x) {
 			x.printStackTrace();
-			JOptionPane.showMessageDialog(Main.main, "Could not read '"+filename.getName()+"'\n"+x.getMessage());
+			JOptionPane.showMessageDialog(Main.main, "Could not read '"+fn+"'\n"+x.getMessage());
 		}
 	}
@@ -103,8 +103,8 @@
 	 * user, if unsure.
 	 */
-	private boolean asRawData(String extension) {
-		if (extension.equals("csv") || extension.equals("txt"))
+	private boolean asRawData(String fn) {
+		if (ExtensionFileFilter.filters[ExtensionFileFilter.CSV].acceptName(fn))
 			return true;
-		if (!extension.equals("gpx"))
+		if (!ExtensionFileFilter.filters[ExtensionFileFilter.GPX].acceptName(fn))
 			return false;
 		return JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(
Index: /src/org/openstreetmap/josm/actions/SaveAction.java
===================================================================
--- /src/org/openstreetmap/josm/actions/SaveAction.java	(revision 50)
+++ /src/org/openstreetmap/josm/actions/SaveAction.java	(revision 51)
@@ -11,4 +11,5 @@
 import javax.swing.JOptionPane;
 import javax.swing.KeyStroke;
+import javax.swing.filechooser.FileFilter;
 
 import org.openstreetmap.josm.Main;
@@ -51,11 +52,18 @@
 
 		try {
-			String fn = file.getName();
+			String fn = file.getPath();
+			if (fn.indexOf('.') == -1) {
+				FileFilter ff = fc.getFileFilter();
+				if (ff instanceof ExtensionFileFilter) {
+					fn = fn + "." + ((ExtensionFileFilter)ff).defaultExtension;
+					file = new File(fn);
+				}
+			}
 			FileWriter fileWriter;
-			if (fn.endsWith(".gpx"))
+			if (ExtensionFileFilter.filters[ExtensionFileFilter.GPX].acceptName(fn))
 				new GpxWriter(fileWriter = new FileWriter(file), Main.main.ds).output();
-			else if (fn.endsWith(".xml") || fn.endsWith(".osm"))
+			else if (ExtensionFileFilter.filters[ExtensionFileFilter.OSM].acceptName(fn))
 				new OsmWriter(fileWriter = new FileWriter(file), Main.main.ds).output();
-			else if (fn.endsWith(".txt") || fn.endsWith(".csv")) {
+			else if (ExtensionFileFilter.filters[ExtensionFileFilter.CSV].acceptName(fn)) {
 				JOptionPane.showMessageDialog(Main.main, "CSV output not supported yet.");
 				return;
@@ -65,4 +73,5 @@
 			}
 			fileWriter.close();
+			Main.main.getMapFrame().mapView.editLayer().cleanData(false, false);
 		} catch (IOException e) {
 			e.printStackTrace();
Index: /src/org/openstreetmap/josm/actions/UploadAction.java
===================================================================
--- /src/org/openstreetmap/josm/actions/UploadAction.java	(revision 50)
+++ /src/org/openstreetmap/josm/actions/UploadAction.java	(revision 51)
@@ -39,7 +39,7 @@
 
 	public void actionPerformed(ActionEvent e) {
-		Collection<OsmPrimitive> add = new LinkedList<OsmPrimitive>();
-		Collection<OsmPrimitive> update = new LinkedList<OsmPrimitive>();
-		Collection<OsmPrimitive> delete = new LinkedList<OsmPrimitive>();
+		final Collection<OsmPrimitive> add = new LinkedList<OsmPrimitive>();
+		final Collection<OsmPrimitive> update = new LinkedList<OsmPrimitive>();
+		final Collection<OsmPrimitive> delete = new LinkedList<OsmPrimitive>();
 		boolean acceptedTracks = false;
 		for (OsmPrimitive osm : Main.main.ds.allPrimitives()) {
@@ -84,9 +84,7 @@
 					JOptionPane.showMessageDialog(Main.main, x.getMessage());
 				}
+				Main.main.getMapFrame().mapView.editLayer().cleanData(true, !add.isEmpty());
 			}
 		}).start();
-		
-		// finished without errors -> clean dataset
-		Main.main.getMapFrame().mapView.editLayer().cleanData();
 	}
 	
Index: /src/org/openstreetmap/josm/data/projection/Epsg4263.java
===================================================================
--- /src/org/openstreetmap/josm/data/projection/Epsg4263.java	(revision 50)
+++ /src/org/openstreetmap/josm/data/projection/Epsg4263.java	(revision 51)
@@ -16,6 +16,6 @@
 
 	public void xy2latlon(GeoPoint p) {
-		p.lat = p.y;
-		p.lon = p.x;
+		p.lat = Math.round(p.y*MAX_SERVER_PRECISION)/MAX_SERVER_PRECISION;
+		p.lon = Math.round(p.x*MAX_SERVER_PRECISION)/MAX_SERVER_PRECISION;
 	}
 
Index: /src/org/openstreetmap/josm/data/projection/Mercator.java
===================================================================
--- /src/org/openstreetmap/josm/data/projection/Mercator.java	(revision 50)
+++ /src/org/openstreetmap/josm/data/projection/Mercator.java	(revision 51)
@@ -22,4 +22,7 @@
 		p.lon = p.x*180/Math.PI;
 		p.lat = Math.atan(Math.sinh(p.y))*180/Math.PI;
+		// round values to maximum server precision
+		p.lon = Math.round(p.lon*MAX_SERVER_PRECISION)/MAX_SERVER_PRECISION;
+		p.lat = Math.round(p.lat*MAX_SERVER_PRECISION)/MAX_SERVER_PRECISION;
 	}
 
Index: /src/org/openstreetmap/josm/data/projection/Projection.java
===================================================================
--- /src/org/openstreetmap/josm/data/projection/Projection.java	(revision 50)
+++ /src/org/openstreetmap/josm/data/projection/Projection.java	(revision 51)
@@ -13,4 +13,5 @@
 	public static double MAX_LAT = 85;
 	public static double MAX_LON = 180;
+	public static final double MAX_SERVER_PRECISION = 1e13;
 	
 	/**
@@ -28,7 +29,4 @@
 	void xy2latlon(GeoPoint p);
 
-	
-	// description functions
-	
 	/**
 	 * Describe the projection converter in one or two words.
Index: /src/org/openstreetmap/josm/gui/MapStatus.java
===================================================================
--- /src/org/openstreetmap/josm/gui/MapStatus.java	(revision 50)
+++ /src/org/openstreetmap/josm/gui/MapStatus.java	(revision 51)
@@ -15,4 +15,5 @@
 import java.beans.PropertyChangeListener;
 import java.util.Collection;
+import java.util.ConcurrentModificationException;
 import java.util.Map.Entry;
 
@@ -107,7 +108,15 @@
 				osmStatus = osms;
 				oldModifiers = ms.modifiers;
-				
-				// Set the text label in the bottom status bar
-				OsmPrimitive osmNearest = mv.getNearest(ms.mousePos, (ms.modifiers & MouseEvent.ALT_DOWN_MASK) != 0);
+
+				// This try/catch is a hack to stop the flooding bug reports about this.
+				// The exception needed to handle with in the first place, means that this
+				// access to the data need to be restarted, if the main thread modifies 
+				// the data.
+				OsmPrimitive osmNearest = null;
+				try {
+					// Set the text label in the bottom status bar
+					osmNearest = mv.getNearest(ms.mousePos, (ms.modifiers & MouseEvent.ALT_DOWN_MASK) != 0);
+				} catch (ConcurrentModificationException x) {
+				}
 				if (osmNearest != null) {
 					SelectionComponentVisitor visitor = new SelectionComponentVisitor();
Index: /src/org/openstreetmap/josm/gui/MapView.java
===================================================================
--- /src/org/openstreetmap/josm/gui/MapView.java	(revision 50)
+++ /src/org/openstreetmap/josm/gui/MapView.java	(revision 51)
@@ -216,5 +216,5 @@
 			if (h < 20)
 				h = 20;
-			
+
 			Bounds bounds = null;
 			for (Layer l : layers) {
@@ -309,5 +309,5 @@
 	public OsmDataLayer editLayer() {
 		if (editLayer == null)
-			addLayer(new OsmDataLayer(new DataSet(), "unnamed"));
+			addLayer(new OsmDataLayer(new DataSet(), "unnamed", false));
 		return editLayer;
 	}
Index: /src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
===================================================================
--- /src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(revision 50)
+++ /src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(revision 51)
@@ -50,4 +50,13 @@
 	private boolean modified = false;
 	/**
+	 * Whether the data was modified due an upload of the data to the server.
+	 */
+	public boolean uploadedModified = false;
+	/**
+	 * Whether the data (or pieces of the data) was loaded from disk rather than from
+	 * the server directly. This affects the modified state.
+	 */
+	private boolean fromDisk = false;
+	/**
 	 * All commands that were made on the dataset.
 	 */
@@ -62,11 +71,13 @@
 	 */
 	LinkedList<ModifiedChangedListener> listener;
+
 	
 	/**
 	 * Construct a OsmDataLayer.
 	 */
-	public OsmDataLayer(DataSet data, String name) {
+	public OsmDataLayer(DataSet data, String name, boolean fromDisk) {
 		super(name);
 		this.data = data;
+		this.fromDisk = fromDisk;
 		Main.pref.addPropertyChangeListener(new PropertyChangeListener() {
 			public void propertyChange(PropertyChangeEvent evt) {
@@ -186,5 +197,5 @@
 		Main.main.redoAction.setEnabled(true);
 		if (commands.isEmpty())
-			setModified(false);
+			setModified(uploadedModified);
 	}
 	/**
@@ -200,4 +211,5 @@
 		Main.main.undoAction.setEnabled(true);
 		Main.main.redoAction.setEnabled(!redoCommands.isEmpty());
+		setModified(true);
 	}
 
@@ -206,19 +218,40 @@
 	 * really deleting all deleted objects and reset the modified flags. This is done
 	 * after a successfull upload.
-	 */
-	public void cleanData() {
+	 * @param uploaded <code>true</code>, if the data was uploaded, false if saved to disk
+	 * @param dataAdded <code>true</code>, if data was added during the upload process.
+	 */
+	public void cleanData(boolean uploaded, boolean dataAdded) {
 		redoCommands.clear();
 		commands.clear();
-		for (Iterator<Node> it = data.nodes.iterator(); it.hasNext();)
-			cleanIterator(it);
-		for (Iterator<LineSegment> it = data.lineSegments.iterator(); it.hasNext();)
-			cleanIterator(it);
-		for (Iterator<Track> it = data.tracks.iterator(); it.hasNext();)
-			cleanIterator(it);
-		
-		// not modified anymore, since either everything reverted to file state or 
-		// everything uploaded properly.		
-		setModified(false); 
-		
+		
+		// if uploaded, clean the modified flags as well
+		if (uploaded) {
+			for (Iterator<Node> it = data.nodes.iterator(); it.hasNext();)
+				cleanModifiedFlag(it);
+			for (Iterator<LineSegment> it = data.lineSegments.iterator(); it.hasNext();)
+				cleanModifiedFlag(it);
+			for (Iterator<Track> it = data.tracks.iterator(); it.hasNext();)
+				cleanModifiedFlag(it);
+		}
+		
+		// update the modified flag
+		
+		if (fromDisk && uploaded && !dataAdded)
+			return; // do nothing when uploading non-harmful changes.
+		
+		// modified if server changed the data (esp. the id).
+		uploadedModified = fromDisk && uploaded && dataAdded;
+		setModified(uploadedModified);
+		//TODO: Replace with listener scheme
+		Main.main.undoAction.setEnabled(false);
+		Main.main.redoAction.setEnabled(false);
+	}
+
+	private void cleanModifiedFlag(Iterator<? extends OsmPrimitive> it) {
+		OsmPrimitive osm = it.next();
+		osm.modified = false;
+		osm.modifiedProperties = false;
+		if (osm.isDeleted())
+			it.remove();
 	}
 
@@ -246,12 +279,4 @@
 	}
 
-	private void cleanIterator(Iterator<? extends OsmPrimitive> it) {
-		OsmPrimitive osm = it.next();
-		osm.modified = false;
-		osm.modifiedProperties = false;
-		if (osm.isDeleted())
-			it.remove();
-	}
-
 	/**
 	 * @return The number of not-deleted primitives in the list.
