diff --git a/docker/chrome/chrome.yaml b/docker/chrome/chrome.yaml
index 37d8227151a..c9c6369c4a2 100644
--- a/docker/chrome/chrome.yaml
+++ b/docker/chrome/chrome.yaml
@@ -16,10 +16,10 @@ jobs:
tests:
- name: "At least one URL found"
onFail: "WARN"
- statistic: "spiderAjax.urls.added"
+ statistic: "stats.client.spider.urls"
site: ""
operator: ">="
value: 1
type: "stats"
- name: "spiderAjax"
- type: "spiderAjax"
\ No newline at end of file
+ name: "spiderClient"
+ type: "spiderClient"
\ No newline at end of file
diff --git a/zap/src/main/java/org/parosproxy/paros/extension/AbstractDialog.java b/zap/src/main/java/org/parosproxy/paros/extension/AbstractDialog.java
index b145e7267df..f6bf326d6c3 100644
--- a/zap/src/main/java/org/parosproxy/paros/extension/AbstractDialog.java
+++ b/zap/src/main/java/org/parosproxy/paros/extension/AbstractDialog.java
@@ -36,9 +36,11 @@
import java.awt.HeadlessException;
import java.awt.Window;
import java.awt.event.ActionEvent;
+import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.WindowEvent;
import javax.swing.AbstractAction;
+import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.KeyStroke;
@@ -54,6 +56,8 @@ public abstract class AbstractDialog extends JDialog {
protected AbstractDialog thisDialog = null;
+ private JButton defaultButton;
+
/**
* Constructs an {@code AbstractDialog} with no owner and not modal.
*
@@ -114,6 +118,39 @@ public void actionPerformed(ActionEvent e) {
};
getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(escape, "ESCAPE");
getRootPane().getActionMap().put("ESCAPE", escapeAction);
+
+ // Handle ctrl+enter to trigger the dialog's default button, regardless of which
+ // component (e.g. a text area or table) currently has focus.
+ KeyStroke ctrlEnter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.CTRL_DOWN_MASK);
+ AbstractAction ctrlEnterAction =
+ new AbstractAction() {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ JButton button = getRootPane().getDefaultButton();
+ if (button != null && button.isEnabled()) {
+ button.doClick();
+ }
+ }
+ };
+ getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(ctrlEnter, "CTRL_ENTER");
+ getRootPane().getActionMap().put("CTRL_ENTER", ctrlEnterAction);
+ }
+
+ /**
+ * Sets the button to use as this dialog's main action (e.g. OK, Apply, Save), giving it the
+ * current look and feel's "default button" highlight and binding it to Ctrl+Enter.
+ *
+ *
Disposing a dialog clears its root pane's default button (see {@link
+ * JButton#removeNotify()}), so this is re-applied every time the dialog is shown, which matters
+ * for dialogs that are constructed once and reused across multiple show/dispose cycles.
+ *
+ * @param button the button to use as this dialog's main action, or {@code null} for none.
+ */
+ protected void setDefaultButton(JButton button) {
+ this.defaultButton = button;
+ getRootPane().setDefaultButton(button);
}
/**
@@ -132,6 +169,7 @@ public void setVisible(boolean show) {
== 0) {
centreDialog();
}
+ getRootPane().setDefaultButton(defaultButton);
}
super.setVisible(show);
}
diff --git a/zap/src/main/java/org/parosproxy/paros/extension/history/ExtensionHistory.java b/zap/src/main/java/org/parosproxy/paros/extension/history/ExtensionHistory.java
index 338bac3cee4..072e055aa0c 100644
--- a/zap/src/main/java/org/parosproxy/paros/extension/history/ExtensionHistory.java
+++ b/zap/src/main/java/org/parosproxy/paros/extension/history/ExtensionHistory.java
@@ -942,6 +942,7 @@ public void purgeHistory(List hrefs) {
" ",
removeWithoutConfirmationCheckBox
};
+ String confirmButtonLabel = Constant.messages.getString("history.purge.confirm");
int result =
JOptionPane.showOptionDialog(
View.getSingleton().getMainFrame(),
@@ -951,10 +952,10 @@ public void purgeHistory(List hrefs) {
JOptionPane.QUESTION_MESSAGE,
null,
new String[] {
- Constant.messages.getString("history.purge.confirm"),
+ confirmButtonLabel,
Constant.messages.getString("history.purge.cancel")
},
- null);
+ confirmButtonLabel);
if (result != JOptionPane.YES_OPTION) {
return;
}
diff --git a/zap/src/main/java/org/parosproxy/paros/extension/option/OptionsConnectionPanel.java b/zap/src/main/java/org/parosproxy/paros/extension/option/OptionsConnectionPanel.java
index 4cfa5b4463e..cb46e7b50f4 100644
--- a/zap/src/main/java/org/parosproxy/paros/extension/option/OptionsConnectionPanel.java
+++ b/zap/src/main/java/org/parosproxy/paros/extension/option/OptionsConnectionPanel.java
@@ -1002,7 +1002,7 @@ public boolean showRemoveDialogue(DomainMatcher e) {
REMOVE_DIALOG_CONFIRM_BUTTON_LABEL,
REMOVE_DIALOG_CANCEL_BUTTON_LABEL
},
- null);
+ REMOVE_DIALOG_CONFIRM_BUTTON_LABEL);
if (option == JOptionPane.OK_OPTION) {
setRemoveWithoutConfirmation(removeWithoutConfirmationCheckBox.isSelected());
diff --git a/zap/src/main/java/org/parosproxy/paros/view/AbstractParamDialog.java b/zap/src/main/java/org/parosproxy/paros/view/AbstractParamDialog.java
index 0b8c1963f97..4c24bed04bf 100644
--- a/zap/src/main/java/org/parosproxy/paros/view/AbstractParamDialog.java
+++ b/zap/src/main/java/org/parosproxy/paros/view/AbstractParamDialog.java
@@ -177,6 +177,7 @@ private javax.swing.JPanel getJContentPane() {
GridBagConstraints.NONE,
GridBagConstraints.EAST,
new Insets(2, 2, 2, 2)));
+ this.setDefaultButton(getBtnOK());
jContentPane.add(footerPane, LayoutHelper.getGBC(0, 1, 1, 1.0, 0.0));
}
diff --git a/zap/src/main/java/org/parosproxy/paros/view/FindDialog.java b/zap/src/main/java/org/parosproxy/paros/view/FindDialog.java
index 23eea0174b2..9cb943c3044 100644
--- a/zap/src/main/java/org/parosproxy/paros/view/FindDialog.java
+++ b/zap/src/main/java/org/parosproxy/paros/view/FindDialog.java
@@ -134,7 +134,7 @@ private void initialize() {
this.setContentPane(getJPanel());
centreDialog();
txtFind.requestFocus();
- this.getRootPane().setDefaultButton(btnFind);
+ this.setDefaultButton(getBtnFind());
pack();
this.setVisible(true);
}
diff --git a/zap/src/main/java/org/parosproxy/paros/view/SiteMapPanel.java b/zap/src/main/java/org/parosproxy/paros/view/SiteMapPanel.java
index b6e2633f086..81164d355b4 100644
--- a/zap/src/main/java/org/parosproxy/paros/view/SiteMapPanel.java
+++ b/zap/src/main/java/org/parosproxy/paros/view/SiteMapPanel.java
@@ -471,6 +471,8 @@ public void actionPerformed(ActionEvent e) {
" ",
removeWithoutConfirmationCheckBox
};
+ String confirmButtonLabel =
+ Constant.messages.getString("sites.purge.confirm");
int result =
JOptionPane.showOptionDialog(
View.getSingleton().getMainFrame(),
@@ -481,12 +483,11 @@ public void actionPerformed(ActionEvent e) {
JOptionPane.QUESTION_MESSAGE,
null,
new String[] {
- Constant.messages.getString(
- "sites.purge.confirm"),
+ confirmButtonLabel,
Constant.messages.getString(
"sites.purge.cancel")
},
- null);
+ confirmButtonLabel);
if (result != JOptionPane.YES_OPTION) {
return;
}
diff --git a/zap/src/main/java/org/zaproxy/zap/extension/alert/AlertAddDialog.java b/zap/src/main/java/org/zaproxy/zap/extension/alert/AlertAddDialog.java
index e7c3dd372f7..5a14ff8a983 100644
--- a/zap/src/main/java/org/zaproxy/zap/extension/alert/AlertAddDialog.java
+++ b/zap/src/main/java/org/zaproxy/zap/extension/alert/AlertAddDialog.java
@@ -167,6 +167,7 @@ private JPanel getJPanel() {
jPanel.add(jLabel2, gridBagConstraints13);
jPanel.add(getBtnCancel(), gridBagConstraints2);
jPanel.add(getBtnOk(), gridBagConstraints3);
+ this.setDefaultButton(getBtnOk());
}
return jPanel;
}
diff --git a/zap/src/main/java/org/zaproxy/zap/extension/anticsrf/OptionsAntiCsrfPanel.java b/zap/src/main/java/org/zaproxy/zap/extension/anticsrf/OptionsAntiCsrfPanel.java
index 9232e11692d..8786bbc2569 100644
--- a/zap/src/main/java/org/zaproxy/zap/extension/anticsrf/OptionsAntiCsrfPanel.java
+++ b/zap/src/main/java/org/zaproxy/zap/extension/anticsrf/OptionsAntiCsrfPanel.java
@@ -197,7 +197,7 @@ public boolean showRemoveDialogue(AntiCsrfParamToken e) {
REMOVE_DIALOG_CONFIRM_BUTTON_LABEL,
REMOVE_DIALOG_CANCEL_BUTTON_LABEL
},
- null);
+ REMOVE_DIALOG_CONFIRM_BUTTON_LABEL);
if (option == JOptionPane.OK_OPTION) {
setRemoveWithoutConfirmation(removeWithoutConfirmationCheckBox.isSelected());
diff --git a/zap/src/main/java/org/zaproxy/zap/extension/api/ExtensionAPI.java b/zap/src/main/java/org/zaproxy/zap/extension/api/ExtensionAPI.java
index f7397e87725..a49d7f6c62d 100644
--- a/zap/src/main/java/org/zaproxy/zap/extension/api/ExtensionAPI.java
+++ b/zap/src/main/java/org/zaproxy/zap/extension/api/ExtensionAPI.java
@@ -115,7 +115,7 @@ public void actionPerformed(java.awt.event.ActionEvent e) {
new String[] {
confirmButtonLabel, cancelButtonLabel
},
- null);
+ confirmButtonLabel);
if (option != JOptionPane.YES_OPTION) {
return;
diff --git a/zap/src/main/java/org/zaproxy/zap/extension/api/OptionsApiPanel.java b/zap/src/main/java/org/zaproxy/zap/extension/api/OptionsApiPanel.java
index 650f9eb03cc..6a0a2a71c81 100644
--- a/zap/src/main/java/org/zaproxy/zap/extension/api/OptionsApiPanel.java
+++ b/zap/src/main/java/org/zaproxy/zap/extension/api/OptionsApiPanel.java
@@ -479,7 +479,7 @@ public boolean showRemoveDialogue(DomainMatcher e) {
REMOVE_DIALOG_CONFIRM_BUTTON_LABEL,
REMOVE_DIALOG_CANCEL_BUTTON_LABEL
},
- null);
+ REMOVE_DIALOG_CONFIRM_BUTTON_LABEL);
if (option == JOptionPane.OK_OPTION) {
setRemoveWithoutConfirmation(removeWithoutConfirmationCheckBox.isSelected());
diff --git a/zap/src/main/java/org/zaproxy/zap/extension/ascan/OptionsVariantPanel.java b/zap/src/main/java/org/zaproxy/zap/extension/ascan/OptionsVariantPanel.java
index ed2ed7a37cc..d45333bf05d 100644
--- a/zap/src/main/java/org/zaproxy/zap/extension/ascan/OptionsVariantPanel.java
+++ b/zap/src/main/java/org/zaproxy/zap/extension/ascan/OptionsVariantPanel.java
@@ -887,7 +887,7 @@ public boolean showRemoveDialogue(ScannerParamFilter e) {
REMOVE_DIALOG_CONFIRM_BUTTON_LABEL,
REMOVE_DIALOG_CANCEL_BUTTON_LABEL
},
- null);
+ REMOVE_DIALOG_CONFIRM_BUTTON_LABEL);
return (option == JOptionPane.OK_OPTION);
}
diff --git a/zap/src/main/java/org/zaproxy/zap/extension/autoupdate/ManageAddOnsDialog.java b/zap/src/main/java/org/zaproxy/zap/extension/autoupdate/ManageAddOnsDialog.java
index d11e93e3723..286d1cd9dc0 100644
--- a/zap/src/main/java/org/zaproxy/zap/extension/autoupdate/ManageAddOnsDialog.java
+++ b/zap/src/main/java/org/zaproxy/zap/extension/autoupdate/ManageAddOnsDialog.java
@@ -205,6 +205,17 @@ public void actionPerformed(ActionEvent e) {
getRootPane().getActionMap().put("ESCAPE", escapeAction);
}
+ @Override
+ public void setVisible(boolean visible) {
+ if (visible) {
+ // This dialog is created once and reused, and disposing it (as the close buttons do)
+ // clears the root pane's default button (see JButton#removeNotify()), so it must be
+ // re-applied every time the dialog is shown.
+ getRootPane().setDefaultButton(getCheckForUpdatesButton());
+ }
+ super.setVisible(visible);
+ }
+
private JPanel getTopPanel() {
if (topPanel == null) {
topPanel = new JPanel();
@@ -266,6 +277,7 @@ private JPanel getCorePanel(boolean update) {
corePanel.add(new JLabel(this.currentVersion), LayoutHelper.getGBC(0, 0, 1, 0.0D));
corePanel.add(new JLabel(""), LayoutHelper.getGBC(1, 0, 1, 1.0D));
corePanel.add(this.getCheckForUpdatesButton(), LayoutHelper.getGBC(2, 0, 1, 0.0D));
+ getRootPane().setDefaultButton(this.getCheckForUpdatesButton());
refresh = false;
}
} else if (latestInfo != null && this.latestInfo.getZapRelease() != null) {
diff --git a/zap/src/main/java/org/zaproxy/zap/extension/autoupdate/OptionsCheckForUpdatesPanel.java b/zap/src/main/java/org/zaproxy/zap/extension/autoupdate/OptionsCheckForUpdatesPanel.java
index ea787fa0086..af91df7d42a 100644
--- a/zap/src/main/java/org/zaproxy/zap/extension/autoupdate/OptionsCheckForUpdatesPanel.java
+++ b/zap/src/main/java/org/zaproxy/zap/extension/autoupdate/OptionsCheckForUpdatesPanel.java
@@ -444,7 +444,7 @@ public boolean showRemoveDialogue(File f) {
REMOVE_DIALOG_CONFIRM_BUTTON_LABEL,
REMOVE_DIALOG_CANCEL_BUTTON_LABEL
},
- null);
+ REMOVE_DIALOG_CONFIRM_BUTTON_LABEL);
if (option == JOptionPane.OK_OPTION) {
setRemoveWithoutConfirmation(removeWithoutConfirmationCheckBox.isSelected());
diff --git a/zap/src/main/java/org/zaproxy/zap/extension/brk/BreakPanelToolbarFactory.java b/zap/src/main/java/org/zaproxy/zap/extension/brk/BreakPanelToolbarFactory.java
index 127ae829ae4..b2c44209b2c 100644
--- a/zap/src/main/java/org/zaproxy/zap/extension/brk/BreakPanelToolbarFactory.java
+++ b/zap/src/main/java/org/zaproxy/zap/extension/brk/BreakPanelToolbarFactory.java
@@ -254,7 +254,7 @@ private int askForDropConfirmation() {
JOptionPane.QUESTION_MESSAGE,
null,
new String[] {confirmButtonLabel, cancelButtonLabel},
- null);
+ confirmButtonLabel);
if (checkBox.isSelected()) {
breakpointsParams.setConfirmDropMessage(false);
diff --git a/zap/src/main/java/org/zaproxy/zap/extension/custompages/ContextCustomPagePanel.java b/zap/src/main/java/org/zaproxy/zap/extension/custompages/ContextCustomPagePanel.java
index 2a33cb6b1ac..1e86eddd6ba 100644
--- a/zap/src/main/java/org/zaproxy/zap/extension/custompages/ContextCustomPagePanel.java
+++ b/zap/src/main/java/org/zaproxy/zap/extension/custompages/ContextCustomPagePanel.java
@@ -183,7 +183,7 @@ public boolean showRemoveDialogue(CustomPage customPage) {
REMOVE_DIALOG_CONFIRM_BUTTON_LABEL,
REMOVE_DIALOG_CANCEL_BUTTON_LABEL
},
- null);
+ REMOVE_DIALOG_CONFIRM_BUTTON_LABEL);
if (option == JOptionPane.OK_OPTION) {
setRemoveWithoutConfirmation(removeWithoutConfirmationCheckBox.isSelected());
diff --git a/zap/src/main/java/org/zaproxy/zap/extension/globalexcludeurl/OptionsGlobalExcludeURLPanel.java b/zap/src/main/java/org/zaproxy/zap/extension/globalexcludeurl/OptionsGlobalExcludeURLPanel.java
index 5628e81473f..2c874ead360 100644
--- a/zap/src/main/java/org/zaproxy/zap/extension/globalexcludeurl/OptionsGlobalExcludeURLPanel.java
+++ b/zap/src/main/java/org/zaproxy/zap/extension/globalexcludeurl/OptionsGlobalExcludeURLPanel.java
@@ -210,7 +210,7 @@ public boolean showRemoveDialogue(GlobalExcludeURLParamToken e) {
REMOVE_DIALOG_CONFIRM_BUTTON_LABEL,
REMOVE_DIALOG_CANCEL_BUTTON_LABEL
},
- null);
+ REMOVE_DIALOG_CONFIRM_BUTTON_LABEL);
if (option == JOptionPane.OK_OPTION) {
setRemoveWithoutConfirmation(removeWithoutConfirmationCheckBox.isSelected());
diff --git a/zap/src/main/java/org/zaproxy/zap/extension/history/HistoryFilterPlusDialog.java b/zap/src/main/java/org/zaproxy/zap/extension/history/HistoryFilterPlusDialog.java
index ee83abcb03b..94b2cd1afad 100644
--- a/zap/src/main/java/org/zaproxy/zap/extension/history/HistoryFilterPlusDialog.java
+++ b/zap/src/main/java/org/zaproxy/zap/extension/history/HistoryFilterPlusDialog.java
@@ -125,7 +125,7 @@ private void initialize() {
this.setSize(600, 300);
}
centreDialog();
- this.getRootPane().setDefaultButton(btnApply);
+ this.setDefaultButton(getBtnApply());
this.pack();
}
diff --git a/zap/src/main/java/org/zaproxy/zap/extension/history/ManageTagsDialog.java b/zap/src/main/java/org/zaproxy/zap/extension/history/ManageTagsDialog.java
index 0c585470ef1..e158f12d5f0 100644
--- a/zap/src/main/java/org/zaproxy/zap/extension/history/ManageTagsDialog.java
+++ b/zap/src/main/java/org/zaproxy/zap/extension/history/ManageTagsDialog.java
@@ -172,6 +172,7 @@ private JPanel getJPanel() {
jPanel.add(getBtnDelete(), gridBagConstraints31);
jPanel.add(getBtnCancel(), gridBagConstraints40);
jPanel.add(getBtnSave(), gridBagConstraints41);
+ this.setDefaultButton(getBtnSave());
}
return jPanel;
}
diff --git a/zap/src/main/java/org/zaproxy/zap/extension/history/NotesAddDialog.java b/zap/src/main/java/org/zaproxy/zap/extension/history/NotesAddDialog.java
index f8e335fa4cc..503c6583d68 100644
--- a/zap/src/main/java/org/zaproxy/zap/extension/history/NotesAddDialog.java
+++ b/zap/src/main/java/org/zaproxy/zap/extension/history/NotesAddDialog.java
@@ -100,6 +100,8 @@ private void initialize() {
setContentPane(panel);
+ this.setDefaultButton(getBtnOk());
+
this.addWindowListener(
new java.awt.event.WindowAdapter() {
diff --git a/zap/src/main/java/org/zaproxy/zap/extension/history/PopupMenuPurgeSites.java b/zap/src/main/java/org/zaproxy/zap/extension/history/PopupMenuPurgeSites.java
index bdf285416a1..cdeecf9f27d 100644
--- a/zap/src/main/java/org/zaproxy/zap/extension/history/PopupMenuPurgeSites.java
+++ b/zap/src/main/java/org/zaproxy/zap/extension/history/PopupMenuPurgeSites.java
@@ -77,6 +77,7 @@ public void performHistoryReferenceActions(List hrefs) {
" ",
removeWithoutConfirmationCheckBox
};
+ String confirmButtonLabel = Constant.messages.getString("sites.purge.confirm");
int result =
JOptionPane.showOptionDialog(
View.getSingleton().getMainFrame(),
@@ -86,10 +87,10 @@ public void performHistoryReferenceActions(List hrefs) {
JOptionPane.QUESTION_MESSAGE,
null,
new String[] {
- Constant.messages.getString("sites.purge.confirm"),
+ confirmButtonLabel,
Constant.messages.getString("sites.purge.cancel")
},
- null);
+ confirmButtonLabel);
if (result != JOptionPane.YES_OPTION) {
return;
}
diff --git a/zap/src/main/java/org/zaproxy/zap/extension/httpsessions/OptionsHttpSessionsPanel.java b/zap/src/main/java/org/zaproxy/zap/extension/httpsessions/OptionsHttpSessionsPanel.java
index 6255131d5f5..084b6eb61c5 100644
--- a/zap/src/main/java/org/zaproxy/zap/extension/httpsessions/OptionsHttpSessionsPanel.java
+++ b/zap/src/main/java/org/zaproxy/zap/extension/httpsessions/OptionsHttpSessionsPanel.java
@@ -218,7 +218,7 @@ public boolean showRemoveDialogue(HttpSessionToken e) {
REMOVE_DIALOG_CONFIRM_BUTTON_LABEL,
REMOVE_DIALOG_CANCEL_BUTTON_LABEL
},
- null);
+ REMOVE_DIALOG_CONFIRM_BUTTON_LABEL);
if (option == JOptionPane.OK_OPTION) {
setRemoveWithoutConfirmation(removeWithoutConfirmationCheckBox.isSelected());
diff --git a/zap/src/main/java/org/zaproxy/zap/extension/proxies/OptionsProxiesPanel.java b/zap/src/main/java/org/zaproxy/zap/extension/proxies/OptionsProxiesPanel.java
index 1d06ceb7d11..530449fac8b 100644
--- a/zap/src/main/java/org/zaproxy/zap/extension/proxies/OptionsProxiesPanel.java
+++ b/zap/src/main/java/org/zaproxy/zap/extension/proxies/OptionsProxiesPanel.java
@@ -257,7 +257,7 @@ public boolean showRemoveDialogue(ProxiesParamProxy e) {
REMOVE_DIALOG_CONFIRM_BUTTON_LABEL,
REMOVE_DIALOG_CANCEL_BUTTON_LABEL
},
- null);
+ REMOVE_DIALOG_CONFIRM_BUTTON_LABEL);
if (option == JOptionPane.OK_OPTION) {
setRemoveWithoutConfirmation(removeWithoutConfirmationCheckBox.isSelected());
diff --git a/zap/src/main/java/org/zaproxy/zap/extension/pscan/OptionsPassiveScan.java b/zap/src/main/java/org/zaproxy/zap/extension/pscan/OptionsPassiveScan.java
index 12b7a6a6aa7..5e1b4141dd6 100644
--- a/zap/src/main/java/org/zaproxy/zap/extension/pscan/OptionsPassiveScan.java
+++ b/zap/src/main/java/org/zaproxy/zap/extension/pscan/OptionsPassiveScan.java
@@ -193,7 +193,7 @@ public boolean showRemoveDialogue(
REMOVE_DIALOG_CONFIRM_BUTTON_LABEL,
REMOVE_DIALOG_CANCEL_BUTTON_LABEL
},
- null);
+ REMOVE_DIALOG_CONFIRM_BUTTON_LABEL);
if (option == JOptionPane.OK_OPTION) {
setRemoveWithoutConfirmation(removeWithoutConfirmationCheckBox.isSelected());
diff --git a/zap/src/main/java/org/zaproxy/zap/extension/script/OptionsScriptPanel.java b/zap/src/main/java/org/zaproxy/zap/extension/script/OptionsScriptPanel.java
index 4fde31054ab..bd532e228a1 100644
--- a/zap/src/main/java/org/zaproxy/zap/extension/script/OptionsScriptPanel.java
+++ b/zap/src/main/java/org/zaproxy/zap/extension/script/OptionsScriptPanel.java
@@ -203,7 +203,7 @@ public boolean showRemoveDialogue(File f) {
REMOVE_DIALOG_CONFIRM_BUTTON_LABEL,
REMOVE_DIALOG_CANCEL_BUTTON_LABEL
},
- null);
+ REMOVE_DIALOG_CONFIRM_BUTTON_LABEL);
if (option == JOptionPane.OK_OPTION) {
setRemoveWithoutConfirmation(removeWithoutConfirmationCheckBox.isSelected());
diff --git a/zap/src/main/java/org/zaproxy/zap/extension/search/SearchPanel.java b/zap/src/main/java/org/zaproxy/zap/extension/search/SearchPanel.java
index 380e9e2bd95..33d0b5b4693 100644
--- a/zap/src/main/java/org/zaproxy/zap/extension/search/SearchPanel.java
+++ b/zap/src/main/java/org/zaproxy/zap/extension/search/SearchPanel.java
@@ -468,6 +468,9 @@ private void doSearch() {
}
if (pattern.matcher("").find()) {
+ String searchButtonLabel =
+ Constant.messages.getString(
+ "search.toolbar.warn.regex.match.empty.string.button.search");
int option =
JOptionPane.showOptionDialog(
View.getSingleton().getMainFrame(),
@@ -479,12 +482,11 @@ private void doSearch() {
JOptionPane.QUESTION_MESSAGE,
null,
new String[] {
- Constant.messages.getString(
- "search.toolbar.warn.regex.match.empty.string.button.search"),
+ searchButtonLabel,
Constant.messages.getString(
"search.toolbar.warn.regex.match.empty.string.button.cancel")
},
- null);
+ searchButtonLabel);
if (option != JOptionPane.OK_OPTION) {
regEx.requestFocusInWindow();
return;
diff --git a/zap/src/main/java/org/zaproxy/zap/extension/users/ContextUsersPanel.java b/zap/src/main/java/org/zaproxy/zap/extension/users/ContextUsersPanel.java
index 523b706bc83..43a5d27233c 100644
--- a/zap/src/main/java/org/zaproxy/zap/extension/users/ContextUsersPanel.java
+++ b/zap/src/main/java/org/zaproxy/zap/extension/users/ContextUsersPanel.java
@@ -171,7 +171,7 @@ public boolean showRemoveDialogue(User e) {
REMOVE_DIALOG_CONFIRM_BUTTON_LABEL,
REMOVE_DIALOG_CANCEL_BUTTON_LABEL
},
- null);
+ REMOVE_DIALOG_CONFIRM_BUTTON_LABEL);
if (option == JOptionPane.OK_OPTION) {
setRemoveWithoutConfirmation(removeWithoutConfirmationCheckBox.isSelected());
diff --git a/zap/src/main/java/org/zaproxy/zap/view/AbstractFormDialog.java b/zap/src/main/java/org/zaproxy/zap/view/AbstractFormDialog.java
index c951fb9363d..ed2a086aaa4 100644
--- a/zap/src/main/java/org/zaproxy/zap/view/AbstractFormDialog.java
+++ b/zap/src/main/java/org/zaproxy/zap/view/AbstractFormDialog.java
@@ -28,6 +28,7 @@
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
@@ -114,6 +115,25 @@ public void actionPerformed(ActionEvent e) {
};
getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(escape, "ESCAPE");
getRootPane().getActionMap().put("ESCAPE", escapeAction);
+
+ // Handle ctrl+enter to trigger the dialog's default button, regardless of which
+ // component (e.g. a text area or table) currently has focus.
+ KeyStroke ctrlEnter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.CTRL_DOWN_MASK);
+ AbstractAction ctrlEnterAction =
+ new AbstractAction() {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ JButton button = getRootPane().getDefaultButton();
+ if (button != null && button.isEnabled()) {
+ button.doClick();
+ }
+ }
+ };
+ getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(ctrlEnter, "CTRL_ENTER");
+ getRootPane().getActionMap().put("CTRL_ENTER", ctrlEnterAction);
}
protected void initView() {
@@ -206,6 +226,14 @@ public void setVisible(boolean b) {
firstTime = false;
}
+ if (b) {
+ // Disposing the dialog clears the root pane's default button (see
+ // JButton#removeNotify()), so it must be re-applied every time the dialog is shown,
+ // which matters for dialogs that are constructed once and reused across multiple
+ // show/dispose cycles.
+ getRootPane().setDefaultButton(getConfirmButton());
+ }
+
super.setVisible(b);
}
diff --git a/zap/src/main/java/org/zaproxy/zap/view/ContextStructurePanel.java b/zap/src/main/java/org/zaproxy/zap/view/ContextStructurePanel.java
index b1a037ce080..0e59c1ed4ba 100644
--- a/zap/src/main/java/org/zaproxy/zap/view/ContextStructurePanel.java
+++ b/zap/src/main/java/org/zaproxy/zap/view/ContextStructurePanel.java
@@ -361,7 +361,7 @@ public boolean showRemoveDialogue(StructuralNodeModifier e) {
REMOVE_DIALOG_CONFIRM_BUTTON_LABEL,
REMOVE_DIALOG_CANCEL_BUTTON_LABEL
},
- null);
+ REMOVE_DIALOG_CONFIRM_BUTTON_LABEL);
if (option == JOptionPane.OK_OPTION) {
setRemoveWithoutConfirmation(removeWithoutConfirmationCheckBox.isSelected());
diff --git a/zap/src/main/java/org/zaproxy/zap/view/LocaleDialog.java b/zap/src/main/java/org/zaproxy/zap/view/LocaleDialog.java
index e8b5c1a40a8..1a4b64f7431 100644
--- a/zap/src/main/java/org/zaproxy/zap/view/LocaleDialog.java
+++ b/zap/src/main/java/org/zaproxy/zap/view/LocaleDialog.java
@@ -101,6 +101,7 @@ private JPanel getJPanel() {
gridBagConstraints6.anchor = java.awt.GridBagConstraints.SOUTHEAST;
jPanel.add(getViewPanel(), gridBagConstraints5);
jPanel.add(getBtnOK(), gridBagConstraints6);
+ this.setDefaultButton(getBtnOK());
}
return jPanel;
}
diff --git a/zap/src/main/java/org/zaproxy/zap/view/MultipleRegexesOptionsPanel.java b/zap/src/main/java/org/zaproxy/zap/view/MultipleRegexesOptionsPanel.java
index a3c7c18339b..fb0d95bb756 100644
--- a/zap/src/main/java/org/zaproxy/zap/view/MultipleRegexesOptionsPanel.java
+++ b/zap/src/main/java/org/zaproxy/zap/view/MultipleRegexesOptionsPanel.java
@@ -243,7 +243,7 @@ public boolean showRemoveDialogue(String e) {
new String[] {
REMOVE_DIALOG_CONFIRM_BUTTON_LABEL, REMOVE_DIALOG_CANCEL_BUTTON_LABEL
},
- null);
+ REMOVE_DIALOG_CONFIRM_BUTTON_LABEL);
if (option == JOptionPane.OK_OPTION) {
setRemoveWithoutConfirmation(removeWithoutConfirmationCheckBox.isSelected());
diff --git a/zap/src/main/java/org/zaproxy/zap/view/NodeSelectDialog.java b/zap/src/main/java/org/zaproxy/zap/view/NodeSelectDialog.java
index faf0bd32b66..d3e9f0c340b 100644
--- a/zap/src/main/java/org/zaproxy/zap/view/NodeSelectDialog.java
+++ b/zap/src/main/java/org/zaproxy/zap/view/NodeSelectDialog.java
@@ -263,6 +263,7 @@ private JPanel getJPanel() {
jPanel.add(jLabel2, gridBagConstraints13);
jPanel.add(getCancelButton(), gridBagConstraints2);
jPanel.add(getSelectButton(), gridBagConstraints3);
+ this.setDefaultButton(getSelectButton());
}
return jPanel;
}
diff --git a/zap/src/main/java/org/zaproxy/zap/view/PersistSessionDialog.java b/zap/src/main/java/org/zaproxy/zap/view/PersistSessionDialog.java
index 4b6f2d19bf3..5ddd4678d57 100644
--- a/zap/src/main/java/org/zaproxy/zap/view/PersistSessionDialog.java
+++ b/zap/src/main/java/org/zaproxy/zap/view/PersistSessionDialog.java
@@ -126,6 +126,7 @@ public void actionPerformed(ActionEvent e) {
buttonPanel.add(
getStartSessionButton(),
LayoutHelper.getGBC(2, 0, 1, 0.0D, new Insets(4, 4, 4, 4)));
+ this.setDefaultButton(getStartSessionButton());
jPanel.add(buttonPanel, LayoutHelper.getGBC(0, 20, 2, 1.0D, new Insets(4, 4, 4, 4)));
}
diff --git a/zap/src/main/java/org/zaproxy/zap/view/ProxyDialog.java b/zap/src/main/java/org/zaproxy/zap/view/ProxyDialog.java
index 7c9d1576206..93b74b02dc9 100644
--- a/zap/src/main/java/org/zaproxy/zap/view/ProxyDialog.java
+++ b/zap/src/main/java/org/zaproxy/zap/view/ProxyDialog.java
@@ -113,6 +113,7 @@ private JPanel getJPanel() {
jPanel.add(getConnPanel(), gridBagConstraints5);
// jPanel.add(getBtnCancel(), gridBagConstraints7);
jPanel.add(getBtnOK(), gridBagConstraints6);
+ this.setDefaultButton(getBtnOK());
}
return jPanel;
}
diff --git a/zap/src/main/java/org/zaproxy/zap/view/StandardFieldsDialog.java b/zap/src/main/java/org/zaproxy/zap/view/StandardFieldsDialog.java
index d0650acbb16..adfc42a56f2 100644
--- a/zap/src/main/java/org/zaproxy/zap/view/StandardFieldsDialog.java
+++ b/zap/src/main/java/org/zaproxy/zap/view/StandardFieldsDialog.java
@@ -355,6 +355,7 @@ private void initContentPanel(
contentPanel.add(getCancelButton(), LayoutHelper.getGBC(x, 1, 1, 0.0D));
}
}
+ setDefaultButton(getSaveButton());
}
/*
diff --git a/zap/src/main/java/org/zaproxy/zap/view/ZapSupportDialog.java b/zap/src/main/java/org/zaproxy/zap/view/ZapSupportDialog.java
index 64e3ca90bc5..664705d50e9 100644
--- a/zap/src/main/java/org/zaproxy/zap/view/ZapSupportDialog.java
+++ b/zap/src/main/java/org/zaproxy/zap/view/ZapSupportDialog.java
@@ -129,7 +129,7 @@ private JPanel getMainPanel() {
mainPanel.add(getBtnOpen(), gbcOpenButton);
mainPanel.add(getBtnSaveSbom(), gbcSaveSbomButton);
mainPanel.add(getBtnCopy(), gbcCopyButton);
- this.getRootPane().setDefaultButton(getBtnCopy());
+ this.setDefaultButton(getBtnCopy());
mainPanel.add(getBtnOK(), gbcOkButton);
}
return mainPanel;
diff --git a/zap/src/main/java/org/zaproxy/zap/view/messagelocation/AbstractMessageLocationsPanel.java b/zap/src/main/java/org/zaproxy/zap/view/messagelocation/AbstractMessageLocationsPanel.java
index fbe3db9d874..4cdcddc406b 100644
--- a/zap/src/main/java/org/zaproxy/zap/view/messagelocation/AbstractMessageLocationsPanel.java
+++ b/zap/src/main/java/org/zaproxy/zap/view/messagelocation/AbstractMessageLocationsPanel.java
@@ -264,7 +264,7 @@ protected boolean showRemoveDialogueImpl(T e) {
new String[] {
REMOVE_DIALOG_CONFIRM_BUTTON_LABEL, REMOVE_DIALOG_CANCEL_BUTTON_LABEL
},
- null);
+ REMOVE_DIALOG_CONFIRM_BUTTON_LABEL);
if (option == JOptionPane.OK_OPTION) {
getRemoveWithoutConfirmationCheckBox()