Autopsy 4.22.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
AnnotationUtils.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 */
19package org.sleuthkit.autopsy.contentviewers.annotations;
20
21import java.util.ArrayList;
22import java.util.Arrays;
23import java.util.List;
24import java.util.function.Function;
25import java.util.logging.Level;
26import java.util.stream.Collectors;
27import org.apache.commons.lang.StringUtils;
28import org.apache.commons.lang3.tuple.Pair;
29import org.jsoup.Jsoup;
30import org.jsoup.nodes.Document;
31import org.jsoup.nodes.Element;
32import org.openide.nodes.Node;
33import org.openide.util.NbBundle;
34import org.sleuthkit.autopsy.casemodule.Case;
35import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
36import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException;
37import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
38import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
39import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeNormalizationException;
40import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeUtil;
41import org.sleuthkit.autopsy.contentviewers.layout.ContentViewerHtmlStyles;
42import org.sleuthkit.autopsy.coreutils.Logger;
43import org.sleuthkit.autopsy.datamodel.BlackboardArtifactItem;
44import org.sleuthkit.datamodel.AbstractFile;
45import org.sleuthkit.datamodel.AnalysisResult;
46import org.sleuthkit.datamodel.BlackboardArtifact;
47import org.sleuthkit.datamodel.BlackboardArtifactTag;
48import org.sleuthkit.datamodel.BlackboardAttribute;
49import org.sleuthkit.datamodel.Content;
50import org.sleuthkit.datamodel.ContentTag;
51import org.sleuthkit.datamodel.DataArtifact;
52import org.sleuthkit.datamodel.SleuthkitCase;
53import org.sleuthkit.datamodel.Tag;
54import org.sleuthkit.datamodel.TskCoreException;
55
59public class AnnotationUtils {
60
61 @NbBundle.Messages({
62 "AnnotationUtils.title=Annotations",
63 "AnnotationUtils.toolTip=Displays tags and comments associated with the selected content.",
64 "AnnotationUtils.centralRepositoryEntry.title=Central Repository Comments",
65 "AnnotationUtils.centralRepositoryEntryDataLabel.case=Case:",
66 "AnnotationUtils.centralRepositoryEntryDataLabel.type=Type:",
67 "AnnotationUtils.centralRepositoryEntryDataLabel.comment=Comment:",
68 "AnnotationUtils.centralRepositoryEntryDataLabel.path=Path:",
69 "AnnotationUtils.tagEntry.title=Tags",
70 "AnnotationUtils.tagEntryDataLabel.tag=Tag:",
71 "AnnotationUtils.tagEntryDataLabel.tagUser=Examiner:",
72 "AnnotationUtils.tagEntryDataLabel.comment=Comment:",
73 "AnnotationUtils.fileHitEntry.artifactCommentTitle=Artifact Comment",
74 "AnnotationUtils.fileHitEntry.hashSetHitTitle=Hash Set Hit Comments",
75 "AnnotationUtils.fileHitEntry.interestingFileHitTitle=Interesting File Hit Comments",
76 "AnnotationUtils.fileHitEntry.interestingItemTitle=Interesting Item Comments",
77 "AnnotationUtils.fileHitEntry.setName=Set Name:",
78 "AnnotationUtils.fileHitEntry.comment=Comment:",
79 "AnnotationUtils.sourceFile.title=Source File",
80 "AnnotationUtils.onEmpty=No annotations were found for this particular item."
81 })
82
83 private static final Logger logger = Logger.getLogger(AnnotationUtils.class.getName());
84
85 private static final String EMPTY_HTML = "<html><head></head><body></body></html>";
86
87 // describing table values for a tag
88 private static final List<ItemEntry<Tag>> TAG_ENTRIES = Arrays.asList(
89 new ItemEntry<>(Bundle.AnnotationUtils_tagEntryDataLabel_tag(),
90 (tag) -> (tag.getName() != null) ? tag.getName().getDisplayName() : null),
91 new ItemEntry<>(Bundle.AnnotationUtils_tagEntryDataLabel_tagUser(), (tag) -> tag.getUserName()),
92 new ItemEntry<>(Bundle.AnnotationUtils_tagEntryDataLabel_comment(), (tag) -> tag.getComment())
93 );
94
95 private static final SectionConfig<Tag> TAG_CONFIG
96 = new SectionConfig<>(Bundle.AnnotationUtils_tagEntry_title(), TAG_ENTRIES);
97
98 // Item set attributes and table configurations
99 private static final List<ItemEntry<BlackboardArtifact>> ITEMSET_HIT_ENTRIES = Arrays.asList(
100 new ItemEntry<>(Bundle.AnnotationUtils_fileHitEntry_setName(),
101 (bba) -> tryGetAttribute(bba, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME)),
102 new ItemEntry<>(Bundle.AnnotationUtils_fileHitEntry_comment(),
103 (bba) -> tryGetAttribute(bba, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT))
104 );
105
106 private static final SectionConfig<BlackboardArtifact> INTERESTING_FILE_CONFIG
107 = new SectionConfig<>(Bundle.AnnotationUtils_fileHitEntry_interestingFileHitTitle(), ITEMSET_HIT_ENTRIES);
108
109 private static final SectionConfig<BlackboardArtifact> INTERESTING_ITEM_CONFIG
110 = new SectionConfig<>(Bundle.AnnotationUtils_fileHitEntry_interestingItemTitle(), ITEMSET_HIT_ENTRIES);
111
112 private static final SectionConfig<BlackboardArtifact> HASHSET_CONFIG
113 = new SectionConfig<>(Bundle.AnnotationUtils_fileHitEntry_hashSetHitTitle(), ITEMSET_HIT_ENTRIES);
114
115 private static final SectionConfig<BlackboardArtifact> ARTIFACT_COMMENT_CONFIG
116 = new SectionConfig<>(Bundle.AnnotationUtils_fileHitEntry_artifactCommentTitle(), ITEMSET_HIT_ENTRIES);
117
118 // central repository attributes and table configuration
119 private static final List<ItemEntry<CorrelationAttributeInstance>> CR_COMMENTS_ENTRIES = Arrays.asList(
120 new ItemEntry<>(Bundle.AnnotationUtils_centralRepositoryEntryDataLabel_case(),
121 cai -> (cai.getCorrelationCase() != null) ? cai.getCorrelationCase().getDisplayName() : null),
122 new ItemEntry<>(Bundle.AnnotationUtils_centralRepositoryEntryDataLabel_comment(), cai -> cai.getComment()),
123 new ItemEntry<>(Bundle.AnnotationUtils_centralRepositoryEntryDataLabel_path(), cai -> cai.getFilePath())
124 );
125
126 private static final SectionConfig<CorrelationAttributeInstance> CR_COMMENTS_CONFIG
127 = new SectionConfig<>(Bundle.AnnotationUtils_centralRepositoryEntry_title(), CR_COMMENTS_ENTRIES);
128
129 /*
130 * Private constructor for this utility class.
131 */
132 private AnnotationUtils() {
133
134 }
135
144 static DisplayTskItems getDisplayContent(Node node) {
145 BlackboardArtifactItem<?> artItem = node.getLookup().lookup(BlackboardArtifactItem.class);
146 BlackboardArtifact artifact = artItem == null ? null : artItem.getTskContent();
147
148 Content content = artItem != null
149 ? artItem.getSourceContent()
150 : node.getLookup().lookup(AbstractFile.class);
151
152 return new DisplayTskItems(artifact, content);
153 }
154
162 public static boolean isSupported(Node node) {
163 return getDisplayContent(node).getContent() != null;
164 }
165
175 public static Document buildDocument(Node node) {
176 Document html = Jsoup.parse(EMPTY_HTML);
177 Element body = html.getElementsByTag("body").first();
178
179 DisplayTskItems displayItems = getDisplayContent(node);
180 BlackboardArtifact artifact = displayItems.getArtifact();
181 Content srcContent = displayItems.getContent();
182
183 boolean somethingWasRendered = false;
184 if (artifact != null) {
185 somethingWasRendered = renderArtifact(body, artifact, srcContent);
186 } else {
187 somethingWasRendered = renderContent(body, srcContent, false);
188 }
189
190 if (!somethingWasRendered) {
191 return null;
192 }
193
194 return html;
195 }
196
210 @SuppressWarnings("deprecation")
211 private static boolean renderArtifact(Element parent, BlackboardArtifact bba, Content sourceContent) {
212 boolean contentRendered = appendEntries(parent, TAG_CONFIG, getTags(bba), false, true);
213
215 List<CorrelationAttributeInstance> centralRepoComments = getCentralRepositoryData(bba);
216 boolean crRendered = appendEntries(parent, CR_COMMENTS_CONFIG, centralRepoComments, false, !contentRendered);
217 contentRendered = contentRendered || crRendered;
218 }
219
220 // if artifact is a hashset hit or interesting file and has a non-blank comment
221 if ((BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID() == bba.getArtifactTypeID()
222 || BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID() == bba.getArtifactTypeID()
223 || BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID() == bba.getArtifactTypeID()
224 || BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ITEM.getTypeID() == bba.getArtifactTypeID())
225 && (hasTskComment(bba))) {
226
227 boolean filesetRendered = appendEntries(parent, ARTIFACT_COMMENT_CONFIG, Arrays.asList(bba), false, !contentRendered);
228 contentRendered = contentRendered || filesetRendered;
229 }
230
231 Element sourceFileSection = appendSection(parent, Bundle.AnnotationUtils_sourceFile_title());
232 sourceFileSection.attr("class", ContentViewerHtmlStyles.getSpacedSectionClassName());
233
234 Element sourceFileContainer = sourceFileSection.appendElement("div");
235 sourceFileContainer.attr("class", ContentViewerHtmlStyles.getIndentedClassName());
236
237 boolean sourceFileRendered = renderContent(sourceFileContainer, sourceContent, true);
238
239 if (!sourceFileRendered) {
240 sourceFileSection.remove();
241 }
242
243 return contentRendered || sourceFileRendered;
244 }
245
259 @SuppressWarnings("deprecation")
260 private static boolean renderContent(Element parent, Content sourceContent, boolean isSubheader) {
261 boolean contentRendered = appendEntries(parent, TAG_CONFIG, getTags(sourceContent), isSubheader, true);
262
263 if (sourceContent instanceof AbstractFile) {
264 AbstractFile sourceFile = (AbstractFile) sourceContent;
265
267 List<CorrelationAttributeInstance> centralRepoComments = getCentralRepositoryData(sourceFile);
268 boolean crRendered = appendEntries(parent, CR_COMMENTS_CONFIG, centralRepoComments, isSubheader,
269 !contentRendered);
270 contentRendered = contentRendered || crRendered;
271 }
272
273 boolean hashsetRendered = appendEntries(parent, HASHSET_CONFIG,
274 getFileSetHits(sourceFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT),
275 isSubheader,
276 !contentRendered);
277
278 boolean interestingFileRendered = appendEntries(parent, INTERESTING_FILE_CONFIG,
279 getFileSetHits(sourceFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT),
280 isSubheader,
281 !contentRendered);
282
283 boolean interestingItemRendered = appendEntries(parent, INTERESTING_ITEM_CONFIG,
284 getFileSetHits(sourceFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ITEM),
285 isSubheader,
286 !contentRendered);
287
288 contentRendered = contentRendered || hashsetRendered || interestingFileRendered || interestingItemRendered;
289 }
290 return contentRendered;
291 }
292
300 private static List<ContentTag> getTags(Content sourceContent) {
301 try {
302 SleuthkitCase tskCase = Case.getCurrentCaseThrows().getSleuthkitCase();
303 return tskCase.getContentTagsByContent(sourceContent);
304 } catch (NoCurrentCaseException ex) {
305 logger.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS
306 } catch (TskCoreException ex) {
307 logger.log(Level.SEVERE, "Exception while getting tags from the case database.", ex); //NON-NLS
308 }
309 return new ArrayList<>();
310 }
311
319 private static List<BlackboardArtifactTag> getTags(BlackboardArtifact bba) {
320 try {
321 SleuthkitCase tskCase = Case.getCurrentCaseThrows().getSleuthkitCase();
322 return tskCase.getBlackboardArtifactTagsByArtifact(bba);
323 } catch (NoCurrentCaseException ex) {
324 logger.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS
325 } catch (TskCoreException ex) {
326 logger.log(Level.SEVERE, "Exception while getting tags from the case database.", ex); //NON-NLS
327 }
328 return new ArrayList<>();
329 }
330
340 private static List<BlackboardArtifact> getFileSetHits(AbstractFile sourceFile, BlackboardArtifact.ARTIFACT_TYPE type) {
341 try {
342 SleuthkitCase tskCase = Case.getCurrentCaseThrows().getSleuthkitCase();
343 return tskCase.getBlackboardArtifacts(type, sourceFile.getId()).stream()
344 .filter((bba) -> hasTskComment(bba) || hasTskSet(bba))
345 .collect(Collectors.toList());
346 } catch (NoCurrentCaseException ex) {
347 logger.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS
348 } catch (TskCoreException ex) {
349 logger.log(Level.SEVERE, "Exception while getting file set hits from the case database.", ex); //NON-NLS
350 }
351 return new ArrayList<>();
352 }
353
361 private static boolean hasTskComment(BlackboardArtifact artifact) {
362 return StringUtils.isNotBlank(tryGetAttribute(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT));
363 }
364
372 private static boolean hasTskSet(BlackboardArtifact artifact) {
373 return StringUtils.isNotBlank(tryGetAttribute(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME));
374 }
375
385 private static String tryGetAttribute(BlackboardArtifact artifact, BlackboardAttribute.ATTRIBUTE_TYPE attributeType) {
386 if (artifact == null) {
387 return null;
388 }
389
390 BlackboardAttribute attr = null;
391 try {
392 attr = artifact.getAttribute(new BlackboardAttribute.Type(attributeType));
393 } catch (TskCoreException ex) {
394 logger.log(Level.WARNING, String.format("Unable to fetch attribute of type %s for artifact %s", attributeType, artifact), ex);
395 }
396
397 if (attr == null) {
398 return null;
399 }
400
401 return attr.getValueString();
402 }
403
413 private static List<CorrelationAttributeInstance> getCentralRepositoryData(BlackboardArtifact artifact) {
414 if (artifact == null) {
415 return new ArrayList<>();
416 }
417 List<CorrelationAttributeInstance> instances = new ArrayList<>();
418 if (artifact instanceof DataArtifact) {
419 instances.addAll(CorrelationAttributeUtil.makeCorrAttrsForSearch((DataArtifact) artifact));
420 } else if (artifact instanceof AnalysisResult) {
421 instances.addAll(CorrelationAttributeUtil.makeCorrAttrsForSearch((AnalysisResult) artifact));
422 }
423
424 List<Pair<CorrelationAttributeInstance.Type, String>> lookupKeys = instances.stream()
425 .map(cai -> Pair.of(cai.getCorrelationType(), cai.getCorrelationValue()))
426 .collect(Collectors.toList());
427
428 return getCorrelationAttributeComments(lookupKeys);
429 }
430
440 private static List<CorrelationAttributeInstance> getCentralRepositoryData(AbstractFile sourceFile) {
441 if (sourceFile == null || StringUtils.isEmpty(sourceFile.getMd5Hash())) {
442 return new ArrayList<>();
443 }
444
445 List<CorrelationAttributeInstance.Type> artifactTypes = null;
446 try {
448 } catch (CentralRepoException ex) {
449 logger.log(Level.SEVERE, "Error connecting to the Central Repository database.", ex); // NON-NLS
450 }
451
452 if (artifactTypes == null || artifactTypes.isEmpty()) {
453 return new ArrayList<>();
454 }
455
456 String md5 = sourceFile.getMd5Hash();
457
458 // get key lookups for a file attribute types and the md5 hash
459 List<Pair<CorrelationAttributeInstance.Type, String>> lookupKeys = artifactTypes.stream()
460 .filter((attributeType) -> attributeType.getId() == CorrelationAttributeInstance.FILES_TYPE_ID)
461 .map((attributeType) -> Pair.of(attributeType, md5))
462 .collect(Collectors.toList());
463
464 return getCorrelationAttributeComments(lookupKeys);
465 }
466
475 private static List<CorrelationAttributeInstance> getCorrelationAttributeComments(List<Pair<CorrelationAttributeInstance.Type, String>> lookupKeys) {
476 List<CorrelationAttributeInstance> instancesToRet = new ArrayList<>();
477
478 try {
479 // use lookup instances to find the actual correlation attributes for the items selected
480 for (Pair<CorrelationAttributeInstance.Type, String> typeVal : lookupKeys) {
481 instancesToRet.addAll(CentralRepository.getInstance()
482 .getArtifactInstancesByTypeValue(typeVal.getKey(), typeVal.getValue())
483 .stream()
484 // for each one found, if it has a comment, return
485 .filter((cai) -> StringUtils.isNotBlank(cai.getComment()))
486 .collect(Collectors.toList()));
487 }
488
489 } catch (CentralRepoException ex) {
490 logger.log(Level.SEVERE, "Error connecting to the Central Repository database.", ex); // NON-NLS
492 logger.log(Level.WARNING, "Error normalizing instance from Central Repository database.", ex); // NON-NLS
493 }
494
495 return instancesToRet;
496 }
497
515 private static <T> boolean appendEntries(Element parent, AnnotationUtils.SectionConfig<T> config, List<? extends T> items,
516 boolean isSubsection, boolean isFirstSection) {
517 if (items == null || items.isEmpty()) {
518 return false;
519 }
520
521 Element sectionDiv = (isSubsection) ? appendSubsection(parent, config.getTitle()) : appendSection(parent, config.getTitle());
522 if (!isFirstSection) {
523 sectionDiv.attr("class", ContentViewerHtmlStyles.getSpacedSectionClassName());
524 }
525
526 Element sectionContainer = sectionDiv.appendElement("div");
527
528 if (!isSubsection) {
529 sectionContainer.attr("class", ContentViewerHtmlStyles.getIndentedClassName());
530 }
531
532 appendVerticalEntryTables(sectionContainer, items, config.getAttributes());
533 return true;
534 }
535
546 private static <T> Element appendVerticalEntryTables(Element parent, List<? extends T> items, List<ItemEntry<T>> rowHeaders) {
547 boolean isFirst = true;
548 for (T item : items) {
549 if (item == null) {
550 continue;
551 }
552
553 List<List<String>> tableData = rowHeaders.stream()
554 .map(row -> Arrays.asList(row.getItemName(), row.retrieveValue(item)))
555 .collect(Collectors.toList());
556
557 Element childTable = appendTable(parent, 2, tableData, null);
558
559 if (isFirst) {
560 isFirst = false;
561 } else {
562 childTable.attr("class", ContentViewerHtmlStyles.getSpacedSectionClassName());
563 }
564 }
565
566 return parent;
567 }
568
581 private static Element appendTable(Element parent, int columnNumber, List<List<String>> content, List<String> columnHeaders) {
582 Element table = parent.appendElement("table")
583 .attr("valign", "top")
584 .attr("align", "left");
585
586 if (columnHeaders != null && !columnHeaders.isEmpty()) {
587 Element header = table.appendElement("thead");
588 appendRow(header, columnHeaders, columnNumber, true);
589 }
590 Element tableBody = table.appendElement("tbody");
591
592 content.forEach((rowData) -> appendRow(tableBody, rowData, columnNumber, false));
593 return table;
594 }
595
607 private static Element appendRow(Element rowParent, List<String> data, int columnNumber, boolean isHeader) {
608 String cellType = isHeader ? "th" : "td";
609 Element row = rowParent.appendElement("tr");
610 for (int i = 0; i < columnNumber; i++) {
611 Element cell = row.appendElement(cellType);
612
613 if (i == 0) {
615 }
616
617 if (data != null && i < data.size()) {
618 cell.appendElement("span")
620 .text(StringUtils.isEmpty(data.get(i)) ? "" : data.get(i));
621 }
622 }
623 return row;
624 }
625
634 private static Element appendSection(Element parent, String headerText) {
635 Element sectionDiv = parent.appendElement("div");
636 Element header = sectionDiv.appendElement("h1");
637 header.text(headerText);
638 header.attr("class", ContentViewerHtmlStyles.getHeaderClassName());
639 return sectionDiv;
640 }
641
650 private static Element appendSubsection(Element parent, String headerText) {
651 Element subsectionDiv = parent.appendElement("div");
652 Element header = subsectionDiv.appendElement("h2");
653 header.text(headerText);
654 header.attr("class", ContentViewerHtmlStyles.getHeaderClassName());
655 return subsectionDiv;
656 }
657
665 static class ItemEntry<T> {
666
667 private final String itemName;
668 private final Function<T, String> valueRetriever;
669
670 ItemEntry(String itemName, Function<T, String> valueRetriever) {
671 this.itemName = itemName;
672 this.valueRetriever = valueRetriever;
673 }
674
675 String getItemName() {
676 return itemName;
677 }
678
679 Function<T, String> getValueRetriever() {
680 return valueRetriever;
681 }
682
683 String retrieveValue(T object) {
684 return valueRetriever.apply(object);
685 }
686 }
687
693 static class SectionConfig<T> {
694
695 private final String title;
696 private final List<ItemEntry<T>> attributes;
697
698 SectionConfig(String title, List<ItemEntry<T>> attributes) {
699 this.title = title;
700 this.attributes = attributes;
701 }
702
706 String getTitle() {
707 return title;
708 }
709
714 List<ItemEntry<T>> getAttributes() {
715 return attributes;
716 }
717 }
718
723 static class DisplayTskItems {
724
725 private final BlackboardArtifact artifact;
726 private final Content content;
727
735 DisplayTskItems(BlackboardArtifact artifact, Content content) {
736 this.artifact = artifact;
737 this.content = content;
738 }
739
743 BlackboardArtifact getArtifact() {
744 return artifact;
745 }
746
750 Content getContent() {
751 return content;
752 }
753 }
754}
static List< CorrelationAttributeInstance > makeCorrAttrsForSearch(AnalysisResult analysisResult)
static Element appendRow(Element rowParent, List< String > data, int columnNumber, boolean isHeader)
static List< BlackboardArtifact > getFileSetHits(AbstractFile sourceFile, BlackboardArtifact.ARTIFACT_TYPE type)
static final SectionConfig< BlackboardArtifact > HASHSET_CONFIG
static final List< ItemEntry< CorrelationAttributeInstance > > CR_COMMENTS_ENTRIES
static final List< ItemEntry< BlackboardArtifact > > ITEMSET_HIT_ENTRIES
static final SectionConfig< BlackboardArtifact > ARTIFACT_COMMENT_CONFIG
static< T > Element appendVerticalEntryTables(Element parent, List<? extends T > items, List< ItemEntry< T > > rowHeaders)
static List< CorrelationAttributeInstance > getCorrelationAttributeComments(List< Pair< CorrelationAttributeInstance.Type, String > > lookupKeys)
static List< BlackboardArtifactTag > getTags(BlackboardArtifact bba)
static final SectionConfig< BlackboardArtifact > INTERESTING_ITEM_CONFIG
static List< CorrelationAttributeInstance > getCentralRepositoryData(AbstractFile sourceFile)
static Element appendSection(Element parent, String headerText)
static< T > boolean appendEntries(Element parent, AnnotationUtils.SectionConfig< T > config, List<? extends T > items, boolean isSubsection, boolean isFirstSection)
static List< ContentTag > getTags(Content sourceContent)
static boolean renderContent(Element parent, Content sourceContent, boolean isSubheader)
static final SectionConfig< CorrelationAttributeInstance > CR_COMMENTS_CONFIG
static String tryGetAttribute(BlackboardArtifact artifact, BlackboardAttribute.ATTRIBUTE_TYPE attributeType)
static final SectionConfig< BlackboardArtifact > INTERESTING_FILE_CONFIG
static List< CorrelationAttributeInstance > getCentralRepositoryData(BlackboardArtifact artifact)
static Element appendTable(Element parent, int columnNumber, List< List< String > > content, List< String > columnHeaders)
static boolean renderArtifact(Element parent, BlackboardArtifact bba, Content sourceContent)
static boolean hasTskComment(BlackboardArtifact artifact)
static Element appendSubsection(Element parent, String headerText)
synchronized static Logger getLogger(String name)
Definition Logger.java:124
List< CorrelationAttributeInstance > getArtifactInstancesByTypeValue(CorrelationAttributeInstance.Type type, String value)
List< CorrelationAttributeInstance.Type > getDefinedCorrelationTypes()

Copyright © 2012-2024 Sleuth Kit Labs. Generated on:
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.