mirror of
https://github.com/elisspace/autopsy.git
synced 2026-09-15 23:43:01 +00:00
Merge branch 'develop' into 7890-Update-Content-viewer_2
This commit is contained in:
@@ -42,7 +42,6 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeIns
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeNormalizationException;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeUtil;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.PersonaAccount;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
|
||||
@@ -57,15 +56,12 @@ import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CORRELATION_TYPE;
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CORRELATION_VALUE;
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_OTHER_CASES;
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME;
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT;
|
||||
import org.sleuthkit.autopsy.ingest.events.DataSourceAnalysisEvent;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.Image;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.Persona;
|
||||
import org.sleuthkit.datamodel.Score;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
|
||||
@@ -318,77 +314,7 @@ public class IngestEventsListener {
|
||||
value));
|
||||
makeAndPostArtifact(BlackboardArtifact.Type.TSK_PREVIOUSLY_UNSEEN, originalArtifact, attributesForNewArtifact, "",
|
||||
Score.SCORE_LIKELY_NOTABLE, "This application has not been previously seen before");
|
||||
}
|
||||
|
||||
/**
|
||||
* *TEMPORARY* Create a "matching persona" hit for an artifact with an account identifier
|
||||
* associated with a persona
|
||||
*
|
||||
* @param originalArtifact the artifact to create the "previously unseen" item
|
||||
* for
|
||||
*/
|
||||
static private void makeAndPostMatchingPersonaArtifact(BlackboardArtifact originalArtifact, Persona persona,
|
||||
List<String> caseDisplayNames, CorrelationAttributeInstance.Type aType, String value) {
|
||||
String prevCases = caseDisplayNames.stream().distinct().collect(Collectors.joining(","));
|
||||
Collection<BlackboardAttribute> attributesForNewArtifact = Arrays.asList(
|
||||
new BlackboardAttribute(
|
||||
TSK_NAME, MODULE_NAME,
|
||||
persona.getName()),
|
||||
new BlackboardAttribute(
|
||||
TSK_COMMENT, MODULE_NAME,
|
||||
persona.getComment()),
|
||||
new BlackboardAttribute(
|
||||
TSK_CORRELATION_TYPE, MODULE_NAME,
|
||||
aType.getDisplayName()),
|
||||
new BlackboardAttribute(
|
||||
TSK_CORRELATION_VALUE, MODULE_NAME,
|
||||
value),
|
||||
new BlackboardAttribute(
|
||||
TSK_OTHER_CASES, MODULE_NAME,
|
||||
prevCases)
|
||||
);
|
||||
makeAndPostPersonaArtifact(BlackboardArtifact.Type.TSK_MATCHING_PERSONA, originalArtifact, attributesForNewArtifact, "",
|
||||
Score.SCORE_LIKELY_NOTABLE, "This account is associated with a persona");
|
||||
}
|
||||
|
||||
/**
|
||||
* *TEMPORARY* Hack to get all the flagged personas associated with the same file to prevent
|
||||
* duplicates (associate with source file not the account instance artifact).
|
||||
* Make an artifact to flag the passed in content.
|
||||
*
|
||||
* @param originalArtifact Artifact in current case we want to flag
|
||||
* @param attributesForNewArtifact Attributes to assign to the new artifact
|
||||
* @param configuration The configuration to be specified for the new artifact hit
|
||||
* @param score sleuthkit.datamodel.Score to be assigned to this artifact
|
||||
* @param justification Justification string
|
||||
*/
|
||||
private static void makeAndPostPersonaArtifact(BlackboardArtifact.Type newArtifactType, BlackboardArtifact originalArtifact, Collection<BlackboardAttribute> attributesForNewArtifact, String configuration,
|
||||
Score score, String justification) {
|
||||
try {
|
||||
SleuthkitCase tskCase = originalArtifact.getSleuthkitCase();
|
||||
Content originalContent = originalArtifact.getParent(); // Associate artifact with file instead of artifact
|
||||
Blackboard blackboard = tskCase.getBlackboard();
|
||||
// Create artifact if it doesn't already exist.
|
||||
BlackboardArtifact.ARTIFACT_TYPE type = BlackboardArtifact.ARTIFACT_TYPE.fromID(newArtifactType.getTypeID());
|
||||
if (!blackboard.artifactExists(originalContent, type, attributesForNewArtifact)) {
|
||||
BlackboardArtifact newArtifact = originalContent.newAnalysisResult(
|
||||
newArtifactType, score,
|
||||
null, configuration, justification, attributesForNewArtifact)
|
||||
.getAnalysisResult();
|
||||
|
||||
try {
|
||||
// index the artifact for keyword search
|
||||
blackboard.postArtifact(newArtifact, MODULE_NAME);
|
||||
} catch (Blackboard.BlackboardException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Unable to index blackboard artifact " + newArtifact.getArtifactID(), ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Failed to create BlackboardArtifact.", ex); // NON-NLS
|
||||
} catch (IllegalStateException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Failed to create BlackboardAttribute.", ex); // NON-NLS
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an artifact to flag the passed in artifact.
|
||||
@@ -669,28 +595,6 @@ public class IngestEventsListener {
|
||||
makeAndPostPreviousSeenArtifact(bbArtifact, caseDisplayNames, eamArtifact.getCorrelationType(), eamArtifact.getCorrelationValue());
|
||||
}
|
||||
|
||||
// *TEMPORARY* If we have a field that could be associated with a persona, check whether it is
|
||||
// and make an artifact if so. Applicable types should be expanded later.
|
||||
if (flagPreviousItemsEnabled &&
|
||||
((eamArtifact.getCorrelationType().getId() == CorrelationAttributeInstance.EMAIL_TYPE_ID)
|
||||
|| eamArtifact.getCorrelationType().getId() == CorrelationAttributeInstance.PHONE_TYPE_ID)) {
|
||||
String accountId = eamArtifact.getCorrelationValue();
|
||||
Collection<Persona> personaMatches = Persona.getPersonaByAccountIdentifierLike(accountId);
|
||||
for (Persona persona : personaMatches) {
|
||||
// Make sure at least one account is an exact match.
|
||||
boolean foundExactMatch = false;
|
||||
for (PersonaAccount personaAccount : persona.getPersonaAccounts()) {
|
||||
if (accountId.equalsIgnoreCase(personaAccount.getAccount().getIdentifier())) {
|
||||
foundExactMatch = true;
|
||||
}
|
||||
}
|
||||
if (foundExactMatch) {
|
||||
List<String> caseDisplayNames = persona.getCases().stream().map(p -> p.getDisplayName()).collect(Collectors.toList());
|
||||
makeAndPostMatchingPersonaArtifact(bbArtifact, persona, caseDisplayNames, eamArtifact.getCorrelationType(), eamArtifact.getCorrelationValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// flag previously unseen apps and domains
|
||||
if (flagUniqueItemsEnabled
|
||||
&& (eamArtifact.getCorrelationType().getId() == CorrelationAttributeInstance.INSTALLED_PROGS_TYPE_ID
|
||||
|
||||
@@ -2,4 +2,4 @@ IngestSettingsPanel.ingestSettingsLabel.text=Ingest Settings
|
||||
IngestSettingsPanel.flagTaggedNotableItemsCheckbox.text=Flag items previously tagged as notable
|
||||
IngestSettingsPanel.flagPreviouslySeenDevicesCheckbox.text=Flag devices and users previously seen in other cases
|
||||
IngestSettingsPanel.createCorrelationPropertiesCheckbox.text=Save items to the Central Repository
|
||||
IngestSettingsPanel.flagUniqueAppsCheckbox.text=Flag unique apps and domains unseen in other cases
|
||||
IngestSettingsPanel.flagUniqueAppsCheckbox.text=Flag apps and domains not seen in other cases
|
||||
|
||||
@@ -13,4 +13,4 @@ IngestSettingsPanel.ingestSettingsLabel.text=Ingest Settings
|
||||
IngestSettingsPanel.flagTaggedNotableItemsCheckbox.text=Flag items previously tagged as notable
|
||||
IngestSettingsPanel.flagPreviouslySeenDevicesCheckbox.text=Flag devices and users previously seen in other cases
|
||||
IngestSettingsPanel.createCorrelationPropertiesCheckbox.text=Save items to the Central Repository
|
||||
IngestSettingsPanel.flagUniqueAppsCheckbox.text=Flag unique apps and domains unseen in other cases
|
||||
IngestSettingsPanel.flagUniqueAppsCheckbox.text=Flag apps and domains not seen in other cases
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
|
||||
/**
|
||||
* A DataContentViewer that displays text with the TextViewers available.
|
||||
@@ -91,14 +92,10 @@ public class TextContentViewer implements DataContentViewer {
|
||||
if (node == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// get the node's File, if it has one
|
||||
AbstractFile file = node.getLookup().lookup(AbstractFile.class);
|
||||
if (file == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// disable the text content viewer for directories and empty files
|
||||
if (file.isDir() || file.getSize() == 0) {
|
||||
if (file != null && (file.isDir() || file.getSize() == 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -250,18 +250,16 @@ public class Artifacts {
|
||||
KeywordHits.RootNode keywordsNode = new KeywordHits(skCase, dsObjId).new RootNode();
|
||||
return new TypeNodeKey(keywordsNode, TSK_KEYWORD_HIT);
|
||||
|
||||
} else if (TSK_INTERESTING_ARTIFACT_HIT.getTypeID() == typeId
|
||||
|| TSK_INTERESTING_FILE_HIT.getTypeID() == typeId) {
|
||||
|
||||
InterestingHits.RootNode interestingHitsNode = new InterestingHits(skCase, dsObjId).new RootNode();
|
||||
return new TypeNodeKey(interestingHitsNode,
|
||||
TSK_INTERESTING_ARTIFACT_HIT,
|
||||
TSK_INTERESTING_FILE_HIT);
|
||||
|
||||
} else if (TSK_INTERESTING_ARTIFACT_HIT.getTypeID() == typeId) {
|
||||
InterestingHits.RootNode interestingHitsNode = new InterestingHits(skCase, TSK_INTERESTING_ARTIFACT_HIT, dsObjId).new RootNode();
|
||||
return new TypeNodeKey(interestingHitsNode, TSK_INTERESTING_ARTIFACT_HIT);
|
||||
} else if (TSK_INTERESTING_FILE_HIT.getTypeID() == typeId) {
|
||||
InterestingHits.RootNode interestingHitsNode = new InterestingHits(skCase, TSK_INTERESTING_FILE_HIT, dsObjId).new RootNode();
|
||||
return new TypeNodeKey(interestingHitsNode, TSK_INTERESTING_FILE_HIT);
|
||||
} else if (TSK_HASHSET_HIT.getTypeID() == typeId) {
|
||||
HashsetHits.RootNode hashsetHits = new HashsetHits(skCase, dsObjId).new RootNode();
|
||||
return new TypeNodeKey(hashsetHits, TSK_HASHSET_HIT);
|
||||
|
||||
|
||||
} else {
|
||||
return new TypeNodeKey(type, dsObjId);
|
||||
}
|
||||
@@ -278,7 +276,7 @@ public class Artifacts {
|
||||
*/
|
||||
private final RefreshThrottler refreshThrottler = new RefreshThrottler(this);
|
||||
private final Category category;
|
||||
|
||||
|
||||
private final PropertyChangeListener weakPcl;
|
||||
|
||||
/**
|
||||
@@ -293,7 +291,7 @@ public class Artifacts {
|
||||
super();
|
||||
this.filteringDSObjId = filteringDSObjId;
|
||||
this.category = category;
|
||||
|
||||
|
||||
PropertyChangeListener pcl = (PropertyChangeEvent evt) -> {
|
||||
String eventType = evt.getPropertyName();
|
||||
if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
|
||||
@@ -322,9 +320,9 @@ public class Artifacts {
|
||||
|
||||
weakPcl = WeakListeners.propertyChange(pcl, null);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void addNotify() {
|
||||
protected void addNotify() {
|
||||
super.addNotify();
|
||||
refreshThrottler.registerForIngestModuleEvents();
|
||||
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl);
|
||||
@@ -632,7 +630,7 @@ public class Artifacts {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
|
||||
|
||||
@Override
|
||||
@@ -643,7 +641,7 @@ public class Artifacts {
|
||||
|
||||
@Override
|
||||
protected void onRemove() {
|
||||
if(refreshThrottler != null) {
|
||||
if (refreshThrottler != null) {
|
||||
refreshThrottler.unregisterEventListener();
|
||||
}
|
||||
IngestManager.getInstance().removeIngestJobEventListener(weakPcl);
|
||||
@@ -663,14 +661,14 @@ public class Artifacts {
|
||||
|
||||
case ANALYSIS_RESULT:
|
||||
arts = (filteringDSObjId > 0)
|
||||
? blackboard.getAnalysisResultsByType(type.getTypeID(), filteringDSObjId)
|
||||
: blackboard.getAnalysisResultsByType(type.getTypeID());
|
||||
? blackboard.getAnalysisResultsByType(type.getTypeID(), filteringDSObjId)
|
||||
: blackboard.getAnalysisResultsByType(type.getTypeID());
|
||||
break;
|
||||
case DATA_ARTIFACT:
|
||||
default:
|
||||
arts = (filteringDSObjId > 0)
|
||||
? blackboard.getDataArtifacts(type.getTypeID(), filteringDSObjId)
|
||||
: blackboard.getDataArtifacts(type.getTypeID());
|
||||
? blackboard.getDataArtifacts(type.getTypeID(), filteringDSObjId)
|
||||
: blackboard.getDataArtifacts(type.getTypeID());
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -679,9 +677,9 @@ public class Artifacts {
|
||||
//See JIRA-5969
|
||||
art.getAttributes();
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<BlackboardArtifact> toRet = (List<BlackboardArtifact>)(List<?>)arts;
|
||||
List<BlackboardArtifact> toRet = (List<BlackboardArtifact>) (List<?>) arts;
|
||||
return toRet;
|
||||
} catch (NoCurrentCaseException ex) {
|
||||
logger.log(Level.WARNING, "Trying to access case when no case is open.", ex); //NON-NLS
|
||||
|
||||
@@ -181,15 +181,13 @@ public interface DisplayableItemNodeVisitor<T> {
|
||||
|
||||
T visit(EmptyNode.MessageNode emptyNode);
|
||||
|
||||
T visit(InterestingHits.InterestingItemTypeNode aThis);
|
||||
|
||||
/*
|
||||
* Attachments
|
||||
*/
|
||||
T visit(AttachmentNode node);
|
||||
|
||||
|
||||
T visit(OsAccounts.OsAccountNode node);
|
||||
|
||||
|
||||
T visit(OsAccounts.OsAccountListNode node);
|
||||
|
||||
T visit(PersonNode node);
|
||||
@@ -197,12 +195,12 @@ public interface DisplayableItemNodeVisitor<T> {
|
||||
T visit(HostNode node);
|
||||
|
||||
T visit(DataSourcesNode node);
|
||||
|
||||
|
||||
/*
|
||||
* Unsupported node
|
||||
*/
|
||||
T visit(UnsupportedContentNode ucn);
|
||||
|
||||
|
||||
T visit(LocalFilesDataSourceNode lfdsn);
|
||||
|
||||
/**
|
||||
@@ -332,11 +330,6 @@ public interface DisplayableItemNodeVisitor<T> {
|
||||
return defaultVisit(ftByMimeTypeEmptyNode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visit(InterestingHits.InterestingItemTypeNode interestingItemTypeNode) {
|
||||
return defaultVisit(interestingItemTypeNode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visit(DeletedContentNode dcn) {
|
||||
return defaultVisit(dcn);
|
||||
@@ -546,12 +539,12 @@ public interface DisplayableItemNodeVisitor<T> {
|
||||
public T visit(AttachmentNode node) {
|
||||
return defaultVisit(node);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public T visit(OsAccounts.OsAccountNode node) {
|
||||
return defaultVisit(node);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public T visit(OsAccounts.OsAccountListNode node) {
|
||||
return defaultVisit(node);
|
||||
@@ -571,12 +564,12 @@ public interface DisplayableItemNodeVisitor<T> {
|
||||
public T visit(PersonNode node) {
|
||||
return defaultVisit(node);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public T visit(UnsupportedContentNode node) {
|
||||
return defaultVisit(node);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public T visit(LocalFilesDataSourceNode node) {
|
||||
return defaultVisit(node);
|
||||
|
||||
@@ -51,70 +51,95 @@ import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase.CaseDbQuery;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.autopsy.datamodel.Artifacts.UpdatableCountTypeNode;
|
||||
import org.sleuthkit.datamodel.AnalysisResult;
|
||||
import org.sleuthkit.autopsy.datamodel.Artifacts.UpdatableCountTypeNode;
|
||||
|
||||
public class InterestingHits implements AutopsyVisitableItem {
|
||||
|
||||
private static final String INTERESTING_ITEMS = NbBundle
|
||||
.getMessage(InterestingHits.class, "InterestingHits.interestingItems.text");
|
||||
private static final String DISPLAY_NAME = NbBundle.getMessage(InterestingHits.class, "InterestingHits.displayName.text");
|
||||
private static final Logger logger = Logger.getLogger(InterestingHits.class.getName());
|
||||
private static final Set<IngestManager.IngestJobEvent> INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED);
|
||||
private static final Set<IngestManager.IngestModuleEvent> INGEST_MODULE_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestModuleEvent.DATA_ADDED);
|
||||
|
||||
private SleuthkitCase skCase;
|
||||
private final InterestingResults interestingResults = new InterestingResults();
|
||||
private final long filteringDSObjId; // 0 if not filtering/grouping by data source
|
||||
private final BlackboardArtifact.Type artifactType;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param skCase Case DB
|
||||
* @param skCase Case DB
|
||||
* @param artifactType The artifact type (either interesting file or
|
||||
* artifact).
|
||||
*
|
||||
*/
|
||||
public InterestingHits(SleuthkitCase skCase) {
|
||||
this(skCase, 0);
|
||||
public InterestingHits(SleuthkitCase skCase, BlackboardArtifact.Type artifactType) {
|
||||
this(skCase, artifactType, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param skCase Case DB
|
||||
* @param objId Object id of the data source
|
||||
* @param skCase Case DB
|
||||
* @param artifactType The artifact type (either interesting file or
|
||||
* artifact).
|
||||
* @param objId Object id of the data source
|
||||
*
|
||||
*/
|
||||
public InterestingHits(SleuthkitCase skCase, long objId) {
|
||||
public InterestingHits(SleuthkitCase skCase, BlackboardArtifact.Type artifactType, long objId) {
|
||||
this.skCase = skCase;
|
||||
this.artifactType = artifactType;
|
||||
this.filteringDSObjId = objId;
|
||||
interestingResults.update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache of result ids mapped by artifact type -> set name -> artifact id.
|
||||
*/
|
||||
private class InterestingResults extends Observable {
|
||||
|
||||
// NOTE: the map can be accessed by multiple worker threads and needs to be synchronized
|
||||
private final Map<String, Map<String, Set<Long>>> interestingItemsMap = new LinkedHashMap<>();
|
||||
private final Map<String, Set<Long>> interestingItemsMap = new LinkedHashMap<>();
|
||||
|
||||
public List<String> getSetNames() {
|
||||
/**
|
||||
* Returns all the set names for a given interesting item type.
|
||||
*
|
||||
* @param type The interesting item type.
|
||||
*
|
||||
* @return The set names.
|
||||
*/
|
||||
List<String> getSetNames() {
|
||||
List<String> setNames;
|
||||
synchronized (interestingItemsMap) {
|
||||
setNames = new ArrayList<>(interestingItemsMap.keySet());
|
||||
}
|
||||
Collections.sort(setNames);
|
||||
Collections.sort(setNames, (a, b) -> a.compareToIgnoreCase(b));
|
||||
return setNames;
|
||||
}
|
||||
|
||||
public Set<Long> getArtifactIds(String setName, String typeName) {
|
||||
/**
|
||||
* Returns all artifact ids belonging to the specified interesting item
|
||||
* type and set name.
|
||||
*
|
||||
* @param type The interesting item type.
|
||||
* @param setName The set name.
|
||||
*
|
||||
* @return The artifact ids in that set name and type.
|
||||
*/
|
||||
Set<Long> getArtifactIds(String setName) {
|
||||
synchronized (interestingItemsMap) {
|
||||
return interestingItemsMap.get(setName).get(typeName);
|
||||
return new HashSet<>(interestingItemsMap.getOrDefault(setName, Collections.emptySet()));
|
||||
}
|
||||
}
|
||||
|
||||
public void update() {
|
||||
/**
|
||||
* Triggers a fetch from the database to update this cache.
|
||||
*/
|
||||
void update() {
|
||||
synchronized (interestingItemsMap) {
|
||||
interestingItemsMap.clear();
|
||||
}
|
||||
loadArtifacts(BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT);
|
||||
loadArtifacts(BlackboardArtifact.Type.TSK_INTERESTING_ARTIFACT_HIT);
|
||||
loadArtifacts();
|
||||
setChanged();
|
||||
notifyObservers();
|
||||
}
|
||||
@@ -124,18 +149,18 @@ public class InterestingHits implements AutopsyVisitableItem {
|
||||
* the interestingItemsMap
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private void loadArtifacts(BlackboardArtifact.Type artType) {
|
||||
private void loadArtifacts() {
|
||||
if (skCase == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int setNameId = BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID();
|
||||
int artId = artType.getTypeID();
|
||||
String query = "SELECT value_text,blackboard_artifacts.artifact_obj_id,attribute_type_id " //NON-NLS
|
||||
|
||||
String query = "SELECT value_text, blackboard_artifacts.artifact_obj_id " //NON-NLS
|
||||
+ "FROM blackboard_attributes,blackboard_artifacts WHERE " //NON-NLS
|
||||
+ "attribute_type_id=" + setNameId //NON-NLS
|
||||
+ " AND blackboard_attributes.artifact_id=blackboard_artifacts.artifact_id" //NON-NLS
|
||||
+ " AND blackboard_artifacts.artifact_type_id=" + artId; //NON-NLS
|
||||
+ " AND blackboard_artifacts.artifact_type_id = " + artifactType.getTypeID(); //NON-NLS
|
||||
if (filteringDSObjId > 0) {
|
||||
query += " AND blackboard_artifacts.data_source_obj_id = " + filteringDSObjId;
|
||||
}
|
||||
@@ -146,12 +171,9 @@ public class InterestingHits implements AutopsyVisitableItem {
|
||||
while (resultSet.next()) {
|
||||
String value = resultSet.getString("value_text"); //NON-NLS
|
||||
long artifactObjId = resultSet.getLong("artifact_obj_id"); //NON-NLS
|
||||
if (!interestingItemsMap.containsKey(value)) {
|
||||
interestingItemsMap.put(value, new LinkedHashMap<>());
|
||||
interestingItemsMap.get(value).put(BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT.getDisplayName(), new HashSet<>());
|
||||
interestingItemsMap.get(value).put(BlackboardArtifact.Type.TSK_INTERESTING_ARTIFACT_HIT.getDisplayName(), new HashSet<>());
|
||||
}
|
||||
interestingItemsMap.get(value).get(artType.getDisplayName()).add(artifactObjId);
|
||||
interestingItemsMap
|
||||
.computeIfAbsent(value, (k) -> new HashSet<>())
|
||||
.add(artifactObjId);
|
||||
}
|
||||
}
|
||||
} catch (TskCoreException | SQLException ex) {
|
||||
@@ -166,54 +188,8 @@ public class InterestingHits implements AutopsyVisitableItem {
|
||||
}
|
||||
|
||||
/**
|
||||
* Node for the interesting items
|
||||
* Creates nodes for all sets for a specified interesting item type.
|
||||
*/
|
||||
public class RootNode extends UpdatableCountTypeNode {
|
||||
|
||||
public RootNode() {
|
||||
super(Children.create(new SetNameFactory(), true),
|
||||
Lookups.singleton(DISPLAY_NAME),
|
||||
DISPLAY_NAME,
|
||||
filteringDSObjId,
|
||||
BlackboardArtifact.Type.TSK_INTERESTING_ARTIFACT_HIT,
|
||||
BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT);
|
||||
super.setName(INTERESTING_ITEMS);
|
||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/interesting_item.png"); //NON-NLS
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLeafTypeNode() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
|
||||
return visitor.visit(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Sheet createSheet() {
|
||||
Sheet sheet = super.createSheet();
|
||||
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
|
||||
if (sheetSet == null) {
|
||||
sheetSet = Sheet.createPropertiesSet();
|
||||
sheet.put(sheetSet);
|
||||
}
|
||||
|
||||
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.name"),
|
||||
NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.displayName"),
|
||||
NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.desc"),
|
||||
getName()));
|
||||
|
||||
return sheet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getItemType() {
|
||||
return getClass().getName();
|
||||
}
|
||||
}
|
||||
|
||||
private class SetNameFactory extends ChildFactory.Detachable<String> implements Observer {
|
||||
|
||||
/*
|
||||
@@ -239,8 +215,7 @@ public class InterestingHits implements AutopsyVisitableItem {
|
||||
* event to have a null oldValue.
|
||||
*/
|
||||
ModuleDataEvent eventData = (ModuleDataEvent) evt.getOldValue();
|
||||
if (null != eventData && (eventData.getBlackboardArtifactType().getTypeID() == BlackboardArtifact.Type.TSK_INTERESTING_ARTIFACT_HIT.getTypeID()
|
||||
|| eventData.getBlackboardArtifactType().getTypeID() == BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT.getTypeID())) {
|
||||
if (null != eventData && (eventData.getBlackboardArtifactType().getTypeID() == artifactType.getTypeID())) {
|
||||
interestingResults.update();
|
||||
}
|
||||
} catch (NoCurrentCaseException notUsed) {
|
||||
@@ -272,26 +247,8 @@ public class InterestingHits implements AutopsyVisitableItem {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
|
||||
|
||||
@Override
|
||||
protected void addNotify() {
|
||||
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl);
|
||||
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl);
|
||||
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
|
||||
interestingResults.update();
|
||||
interestingResults.addObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
super.finalize();
|
||||
IngestManager.getInstance().removeIngestJobEventListener(weakPcl);
|
||||
IngestManager.getInstance().removeIngestModuleEventListener(weakPcl);
|
||||
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
|
||||
interestingResults.deleteObserver(this);
|
||||
}
|
||||
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
|
||||
|
||||
@Override
|
||||
protected boolean createKeys(List<String> list) {
|
||||
@@ -308,14 +265,35 @@ public class InterestingHits implements AutopsyVisitableItem {
|
||||
public void update(Observable o, Object arg) {
|
||||
refresh(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addNotify() {
|
||||
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl);
|
||||
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl);
|
||||
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
|
||||
interestingResults.addObserver(this);
|
||||
interestingResults.update();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
super.finalize();
|
||||
IngestManager.getInstance().removeIngestJobEventListener(weakPcl);
|
||||
IngestManager.getInstance().removeIngestModuleEventListener(weakPcl);
|
||||
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
|
||||
interestingResults.deleteObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A node for a set to be displayed in the tree.
|
||||
*/
|
||||
public class SetNameNode extends DisplayableItemNode implements Observer {
|
||||
|
||||
private final String setName;
|
||||
|
||||
public SetNameNode(String setName) {//, Set<Long> children) {
|
||||
super(Children.create(new HitTypeFactory(setName), true), Lookups.singleton(setName));
|
||||
super(Children.create(new HitFactory(setName), true), Lookups.singleton(setName));
|
||||
this.setName = setName;
|
||||
super.setName(setName);
|
||||
updateDisplayName();
|
||||
@@ -324,111 +302,81 @@ public class InterestingHits implements AutopsyVisitableItem {
|
||||
}
|
||||
|
||||
private void updateDisplayName() {
|
||||
int sizeOfSet = interestingResults.getArtifactIds(setName, BlackboardArtifact.Type.TSK_INTERESTING_ARTIFACT_HIT.getDisplayName()).size()
|
||||
+ interestingResults.getArtifactIds(setName, BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT.getDisplayName()).size();
|
||||
int sizeOfSet = interestingResults.getArtifactIds(setName).size();
|
||||
super.setDisplayName(setName + " (" + sizeOfSet + ")");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLeafTypeNode() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Sheet createSheet() {
|
||||
Sheet sheet = super.createSheet();
|
||||
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
|
||||
if (sheetSet == null) {
|
||||
sheetSet = Sheet.createPropertiesSet();
|
||||
sheet.put(sheetSet);
|
||||
}
|
||||
|
||||
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.name"),
|
||||
NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.name"),
|
||||
NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.desc"),
|
||||
getName()));
|
||||
|
||||
return sheet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
|
||||
return visitor.visit(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
updateDisplayName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getItemType() {
|
||||
/**
|
||||
* For custom settings for each rule set, return
|
||||
* getClass().getName() + setName instead.
|
||||
*/
|
||||
return getClass().getName();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parent node for interesting item type that shows child set nodes.
|
||||
*/
|
||||
public class RootNode extends UpdatableCountTypeNode {
|
||||
|
||||
/**
|
||||
* Main constructor.
|
||||
*/
|
||||
public RootNode() {
|
||||
super(Children.create(new SetNameFactory(), true),
|
||||
Lookups.singleton(artifactType),
|
||||
artifactType.getDisplayName(),
|
||||
filteringDSObjId,
|
||||
artifactType);
|
||||
|
||||
/**
|
||||
* We use the combination of setName and typeName as the name of the
|
||||
* node to ensure that nodes have a unique name. This comes into
|
||||
* play when associating paging state with the node.
|
||||
*/
|
||||
setName(artifactType.getDisplayName());
|
||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/interesting_item.png"); //NON-NLS
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLeafTypeNode() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Sheet createSheet() {
|
||||
Sheet sheet = super.createSheet();
|
||||
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
|
||||
if (sheetSet == null) {
|
||||
sheetSet = Sheet.createPropertiesSet();
|
||||
sheet.put(sheetSet);
|
||||
}
|
||||
|
||||
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.name"),
|
||||
NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.name"),
|
||||
NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.desc"),
|
||||
getName()));
|
||||
|
||||
return sheet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
|
||||
return visitor.visit(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
updateDisplayName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getItemType() {
|
||||
/**
|
||||
* For custom settings for each rule set, return
|
||||
* getClass().getName() + setName instead.
|
||||
*/
|
||||
return getClass().getName();
|
||||
}
|
||||
}
|
||||
|
||||
private class HitTypeFactory extends ChildFactory<String> implements Observer {
|
||||
|
||||
private final String setName;
|
||||
private final Map<Long, BlackboardArtifact> artifactHits = new HashMap<>();
|
||||
|
||||
private HitTypeFactory(String setName) {
|
||||
super();
|
||||
this.setName = setName;
|
||||
interestingResults.addObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean createKeys(List<String> list) {
|
||||
list.add(BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT.getDisplayName());
|
||||
list.add(BlackboardArtifact.Type.TSK_INTERESTING_ARTIFACT_HIT.getDisplayName());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node createNodeForKey(String key) {
|
||||
return new InterestingItemTypeNode(setName, key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
refresh(true);
|
||||
}
|
||||
}
|
||||
|
||||
public class InterestingItemTypeNode extends DisplayableItemNode implements Observer {
|
||||
|
||||
private final String typeName;
|
||||
private final String setName;
|
||||
|
||||
private InterestingItemTypeNode(String setName, String typeName) {
|
||||
super(Children.create(new HitFactory(setName, typeName), true), Lookups.singleton(setName));
|
||||
this.typeName = typeName;
|
||||
this.setName = setName;
|
||||
/**
|
||||
* We use the combination of setName and typeName as the name of the
|
||||
* node to ensure that nodes have a unique name. This comes into
|
||||
* play when associating paging state with the node.
|
||||
*/
|
||||
super.setName(setName + "_" + typeName);
|
||||
updateDisplayName();
|
||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/interesting_item.png"); //NON-NLS
|
||||
interestingResults.addObserver(this);
|
||||
}
|
||||
|
||||
private void updateDisplayName() {
|
||||
super.setDisplayName(typeName + " (" + interestingResults.getArtifactIds(setName, typeName).size() + ")");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLeafTypeNode() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Sheet createSheet() {
|
||||
Sheet sheet = super.createSheet();
|
||||
@@ -449,11 +397,6 @@ public class InterestingHits implements AutopsyVisitableItem {
|
||||
return visitor.visit(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
updateDisplayName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getItemType() {
|
||||
/**
|
||||
@@ -464,21 +407,27 @@ public class InterestingHits implements AutopsyVisitableItem {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory for creating individual interesting item BlackboardArtifactNodes.
|
||||
*/
|
||||
private class HitFactory extends BaseChildFactory<AnalysisResult> implements Observer {
|
||||
|
||||
private final String setName;
|
||||
private final String typeName;
|
||||
private final Map<Long, AnalysisResult> artifactHits = new HashMap<>();
|
||||
|
||||
private HitFactory(String setName, String typeName) {
|
||||
/**
|
||||
* Main constructor.
|
||||
*
|
||||
* @param setName The set name of artifacts to be displayed.
|
||||
*/
|
||||
private HitFactory(String setName) {
|
||||
/**
|
||||
* The node name passed to the parent constructor must be the same
|
||||
* as the name set in the InterestingItemTypeNode constructor, i.e.
|
||||
* setName underscore typeName
|
||||
*/
|
||||
super(setName + "_" + typeName);
|
||||
super(setName);
|
||||
this.setName = setName;
|
||||
this.typeName = typeName;
|
||||
interestingResults.addObserver(this);
|
||||
}
|
||||
|
||||
@@ -486,7 +435,7 @@ public class InterestingHits implements AutopsyVisitableItem {
|
||||
protected List<AnalysisResult> makeKeys() {
|
||||
|
||||
if (skCase != null) {
|
||||
interestingResults.getArtifactIds(setName, typeName).forEach((id) -> {
|
||||
interestingResults.getArtifactIds(setName).forEach((id) -> {
|
||||
try {
|
||||
if (!artifactHits.containsKey(id)) {
|
||||
AnalysisResult art = skCase.getBlackboard().getAnalysisResultById(id);
|
||||
|
||||
@@ -1481,7 +1481,7 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
}
|
||||
}
|
||||
|
||||
final private class CreditCardNumberFactory extends ObservingChildren<Long> {
|
||||
final private class CreditCardNumberFactory extends ObservingChildren<DataArtifact> {
|
||||
|
||||
private final BinResult bin;
|
||||
|
||||
@@ -1502,10 +1502,10 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean createKeys(List<Long> list) {
|
||||
protected boolean createKeys(List<DataArtifact> list) {
|
||||
|
||||
String query
|
||||
= "SELECT blackboard_artifacts.artifact_id " //NON-NLS
|
||||
= "SELECT blackboard_artifacts.artifact_obj_id " //NON-NLS
|
||||
+ " FROM blackboard_artifacts " //NON-NLS
|
||||
+ " JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id " //NON-NLS
|
||||
+ " WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.Type.TSK_ACCOUNT.getTypeID() //NON-NLS
|
||||
@@ -1517,7 +1517,7 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
|
||||
ResultSet rs = results.getResultSet();) {
|
||||
while (rs.next()) {
|
||||
list.add(rs.getLong("artifact_id")); //NON-NLS
|
||||
list.add(skCase.getBlackboard().getDataArtifactById(rs.getLong("artifact_obj_id"))); //NON-NLS
|
||||
}
|
||||
} catch (TskCoreException | SQLException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error querying for account artifacts.", ex); //NON-NLS
|
||||
@@ -1527,18 +1527,8 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node[] createNodesForKey(Long artifactID) {
|
||||
if (skCase == null) {
|
||||
return new Node[0];
|
||||
}
|
||||
|
||||
try {
|
||||
DataArtifact art = skCase.getBlackboard().getDataArtifactById(artifactID);
|
||||
return new Node[]{new AccountArtifactNode(art)};
|
||||
} catch (TskCoreException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error creating BlackboardArtifactNode for artifact with ID " + artifactID, ex); //NON-NLS
|
||||
return new Node[0];
|
||||
}
|
||||
protected Node[] createNodesForKey(DataArtifact artifact) {
|
||||
return new Node[]{new AccountArtifactNode(artifact)};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1271,9 +1271,10 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
treeNode = getHashsetNode(typesChildren, art);
|
||||
} else if (typeID == BlackboardArtifact.Type.TSK_KEYWORD_HIT.getTypeID()) {
|
||||
treeNode = getKeywordHitNode(typesChildren, art);
|
||||
} else if (typeID == BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT.getTypeID()
|
||||
|| typeID == BlackboardArtifact.Type.TSK_INTERESTING_ARTIFACT_HIT.getTypeID()) {
|
||||
treeNode = getInterestingItemNode(typesChildren, art);
|
||||
} else if (typeID == BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT.getTypeID()) {
|
||||
treeNode = getInterestingItemNode(typesChildren, BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT, art);
|
||||
} else if (typeID == BlackboardArtifact.Type.TSK_INTERESTING_ARTIFACT_HIT.getTypeID()) {
|
||||
treeNode = getInterestingItemNode(typesChildren, BlackboardArtifact.Type.TSK_INTERESTING_ARTIFACT_HIT, art);
|
||||
} else if (typeID == BlackboardArtifact.Type.TSK_EMAIL_MSG.getTypeID()) {
|
||||
treeNode = getEmailNode(typesChildren, art);
|
||||
} else if (typeID == BlackboardArtifact.Type.TSK_ACCOUNT.getTypeID()) {
|
||||
@@ -1401,42 +1402,46 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
*
|
||||
* @param typesChildren The children object of the same category as
|
||||
* interesting item.
|
||||
* @param artifactType The type of the artifact (interesting hit or
|
||||
* artifact).
|
||||
* @param art The artifact.
|
||||
*
|
||||
* @return The interesting item artifact's parent node or null if cannot be
|
||||
* found.
|
||||
*/
|
||||
private Node getInterestingItemNode(Children typesChildren, BlackboardArtifact art) {
|
||||
Node interestingItemsRootNode = typesChildren.findChild(NbBundle
|
||||
.getMessage(InterestingHits.class, "InterestingHits.interestingItems.text"));
|
||||
Children interestingItemsRootChildren = interestingItemsRootNode.getChildren();
|
||||
private Node getInterestingItemNode(Children typesChildren, BlackboardArtifact.Type artifactType, BlackboardArtifact art) {
|
||||
Node interestingItemsRootNode = typesChildren.findChild(artifactType.getDisplayName());
|
||||
Children setNodeChildren = (interestingItemsRootNode == null) ? null : interestingItemsRootNode.getChildren();
|
||||
|
||||
// set node children for type could not be found, so return null.
|
||||
if (setNodeChildren == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String setName = null;
|
||||
try {
|
||||
String setName = null;
|
||||
List<BlackboardAttribute> attributes = art.getAttributes();
|
||||
for (BlackboardAttribute att : attributes) {
|
||||
int typeId = att.getAttributeType().getTypeID();
|
||||
if (typeId == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()) {
|
||||
setName = att.getValueString();
|
||||
}
|
||||
}
|
||||
Node setNode = interestingItemsRootChildren.findChild(setName);
|
||||
if (setNode == null) {
|
||||
return null;
|
||||
}
|
||||
setName = art.getAttributes().stream()
|
||||
.filter(attr -> attr.getAttributeType().getTypeID() == BlackboardAttribute.Type.TSK_SET_NAME.getTypeID())
|
||||
.map(attr -> attr.getValueString())
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
Children fileArtifactChildren = setNode.getChildren();
|
||||
Node[] fileArtifactNodes = fileArtifactChildren == null ? null : fileArtifactChildren.getNodes();
|
||||
if (fileArtifactNodes == null || fileArtifactNodes.length != 2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (art.getArtifactTypeID() == BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT.getTypeID())
|
||||
? fileArtifactNodes[0]
|
||||
: fileArtifactNodes[1];
|
||||
} catch (TskCoreException ex) {
|
||||
LOGGER.log(Level.WARNING, "Error retrieving attributes", ex); //NON-NLS
|
||||
return null;
|
||||
}
|
||||
|
||||
// if no set name, no set node will be identified.
|
||||
if (setName == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// make sure data is fully loaded
|
||||
final String finalSetName = setName;
|
||||
return Stream.of(setNodeChildren.getNodes(true))
|
||||
.filter(setNode -> finalSetName.equals(setNode.getLookup().lookup(String.class)))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,31 +23,28 @@ import javax.swing.AbstractAction;
|
||||
import org.openide.util.Lookup;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author dfickling
|
||||
* The “File Search by Attributes” action for data sources in the tree.
|
||||
*/
|
||||
public class FileSearchAction extends AbstractAction {
|
||||
|
||||
private final Long dataSourceId;
|
||||
private final long dataSourceId;
|
||||
|
||||
/**
|
||||
* Main constructor.
|
||||
*
|
||||
* @param title The display name for the action.
|
||||
* @param dataSourceID The data source id of the item that is selected in
|
||||
* the tree.
|
||||
*/
|
||||
public FileSearchAction(String title, long dataSourceID) {
|
||||
super(title);
|
||||
dataSourceId = dataSourceID;
|
||||
}
|
||||
|
||||
public FileSearchAction(String title) {
|
||||
super(title);
|
||||
dataSourceId = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
FileSearchProvider searcher = Lookup.getDefault().lookup(FileSearchProvider.class);
|
||||
if (dataSourceId == null) {
|
||||
searcher.showDialog();
|
||||
} else {
|
||||
searcher.showDialog(dataSourceId);
|
||||
}
|
||||
searcher.showDialog(dataSourceId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -326,7 +326,7 @@ public class PlasoIngestModule implements DataSourceIngestModule {
|
||||
// If the description is empty use the event type display name
|
||||
// as the description.
|
||||
if (description == null || description.isEmpty()) {
|
||||
if (eventType != TimelineEventType.OTHER) {
|
||||
if (eventType != TimelineEventType.STANDARD_ARTIFACT_CATCH_ALL) {
|
||||
description = eventType.getDisplayName();
|
||||
} else {
|
||||
continue;
|
||||
@@ -440,7 +440,7 @@ public class PlasoIngestModule implements DataSourceIngestModule {
|
||||
return TimelineEventType.REGISTRY;
|
||||
}
|
||||
default:
|
||||
return TimelineEventType.OTHER;
|
||||
return TimelineEventType.STANDARD_ARTIFACT_CATCH_ALL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user