From 2d5cb003305106f8663042b6dff547c0edefc1b6 Mon Sep 17 00:00:00 2001
From: George Hopkins <george-hopkins@null.net>
Date: Mon, 25 Dec 2017 17:29:59 +0100
Subject: [PATCH] Remember confirmations of command actions

---
 .../io/remotecontrol/handler/RequestHandler.java   | 41 +++++++++++++++++++---
 1 file changed, 36 insertions(+), 5 deletions(-)

diff --git a/src/org/openstreetmap/josm/io/remotecontrol/handler/RequestHandler.java b/src/org/openstreetmap/josm/io/remotecontrol/handler/RequestHandler.java
index 6849dd2..7183e35 100644
--- a/src/org/openstreetmap/josm/io/remotecontrol/handler/RequestHandler.java
+++ b/src/org/openstreetmap/josm/io/remotecontrol/handler/RequestHandler.java
@@ -21,6 +21,7 @@ import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.io.remotecontrol.PermissionPrefWithDefault;
 import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.Logging;
+import org.openstreetmap.josm.tools.Pair;
 import org.openstreetmap.josm.tools.Utils;
 
 /**
@@ -35,6 +36,9 @@ public abstract class RequestHandler {
     public static final String loadInNewLayerKey = "remotecontrol.new-layer";
     public static final boolean loadInNewLayerDefault = false;
 
+    /** past confirmations */
+    protected static PermissionCache PERMISSIONS = new PermissionCache();
+
     /** The GET request arguments */
     protected Map<String, String> args;
 
@@ -154,6 +158,14 @@ public abstract class RequestHandler {
             throw new RequestHandlerForbiddenException(err);
         }
 
+        /*
+         * Did the user confirm this action previously?
+         * If yes, skip the global confirmation dialog.
+         */
+        if (PERMISSIONS.isAllowed(myCommand, sender)) {
+            return;
+        }
+
         /* Does the user want to confirm everything?
          * If yes, display specific confirmation message.
          */
@@ -166,11 +178,14 @@ public abstract class RequestHandler {
             if (label.getPreferredSize().width > maxWidth) {
                 label.setText(message.replaceFirst("<div>", "<div style=\"width:" + maxWidth + "px;\">"));
             }
-            if (JOptionPane.showConfirmDialog(Main.parent, label,
-                tr("Confirm Remote Control action"),
-                JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION) {
-                    String err = MessageFormat.format("RemoteControl: ''{0}'' forbidden by user''s choice", myCommand);
-                    throw new RequestHandlerForbiddenException(err);
+            Object[] choices = new Object[] { tr("Yes, always"), tr("Yes, once"), tr("No") };
+            int choice = JOptionPane.showOptionDialog(Main.parent, label, tr("Confirm Remote Control action"),
+                    JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, choices, choices[1]);
+            if (choice != JOptionPane.YES_OPTION && choice != JOptionPane.NO_OPTION) { // Yes/no refer to always/once
+                String err = MessageFormat.format("RemoteControl: ''{0}'' forbidden by user''s choice", myCommand);
+                throw new RequestHandlerForbiddenException(err);
+            } else if (choice == JOptionPane.YES_OPTION) {
+                PERMISSIONS.allow(myCommand, sender);
             }
         }
     }
@@ -390,4 +405,20 @@ public abstract class RequestHandler {
             this.args = args;
         }
     }
+
+    public static class PermissionCache {
+        private final HashSet<Pair<String, String>> allowed = new HashSet<Pair<String, String>>();
+
+        public void allow(String command, String sender) {
+            allowed.add(Pair.create(command, sender));
+        }
+
+        public boolean isAllowed(String command, String sender) {
+            return allowed.contains(Pair.create(command, sender));
+        }
+
+        public void clear() {
+            allowed.clear();
+        }
+    }
 }
-- 
2.7.4

