Autopsy  4.19.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
AnalysisResultsViewModel.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2021 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.contentviewers.analysisresults;
20 
21 import java.util.Collection;
22 import java.util.Collections;
23 import java.util.HashMap;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Optional;
27 import java.util.logging.Level;
28 import java.util.logging.Logger;
29 import java.util.stream.Collectors;
30 import java.util.stream.Stream;
31 import org.apache.commons.lang3.tuple.Pair;
32 import org.openide.nodes.Node;
33 import org.openide.util.NbBundle;
34 import org.sleuthkit.datamodel.AnalysisResult;
35 import org.sleuthkit.datamodel.BlackboardArtifact;
36 import org.sleuthkit.datamodel.Content;
37 import org.sleuthkit.datamodel.Score;
38 import org.sleuthkit.datamodel.TskCoreException;
39 
45 
46  private static final Logger logger = Logger.getLogger(AnalysisResultsViewModel.class.getName());
47 
51  static class ResultDisplayAttributes {
52 
53  private final AnalysisResult analysisResult;
54  private final List<Pair<String, String>> attributesToDisplay;
55 
64  ResultDisplayAttributes(AnalysisResult analysisResult, List<Pair<String, String>> attributesToDisplay) {
65  this.analysisResult = analysisResult;
66  this.attributesToDisplay = attributesToDisplay;
67  }
68 
74  List<Pair<String, String>> getAttributesToDisplay() {
75  return attributesToDisplay;
76  }
77 
83  AnalysisResult getAnalysisResult() {
84  return analysisResult;
85  }
86  }
87 
92  static class NodeResults {
93 
94  private final List<ResultDisplayAttributes> analysisResults;
95  private final Optional<AnalysisResult> selectedResult;
96  private final Optional<Score> aggregateScore;
97  private final Optional<Content> content;
98 
108  NodeResults(List<ResultDisplayAttributes> analysisResults, Optional<AnalysisResult> selectedResult, Optional<Score> aggregateScore, Optional<Content> content) {
109  this.analysisResults = analysisResults;
110  this.selectedResult = selectedResult;
111  this.aggregateScore = aggregateScore;
112  this.content = content;
113  }
114 
120  List<ResultDisplayAttributes> getAnalysisResults() {
121  return analysisResults;
122  }
123 
129  Optional<AnalysisResult> getSelectedResult() {
130  return selectedResult;
131  }
132 
138  Optional<Score> getAggregateScore() {
139  return aggregateScore;
140  }
141 
149  Optional<Content> getContent() {
150  return content;
151  }
152  }
153 
162  private String normalizeAttr(String originalAttrStr) {
163  return (originalAttrStr == null) ? "" : originalAttrStr.trim();
164  }
165 
173  @NbBundle.Messages({
174  "AnalysisResultsViewModel_displayAttributes_score=Score",
175  "AnalysisResultsViewModel_displayAttributes_type=Type",
176  "AnalysisResultsViewModel_displayAttributes_configuration=Configuration",
177  "AnalysisResultsViewModel_displayAttributes_conclusion=Conclusion"
178  })
179  private ResultDisplayAttributes getDisplayAttributes(AnalysisResult analysisResult) {
180  // The type of BlackboardArtifact.Type of the analysis result.
181  String type = "";
182  try {
183  type = normalizeAttr(analysisResult.getType().getDisplayName());
184  } catch (TskCoreException ex) {
185  logger.log(Level.SEVERE, "Unable to get type for analysis result with id: " + analysisResult.getArtifactID(), ex);
186  }
187 
188  // The standard attributes to display (score, type, configuration, conclusion)
189  Stream<Pair<String, String>> baseAnalysisAttrs = Stream.of(
190  Pair.of(Bundle.AnalysisResultsViewModel_displayAttributes_score(),
191  normalizeAttr(analysisResult.getScore().getSignificance().getDisplayName())),
192  Pair.of(Bundle.AnalysisResultsViewModel_displayAttributes_type(),
193  normalizeAttr(type)),
194  Pair.of(Bundle.AnalysisResultsViewModel_displayAttributes_configuration(),
195  normalizeAttr(analysisResult.getConfiguration())),
196  Pair.of(Bundle.AnalysisResultsViewModel_displayAttributes_conclusion(),
197  normalizeAttr(analysisResult.getConclusion()))
198  );
199 
200  // The BlackboardAttributes sorted by type display name.
201  Stream<Pair<String, String>> blackboardAttributes = Stream.empty();
202  try {
203 
204  blackboardAttributes = analysisResult.getAttributes().stream()
205  .filter(attr -> attr != null && attr.getAttributeType() != null && attr.getAttributeType().getDisplayName() != null)
206  .map(attr -> Pair.of(attr.getAttributeType().getDisplayName(), normalizeAttr(attr.getDisplayString())))
207  .sorted((a, b) -> a.getKey().compareToIgnoreCase(b.getKey()));
208  } catch (TskCoreException ex) {
209  logger.log(Level.SEVERE, "Unable to get attributes for analysis result with id: " + analysisResult.getArtifactID(), ex);
210  }
211 
212  // return the standard attributes along with the key value pairs of the BlackboardAttribute values.
213  List<Pair<String, String>> allDisplayAttributes = Stream.concat(baseAnalysisAttrs, blackboardAttributes)
214  .collect(Collectors.toList());
215 
216  return new ResultDisplayAttributes(analysisResult, allDisplayAttributes);
217  }
218 
219  private List<ResultDisplayAttributes> getOrderedDisplayAttributes(Collection<AnalysisResult> analysisResults) {
220  return analysisResults.stream()
221  .filter(ar -> ar != null && ar.getScore() != null)
222  // reverse order to push more important scores to the top
223  .sorted((a, b) -> -a.getScore().compareTo(b.getScore()))
224  .map((ar) -> getDisplayAttributes(ar))
225  .collect(Collectors.toList());
226  }
227 
236  NodeResults getAnalysisResults(Node node) {
237  if (node == null) {
238  return new NodeResults(Collections.emptyList(), Optional.empty(), Optional.empty(), Optional.empty());
239  }
240 
241  Optional<Score> aggregateScore = Optional.empty();
242  Optional<Content> nodeContent = Optional.empty();
243  // maps id of analysis result to analysis result to prevent duplication
244  Map<Long, AnalysisResult> allAnalysisResults = new HashMap<>();
245  Optional<AnalysisResult> selectedResult = Optional.empty();
246 
247  // Find first content that is not an artifact within node
248  for (Content content : node.getLookup().lookupAll(Content.class)) {
249  if (content == null || content instanceof BlackboardArtifact) {
250  continue;
251  }
252 
253  try {
254  nodeContent = Optional.of(content);
255 
256  // get the aggregate score of that content
257  aggregateScore = Optional.ofNullable(content.getAggregateScore());
258 
259  // and add all analysis results to mapping
260  content.getAllAnalysisResults().stream()
261  .forEach((ar) -> allAnalysisResults.put(ar.getArtifactID(), ar));
262 
263  break;
264  } catch (TskCoreException ex) {
265  logger.log(Level.SEVERE, "Unable to get analysis results for content with obj id " + content.getId(), ex);
266  }
267  }
268 
269  // Find any analysis results in the node
270  Collection<? extends AnalysisResult> analysisResults = node.getLookup().lookupAll(AnalysisResult.class);
271  if (analysisResults.size() > 0) {
272 
273  // get any items with a score
274  List<AnalysisResult> filteredResults = analysisResults.stream()
275  .collect(Collectors.toList());
276 
277  // add them to the map to display
278  filteredResults.forEach((ar) -> allAnalysisResults.put(ar.getArtifactID(), ar));
279 
280  // the selected result will be the highest scored analysis result in the node.
281  selectedResult = filteredResults.stream()
282  .max((a, b) -> a.getScore().compareTo(b.getScore()));
283 
284  // if no aggregate score determined at this point, use the selected result score.
285  if (!aggregateScore.isPresent()) {
286  aggregateScore = selectedResult.flatMap(selectedRes -> Optional.ofNullable(selectedRes.getScore()));
287  }
288  }
289 
290  // get view model representation
291  List<ResultDisplayAttributes> displayAttributes = getOrderedDisplayAttributes(allAnalysisResults.values());
292 
293  return new NodeResults(displayAttributes, selectedResult, aggregateScore, nodeContent);
294  }
295 }
List< ResultDisplayAttributes > getOrderedDisplayAttributes(Collection< AnalysisResult > analysisResults)

Copyright © 2012-2021 Basis Technology. Generated on: Fri Aug 6 2021
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.