source: josm/trunk/src/org/openstreetmap/josm/actions/OpenLocationAction.java@ 7771

Last change on this file since 7771 was 7749, checked in by bastiK, 9 years ago

remotecontrol /import: only allow whitelisted download tasks to be called from remotecontrol

Turned off import of session files for now.
I think it is not really an issue at the moment but as new features are added,
this may accidentally get overlooked.
E.g. any javascript execution with rhino engine as we currently do for loading of
preference snippets is a no-go.

In order to enable remotecontrol for a plugin download-task, override the method
isSafeForRemotecontrolRequests() in AbstractDownloadTask or derive from a
class that is already whitelisted (e.g. DownloadOsmTask).

  • Property svn:eol-style set to native
File size: 8.8 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.actions;
3
4import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
5import static org.openstreetmap.josm.tools.I18n.tr;
6
7import java.awt.GridBagConstraints;
8import java.awt.GridBagLayout;
9import java.awt.event.ActionEvent;
10import java.awt.event.KeyEvent;
11import java.util.ArrayList;
12import java.util.Collection;
13import java.util.Collections;
14import java.util.LinkedList;
15import java.util.List;
16import java.util.concurrent.Future;
17
18import javax.swing.JCheckBox;
19import javax.swing.JLabel;
20import javax.swing.JOptionPane;
21import javax.swing.JPanel;
22
23import org.openstreetmap.josm.Main;
24import org.openstreetmap.josm.actions.downloadtasks.DownloadGpsTask;
25import org.openstreetmap.josm.actions.downloadtasks.DownloadNotesTask;
26import org.openstreetmap.josm.actions.downloadtasks.DownloadOsmChangeCompressedTask;
27import org.openstreetmap.josm.actions.downloadtasks.DownloadOsmChangeTask;
28import org.openstreetmap.josm.actions.downloadtasks.DownloadOsmCompressedTask;
29import org.openstreetmap.josm.actions.downloadtasks.DownloadOsmTask;
30import org.openstreetmap.josm.actions.downloadtasks.DownloadOsmUrlTask;
31import org.openstreetmap.josm.actions.downloadtasks.DownloadSessionTask;
32import org.openstreetmap.josm.actions.downloadtasks.DownloadTask;
33import org.openstreetmap.josm.actions.downloadtasks.PostDownloadHandler;
34import org.openstreetmap.josm.gui.ExtendedDialog;
35import org.openstreetmap.josm.gui.HelpAwareOptionPane;
36import org.openstreetmap.josm.gui.help.HelpUtil;
37import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor;
38import org.openstreetmap.josm.gui.widgets.HistoryComboBox;
39import org.openstreetmap.josm.tools.Shortcut;
40import org.openstreetmap.josm.tools.Utils;
41
42/**
43 * Open an URL input dialog and load data from the given URL.
44 *
45 * @author imi
46 */
47public class OpenLocationAction extends JosmAction {
48
49 protected final List<Class<? extends DownloadTask>> downloadTasks;
50
51 /**
52 * Create an open action. The name is "Open a file".
53 */
54 public OpenLocationAction() {
55 /* I18N: Command to download a specific location/URL */
56 super(tr("Open Location..."), "openlocation", tr("Open an URL."),
57 Shortcut.registerShortcut("system:open_location", tr("File: {0}", tr("Open Location...")), KeyEvent.VK_L, Shortcut.CTRL), true);
58 putValue("help", ht("/Action/OpenLocation"));
59 this.downloadTasks = new ArrayList<>();
60 addDownloadTaskClass(DownloadOsmTask.class);
61 addDownloadTaskClass(DownloadGpsTask.class);
62 addDownloadTaskClass(DownloadNotesTask.class);
63 addDownloadTaskClass(DownloadOsmChangeTask.class);
64 addDownloadTaskClass(DownloadOsmUrlTask.class);
65 addDownloadTaskClass(DownloadOsmCompressedTask.class);
66 addDownloadTaskClass(DownloadOsmChangeCompressedTask.class);
67 addDownloadTaskClass(DownloadSessionTask.class);
68 }
69
70 /**
71 * Restore the current history from the preferences
72 *
73 * @param cbHistory
74 */
75 protected void restoreUploadAddressHistory(HistoryComboBox cbHistory) {
76 List<String> cmtHistory = new LinkedList<>(Main.pref.getCollection(getClass().getName() + ".uploadAddressHistory", new LinkedList<String>()));
77 // we have to reverse the history, because ComboBoxHistory will reverse it again in addElement()
78 //
79 Collections.reverse(cmtHistory);
80 cbHistory.setPossibleItems(cmtHistory);
81 }
82
83 /**
84 * Remind the current history in the preferences
85 * @param cbHistory
86 */
87 protected void remindUploadAddressHistory(HistoryComboBox cbHistory) {
88 cbHistory.addCurrentItemToHistory();
89 Main.pref.putCollection(getClass().getName() + ".uploadAddressHistory", cbHistory.getHistory());
90 }
91
92 @Override
93 public void actionPerformed(ActionEvent e) {
94
95 JCheckBox layer = new JCheckBox(tr("Separate Layer"));
96 layer.setToolTipText(tr("Select if the data should be downloaded into a new layer"));
97 layer.setSelected(Main.pref.getBoolean("download.newlayer"));
98 JPanel all = new JPanel(new GridBagLayout());
99 GridBagConstraints gc = new GridBagConstraints();
100 gc.fill = GridBagConstraints.HORIZONTAL;
101 gc.weightx = 1.0;
102 gc.anchor = GridBagConstraints.FIRST_LINE_START;
103 all.add(new JLabel(tr("Enter URL to download:")), gc);
104 HistoryComboBox uploadAddresses = new HistoryComboBox();
105 uploadAddresses.setToolTipText(tr("Enter an URL from where data should be downloaded"));
106 restoreUploadAddressHistory(uploadAddresses);
107 gc.gridy = 1;
108 all.add(uploadAddresses, gc);
109 gc.gridy = 2;
110 gc.fill = GridBagConstraints.BOTH;
111 gc.weighty = 1.0;
112 all.add(layer, gc);
113 ExtendedDialog dialog = new ExtendedDialog(Main.parent,
114 tr("Download Location"),
115 new String[] {tr("Download URL"), tr("Cancel")}
116 );
117 dialog.setContent(all, false /* don't embedded content in JScrollpane */);
118 dialog.setButtonIcons(new String[] {"download.png", "cancel.png"});
119 dialog.setToolTipTexts(new String[] {
120 tr("Start downloading data"),
121 tr("Close dialog and cancel downloading")
122 });
123 dialog.configureContextsensitiveHelp("/Action/OpenLocation", true /* show help button */);
124 dialog.showDialog();
125 if (dialog.getValue() != 1) return;
126 remindUploadAddressHistory(uploadAddresses);
127 openUrl(layer.isSelected(), Utils.strip(uploadAddresses.getText()));
128 }
129
130 /**
131 * Replies the list of download tasks accepting the given url.
132 * @param url The URL to open
133 * @param isRemotecontrol True if download request comes from remotecontrol.
134 * @return The list of download tasks accepting the given url.
135 * @since 5691
136 */
137 public Collection<DownloadTask> findDownloadTasks(final String url, boolean isRemotecontrol) {
138 List<DownloadTask> result = new ArrayList<>();
139 for (Class<? extends DownloadTask> taskClass : downloadTasks) {
140 if (taskClass != null) {
141 try {
142 DownloadTask task = taskClass.getConstructor().newInstance();
143 if (task.acceptsUrl(url, isRemotecontrol)) {
144 result.add(task);
145 }
146 } catch (Exception e) {
147 Main.error(e);
148 }
149 }
150 }
151 return result;
152 }
153
154 /**
155 * Summarizes acceptable urls for error message purposes.
156 * @return The HTML message to be displayed
157 * @since 6031
158 */
159 public String findSummaryDocumentation() {
160 StringBuilder result = new StringBuilder("<table>");
161 for (Class<? extends DownloadTask> taskClass : downloadTasks) {
162 if (taskClass != null) {
163 try {
164 DownloadTask task = taskClass.getConstructor().newInstance();
165 result.append(task.acceptsDocumentationSummary());
166 } catch (Exception e) {
167 Main.error(e);
168 }
169 }
170 }
171 result.append("</table>");
172 return result.toString();
173 }
174
175 /**
176 * Open the given URL.
177 * @param new_layer true if the URL needs to be opened in a new layer, false otherwise
178 * @param url The URL to open
179 */
180 public void openUrl(boolean new_layer, final String url) {
181 PleaseWaitProgressMonitor monitor = new PleaseWaitProgressMonitor(tr("Download Data"));
182 Collection<DownloadTask> tasks = findDownloadTasks(url, false);
183 DownloadTask task = null;
184 Future<?> future = null;
185 if (!tasks.isEmpty()) {
186 // TODO: handle multiple suitable tasks ?
187 try {
188 task = tasks.iterator().next();
189 future = task.loadUrl(new_layer, url, monitor);
190 } catch (IllegalArgumentException e) {
191 Main.error(e);
192 }
193 }
194 if (future != null) {
195 Main.worker.submit(new PostDownloadHandler(task, future));
196 } else {
197 final String details = findSummaryDocumentation(); // Explain what patterns are supported
198 HelpAwareOptionPane.showMessageDialogInEDT(Main.parent, "<html><p>" + tr(
199 "Cannot open URL ''{0}''<br>The following download tasks accept the URL patterns shown:<br>{1}",
200 url, details) + "</p></html>", tr("Download Location"), JOptionPane.ERROR_MESSAGE, HelpUtil.ht("/Action/OpenLocation"));
201 }
202 }
203
204 /**
205 * Adds a new download task to the supported ones.
206 * @param taskClass The new download task to add
207 * @return <tt>true</tt> (as specified by {@link Collection#add})
208 */
209 public final boolean addDownloadTaskClass(Class<? extends DownloadTask> taskClass) {
210 return this.downloadTasks.add(taskClass);
211 }
212}
Note: See TracBrowser for help on using the repository browser.