/* * Zed Attack Proxy (ZAP) and its related class files. * * ZAP is an HTTP/HTTPS proxy for assessing web application security. * * Copyright 2016 The ZAP Development Team * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zaproxy.zap.view; import java.awt.Dialog; import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import javax.swing.GroupLayout; import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.SortOrder; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import org.parosproxy.paros.Constant; import org.parosproxy.paros.view.View; import org.zaproxy.zap.utils.ZapTextField; /** * A {@code MultipleOptionsTablePanel} to manage regular expressions. * * @since 2.5.0 */ public class MultipleRegexesOptionsPanel extends AbstractMultipleOptionsBaseTablePanel<String> { private static final long serialVersionUID = 1041782873016590998L; private static final String REMOVE_DIALOG_TITLE = Constant.messages .getString("multiple.options.regexes.dialog.remove.regex.title"); private static final String REMOVE_DIALOG_TEXT = Constant.messages .getString("multiple.options.regexes.dialog.remove.regex.text"); private static final String REMOVE_DIALOG_CONFIRM_BUTTON_LABEL = Constant.messages .getString("multiple.options.regexes.dialog.remove.regex.button.confirm"); private static final String REMOVE_DIALOG_CANCEL_BUTTON_LABEL = Constant.messages .getString("multiple.options.regexes.dialog.remove.regex.button.cancel"); private static final String REMOVE_DIALOG_CHECKBOX_LABEL = Constant.messages .getString("multiple.options.regexes.dialog.remove.regex.checkbox.label"); private DialogAddRegex addDialog; private DialogModifyRegex modifyDialog; private final Dialog owner; public MultipleRegexesOptionsPanel(Dialog owner) { this(owner, new RegexesTableModel()); } public MultipleRegexesOptionsPanel(Dialog owner, RegexesTableModel model) { super(model); this.owner = owner; getTable().setSortOrder(0, SortOrder.ASCENDING); } public void setRegexes(List<String> regexes) { ((RegexesTableModel) getMultipleOptionsModel()).setElements(regexes); } public List<String> getRegexes() { return ((RegexesTableModel) getMultipleOptionsModel()).getElements(); } @Override public String showAddDialogue() { if (addDialog == null) { addDialog = new DialogAddRegex(owner); addDialog.pack(); } addDialog.setVisible(true); String regex = addDialog.getRegex(); addDialog.clear(); return regex; } @Override public String showModifyDialogue(String e) { if (modifyDialog == null) { modifyDialog = new DialogModifyRegex(owner); modifyDialog.pack(); } modifyDialog.setRegex(e); modifyDialog.setVisible(true); String regex = modifyDialog.getRegex(); modifyDialog.clear(); if (!regex.equals(e)) { return regex; } return null; } @Override public boolean showRemoveDialogue(String e) { JCheckBox removeWithoutConfirmationCheckBox = new JCheckBox(REMOVE_DIALOG_CHECKBOX_LABEL); Object[] messages = { REMOVE_DIALOG_TEXT, " ", removeWithoutConfirmationCheckBox }; int option = JOptionPane.showOptionDialog( View.getSingleton().getMainFrame(), messages, REMOVE_DIALOG_TITLE, JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, new String[] { REMOVE_DIALOG_CONFIRM_BUTTON_LABEL, REMOVE_DIALOG_CANCEL_BUTTON_LABEL }, null); if (option == JOptionPane.OK_OPTION) { setRemoveWithoutConfirmation(removeWithoutConfirmationCheckBox.isSelected()); return true; } return false; } protected static class DialogAddRegex extends AbstractFormDialog { private static final long serialVersionUID = 9172864521259395417L; private static final String DIALOG_TITLE = Constant.messages .getString("multiple.options.regexes.dialog.add.regex.title"); private static final String CONFIRM_BUTTON_LABEL = Constant.messages .getString("multiple.options.regexes.dialog.add.regex.button.confirm"); private static final String REGEX_FIELD_LABEL = Constant.messages .getString("multiple.options.regexes.dialog.regex.label"); private static final String TITLE_INVALID_REGEX_DIALOG = Constant.messages .getString("multiple.options.regexes.dialog.regex.invalid.title"); private static final String TEXT_INVALID_REGEX_DIALOG = Constant.messages .getString("multiple.options.regexes.dialog.regex.invalid.text"); private ZapTextField regexTextField; protected String regex; public DialogAddRegex(Dialog owner) { super(owner, DIALOG_TITLE); } protected DialogAddRegex(Dialog owner, String title) { super(owner, title); } @Override protected JPanel getFieldsPanel() { JPanel fieldsPanel = new JPanel(); GroupLayout layout = new GroupLayout(fieldsPanel); fieldsPanel.setLayout(layout); layout.setAutoCreateGaps(true); layout.setAutoCreateContainerGaps(true); JLabel regexLabel = new JLabel(REGEX_FIELD_LABEL); layout.setHorizontalGroup( layout.createSequentialGroup().addComponent(regexLabel).addComponent(getRegexTextField())); layout.setVerticalGroup( layout.createParallelGroup(GroupLayout.Alignment.BASELINE) .addComponent(regexLabel) .addComponent(getRegexTextField())); return fieldsPanel; } @Override protected String getConfirmButtonLabel() { return CONFIRM_BUTTON_LABEL; } @Override protected void init() { getRegexTextField().setText(""); regex = null; } @Override protected boolean validateFields() { try { Pattern.compile(getRegexTextField().getText(), Pattern.CASE_INSENSITIVE); } catch (PatternSyntaxException e) { JOptionPane.showMessageDialog( this, MessageFormat.format(TEXT_INVALID_REGEX_DIALOG, e.getLocalizedMessage()), TITLE_INVALID_REGEX_DIALOG, JOptionPane.INFORMATION_MESSAGE); getRegexTextField().requestFocusInWindow(); return false; } return true; } @Override protected void performAction() { regex = getRegexTextField().getText(); } @Override protected void clearFields() { getRegexTextField().setText(""); getRegexTextField().discardAllEdits(); } public String getRegex() { return regex; } protected ZapTextField getRegexTextField() { if (regexTextField == null) { regexTextField = new ZapTextField(30); regexTextField.getDocument().addDocumentListener(new DocumentListener() { @Override public void removeUpdate(DocumentEvent e) { checkAndEnableConfirmButton(); } @Override public void insertUpdate(DocumentEvent e) { checkAndEnableConfirmButton(); } @Override public void changedUpdate(DocumentEvent e) { checkAndEnableConfirmButton(); } private void checkAndEnableConfirmButton() { setConfirmButtonEnabled(getRegexTextField().getDocument().getLength() > 0); } }); } return regexTextField; } public void clear() { this.regex = null; } } protected static class DialogModifyRegex extends DialogAddRegex { private static final long serialVersionUID = 3803499933691686617L; private static final String DIALOG_TITLE = Constant.messages .getString("multiple.options.regexes.dialog.modify.regex.title"); private static final String CONFIRM_BUTTON_LABEL = Constant.messages .getString("multiple.options.regexes.dialog.modify.regex.button.confirm"); protected DialogModifyRegex(Dialog owner) { super(owner, DIALOG_TITLE); } @Override protected String getConfirmButtonLabel() { return CONFIRM_BUTTON_LABEL; } public void setRegex(String regex) { this.regex = regex; } @Override protected void init() { getRegexTextField().setText(regex); getRegexTextField().discardAllEdits(); } } protected static class RegexesTableModel extends AbstractMultipleOptionsBaseTableModel<String> { private static final long serialVersionUID = -7644711449311289615L; private static final String[] COLUMN_NAMES = { Constant.messages.getString("multiple.options.regexes.table.header.regex") }; private static final int COLUMN_COUNT = COLUMN_NAMES.length; private List<String> elements; public RegexesTableModel() { elements = new ArrayList<>(); } @Override public String getColumnName(int col) { return COLUMN_NAMES[col]; } @Override public int getColumnCount() { return COLUMN_COUNT; } @Override public Class<?> getColumnClass(int c) { return String.class; } @Override public int getRowCount() { return elements.size(); } @Override public String getValueAt(int rowIndex, int columnIndex) { return elements.get(rowIndex); } @Override public List<String> getElements() { return elements; } public void setElements(List<String> regexes) { this.elements = new ArrayList<>(regexes); fireTableDataChanged(); } } }