2024-05-06 12:56:56 +08:00
|
|
|
|
package hae.component.board.message;
|
|
|
|
|
|
|
|
|
|
|
|
import burp.api.montoya.MontoyaApi;
|
|
|
|
|
|
import burp.api.montoya.core.ByteArray;
|
|
|
|
|
|
import burp.api.montoya.http.message.HttpHeader;
|
|
|
|
|
|
import burp.api.montoya.http.message.HttpRequestResponse;
|
|
|
|
|
|
import burp.api.montoya.http.message.requests.HttpRequest;
|
|
|
|
|
|
import burp.api.montoya.http.message.responses.HttpResponse;
|
|
|
|
|
|
import burp.api.montoya.ui.UserInterface;
|
|
|
|
|
|
import burp.api.montoya.ui.editor.HttpRequestEditor;
|
|
|
|
|
|
import burp.api.montoya.ui.editor.HttpResponseEditor;
|
|
|
|
|
|
import hae.Config;
|
|
|
|
|
|
import hae.cache.CachePool;
|
|
|
|
|
|
import hae.utils.string.HashCalculator;
|
|
|
|
|
|
import hae.utils.string.StringProcessor;
|
|
|
|
|
|
|
2023-10-18 15:14:48 +08:00
|
|
|
|
import java.nio.charset.StandardCharsets;
|
2024-02-02 19:07:03 +08:00
|
|
|
|
import java.text.MessageFormat;
|
2024-05-06 12:56:56 +08:00
|
|
|
|
import java.util.*;
|
2023-10-12 21:38:27 +08:00
|
|
|
|
import javax.swing.JScrollPane;
|
|
|
|
|
|
import javax.swing.JSplitPane;
|
|
|
|
|
|
import javax.swing.JTabbedPane;
|
|
|
|
|
|
import javax.swing.JTable;
|
|
|
|
|
|
import javax.swing.SwingWorker;
|
|
|
|
|
|
import javax.swing.table.AbstractTableModel;
|
|
|
|
|
|
import javax.swing.table.DefaultTableModel;
|
|
|
|
|
|
import javax.swing.table.TableModel;
|
|
|
|
|
|
import javax.swing.table.TableRowSorter;
|
2024-05-06 12:56:56 +08:00
|
|
|
|
import java.util.concurrent.atomic.AtomicBoolean;
|
|
|
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
|
|
|
|
import static burp.api.montoya.ui.editor.EditorOptions.READ_ONLY;
|
|
|
|
|
|
|
|
|
|
|
|
public class MessageTableModel extends AbstractTableModel {
|
|
|
|
|
|
private final MontoyaApi api;
|
|
|
|
|
|
private final MessageTable messageTable;
|
|
|
|
|
|
private final JTabbedPane messageTab;
|
|
|
|
|
|
private final JSplitPane splitPane;
|
|
|
|
|
|
private final List<MessageEntry> log = new ArrayList<MessageEntry>();
|
|
|
|
|
|
private LinkedList<MessageEntry> filteredLog;
|
|
|
|
|
|
|
|
|
|
|
|
public MessageTableModel(MontoyaApi api) {
|
|
|
|
|
|
this.filteredLog = new LinkedList<>();
|
|
|
|
|
|
this.api = api;
|
|
|
|
|
|
|
|
|
|
|
|
messageTab = new JTabbedPane();
|
|
|
|
|
|
UserInterface userInterface = api.userInterface();
|
|
|
|
|
|
HttpRequestEditor requestViewer = userInterface.createHttpRequestEditor(READ_ONLY);
|
|
|
|
|
|
HttpResponseEditor responseViewer = userInterface.createHttpResponseEditor(READ_ONLY);
|
|
|
|
|
|
messageTab.addTab("Request", requestViewer.uiComponent());
|
|
|
|
|
|
messageTab.addTab("Response", responseViewer.uiComponent());
|
|
|
|
|
|
|
|
|
|
|
|
// 请求条目表格
|
|
|
|
|
|
messageTable = new MessageTable(MessageTableModel.this, requestViewer, responseViewer);
|
|
|
|
|
|
messageTable.setDefaultRenderer(Object.class, new MessageRenderer(filteredLog, messageTable));
|
|
|
|
|
|
messageTable.setAutoCreateRowSorter(true);
|
2023-10-12 21:38:27 +08:00
|
|
|
|
|
|
|
|
|
|
// Length字段根据大小进行排序
|
2024-05-06 12:56:56 +08:00
|
|
|
|
TableRowSorter<DefaultTableModel> sorter = (TableRowSorter<DefaultTableModel>) messageTable.getRowSorter();
|
2023-10-26 14:17:56 +08:00
|
|
|
|
sorter.setComparator(4, new Comparator<String>() {
|
2023-10-12 21:38:27 +08:00
|
|
|
|
@Override
|
|
|
|
|
|
public int compare(String s1, String s2) {
|
|
|
|
|
|
Integer age1 = Integer.parseInt(s1);
|
|
|
|
|
|
Integer age2 = Integer.parseInt(s2);
|
|
|
|
|
|
return age1.compareTo(age2);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2024-01-18 12:07:20 +08:00
|
|
|
|
|
2023-10-12 21:38:27 +08:00
|
|
|
|
// Color字段根据颜色顺序进行排序
|
2023-10-26 14:17:56 +08:00
|
|
|
|
sorter.setComparator(5, new Comparator<String>() {
|
2023-10-12 21:38:27 +08:00
|
|
|
|
@Override
|
|
|
|
|
|
public int compare(String s1, String s2) {
|
|
|
|
|
|
int index1 = getIndex(s1);
|
|
|
|
|
|
int index2 = getIndex(s2);
|
|
|
|
|
|
return Integer.compare(index1, index2);
|
|
|
|
|
|
}
|
|
|
|
|
|
private int getIndex(String color) {
|
2024-05-06 12:56:56 +08:00
|
|
|
|
for (int i = 0; i < Config.color.length; i++) {
|
|
|
|
|
|
if (Config.color[i].equals(color)) {
|
2023-10-12 21:38:27 +08:00
|
|
|
|
return i;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2024-05-06 12:56:56 +08:00
|
|
|
|
messageTable.setRowSorter(sorter);
|
|
|
|
|
|
messageTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
|
2023-10-12 21:38:27 +08:00
|
|
|
|
|
2024-05-06 12:56:56 +08:00
|
|
|
|
splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
|
|
|
|
|
|
// 请求/相应文本框
|
|
|
|
|
|
JScrollPane scrollPane = new JScrollPane(messageTable);
|
2023-10-12 21:38:27 +08:00
|
|
|
|
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
|
|
|
|
|
|
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
|
|
|
|
|
|
splitPane.setLeftComponent(scrollPane);
|
2024-05-06 12:56:56 +08:00
|
|
|
|
splitPane.setRightComponent(messageTab);
|
2023-10-12 21:38:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-05-06 12:56:56 +08:00
|
|
|
|
public void add(HttpRequestResponse messageInfo, String comment, String color) {
|
|
|
|
|
|
synchronized(log) {
|
|
|
|
|
|
HttpRequest httpRequest = messageInfo.request();
|
|
|
|
|
|
String url = httpRequest.url();
|
|
|
|
|
|
String method = httpRequest.method();
|
2023-10-12 21:38:27 +08:00
|
|
|
|
|
2024-05-06 12:56:56 +08:00
|
|
|
|
HttpResponse httpResponse = messageInfo.response();
|
|
|
|
|
|
String status = String.valueOf(httpResponse.statusCode());
|
|
|
|
|
|
String length = String.valueOf(httpResponse.body().length());
|
2023-10-12 21:38:27 +08:00
|
|
|
|
|
2024-05-06 12:56:56 +08:00
|
|
|
|
MessageEntry logEntry = new MessageEntry(messageInfo, method, url, comment, length, color, status);
|
2023-10-12 21:38:27 +08:00
|
|
|
|
|
2024-05-06 12:56:56 +08:00
|
|
|
|
try {
|
|
|
|
|
|
// 比较Hash,如若存在重复的请求或响应,则不放入消息内容里
|
|
|
|
|
|
byte[] reqByteA = httpRequest.toByteArray().getBytes();
|
|
|
|
|
|
byte[] resByteA = httpResponse.toByteArray().getBytes();
|
|
|
|
|
|
boolean isDuplicate = false;
|
2023-10-12 21:38:27 +08:00
|
|
|
|
|
2024-05-06 12:56:56 +08:00
|
|
|
|
if (log.size() > 0) {
|
|
|
|
|
|
for (MessageEntry entry : log) {
|
|
|
|
|
|
HttpRequestResponse reqResMessage = entry.getRequestResponse();
|
|
|
|
|
|
byte[] reqByteB = reqResMessage.request().toByteArray().getBytes();
|
|
|
|
|
|
byte[] resByteB = reqResMessage.response().toByteArray().getBytes();
|
|
|
|
|
|
try {
|
|
|
|
|
|
// 通过URL、请求和响应报文、匹配数据内容,多维度进行对比
|
|
|
|
|
|
if ((entry.getUrl().toString().equals(url.toString()) || (Arrays.equals(reqByteB, reqByteA) || Arrays.equals(resByteB, resByteA))) && (areMapsEqual(getCacheData(reqByteB), getCacheData(reqByteA)) && areMapsEqual(getCacheData(resByteB), getCacheData(resByteA)))) {
|
|
|
|
|
|
isDuplicate = true;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (Exception ignored) {
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-10-12 21:38:27 +08:00
|
|
|
|
|
2024-05-06 12:56:56 +08:00
|
|
|
|
if (!isDuplicate) {
|
|
|
|
|
|
log.add(logEntry);
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (Exception ignored) {
|
|
|
|
|
|
}
|
2023-10-12 21:38:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-05-06 12:56:56 +08:00
|
|
|
|
public void deleteByHost(String filterText) {
|
|
|
|
|
|
filteredLog.clear();
|
|
|
|
|
|
List<Integer> rowsToRemove = new ArrayList<>();
|
|
|
|
|
|
for (int i = 0; i < log.size(); i++) {
|
|
|
|
|
|
MessageEntry entry = log.get(i);
|
|
|
|
|
|
String host = StringProcessor.getHostByUrl(entry.getUrl());
|
|
|
|
|
|
if (!host.isEmpty()) {
|
|
|
|
|
|
if (StringProcessor.matchFromEnd(host, filterText) || filterText.contains("*")) {
|
|
|
|
|
|
rowsToRemove.add(i);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-11-07 11:15:20 +08:00
|
|
|
|
}
|
2024-05-06 12:56:56 +08:00
|
|
|
|
|
|
|
|
|
|
for (int i = rowsToRemove.size() - 1; i >= 0; i--) {
|
|
|
|
|
|
int row = rowsToRemove.get(i);
|
|
|
|
|
|
log.remove(row);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!rowsToRemove.isEmpty()) {
|
|
|
|
|
|
int[] rows = rowsToRemove.stream().mapToInt(Integer::intValue).toArray();
|
|
|
|
|
|
fireTableRowsDeleted(rows[0], rows[rows.length - 1]);
|
2023-10-12 21:38:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void applyHostFilter(String filterText) {
|
|
|
|
|
|
filteredLog.clear();
|
|
|
|
|
|
fireTableDataChanged();
|
2024-05-06 12:56:56 +08:00
|
|
|
|
String cleanedText = StringProcessor.replaceFirstOccurrence(filterText, "*.", "");
|
|
|
|
|
|
|
|
|
|
|
|
for (MessageEntry entry : log) {
|
|
|
|
|
|
String host = StringProcessor.getHostByUrl(entry.getUrl());
|
|
|
|
|
|
if (!host.isEmpty()) {
|
|
|
|
|
|
if (filterText.contains("*.") && StringProcessor.matchFromEnd(host, cleanedText)) {
|
|
|
|
|
|
filteredLog.add(entry);
|
|
|
|
|
|
} else if (host.equals(filterText) || filterText.contains("*")) {
|
|
|
|
|
|
filteredLog.add(entry);
|
|
|
|
|
|
}
|
2023-10-12 21:38:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-05-06 12:56:56 +08:00
|
|
|
|
|
2023-10-12 21:38:27 +08:00
|
|
|
|
fireTableDataChanged();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void applyMessageFilter(String tableName, String filterText) {
|
|
|
|
|
|
filteredLog.clear();
|
2024-05-06 12:56:56 +08:00
|
|
|
|
for (MessageEntry entry : log) {
|
|
|
|
|
|
HttpRequestResponse requestResponse = entry.getRequestResponse();
|
|
|
|
|
|
HttpRequest httpRequest = requestResponse.request();
|
|
|
|
|
|
HttpResponse httpResponse = requestResponse.response();
|
|
|
|
|
|
|
|
|
|
|
|
String requestString = new String(httpRequest.toByteArray().getBytes(), StandardCharsets.UTF_8);
|
|
|
|
|
|
String requestBody = new String(httpRequest.body().getBytes(), StandardCharsets.UTF_8);
|
|
|
|
|
|
String requestHeaders = httpRequest.headers().stream()
|
|
|
|
|
|
.map(HttpHeader::toString)
|
|
|
|
|
|
.collect(Collectors.joining("\n"));
|
|
|
|
|
|
|
|
|
|
|
|
String responseString = new String(httpResponse.toByteArray().getBytes(), StandardCharsets.UTF_8);
|
|
|
|
|
|
String responseBody = new String(httpResponse.body().getBytes(), StandardCharsets.UTF_8);
|
|
|
|
|
|
String responseHeaders = httpResponse.headers().stream()
|
|
|
|
|
|
.map(HttpHeader::toString)
|
|
|
|
|
|
.collect(Collectors.joining("\n"));
|
2023-10-12 21:38:27 +08:00
|
|
|
|
|
2024-02-02 19:07:03 +08:00
|
|
|
|
// 标志变量,表示是否满足过滤条件
|
|
|
|
|
|
AtomicBoolean isMatched = new AtomicBoolean(false);
|
2023-10-12 21:38:27 +08:00
|
|
|
|
|
2024-05-06 12:56:56 +08:00
|
|
|
|
Config.globalRules.keySet().forEach(i -> {
|
|
|
|
|
|
for (Object[] objects : Config.globalRules.get(i)) {
|
2023-10-12 21:38:27 +08:00
|
|
|
|
String name = objects[1].toString();
|
2024-02-02 19:07:03 +08:00
|
|
|
|
String format = objects[4].toString();
|
|
|
|
|
|
String scope = objects[6].toString();
|
|
|
|
|
|
|
|
|
|
|
|
// 从注释中查看是否包含当前规则名,包含的再进行查询,有效减少无意义的检索时间
|
|
|
|
|
|
if (entry.getComment().contains(name)) {
|
|
|
|
|
|
if (name.equals(tableName)) {
|
|
|
|
|
|
// 标志变量,表示当前规则是否匹配
|
|
|
|
|
|
boolean isMatch = false;
|
|
|
|
|
|
|
|
|
|
|
|
switch (scope) {
|
|
|
|
|
|
case "any":
|
|
|
|
|
|
isMatch = matchingString(format, filterText, requestString) || matchingString(format, filterText, responseString);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "request":
|
|
|
|
|
|
isMatch = matchingString(format, filterText, requestString);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "response":
|
|
|
|
|
|
isMatch = matchingString(format, filterText, responseString);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "any header":
|
|
|
|
|
|
isMatch = matchingString(format, filterText, requestHeaders) || matchingString(format, filterText, responseHeaders);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "request header":
|
|
|
|
|
|
isMatch = matchingString(format, filterText, requestHeaders);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "response header":
|
|
|
|
|
|
isMatch = matchingString(format, filterText, responseHeaders);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "any body":
|
|
|
|
|
|
isMatch = matchingString(format, filterText, requestBody) || matchingString(format, filterText, responseBody);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "request body":
|
|
|
|
|
|
isMatch = matchingString(format, filterText, requestBody);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "response body":
|
|
|
|
|
|
isMatch = matchingString(format, filterText, responseBody);
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
isMatched.set(isMatch);
|
2023-10-12 21:38:27 +08:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2024-02-02 19:07:03 +08:00
|
|
|
|
if (isMatched.get()) {
|
2023-10-12 21:38:27 +08:00
|
|
|
|
filteredLog.add(entry);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-05-06 12:56:56 +08:00
|
|
|
|
|
2023-10-12 21:38:27 +08:00
|
|
|
|
fireTableDataChanged();
|
2024-05-06 12:56:56 +08:00
|
|
|
|
messageTable.lastSelectedIndex = -1;
|
2023-10-12 21:38:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-02-02 19:07:03 +08:00
|
|
|
|
private boolean matchingString(String format, String filterText, String target) {
|
|
|
|
|
|
boolean isMatch = true;
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
MessageFormat mf = new MessageFormat(format);
|
|
|
|
|
|
Object[] parsedObjects = mf.parse(filterText);
|
|
|
|
|
|
|
|
|
|
|
|
for (Object parsedObject : parsedObjects) {
|
|
|
|
|
|
if (!target.contains(parsedObject.toString())) {
|
|
|
|
|
|
isMatch = false;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
isMatch = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return isMatch;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-05-06 12:56:56 +08:00
|
|
|
|
private Map<String, Map<String, Object>> getCacheData(byte[] content) {
|
2023-10-24 17:51:21 +08:00
|
|
|
|
String hashIndex = HashCalculator.calculateHash(content);
|
2024-05-06 12:56:56 +08:00
|
|
|
|
return CachePool.getFromCache(hashIndex);
|
2023-10-24 17:51:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private boolean areMapsEqual(Map<String, Map<String, Object>> map1, Map<String, Map<String, Object>> map2) {
|
2023-11-07 11:15:20 +08:00
|
|
|
|
if (map1 == null || map2 == null) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2023-10-24 17:51:21 +08:00
|
|
|
|
if (map1.size() != map2.size()) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for (String key : map1.keySet()) {
|
|
|
|
|
|
if (!map2.containsKey(key)) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!areInnerMapsEqual(map1.get(key), map2.get(key))) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private boolean areInnerMapsEqual(Map<String, Object> innerMap1, Map<String, Object> innerMap2) {
|
|
|
|
|
|
if (innerMap1.size() != innerMap2.size()) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for (String key : innerMap1.keySet()) {
|
|
|
|
|
|
if (!innerMap2.containsKey(key)) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
Object value1 = innerMap1.get(key);
|
|
|
|
|
|
Object value2 = innerMap2.get(key);
|
|
|
|
|
|
|
|
|
|
|
|
// 如果值是Map,则递归对比
|
|
|
|
|
|
if (value1 instanceof Map && value2 instanceof Map) {
|
|
|
|
|
|
if (!areInnerMapsEqual((Map<String, Object>) value1, (Map<String, Object>) value2)) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
} else if (!value1.equals(value2)) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2023-10-23 21:51:12 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-10-24 17:51:21 +08:00
|
|
|
|
return true;
|
2023-10-12 21:38:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-05-06 12:56:56 +08:00
|
|
|
|
|
|
|
|
|
|
public JSplitPane getSplitPane()
|
|
|
|
|
|
{
|
|
|
|
|
|
return splitPane;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public MessageTable getMessageTable()
|
|
|
|
|
|
{
|
|
|
|
|
|
return messageTable;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public List<MessageEntry> getLogs() {
|
|
|
|
|
|
return log;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public int getRowCount() {
|
|
|
|
|
|
return filteredLog.size();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public int getColumnCount() {
|
|
|
|
|
|
return 6;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public Object getValueAt(int rowIndex, int columnIndex)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (filteredLog.isEmpty()) {
|
|
|
|
|
|
return "";
|
|
|
|
|
|
}
|
|
|
|
|
|
MessageEntry messageEntry = filteredLog.get(rowIndex);
|
|
|
|
|
|
|
|
|
|
|
|
return switch (columnIndex) {
|
|
|
|
|
|
case 0 -> messageEntry.getMethod();
|
|
|
|
|
|
case 1 -> messageEntry.getUrl();
|
|
|
|
|
|
case 2 -> messageEntry.getComment();
|
|
|
|
|
|
case 3 -> messageEntry.getStatus();
|
|
|
|
|
|
case 4 -> messageEntry.getLength();
|
|
|
|
|
|
case 5 -> messageEntry.getColor();
|
|
|
|
|
|
default -> "";
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public String getColumnName(int columnIndex)
|
|
|
|
|
|
{
|
|
|
|
|
|
return switch (columnIndex) {
|
|
|
|
|
|
case 0 -> "Method";
|
|
|
|
|
|
case 1 -> "URL";
|
|
|
|
|
|
case 2 -> "Comment";
|
|
|
|
|
|
case 3 -> "Status";
|
|
|
|
|
|
case 4 -> "Length";
|
|
|
|
|
|
case 5 -> "Color";
|
|
|
|
|
|
default -> "";
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public class MessageTable extends JTable {
|
|
|
|
|
|
private MessageEntry MessageEntry;
|
2023-11-07 11:15:20 +08:00
|
|
|
|
private SwingWorker<Object, Void> currentWorker;
|
|
|
|
|
|
// 设置响应报文返回的最大长度为3MB
|
|
|
|
|
|
private final int MAX_LENGTH = 3145728;
|
|
|
|
|
|
private int lastSelectedIndex = -1;
|
2024-05-06 12:56:56 +08:00
|
|
|
|
private final HttpRequestEditor requestEditor;
|
|
|
|
|
|
private final HttpResponseEditor responseEditor;
|
2023-10-12 21:38:27 +08:00
|
|
|
|
|
2024-05-06 12:56:56 +08:00
|
|
|
|
public MessageTable(TableModel messageTableModel, HttpRequestEditor requestEditor, HttpResponseEditor responseEditor) {
|
|
|
|
|
|
super(messageTableModel);
|
|
|
|
|
|
this.requestEditor = requestEditor;
|
|
|
|
|
|
this.responseEditor = responseEditor;
|
2023-10-12 21:38:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void changeSelection(int row, int col, boolean toggle, boolean extend) {
|
2023-10-23 21:51:12 +08:00
|
|
|
|
super.changeSelection(row, col, toggle, extend);
|
2023-11-07 11:15:20 +08:00
|
|
|
|
int selectedIndex = convertRowIndexToModel(row);
|
|
|
|
|
|
if (lastSelectedIndex != selectedIndex) {
|
|
|
|
|
|
lastSelectedIndex = selectedIndex;
|
2024-05-06 12:56:56 +08:00
|
|
|
|
MessageEntry = filteredLog.get(selectedIndex);
|
2023-10-23 21:51:12 +08:00
|
|
|
|
|
2024-05-06 12:56:56 +08:00
|
|
|
|
requestEditor.setRequest(HttpRequest.httpRequest("Loading..."));
|
|
|
|
|
|
responseEditor.setResponse(HttpResponse.httpResponse("Loading..."));
|
2023-10-12 21:38:27 +08:00
|
|
|
|
|
2023-11-07 11:15:20 +08:00
|
|
|
|
if (currentWorker != null && !currentWorker.isDone()) {
|
|
|
|
|
|
currentWorker.cancel(true);
|
2023-10-12 21:38:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-05-06 12:56:56 +08:00
|
|
|
|
currentWorker = new SwingWorker<>() {
|
2023-11-07 11:15:20 +08:00
|
|
|
|
@Override
|
2024-05-06 12:56:56 +08:00
|
|
|
|
protected ByteArray[] doInBackground() {
|
|
|
|
|
|
ByteArray requestByte = MessageEntry.getRequestResponse().request().toByteArray();
|
|
|
|
|
|
ByteArray responseByte = MessageEntry.getRequestResponse().response().toByteArray();
|
2023-11-07 11:15:20 +08:00
|
|
|
|
|
2024-05-06 12:56:56 +08:00
|
|
|
|
if (responseByte.length() > MAX_LENGTH) {
|
2023-11-07 11:15:20 +08:00
|
|
|
|
String ellipsis = "\r\n......";
|
2024-05-06 12:56:56 +08:00
|
|
|
|
responseByte = responseByte.subArray(0, MAX_LENGTH).withAppended(ellipsis);
|
2023-11-07 11:15:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-05-06 12:56:56 +08:00
|
|
|
|
return new ByteArray[]{requestByte, responseByte};
|
2023-11-07 11:15:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
protected void done() {
|
|
|
|
|
|
if (!isCancelled()) {
|
|
|
|
|
|
try {
|
2024-05-06 12:56:56 +08:00
|
|
|
|
ByteArray[] result = (ByteArray[]) get();
|
|
|
|
|
|
requestEditor.setRequest(HttpRequest.httpRequest(MessageEntry.getRequestResponse().httpService(), result[0]));
|
|
|
|
|
|
responseEditor.setResponse(HttpResponse.httpResponse(result[1]));
|
2023-11-07 11:15:20 +08:00
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
currentWorker.execute();
|
|
|
|
|
|
}
|
2023-10-12 21:38:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-05-06 12:56:56 +08:00
|
|
|
|
}
|