Files
HaE/src/main/java/hae/component/Config.java

438 lines
16 KiB
Java
Raw Normal View History

2024-08-23 22:03:31 +08:00
package hae.component;
2024-05-06 12:56:56 +08:00
import burp.api.montoya.MontoyaApi;
2024-11-16 18:06:49 +08:00
import burp.api.montoya.core.Registration;
import hae.component.board.message.MessageTableModel;
2024-05-06 12:56:56 +08:00
import hae.component.rule.Rules;
2024-11-16 18:06:49 +08:00
import hae.instances.http.HttpMessageActiveHandler;
import hae.instances.http.HttpMessagePassiveHandler;
2024-05-24 15:00:49 +08:00
import hae.utils.ConfigLoader;
import hae.utils.UIEnhancer;
2024-05-06 12:56:56 +08:00
import javax.swing.*;
2024-05-23 12:00:13 +08:00
import javax.swing.border.EmptyBorder;
2024-07-23 09:21:30 +08:00
import javax.swing.border.TitledBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
2024-05-23 12:00:13 +08:00
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;
2024-05-06 12:56:56 +08:00
import java.awt.*;
2024-05-23 12:00:13 +08:00
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
2024-11-16 18:06:49 +08:00
import java.awt.event.*;
2024-05-23 12:00:13 +08:00
import java.util.List;
2024-07-23 09:21:30 +08:00
import java.util.*;
2024-05-06 12:56:56 +08:00
public class Config extends JPanel {
private final MontoyaApi api;
private final ConfigLoader configLoader;
2024-11-16 18:06:49 +08:00
private final MessageTableModel messageTableModel;
2024-05-06 12:56:56 +08:00
private final Rules rules;
2024-11-16 18:06:49 +08:00
private Registration activeHandler;
private Registration passiveHandler;
public Config(MontoyaApi api, ConfigLoader configLoader, MessageTableModel messageTableModel, Rules rules) {
2024-05-06 12:56:56 +08:00
this.api = api;
this.configLoader = configLoader;
2024-11-16 18:06:49 +08:00
this.messageTableModel = messageTableModel;
2024-05-06 12:56:56 +08:00
this.rules = rules;
2024-11-16 18:06:49 +08:00
this.activeHandler = api.http().registerHttpHandler(new HttpMessageActiveHandler(api, configLoader, messageTableModel));
this.passiveHandler = api.scanner().registerScanCheck(new HttpMessagePassiveHandler(api, configLoader, messageTableModel));
2024-05-06 12:56:56 +08:00
initComponents();
}
private void initComponents() {
2024-05-23 12:00:13 +08:00
setLayout(new BorderLayout());
2024-08-12 10:34:26 +08:00
GridBagConstraints constraints = new GridBagConstraints();
constraints.weightx = 1.0;
constraints.fill = GridBagConstraints.HORIZONTAL;
2024-05-23 12:00:13 +08:00
JPanel ruleInfoPanel = new JPanel(new GridBagLayout());
2024-05-24 15:00:49 +08:00
ruleInfoPanel.setBorder(new EmptyBorder(10, 15, 5, 15));
2024-05-06 12:56:56 +08:00
2024-05-23 12:00:13 +08:00
JLabel ruleLabel = new JLabel("Path:");
JTextField pathTextField = new JTextField();
pathTextField.setEditable(false);
pathTextField.setText(configLoader.getRulesFilePath());
JButton reloadButton = new JButton("Reload");
2024-12-21 15:34:45 +08:00
JButton reinitButton = new JButton("Reinit");
2024-05-23 12:00:13 +08:00
ruleInfoPanel.add(ruleLabel);
ruleInfoPanel.add(pathTextField, constraints);
ruleInfoPanel.add(Box.createHorizontalStrut(5));
2024-12-21 15:34:45 +08:00
ruleInfoPanel.add(reinitButton);
2024-05-23 12:00:13 +08:00
ruleInfoPanel.add(Box.createHorizontalStrut(5));
2024-12-21 15:34:45 +08:00
ruleInfoPanel.add(reloadButton);
2024-05-06 12:56:56 +08:00
reloadButton.addActionListener(this::reloadActionPerformed);
2024-12-21 15:34:45 +08:00
reinitButton.addActionListener(this::reinitActionPerformed);
2024-05-23 12:00:13 +08:00
2024-07-23 09:21:30 +08:00
constraints.gridx = 1;
JTabbedPane configTabbedPanel = new JTabbedPane();
2024-11-16 18:06:49 +08:00
String[] settingMode = new String[]{"Exclude suffix", "Block host", "Exclude status"};
2024-12-21 15:34:45 +08:00
JPanel settingPanel = createConfigTablePanel(settingMode);
2024-11-16 18:06:49 +08:00
JPanel northPanel = new JPanel(new BorderLayout());
JPanel modePanel = getModePanel();
JScrollPane modeScrollPane = new JScrollPane(modePanel);
modeScrollPane.setBorder(new TitledBorder("Mode"));
JTextField limitPanel = getLimitPanel();
JScrollPane limitScrollPane = new JScrollPane(limitPanel);
limitScrollPane.setBorder(new TitledBorder("Limit Size (MB)"));
JSplitPane northTopPanel = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, modeScrollPane, limitScrollPane);
northTopPanel.addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
northTopPanel.setDividerLocation(0.5);
}
});
2024-07-23 09:21:30 +08:00
JPanel scopePanel = getScopePanel();
JScrollPane scopeScrollPane = new JScrollPane(scopePanel);
scopeScrollPane.setBorder(new TitledBorder("Scope"));
2024-11-16 18:06:49 +08:00
northPanel.add(scopeScrollPane, BorderLayout.SOUTH);
northPanel.add(northTopPanel, BorderLayout.NORTH);
settingPanel.add(northPanel, BorderLayout.NORTH);
2024-07-23 09:21:30 +08:00
configTabbedPanel.add("Setting", settingPanel);
add(ruleInfoPanel, BorderLayout.NORTH);
add(configTabbedPanel, BorderLayout.CENTER);
}
private JPanel getScopePanel() {
JPanel scopePanel = new JPanel();
scopePanel.setLayout(new BoxLayout(scopePanel, BoxLayout.X_AXIS));
2024-11-16 18:06:49 +08:00
scopePanel.setBorder(new EmptyBorder(3, 0, 6, 0));
2024-07-23 09:21:30 +08:00
String[] scopeInit = hae.Config.scopeOptions.split("\\|");
String[] scopeMode = configLoader.getScope().split("\\|");
for (String scope : scopeInit) {
JCheckBox checkBox = new JCheckBox(scope);
scopePanel.add(checkBox);
2024-11-16 18:06:49 +08:00
checkBox.addActionListener(e -> updateScope(checkBox));
2024-07-23 09:21:30 +08:00
for (String mode : scopeMode) {
if (scope.equals(mode)) {
checkBox.setSelected(true);
}
}
2024-11-16 18:06:49 +08:00
updateScope(checkBox);
2024-07-23 09:21:30 +08:00
}
2024-11-16 18:06:49 +08:00
2024-07-23 09:21:30 +08:00
return scopePanel;
}
2024-11-16 18:06:49 +08:00
private JPanel getModePanel() {
JPanel modePanel = new JPanel();
modePanel.setLayout(new BoxLayout(modePanel, BoxLayout.X_AXIS));
JCheckBox checkBox = new JCheckBox("Enable active http message handler");
modePanel.add(checkBox);
checkBox.addActionListener(e -> updateModeStatus(checkBox));
checkBox.setSelected(configLoader.getMode());
updateModeStatus(checkBox);
return modePanel;
}
private JTextField getLimitPanel() {
JTextField limitSizeTextField = new JTextField();
limitSizeTextField.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent e) {
onTextChange();
}
@Override
public void removeUpdate(DocumentEvent e) {
onTextChange();
}
@Override
public void changedUpdate(DocumentEvent e) {
onTextChange();
}
private void onTextChange() {
String limitSizeText = limitSizeTextField.getText();
configLoader.setLimitSize(limitSizeText);
}
});
limitSizeTextField.setText(configLoader.getLimitSize());
return limitSizeTextField;
}
2024-07-23 09:21:30 +08:00
private TableModelListener craeteSettingTableModelListener(JComboBox<String> setTypeComboBox, DefaultTableModel model) {
return new TableModelListener() {
@Override
public void tableChanged(TableModelEvent e) {
String selected = (String) setTypeComboBox.getSelectedItem();
String values = getFirstColumnDataAsString(model);
if (selected.equals("Exclude suffix")) {
if (!values.equals(configLoader.getExcludeSuffix()) && !values.isEmpty()) {
configLoader.setExcludeSuffix(values);
}
}
if (selected.equals("Block host")) {
if (!values.equals(configLoader.getBlockHost()) && !values.isEmpty()) {
configLoader.setBlockHost(values);
}
}
2024-08-12 10:34:26 +08:00
if (selected.equals("Exclude status")) {
if (!values.equals(configLoader.getExcludeStatus()) && !values.isEmpty()) {
configLoader.setExcludeStatus(values);
}
}
2024-09-19 17:08:46 +08:00
2024-07-23 09:21:30 +08:00
}
};
}
private ActionListener createSettingActionListener(JComboBox<String> setTypeComboBox, DefaultTableModel model) {
return new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String selected = (String) setTypeComboBox.getSelectedItem();
model.setRowCount(0);
if (selected.equals("Exclude suffix")) {
addDataToTable(configLoader.getExcludeSuffix().replaceAll("\\|", "\r\n"), model);
}
if (selected.equals("Block host")) {
addDataToTable(configLoader.getBlockHost().replaceAll("\\|", "\r\n"), model);
}
2024-08-12 10:34:26 +08:00
if (selected.equals("Exclude status")) {
addDataToTable(configLoader.getExcludeStatus().replaceAll("\\|", "\r\n"), model);
}
2024-07-23 09:21:30 +08:00
}
};
}
2024-12-21 15:34:45 +08:00
private JPanel createConfigTablePanel(String[] mode) {
2024-08-12 10:34:26 +08:00
GridBagConstraints constraints = new GridBagConstraints();
constraints.weightx = 1.0;
constraints.fill = GridBagConstraints.HORIZONTAL;
2024-05-23 12:00:13 +08:00
JPanel settingPanel = new JPanel(new BorderLayout());
DefaultTableModel model = new DefaultTableModel();
JTable table = new JTable(model);
model.addColumn("Value");
JScrollPane scrollPane = new JScrollPane(table);
JPanel buttonPanel = new JPanel();
buttonPanel.setBorder(new EmptyBorder(0, 3, 0, 0));
GridBagLayout layout = new GridBagLayout();
layout.rowHeights = new int[]{0, 0, 0, 0, 0, 0, 0};
layout.rowWeights = new double[]{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Double.MIN_VALUE};
buttonPanel.setLayout(layout);
JPanel inputPanel = new JPanel(new BorderLayout());
JPanel inputPanelB = new JPanel(new BorderLayout());
inputPanelB.setBorder(new EmptyBorder(0, 0, 3, 0));
JButton addButton = new JButton("Add");
JButton removeButton = new JButton("Remove");
JButton pasteButton = new JButton("Paste");
JButton clearButton = new JButton("Clear");
JComboBox<String> setTypeComboBox = new JComboBox<>();
setTypeComboBox.setModel(new DefaultComboBoxModel<>(mode));
2024-12-21 15:34:45 +08:00
model.addTableModelListener(craeteSettingTableModelListener(setTypeComboBox, model));
2024-11-16 18:06:49 +08:00
2024-12-21 15:34:45 +08:00
setTypeComboBox.addActionListener(createSettingActionListener(setTypeComboBox, model));
2024-05-23 12:00:13 +08:00
2024-07-23 09:21:30 +08:00
setTypeComboBox.setSelectedItem(mode[0]);
2024-05-23 12:00:13 +08:00
constraints.insets = new Insets(0, 0, 3, 0);
constraints.gridy = 0;
buttonPanel.add(setTypeComboBox, constraints);
constraints.gridy = 1;
buttonPanel.add(addButton, constraints);
constraints.gridy = 2;
buttonPanel.add(removeButton, constraints);
constraints.gridy = 3;
buttonPanel.add(pasteButton, constraints);
constraints.gridy = 4;
buttonPanel.add(clearButton, constraints);
2024-08-12 10:34:26 +08:00
JTextField addTextField = new JTextField();
2024-12-21 15:34:45 +08:00
String defaultText = "Enter a new item";
2024-05-23 12:00:13 +08:00
UIEnhancer.setTextFieldPlaceholder(addTextField, defaultText);
inputPanelB.add(addTextField, BorderLayout.CENTER);
inputPanel.add(scrollPane, BorderLayout.CENTER);
inputPanel.add(inputPanelB, BorderLayout.NORTH);
settingPanel.add(buttonPanel, BorderLayout.EAST);
settingPanel.add(inputPanel, BorderLayout.CENTER);
2024-05-24 15:00:49 +08:00
2024-09-19 17:08:46 +08:00
addButton.addActionListener(e -> addActionPerformed(e, model, addTextField, setTypeComboBox.getSelectedItem().toString()));
2024-05-24 15:00:49 +08:00
addTextField.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
2024-09-19 17:08:46 +08:00
addActionPerformed(null, model, addTextField, setTypeComboBox.getSelectedItem().toString());
2024-05-24 15:00:49 +08:00
}
2024-05-23 12:00:13 +08:00
}
});
pasteButton.addActionListener(e -> {
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
try {
String data = (String) clipboard.getData(DataFlavor.stringFlavor);
if (data != null && !data.isEmpty()) {
addDataToTable(data, model);
}
} catch (Exception ignored) {
}
});
2024-05-06 12:56:56 +08:00
2024-05-23 12:00:13 +08:00
removeButton.addActionListener(e -> {
int selectedRow = table.getSelectedRow();
if (selectedRow != -1) {
model.removeRow(selectedRow);
}
});
clearButton.addActionListener(e -> model.setRowCount(0));
JPanel settingMainPanel = new JPanel(new BorderLayout());
2024-07-23 09:21:30 +08:00
settingMainPanel.setBorder(new EmptyBorder(5, 15, 10, 15));
JScrollPane settingScroller = new JScrollPane(settingPanel);
2024-12-21 15:34:45 +08:00
settingScroller.setBorder(new TitledBorder("Setting"));
2024-07-23 09:21:30 +08:00
settingMainPanel.add(settingScroller, BorderLayout.CENTER);
2024-05-23 12:00:13 +08:00
2024-07-23 09:21:30 +08:00
return settingMainPanel;
2024-05-23 12:00:13 +08:00
}
2024-05-24 15:00:49 +08:00
2024-05-23 12:00:13 +08:00
private String getFirstColumnDataAsString(DefaultTableModel model) {
StringBuilder firstColumnData = new StringBuilder();
int numRows = model.getRowCount();
for (int row = 0; row < numRows; row++) {
firstColumnData.append(model.getValueAt(row, 0));
if (row < numRows - 1) {
firstColumnData.append("|");
}
}
return firstColumnData.toString();
}
private void addDataToTable(String data, DefaultTableModel model) {
if (!data.isBlank()) {
String[] rows = data.split("\\r?\\n");
for (String row : rows) {
model.addRow(new String[]{row});
}
deduplicateTableData(model);
}
}
private void deduplicateTableData(DefaultTableModel model) {
// 使用 Map 存储每一行的数据,用于去重
Set<List<Object>> rowData = new LinkedHashSet<>();
int columnCount = model.getColumnCount();
// 将每一行数据作为一个列表,添加到 Set 中
for (int i = 0; i < model.getRowCount(); i++) {
List<Object> row = new ArrayList<>();
for (int j = 0; j < columnCount; j++) {
row.add(model.getValueAt(i, j));
}
rowData.add(row);
}
// 清除原始数据
model.setRowCount(0);
// 将去重后的数据添加回去
for (List<Object> uniqueRow : rowData) {
model.addRow(uniqueRow.toArray());
}
2024-05-06 12:56:56 +08:00
}
2024-11-16 18:06:49 +08:00
public void updateModeStatus(JCheckBox checkBox) {
boolean selected = checkBox.isSelected();
configLoader.setMode(selected ? "true" : "false");
if (checkBox.isSelected()) {
if (passiveHandler.isRegistered()) {
passiveHandler.deregister();
}
if (!activeHandler.isRegistered()) {
activeHandler = api.http().registerHttpHandler(new HttpMessageActiveHandler(api, configLoader, messageTableModel));
}
} else {
if (!passiveHandler.isRegistered()) {
passiveHandler = api.scanner().registerScanCheck(new HttpMessagePassiveHandler(api, configLoader, messageTableModel));
}
if (activeHandler.isRegistered()) {
activeHandler.deregister();
}
}
}
2024-07-23 09:21:30 +08:00
public void updateScope(JCheckBox checkBox) {
String boxText = checkBox.getText();
boolean selected = checkBox.isSelected();
Set<String> HaEScope = new HashSet<>(Arrays.asList(configLoader.getScope().split("\\|")));
if (selected) {
HaEScope.add(boxText);
} else {
HaEScope.remove(boxText);
}
configLoader.setScope(String.join("|", HaEScope));
}
2024-09-19 17:08:46 +08:00
private void addActionPerformed(ActionEvent e, DefaultTableModel model, JTextField addTextField, String comboBoxSelected) {
2024-05-24 15:00:49 +08:00
String addTextFieldText = addTextField.getText();
2024-09-19 17:08:46 +08:00
if (addTextField.getForeground().equals(Color.BLACK)) {
2024-05-24 15:00:49 +08:00
addDataToTable(addTextFieldText, model);
2024-09-19 17:08:46 +08:00
addTextField.setText("");
addTextField.requestFocusInWindow();
2024-05-24 15:00:49 +08:00
}
}
2024-05-06 12:56:56 +08:00
private void reloadActionPerformed(ActionEvent e) {
rules.reloadRuleGroup();
}
2024-12-21 15:34:45 +08:00
private void reinitActionPerformed(ActionEvent e) {
int retCode = JOptionPane.showConfirmDialog(this, "Do you want to reinitialize rules? This action will overwrite your existing rules.", "Info", JOptionPane.YES_NO_OPTION);
if (retCode == JOptionPane.YES_OPTION) {
boolean ret = configLoader.initRules();
if (ret) {
rules.reloadRuleGroup();
}
}
}
2024-05-06 12:56:56 +08:00
}