/*
* Zed Attack Proxy (ZAP) and its related class files.
*
* ZAP is an HTTP/HTTPS proxy for assessing web application security.
*
* 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.extension.httppanel.view.syntaxhighlight.menus;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Vector;
import javax.swing.ButtonGroup;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.text.JTextComponent;
import javax.swing.text.TextAction;
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
import org.parosproxy.paros.Constant;
import org.zaproxy.zap.extension.ExtensionPopupMenu;
import org.zaproxy.zap.extension.httppanel.view.syntaxhighlight.AutoDetectSyntaxHttpPanelTextArea;
import org.zaproxy.zap.extension.httppanel.view.syntaxhighlight.HttpPanelSyntaxHighlightTextArea;
import org.zaproxy.zap.extension.httppanel.view.syntaxhighlight.HttpPanelSyntaxHighlightTextArea.SyntaxStyle;
public class SyntaxMenu extends ExtensionPopupMenu {
private static final long serialVersionUID = 8472491919281117716L;
private static final String MENU_LABEL = Constant.messages.getString("http.panel.view.syntaxtext.popup.syntax.label");
private static final String AUTO_DETECT_SYNTAX_OPTION = Constant.messages.getString("http.panel.view.syntaxtext.popup.syntax.autoDetect");
private JCheckBoxMenuItem autoDetectSyntax;
private JPopupMenu.Separator autoDetectSyntaxSeparator;
private ButtonGroup syntaxStylesButtonGroup;
private Map<String, JRadioButtonMenuItem> syntaxOptions;
private JPopupMenu.Separator plainSyntaxSeparator;
public SyntaxMenu() {
super(MENU_LABEL);
syntaxStylesButtonGroup = new ButtonGroup();
syntaxOptions = new HashMap<>();
autoDetectSyntax = new JCheckBoxMenuItem(new ChangeAutoDetectSyntaxAction(AUTO_DETECT_SYNTAX_OPTION));
add(autoDetectSyntax);
autoDetectSyntaxSeparator = new JPopupMenu.Separator();
add(autoDetectSyntaxSeparator);
//Create plain syntax as all HttpPanelSyntaxHighlightTextArea will have this style
addSyntaxOption(HttpPanelSyntaxHighlightTextArea.PLAIN_SYNTAX_LABEL, SyntaxConstants.SYNTAX_STYLE_NONE);
syntaxOptions.get(SyntaxConstants.SYNTAX_STYLE_NONE).setSelected(true);
plainSyntaxSeparator = new JPopupMenu.Separator();
add(plainSyntaxSeparator);
}
@Override
public boolean isEnableForComponent(Component invoker) {
if (invoker instanceof HttpPanelSyntaxHighlightTextArea) {
HttpPanelSyntaxHighlightTextArea httpPanelTextArea = (HttpPanelSyntaxHighlightTextArea)invoker;
updateState(httpPanelTextArea);
return true;
}
return false;
}
@Override
public boolean precedeWithSeparator() {
return true;
}
public void updateState(HttpPanelSyntaxHighlightTextArea httpPanelTextArea) {
if (httpPanelTextArea instanceof AutoDetectSyntaxHttpPanelTextArea) {
AutoDetectSyntaxHttpPanelTextArea textArea = (AutoDetectSyntaxHttpPanelTextArea)httpPanelTextArea;
autoDetectSyntax.setSelected(textArea.isAutoDetectSyntax());
autoDetectSyntax.setVisible(true);
autoDetectSyntaxSeparator.setVisible(true);
} else {
autoDetectSyntax.setVisible(false);
autoDetectSyntaxSeparator.setVisible(false);
}
Vector<SyntaxStyle> styles = httpPanelTextArea.getSyntaxStyles();
boolean hasMultipleStyles = true;
if (hasMultipleStyles && styles.size() == 1) {
hasMultipleStyles = false;
}
plainSyntaxSeparator.setVisible(hasMultipleStyles);
Iterator<JRadioButtonMenuItem> itSyntaxOptions = syntaxOptions.values().iterator();
while (itSyntaxOptions.hasNext()) {
itSyntaxOptions.next().setVisible(false);
}
syntaxOptions.get(SyntaxConstants.SYNTAX_STYLE_NONE).setVisible(true);
if (hasMultipleStyles) {
String styleKey;
JRadioButtonMenuItem radioButton;
Iterator<SyntaxStyle> it = styles.iterator();
while (it.hasNext()) {
SyntaxStyle syntaxStyle = it.next();
styleKey = syntaxStyle.getStyleKey();
radioButton = syntaxOptions.get(styleKey);
if (radioButton != null) {
radioButton.setVisible(true);
} else {
addSyntaxOption(syntaxStyle.getLabel(), styleKey);
syntaxOptions.get(styleKey).setVisible(true);
}
}
}
final String style = httpPanelTextArea.getSyntaxEditingStyle();
final JRadioButtonMenuItem radioButton = syntaxOptions.get(style);
if (radioButton != null) {
radioButton.setSelected(true);
} else if (!SyntaxConstants.SYNTAX_STYLE_NONE.equals(style)) {
//Some style that is not on the pop up menu, but it is on the RSyntaxTextArea.
//Shouldn't happen.
} else {
//Some style that is not recognized by RSyntaxTextArea, select plain
//as it is the default action taken in RSyntaxTextArea
syntaxOptions.get(SyntaxConstants.SYNTAX_STYLE_NONE).setSelected(true);
}
}
private void addSyntaxOption(String text, String styleKey) {
JRadioButtonMenuItem syntaxOption = new JRadioButtonMenuItem(new ChangeSyntaxAction(text, styleKey));
syntaxStylesButtonGroup.add(syntaxOption);
add(syntaxOption);
syntaxOptions.put(styleKey, syntaxOption);
}
private static class ChangeSyntaxAction extends TextAction {
private static final long serialVersionUID = 5136037355346821365L;
private final String styleKey;
public ChangeSyntaxAction(String text, String styleKey) {
super(text);
this.styleKey = styleKey;
}
@Override
public void actionPerformed(ActionEvent e) {
final JTextComponent textComponent = getTextComponent(e);
if (textComponent instanceof HttpPanelSyntaxHighlightTextArea) {
final HttpPanelSyntaxHighlightTextArea httpPanelTextArea = ((HttpPanelSyntaxHighlightTextArea)textComponent);
httpPanelTextArea.setSyntaxEditingStyle(styleKey);
}
}
}
private static class ChangeAutoDetectSyntaxAction extends TextAction {
private static final long serialVersionUID = -6045054098695629693L;
public ChangeAutoDetectSyntaxAction(String text) {
super(text);
}
@Override
public void actionPerformed(ActionEvent e) {
final JTextComponent textComponent = getTextComponent(e);
if (textComponent instanceof AutoDetectSyntaxHttpPanelTextArea) {
final AutoDetectSyntaxHttpPanelTextArea textArea = ((AutoDetectSyntaxHttpPanelTextArea)textComponent);
textArea.setAutoDetectSyntax(!textArea.isAutoDetectSyntax());
}
}
}
}