Index: /applications/editors/josm/plugins/mirrored_download/src/mirrored_download/MirroredDownloadPlugin.java
===================================================================
--- /applications/editors/josm/plugins/mirrored_download/src/mirrored_download/MirroredDownloadPlugin.java	(revision 29642)
+++ /applications/editors/josm/plugins/mirrored_download/src/mirrored_download/MirroredDownloadPlugin.java	(revision 29643)
@@ -11,4 +11,5 @@
     public MirroredDownloadPlugin(PluginInformation info) {
         super(info);
+        MainMenu.addAfter(Main.main.menu.fileMenu, new OverpassDownloadAction(), false, Main.main.menu.download);
         MainMenu.addAfter(Main.main.menu.fileMenu, new MirroredDownloadAction(), false, Main.main.menu.download);
         MainMenu.add(Main.main.menu.editMenu, new UrlSelectionAction());
Index: /applications/editors/josm/plugins/mirrored_download/src/mirrored_download/OverpassDownloadAction.java
===================================================================
--- /applications/editors/josm/plugins/mirrored_download/src/mirrored_download/OverpassDownloadAction.java	(revision 29643)
+++ /applications/editors/josm/plugins/mirrored_download/src/mirrored_download/OverpassDownloadAction.java	(revision 29643)
@@ -0,0 +1,159 @@
+// License: GPL. For details, see LICENSE file.
+package mirrored_download;
+
+import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.Component;
+import java.awt.GridBagConstraints;
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyEvent;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.util.LinkedList;
+import java.util.concurrent.Future;
+import java.util.regex.Pattern;
+
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.text.JTextComponent;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.JosmAction;
+import org.openstreetmap.josm.actions.downloadtasks.DownloadOsmTask;
+import org.openstreetmap.josm.actions.downloadtasks.PostDownloadHandler;
+import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.DataSource;
+import org.openstreetmap.josm.gui.download.DownloadDialog;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
+import org.openstreetmap.josm.gui.widgets.AbstractTextComponentValidator;
+import org.openstreetmap.josm.io.BoundingBoxDownloader;
+import org.openstreetmap.josm.io.OsmTransferException;
+import org.openstreetmap.josm.tools.GBC;
+import org.openstreetmap.josm.tools.Shortcut;
+
+public class OverpassDownloadAction extends JosmAction {
+
+    public OverpassDownloadAction() {
+        super(tr("Download from Overpass API ..."), "download_mirror", tr("Download map data from Overpass API server."),
+                Shortcut.registerShortcut("overpass:download", tr("File: {0}", tr("Download from Overpass API ...")), KeyEvent.VK_DOWN, Shortcut.ALT_SHIFT),
+                true, "overpassdownload/download", true);
+        putValue("help", ht("/Action/OverpassDownload"));
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent e) {
+        OverpassDownloadDialog dialog = OverpassDownloadDialog.getInstance();
+        dialog.restoreSettings();
+        dialog.setVisible(true);
+        if (!dialog.isCanceled()) {
+            dialog.rememberSettings();
+            Bounds area = dialog.getSelectedDownloadArea();
+            DownloadOsmTask task = new DownloadOsmTask();
+            Future<?> future = task.download(
+                    new OverpassDownloadReader(area, dialog.getOverpassQuery()),
+                    dialog.isNewLayerRequired(), area, null);
+            Main.worker.submit(new PostDownloadHandler(task, future));
+        }
+    }
+
+    static class OverpassDownloadDialog extends DownloadDialog {
+
+        protected JTextArea overpassQuery;
+        private static OverpassDownloadDialog instance;
+
+        private OverpassDownloadDialog(Component parent) {
+            super(parent);
+            cbDownloadOsmData.setEnabled(false);
+            cbDownloadGpxData.setEnabled(false);
+            cbStartup.setEnabled(false);
+        }
+
+        static public OverpassDownloadDialog getInstance() {
+            if (instance == null) {
+                instance = new OverpassDownloadDialog(Main.parent);
+            }
+            return instance;
+        }
+
+        @Override
+        protected void buildMainPanelAboveDownloadSelections(JPanel pnl) {
+            overpassQuery = new JTextArea("[timeout:15];", 8, 80);
+            pnl.add(new JLabel(tr("Overpass query: ")), GBC.std().insets(5, 5, 5, 5));
+            pnl.add(new JScrollPane(overpassQuery), GBC.eol().fill(GridBagConstraints.BOTH));
+        }
+
+        public String getOverpassQuery() {
+            return overpassQuery.getText();
+        }
+    }
+
+    static class OverpassDownloadReader extends BoundingBoxDownloader {
+
+        final String overpassQuery;
+
+        public OverpassDownloadReader(Bounds downloadArea, String overpassQuery) {
+            super(downloadArea);
+            this.overpassQuery = overpassQuery.trim();
+        }
+
+        @Override
+        protected String getBaseUrl() {
+            String url = MirroredDownloadPlugin.getDownloadUrl();
+            System.out.println(url.substring(url.length() - 5, url.length()));
+            if ("xapi?".equals(url.substring(url.length() - 5, url.length())))
+            {
+                System.out.println(url.substring(0, url.length() - 5));
+                return url.substring(0, url.length() - 5);
+            }
+            else
+                return url;
+        }
+
+        @Override
+        protected String getRequestForBbox(double lon1, double lat1, double lon2, double lat2) {
+            if (overpassQuery.isEmpty())
+                return "xapi?" + super.getRequestForBbox(lon1, lat1, lon2, lat2);
+            else
+            {
+                String url = "interpreter?data=" + overpassQuery + "&bbox=" + lon1 + "," + lat1 + "," + lon2 + "," + lat2;
+                    
+                try
+                {
+                    url = "interpreter?data=" + URLEncoder.encode(overpassQuery, "UTF-8") + "&bbox=" + lon1 + "," + lat1 + "," + lon2 + "," + lat2;
+                }
+                catch (UnsupportedEncodingException e) {}
+                return url;
+            }
+        }
+
+        @Override
+        public DataSet parseOsm(ProgressMonitor progressMonitor) throws OsmTransferException {
+
+            DataSet ds = super.parseOsm(progressMonitor);
+
+            // add bounds if necessary (note that Overpass API does not return bounds in the response XML)
+            if (ds != null && ds.dataSources.isEmpty()) {
+                if (crosses180th) {
+                    Bounds bounds = new Bounds(lat1, lon1, lat2, 180.0);
+                    DataSource src = new DataSource(bounds, MirroredDownloadPlugin.getDownloadUrl());
+                    ds.dataSources.add(src);
+
+                    bounds = new Bounds(lat1, -180.0, lat2, lon2);
+                    src = new DataSource(bounds, MirroredDownloadPlugin.getDownloadUrl());
+                    ds.dataSources.add(src);
+                } else {
+                    Bounds bounds = new Bounds(lat1, lon1, lat2, lon2);
+                    DataSource src = new DataSource(bounds, MirroredDownloadPlugin.getDownloadUrl());
+                    ds.dataSources.add(src);
+                }
+            }
+
+            return ds;
+        }
+    }
+}
