change in analysis results header attributes

This commit is contained in:
Greg DiCristofaro 2021-06-09 15:45:13 -04:00
parent 630d259653
commit c26efab04d
2 changed files with 72 additions and 20 deletions

View File

@ -26,20 +26,22 @@ import org.jsoup.Jsoup;
import org.jsoup.nodes.Document; import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element; import org.jsoup.nodes.Element;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.contentviewers.analysisresults.AnalysisResultsViewModel.NodeResults; import org.sleuthkit.autopsy.contentviewers.analysisresults.AnalysisResultsViewModel.NodeResults;
import org.sleuthkit.autopsy.contentviewers.analysisresults.AnalysisResultsViewModel.ResultDisplayAttributes; import org.sleuthkit.autopsy.contentviewers.analysisresults.AnalysisResultsViewModel.ResultDisplayAttributes;
import org.sleuthkit.autopsy.contentviewers.layout.ContentViewerHtmlStyles; import org.sleuthkit.autopsy.contentviewers.layout.ContentViewerHtmlStyles;
import org.sleuthkit.autopsy.coreutils.EscapeUtil; import org.sleuthkit.autopsy.coreutils.EscapeUtil;
import org.sleuthkit.datamodel.AnalysisResult; import org.sleuthkit.datamodel.AnalysisResult;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.Score; import org.sleuthkit.datamodel.Score;
/** /**
* Displays a list of analysis results in a panel. * Displays a list of analysis results in a panel.
*/ */
public class AnalysisResultsContentPanel extends javax.swing.JPanel { public class AnalysisResultsContentPanel extends javax.swing.JPanel {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private static final String EMPTY_HTML = "<html><head></head><body></body></html>"; private static final String EMPTY_HTML = "<html><head></head><body></body></html>";
// Anchors are inserted into the navigation so that the viewer can navigate to a selection. // Anchors are inserted into the navigation so that the viewer can navigate to a selection.
@ -80,27 +82,18 @@ public class AnalysisResultsContentPanel extends javax.swing.JPanel {
* *
* @param nodeResults The analysis results data to display. * @param nodeResults The analysis results data to display.
*/ */
@NbBundle.Messages("AnalysisResultsContentPanel_aggregateScore_displayKey=Aggregate Score")
void displayResults(NodeResults nodeResults) { void displayResults(NodeResults nodeResults) {
Document document = Jsoup.parse(EMPTY_HTML); Document document = Jsoup.parse(EMPTY_HTML);
Element body = document.getElementsByTag("body").first(); Element body = document.getElementsByTag("body").first();
// if there is an aggregate score, append a section with the value Optional<Element> panelHeader = appendPanelHeader(body, nodeResults.getContent(), nodeResults.getAggregateScore());
Optional<Score> aggregateScore = nodeResults.getAggregateScore();
if (aggregateScore.isPresent()) {
appendSection(body,
MessageFormat.format("{0}: {1}",
Bundle.AnalysisResultsContentPanel_aggregateScore_displayKey(),
aggregateScore.get().getSignificance().getDisplayName()),
Optional.empty());
}
// for each analysis result item, display the data. // for each analysis result item, display the data.
List<ResultDisplayAttributes> displayAttributes = nodeResults.getAnalysisResults(); List<ResultDisplayAttributes> displayAttributes = nodeResults.getAnalysisResults();
for (int idx = 0; idx < displayAttributes.size(); idx++) { for (int idx = 0; idx < displayAttributes.size(); idx++) {
AnalysisResultsViewModel.ResultDisplayAttributes resultAttrs = displayAttributes.get(idx); AnalysisResultsViewModel.ResultDisplayAttributes resultAttrs = displayAttributes.get(idx);
Element sectionDiv = appendResult(body, idx, resultAttrs); Element sectionDiv = appendResult(body, idx, resultAttrs);
if (idx > 0 || aggregateScore.isPresent()) { if (idx > 0 || panelHeader.isPresent()) {
sectionDiv.attr("class", ContentViewerHtmlStyles.getSpacedSectionClassName()); sectionDiv.attr("class", ContentViewerHtmlStyles.getSpacedSectionClassName());
} }
} }
@ -119,6 +112,48 @@ public class AnalysisResultsContentPanel extends javax.swing.JPanel {
} }
} }
/**
* Appends the header to the panel.
*
* @param parent The parent html element.
* @param content The content whose name will be added if present.
* @param score The aggregate score whose significance will be added if
* present.
*
* @return The html element.
*/
@Messages({
"AnalysisResultsContentPanel_aggregateScore_displayKey=Aggregate Score",
"AnalysisResultsContentPanel_content_displayKey=Item"
})
private Optional<Element> appendPanelHeader(Element parent, Optional<Content> content, Optional<Score> score) {
if (!content.isPresent() || !score.isPresent()) {
return Optional.empty();
}
Element container = parent.appendElement("div");
// if there is content append the name
content.ifPresent((c) -> {
container.appendElement("p")
.attr("class", ContentViewerHtmlStyles.getTextClassName())
.text(MessageFormat.format("{0}: {1}",
Bundle.AnalysisResultsContentPanel_content_displayKey(),
c.getName()));
});
// if there is an aggregate score, append the value
score.ifPresent((s) -> {
container.appendElement("p")
.attr("class", ContentViewerHtmlStyles.getTextClassName())
.text(MessageFormat.format("{0}: {1}",
Bundle.AnalysisResultsContentPanel_aggregateScore_displayKey(),
s.getSignificance().getDisplayName()));
});
return Optional.ofNullable(container);
}
/** /**
* Returns the anchor id to use with the analysis result (based on the id). * Returns the anchor id to use with the analysis result (based on the id).
* *
@ -151,7 +186,7 @@ public class AnalysisResultsContentPanel extends javax.swing.JPanel {
// create a table // create a table
Element table = sectionDiv.appendElement("table"); Element table = sectionDiv.appendElement("table");
table.attr("class", ContentViewerHtmlStyles.getIndentedClassName()); table.attr("class", ContentViewerHtmlStyles.getIndentedClassName());
Element tableBody = table.appendElement("tbody"); Element tableBody = table.appendElement("tbody");
// append a row for each item // append a row for each item
@ -160,7 +195,7 @@ public class AnalysisResultsContentPanel extends javax.swing.JPanel {
String keyString = keyVal.getKey() == null ? "" : keyVal.getKey() + ":"; String keyString = keyVal.getKey() == null ? "" : keyVal.getKey() + ":";
Element keyTd = row.appendElement("td") Element keyTd = row.appendElement("td")
.attr("class", ContentViewerHtmlStyles.getTextClassName()); .attr("class", ContentViewerHtmlStyles.getTextClassName());
keyTd.appendElement("span") keyTd.appendElement("span")
.text(keyString) .text(keyString)
.attr("class", ContentViewerHtmlStyles.getKeyColumnClassName()); .attr("class", ContentViewerHtmlStyles.getKeyColumnClassName());
@ -170,7 +205,7 @@ public class AnalysisResultsContentPanel extends javax.swing.JPanel {
.text(valueString) .text(valueString)
.attr("class", ContentViewerHtmlStyles.getTextClassName()); .attr("class", ContentViewerHtmlStyles.getTextClassName());
} }
return sectionDiv; return sectionDiv;
} }
@ -199,7 +234,7 @@ public class AnalysisResultsContentPanel extends javax.swing.JPanel {
header = (anchorEl == null) header = (anchorEl == null)
? sectionDiv.appendElement("h1") ? sectionDiv.appendElement("h1")
: anchorEl.appendElement("h1"); : anchorEl.appendElement("h1");
header.text(headerText); header.text(headerText);
header.attr("class", ContentViewerHtmlStyles.getHeaderClassName()); header.attr("class", ContentViewerHtmlStyles.getHeaderClassName());
header.attr("style", "display: inline-block"); header.attr("style", "display: inline-block");

View File

@ -94,6 +94,7 @@ public class AnalysisResultsViewModel {
private final List<ResultDisplayAttributes> analysisResults; private final List<ResultDisplayAttributes> analysisResults;
private final Optional<AnalysisResult> selectedResult; private final Optional<AnalysisResult> selectedResult;
private final Optional<Score> aggregateScore; private final Optional<Score> aggregateScore;
private final Optional<Content> content;
/** /**
* Constructor. * Constructor.
@ -102,11 +103,13 @@ public class AnalysisResultsViewModel {
* @param selectedResult The selected analysis result or empty if none * @param selectedResult The selected analysis result or empty if none
* selected. * selected.
* @param aggregateScore The aggregate score or empty if no score. * @param aggregateScore The aggregate score or empty if no score.
* @param content The content associated with these results.
*/ */
NodeResults(List<ResultDisplayAttributes> analysisResults, Optional<AnalysisResult> selectedResult, Optional<Score> aggregateScore) { NodeResults(List<ResultDisplayAttributes> analysisResults, Optional<AnalysisResult> selectedResult, Optional<Score> aggregateScore, Optional<Content> content) {
this.analysisResults = analysisResults; this.analysisResults = analysisResults;
this.selectedResult = selectedResult; this.selectedResult = selectedResult;
this.aggregateScore = aggregateScore; this.aggregateScore = aggregateScore;
this.content = content;
} }
/** /**
@ -135,6 +138,17 @@ public class AnalysisResultsViewModel {
Optional<Score> getAggregateScore() { Optional<Score> getAggregateScore() {
return aggregateScore; return aggregateScore;
} }
/**
* Returns the content associated with these results or empty if not
* present.
*
* @return The content associated with these results or empty if not
* present.
*/
Optional<Content> getContent() {
return content;
}
} }
/** /**
@ -221,10 +235,11 @@ public class AnalysisResultsViewModel {
*/ */
NodeResults getAnalysisResults(Node node) { NodeResults getAnalysisResults(Node node) {
if (node == null) { if (node == null) {
return new NodeResults(Collections.emptyList(), Optional.empty(), Optional.empty()); return new NodeResults(Collections.emptyList(), Optional.empty(), Optional.empty(), Optional.empty());
} }
Optional<Score> aggregateScore = Optional.empty(); Optional<Score> aggregateScore = Optional.empty();
Optional<Content> nodeContent = Optional.empty();
// maps id of analysis result to analysis result to prevent duplication // maps id of analysis result to analysis result to prevent duplication
Map<Long, AnalysisResult> allAnalysisResults = new HashMap<>(); Map<Long, AnalysisResult> allAnalysisResults = new HashMap<>();
Optional<AnalysisResult> selectedResult = Optional.empty(); Optional<AnalysisResult> selectedResult = Optional.empty();
@ -236,6 +251,8 @@ public class AnalysisResultsViewModel {
} }
try { try {
nodeContent = Optional.of(content);
// get the aggregate score of that content // get the aggregate score of that content
aggregateScore = Optional.ofNullable(content.getAggregateScore()); aggregateScore = Optional.ofNullable(content.getAggregateScore());
@ -273,6 +290,6 @@ public class AnalysisResultsViewModel {
// get view model representation // get view model representation
List<ResultDisplayAttributes> displayAttributes = getOrderedDisplayAttributes(allAnalysisResults.values()); List<ResultDisplayAttributes> displayAttributes = getOrderedDisplayAttributes(allAnalysisResults.values());
return new NodeResults(displayAttributes, selectedResult, aggregateScore); return new NodeResults(displayAttributes, selectedResult, aggregateScore, nodeContent);
} }
} }