mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-14 17:06:16 +00:00
integrating jsoup
This commit is contained in:
parent
23782a90cc
commit
f6ed6462a2
@ -20,8 +20,14 @@ package org.sleuthkit.autopsy.contentviewers;
|
|||||||
|
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import javax.swing.JLabel;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.apache.commons.lang3.StringEscapeUtils;
|
import org.apache.commons.lang3.StringEscapeUtils;
|
||||||
|
|
||||||
@ -48,6 +54,10 @@ import org.sleuthkit.datamodel.Tag;
|
|||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
||||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||||
|
import org.jsoup.Jsoup;
|
||||||
|
import org.jsoup.nodes.Document;
|
||||||
|
import org.jsoup.nodes.Element;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Annotations view of file contents.
|
* Annotations view of file contents.
|
||||||
@ -77,7 +87,8 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder html = new StringBuilder();
|
Document html = Jsoup.parse(EMPTY_HTML);
|
||||||
|
Element body = html.getElementsByTag("body").first();
|
||||||
|
|
||||||
BlackboardArtifact artifact = node.getLookup().lookup(BlackboardArtifact.class);
|
BlackboardArtifact artifact = node.getLookup().lookup(BlackboardArtifact.class);
|
||||||
Content sourceFile = null;
|
Content sourceFile = null;
|
||||||
@ -104,20 +115,22 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (artifact != null) {
|
if (artifact != null) {
|
||||||
populateTagData(html, artifact, sourceFile);
|
populateTagData(body, artifact, sourceFile);
|
||||||
} else {
|
} else {
|
||||||
populateTagData(html, sourceFile);
|
populateTagData(body, sourceFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sourceFile instanceof AbstractFile) {
|
if (sourceFile instanceof AbstractFile) {
|
||||||
populateCentralRepositoryData(html, artifact, (AbstractFile) sourceFile);
|
populateCentralRepositoryData(body, artifact, (AbstractFile) sourceFile);
|
||||||
populateFileSetData(html, sourceFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT);
|
populateFileSetData(body, sourceFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT);
|
||||||
populateFileSetData(html, sourceFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT);
|
populateFileSetData(body, sourceFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
setText(html.toString());
|
jTextPane1.setText(html.html());
|
||||||
jTextPane1.setCaretPosition(0);
|
jTextPane1.setCaretPosition(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Populates the html provided with data concerning the source file and
|
* Populates the html provided with data concerning the source file and
|
||||||
@ -285,9 +298,15 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data
|
|||||||
* @param sourceFile A selected file, or a source file of the selected
|
* @param sourceFile A selected file, or a source file of the selected
|
||||||
* artifact.
|
* artifact.
|
||||||
*/
|
*/
|
||||||
private void populateCentralRepositoryData(StringBuilder html, BlackboardArtifact artifact, AbstractFile sourceFile) {
|
@NbBundle.Messages({
|
||||||
|
"AnnotationsContentViewer.centralRepositoryEntryDataLabel.case=Case:",
|
||||||
|
"AnnotationsContentViewer.centralRepositoryEntryDataLabel.type=Type:",
|
||||||
|
"AnnotationsContentViewer.centralRepositoryEntryDataLabel.comment=Comment:",
|
||||||
|
"AnnotationsContentViewer.centralRepositoryEntryDataLabel.path=Path:"
|
||||||
|
})
|
||||||
|
private List<CorrelationAttributeInstance> populateCentralRepositoryData(StringBuilder html, BlackboardArtifact artifact, AbstractFile sourceFile) {
|
||||||
if (CentralRepository.isEnabled()) {
|
if (CentralRepository.isEnabled()) {
|
||||||
startSection(html, "Central Repository Comments");
|
//startSection(html, "Central Repository Comments");
|
||||||
List<CorrelationAttributeInstance> instancesList = new ArrayList<>();
|
List<CorrelationAttributeInstance> instancesList = new ArrayList<>();
|
||||||
if (artifact != null) {
|
if (artifact != null) {
|
||||||
instancesList.addAll(CorrelationAttributeUtil.makeCorrAttrsForCorrelation(artifact));
|
instancesList.addAll(CorrelationAttributeUtil.makeCorrAttrsForCorrelation(artifact));
|
||||||
@ -338,38 +357,6 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the text of the text panel.
|
|
||||||
*
|
|
||||||
* @param text The text to set to the text panel.
|
|
||||||
*/
|
|
||||||
private void setText(String text) {
|
|
||||||
jTextPane1.setText("<html><body>" + text + "</body></html>"); //NON-NLS
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start a new data section.
|
|
||||||
*
|
|
||||||
* @param html The HTML text to add the section to.
|
|
||||||
* @param sectionName The name of the section.
|
|
||||||
*/
|
|
||||||
private void startSection(StringBuilder html, String sectionName) {
|
|
||||||
html.append("<p style=\"font-size:14px;font-weight:bold;\">")
|
|
||||||
.append(sectionName)
|
|
||||||
.append("</p><br>"); //NON-NLS
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a message.
|
|
||||||
*
|
|
||||||
* @param html The HTML text to add the message to.
|
|
||||||
* @param message The message text.
|
|
||||||
*/
|
|
||||||
private void addMessage(StringBuilder html, String message) {
|
|
||||||
html.append("<p style=\"font-size:11px;font-style:italic;\">")
|
|
||||||
.append(message)
|
|
||||||
.append("</p><br>"); //NON-NLS
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a data table containing information about a tag.
|
* Add a data table containing information about a tag.
|
||||||
@ -390,83 +377,137 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data
|
|||||||
endTable(html);
|
endTable(html);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a data table containing information about a correlation attribute
|
private static final String EMPTY_HTML = "<html><head></head><body></body></html>";
|
||||||
* instance in the Central Repository.
|
|
||||||
*
|
private static final int DEFAULT_FONT_SIZE = new JLabel().getFont().getSize();
|
||||||
* @param html The HTML text to add the table to.
|
private static final int SUBHEADER_FONT_SIZE = DEFAULT_FONT_SIZE * 12 / 11;
|
||||||
* @param attributeInstance The attribute instance whose information will be
|
private static final int HEADER_FONT_SIZE = DEFAULT_FONT_SIZE * 14 / 11;
|
||||||
* used to populate the table.
|
|
||||||
*/
|
private static final String HEADER_STYLE = "font-size:" + HEADER_FONT_SIZE + "px;font-weight:bold;";
|
||||||
@NbBundle.Messages({
|
private static final String SUBHEADER_STYLE = "font-size:" + SUBHEADER_FONT_SIZE + "px;font-weight:bold;";
|
||||||
"AnnotationsContentViewer.centralRepositoryEntryDataLabel.case=Case:",
|
private static final String MESSAGE_STYLE = "font-size:" + DEFAULT_FONT_SIZE + "px;font-style:italic;";
|
||||||
"AnnotationsContentViewer.centralRepositoryEntryDataLabel.type=Type:",
|
private static final String CONTENT_STYLE = "font-size:" + DEFAULT_FONT_SIZE + "px;";
|
||||||
"AnnotationsContentViewer.centralRepositoryEntryDataLabel.comment=Comment:",
|
|
||||||
"AnnotationsContentViewer.centralRepositoryEntryDataLabel.path=Path:"
|
private static final int DEFAULT_TABLE_SPACING = DEFAULT_FONT_SIZE * 2;
|
||||||
})
|
private static final int DEFAULT_SECTION_SPACING = DEFAULT_FONT_SIZE;
|
||||||
private void addCentralRepositoryEntry(StringBuilder html, CorrelationAttributeInstance attributeInstance) {
|
private static final int DEFAULT_SUBSECTION_SPACING = DEFAULT_FONT_SIZE;
|
||||||
startTable(html);
|
|
||||||
addRow(html, Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_case(), attributeInstance.getCorrelationCase().getDisplayName());
|
|
||||||
addRow(html, Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_type(), attributeInstance.getCorrelationType().getDisplayName());
|
private static final List<ColumnEntry<CorrelationAttributeInstance>> CENTRAL_REPO_COMMENTS = Arrays.asList(
|
||||||
addRow(html, Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_comment(), formatHtmlString(attributeInstance.getComment()));
|
new ColumnEntry<>(Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_case(), cai -> cai.getCorrelationCase().getDisplayName()),
|
||||||
addRow(html, Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_path(), attributeInstance.getFilePath());
|
new ColumnEntry<>(Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_type(), cai -> cai.getCorrelationType().getDisplayName()),
|
||||||
endTable(html);
|
new ColumnEntry<>(Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_comment(), cai -> cai.getComment()),
|
||||||
|
new ColumnEntry<>(Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_path(), cai -> cai.getFilePath())
|
||||||
|
);
|
||||||
|
|
||||||
|
private static class ColumnEntry<T> {
|
||||||
|
private final String columnName;
|
||||||
|
private final Function<T,String> valueRetriever;
|
||||||
|
|
||||||
|
ColumnEntry(String columnName, Function<T, String> valueRetriever) {
|
||||||
|
this.columnName = columnName;
|
||||||
|
this.valueRetriever = valueRetriever;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getColumnName() {
|
||||||
|
return columnName;
|
||||||
|
}
|
||||||
|
|
||||||
|
Function<T, String> getValueRetriever() {
|
||||||
|
return valueRetriever;
|
||||||
|
}
|
||||||
|
|
||||||
|
String retrieveValue(T object) {
|
||||||
|
return valueRetriever.apply(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> Element appendVerticalEntryTables(Element parent, List<T> items, List<ColumnEntry<T>> rowHeaders) {
|
||||||
|
items.stream()
|
||||||
|
.filter(item -> item != null)
|
||||||
|
.forEach((item) -> {
|
||||||
|
List<List<String>> tableData = rowHeaders.stream()
|
||||||
|
.map(row -> Arrays.asList(row.getColumnName(), row.retrieveValue(item)))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
Element childTable = appendTable(parent, 2, tableData, null);
|
||||||
|
childTable.attr("style", String.format("margin-bottom: %dpx", DEFAULT_TABLE_SPACING));
|
||||||
|
});
|
||||||
|
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> Element appendEntryTable(Element parent, List<T> items, List<ColumnEntry<T>> columns) {
|
||||||
|
int columnNumber = columns.size();
|
||||||
|
List<String> columnHeaders = columns.stream().map(c -> c.getColumnName()).collect(Collectors.toList());
|
||||||
|
List<List<String>> rows = items.stream()
|
||||||
|
.filter(r -> r != null)
|
||||||
|
.map(r -> {
|
||||||
|
return columns.stream()
|
||||||
|
.map(c -> c.retrieveValue(r))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
})
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
Element table = appendTable(parent, columnNumber, rows, columnHeaders);
|
||||||
|
table.attr("style", String.format("margin-bottom: %dpx", DEFAULT_TABLE_SPACING));
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Element appendTable(Element parent, int columnNumber, List<List<String>> content, List<String> columnHeaders) {
|
||||||
|
Element table = parent.appendElement("table");
|
||||||
|
if (columnHeaders != null && !columnHeaders.isEmpty()) {
|
||||||
|
Element header = parent.appendElement("thead");
|
||||||
|
appendRow(header, columnHeaders, columnNumber, true);
|
||||||
|
}
|
||||||
|
Element tableBody = table.appendElement("tbody");
|
||||||
|
|
||||||
|
content.forEach((rowData) -> appendRow(tableBody, rowData, columnNumber, false));
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO test sanitizing string
|
||||||
|
private Element appendRow(Element rowParent, List<String> data, int columnNumber, boolean isHeader) {
|
||||||
|
String cellType = isHeader ? "th" : "td";
|
||||||
|
Element row = rowParent.appendElement("tr");
|
||||||
|
for (int i = 0; i < columnNumber; i++) {
|
||||||
|
Element cell = row.appendElement(cellType);
|
||||||
|
if (data != null && i < data.size()) {
|
||||||
|
cell.attr("valign", "top");
|
||||||
|
cell.attr("style", CONTENT_STYLE);
|
||||||
|
cell.text(StringUtils.isEmpty(data.get(i)) ? "" : data.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Element appendSection(Element parent, String headerText) {
|
||||||
|
Element parentDiv = parent.appendElement("div");
|
||||||
|
parentDiv.attr("style", String.format("margin-bottom: %dpx;", DEFAULT_SECTION_SPACING));
|
||||||
|
Element header = parentDiv.appendElement("h1");
|
||||||
|
header.text(headerText);
|
||||||
|
header.attr("style", HEADER_STYLE);
|
||||||
|
return parentDiv;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Element appendSubsection(Element parent, String headerText) {
|
||||||
|
Element parentDiv = parent.appendElement("div");
|
||||||
|
parentDiv.attr("style", String.format("margin-bottom: %dpx;", DEFAULT_SUBSECTION_SPACING));
|
||||||
|
Element header = parentDiv.appendElement("h2");
|
||||||
|
header.text(headerText);
|
||||||
|
header.attr("style", SUBHEADER_STYLE);
|
||||||
|
return parentDiv;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Element appendMessage(Element parent, String message) {
|
||||||
|
Element messageEl = parent.appendElement("p");
|
||||||
|
messageEl.text(message);
|
||||||
|
messageEl.attr("style", MESSAGE_STYLE);
|
||||||
|
return messageEl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Start a data table.
|
|
||||||
*
|
|
||||||
* @param html The HTML text to add the table to.
|
|
||||||
*/
|
|
||||||
private void startTable(StringBuilder html) {
|
|
||||||
html.append("<table>"); //NON-NLS
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a data row to a table.
|
|
||||||
*
|
|
||||||
* @param html The HTML text to add the row to.
|
|
||||||
* @param key The key for the left column of the data row.
|
|
||||||
* @param value The value for the right column of the data row.
|
|
||||||
*/
|
|
||||||
private void addRow(StringBuilder html, String key, String value) {
|
|
||||||
html.append("<tr><td valign=\"top\">"); //NON-NLS
|
|
||||||
html.append(key);
|
|
||||||
html.append("</td><td>"); //NON-NLS
|
|
||||||
html.append(value);
|
|
||||||
html.append("</td></tr>"); //NON-NLS
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* End a data table.
|
|
||||||
*
|
|
||||||
* @param html The HTML text on which to end a table.
|
|
||||||
*/
|
|
||||||
private void endTable(StringBuilder html) {
|
|
||||||
html.append("</table><br><br>"); //NON-NLS
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* End a data section.
|
|
||||||
*
|
|
||||||
* @param html The HTML text on which to end a section.
|
|
||||||
*/
|
|
||||||
private void endSection(StringBuilder html) {
|
|
||||||
html.append("<br>"); //NON-NLS
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply escape sequence to special characters. Line feed and carriage
|
|
||||||
* return character combinations will be converted to HTML line breaks.
|
|
||||||
*
|
|
||||||
* @param text The text to format.
|
|
||||||
*
|
|
||||||
* @return The formatted text.
|
|
||||||
*/
|
|
||||||
private String formatHtmlString(String text) {
|
|
||||||
String formattedString = StringEscapeUtils.escapeHtml4(text);
|
|
||||||
return formattedString.replaceAll("(\r\n|\r|\n|\n\r)", "<br>");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called from within the constructor to initialize the form.
|
* This method is called from within the constructor to initialize the form.
|
||||||
@ -554,6 +595,6 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void resetComponent() {
|
public void resetComponent() {
|
||||||
setText("");
|
jTextPane1.setText(EMPTY_HTML);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user