Version: 4.3.1 Update
Signed-off-by: gh0stkey <24655118+gh0stkey@users.noreply.github.com>
This commit is contained in:
@@ -60,7 +60,8 @@ public class Config {
|
||||
"blue",
|
||||
"pink",
|
||||
"magenta",
|
||||
"gray"
|
||||
"gray",
|
||||
"none"
|
||||
};
|
||||
|
||||
public static Boolean proVersionStatus = true;
|
||||
|
||||
@@ -19,7 +19,7 @@ public class HaE implements BurpExtension {
|
||||
public void initialize(MontoyaApi api) {
|
||||
// 设置扩展名称
|
||||
api.extension().setName("HaE - Highlighter and Extractor");
|
||||
String version = "4.3";
|
||||
String version = "4.3.1";
|
||||
|
||||
// 加载扩展后输出的项目信息
|
||||
Logging logging = api.logging();
|
||||
|
||||
@@ -5,6 +5,7 @@ import hae.component.board.Databoard;
|
||||
import hae.component.board.message.MessageTableModel;
|
||||
import hae.component.rule.Rules;
|
||||
import hae.utils.ConfigLoader;
|
||||
import hae.utils.UIEnhancer;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
@@ -36,7 +37,7 @@ public class Main extends JPanel {
|
||||
|
||||
// 新增Logo
|
||||
JTabbedPane HaETabbedPane = new JTabbedPane();
|
||||
boolean isDarkBg = isDarkBg(HaETabbedPane);
|
||||
boolean isDarkBg = UIEnhancer.isDarkColor(HaETabbedPane.getBackground());
|
||||
HaETabbedPane.addTab("", getImageIcon(isDarkBg), mainTabbedPane);
|
||||
// 中文Slogan:赋能白帽,高效作战
|
||||
HaETabbedPane.addTab(" Highlighter and Extractor - Empower ethical hacker for efficient operations. ", null);
|
||||
@@ -44,7 +45,7 @@ public class Main extends JPanel {
|
||||
HaETabbedPane.addPropertyChangeListener("background", new PropertyChangeListener() {
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent e) {
|
||||
boolean isDarkBg = isDarkBg(HaETabbedPane);
|
||||
boolean isDarkBg = UIEnhancer.isDarkColor(HaETabbedPane.getBackground());
|
||||
HaETabbedPane.setIconAt(0, getImageIcon(isDarkBg));
|
||||
}
|
||||
});
|
||||
@@ -60,16 +61,6 @@ public class Main extends JPanel {
|
||||
mainTabbedPane.addTab("Config", new Config(api, configLoader, messageTableModel, rules));
|
||||
}
|
||||
|
||||
private boolean isDarkBg(JTabbedPane HaETabbedPane) {
|
||||
Color bg = HaETabbedPane.getBackground();
|
||||
int r = bg.getRed();
|
||||
int g = bg.getGreen();
|
||||
int b = bg.getBlue();
|
||||
int avg = (r + g + b) / 3;
|
||||
|
||||
return avg < 128;
|
||||
}
|
||||
|
||||
private ImageIcon getImageIcon(boolean isDark) {
|
||||
ClassLoader classLoader = getClass().getClassLoader();
|
||||
URL imageURL;
|
||||
|
||||
@@ -18,8 +18,9 @@ import javax.swing.table.TableModel;
|
||||
import javax.swing.table.TableRowSorter;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.util.List;
|
||||
import java.text.Collator;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -415,7 +416,7 @@ public class Databoard extends JPanel {
|
||||
String tabTitle = String.format("%s (%s)", entry.getKey(), entry.getValue().size());
|
||||
Datatable datatablePanel = new Datatable(api, configLoader, entry.getKey(), entry.getValue());
|
||||
datatablePanel.setTableListener(messageTableModel);
|
||||
dataTabbedPane.addTab(tabTitle, datatablePanel);
|
||||
insertTabSorted(dataTabbedPane, tabTitle, datatablePanel);
|
||||
}
|
||||
|
||||
JSplitPane messageSplitPane = messageTableModel.getSplitPane();
|
||||
@@ -438,6 +439,26 @@ public class Databoard extends JPanel {
|
||||
}
|
||||
}
|
||||
|
||||
public static void insertTabSorted(JTabbedPane tabbedPane, String title, Component component) {
|
||||
int insertIndex = 0;
|
||||
int tabCount = tabbedPane.getTabCount();
|
||||
|
||||
// 使用 Collator 实现更友好的语言排序(支持中文、特殊字符等)
|
||||
Collator collator = Collator.getInstance(Locale.getDefault());
|
||||
collator.setStrength(Collator.PRIMARY); // 忽略大小写和重音
|
||||
|
||||
for (int i = 0; i < tabCount; i++) {
|
||||
String existingTitle = tabbedPane.getTitleAt(i);
|
||||
if (collator.compare(existingTitle, title) > 0) {
|
||||
insertIndex = i;
|
||||
break;
|
||||
}
|
||||
insertIndex = i + 1;
|
||||
}
|
||||
|
||||
tabbedPane.insertTab(title, null, component, null, insertIndex);
|
||||
}
|
||||
|
||||
// 提供一个公共方法来发布进度
|
||||
public void publishProgress(int progress) {
|
||||
publish(progress);
|
||||
|
||||
@@ -25,6 +25,7 @@ public class MessageRenderer extends DefaultTableCellRenderer {
|
||||
this.colorMap.put("pink", new Color(0xFF, 0xC8, 0xC8));
|
||||
this.colorMap.put("magenta", new Color(0xFF, 0x64, 0xFF));
|
||||
this.colorMap.put("gray", new Color(0xB4, 0xB4, 0xB4));
|
||||
this.colorMap.put("none", new Color(0, 0, 0, 0));
|
||||
this.table = table;
|
||||
}
|
||||
|
||||
@@ -41,7 +42,7 @@ public class MessageRenderer extends DefaultTableCellRenderer {
|
||||
component.setForeground(Color.BLACK);
|
||||
return component;
|
||||
}
|
||||
|
||||
|
||||
MessageEntry messageEntry = log.get(modelRow);
|
||||
|
||||
// 设置颜色
|
||||
@@ -54,13 +55,8 @@ public class MessageRenderer extends DefaultTableCellRenderer {
|
||||
}
|
||||
|
||||
if (isSelected) {
|
||||
// 通过更改RGB颜色来达成阴影效果
|
||||
int red = Math.max(0, color.getRed() - 0x20);
|
||||
int green = Math.max(0, color.getGreen() - 0x20);
|
||||
int blue = Math.max(0, color.getBlue() - 0x20);
|
||||
component.setBackground(new Color(red, green, blue));
|
||||
component.setBackground(UIManager.getColor("Table.selectionBackground"));
|
||||
} else {
|
||||
// 否则使用原始颜色
|
||||
component.setBackground(color);
|
||||
}
|
||||
|
||||
|
||||
@@ -162,17 +162,17 @@ public class Datatable extends JPanel {
|
||||
}
|
||||
|
||||
private void performSearch() {
|
||||
RowFilter<Object, Object> firstRowFilter = getObjectObjectRowFilter(searchField, true);
|
||||
RowFilter<Object, Object> secondRowFilter = getObjectObjectRowFilter(secondSearchField, false);
|
||||
if (searchField.getForeground().equals(Color.BLACK)) {
|
||||
sorter.setRowFilter(firstRowFilter);
|
||||
if (secondSearchField.getForeground().equals(Color.BLACK)) {
|
||||
List<RowFilter<Object, Object>> filters = new ArrayList<>();
|
||||
filters.add(firstRowFilter);
|
||||
filters.add(secondRowFilter);
|
||||
sorter.setRowFilter(RowFilter.andFilter(filters));
|
||||
}
|
||||
List<RowFilter<Object, Object>> filters = new ArrayList<>();
|
||||
|
||||
if (UIEnhancer.hasUserInput(searchField)) {
|
||||
filters.add(getObjectObjectRowFilter(searchField, true));
|
||||
}
|
||||
|
||||
if (UIEnhancer.hasUserInput(secondSearchField)) {
|
||||
filters.add(getObjectObjectRowFilter(secondSearchField, false));
|
||||
}
|
||||
|
||||
sorter.setRowFilter(filters.isEmpty() ? null : RowFilter.andFilter(filters));
|
||||
}
|
||||
|
||||
private RowFilter<Object, Object> getObjectObjectRowFilter(JTextField searchField, boolean firstFlag) {
|
||||
|
||||
@@ -181,8 +181,7 @@ public class Rule extends JPanel {
|
||||
panel.setOpaque(true);
|
||||
|
||||
// 复制原始组件的样式
|
||||
if (originalComponent instanceof JComponent) {
|
||||
JComponent origComp = (JComponent) originalComponent;
|
||||
if (originalComponent instanceof JComponent origComp) {
|
||||
panel.setBackground(origComp.getBackground());
|
||||
panel.setBorder(origComp.getBorder());
|
||||
}
|
||||
|
||||
@@ -7,38 +7,75 @@ import java.awt.event.FocusListener;
|
||||
|
||||
public class UIEnhancer {
|
||||
public static void setTextFieldPlaceholder(JTextField textField, String placeholderText) {
|
||||
// 使用客户端属性来存储占位符文本和占位符状态
|
||||
// 存储占位符文本
|
||||
textField.putClientProperty("placeholderText", placeholderText);
|
||||
textField.putClientProperty("isPlaceholder", true);
|
||||
|
||||
// 设置占位符文本和颜色
|
||||
setPlaceholderText(textField);
|
||||
updatePlaceholderText(textField);
|
||||
|
||||
textField.addPropertyChangeListener("background", evt -> {
|
||||
updateForeground(textField);
|
||||
});
|
||||
|
||||
textField.addFocusListener(new FocusListener() {
|
||||
@Override
|
||||
public void focusGained(FocusEvent e) {
|
||||
// 当获得焦点且文本是占位符时,清除文本并更改颜色
|
||||
if ((boolean) textField.getClientProperty("isPlaceholder")) {
|
||||
textField.setText("");
|
||||
textField.setForeground(Color.BLACK);
|
||||
if (Boolean.TRUE.equals(textField.getClientProperty("isPlaceholder"))) {
|
||||
textField.putClientProperty("isPlaceholder", false);
|
||||
updateForeground(textField);
|
||||
|
||||
textField.setText("");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusLost(FocusEvent e) {
|
||||
// 当失去焦点且文本为空时,设置占位符文本和颜色
|
||||
if (textField.getText().isEmpty()) {
|
||||
setPlaceholderText(textField);
|
||||
updatePlaceholderText(textField);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
textField.addPropertyChangeListener("text", evt -> {
|
||||
if (Boolean.TRUE.equals(textField.getClientProperty("isPlaceholder"))) {
|
||||
if (!textField.getText().isEmpty()) {
|
||||
textField.putClientProperty("isPlaceholder", false);
|
||||
updateForeground(textField);
|
||||
}
|
||||
} else {
|
||||
if (textField.getText().isEmpty()) {
|
||||
updatePlaceholderText(textField);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void setPlaceholderText(JTextField textField) {
|
||||
private static void updatePlaceholderText(JTextField textField) {
|
||||
String placeholderText = (String) textField.getClientProperty("placeholderText");
|
||||
textField.setForeground(Color.GRAY);
|
||||
textField.setText(placeholderText);
|
||||
textField.putClientProperty("isPlaceholder", true);
|
||||
textField.setText(placeholderText);
|
||||
textField.setForeground(Color.GRAY);
|
||||
}
|
||||
}
|
||||
|
||||
private static void updateForeground(JTextField textField) {
|
||||
Color bg = textField.getBackground();
|
||||
Color fg = isDarkColor(bg) ? Color.WHITE : Color.BLACK;
|
||||
|
||||
if (!Boolean.TRUE.equals(textField.getClientProperty("isPlaceholder"))) {
|
||||
textField.setForeground(fg);
|
||||
textField.putClientProperty("isPlaceholder", false);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isDarkColor(Color color) {
|
||||
double brightness = 0.299 * color.getRed()
|
||||
+ 0.587 * color.getGreen()
|
||||
+ 0.114 * color.getBlue();
|
||||
return brightness < 128;
|
||||
}
|
||||
|
||||
public static boolean hasUserInput(JTextField field) {
|
||||
Object prop = field.getClientProperty("isPlaceholder");
|
||||
return prop instanceof Boolean && !((Boolean) prop);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user