mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-15 09:17:42 +00:00
6711 move attributes out of file search class
This commit is contained in:
parent
98e790c4e6
commit
1b73edee7d
@ -1,5 +1,3 @@
|
|||||||
AttributeSearchData.AttributeType.Domain.displayName=Domain
|
|
||||||
AttributeSearchData.AttributeType.Other.displayName=Other
|
|
||||||
DiscoveryKeyUtils.FileTagGroupKey.noSets=None
|
DiscoveryKeyUtils.FileTagGroupKey.noSets=None
|
||||||
DiscoveryKeyUtils.NoGroupingGroupKey.allFiles=All Files
|
DiscoveryKeyUtils.NoGroupingGroupKey.allFiles=All Files
|
||||||
FileGroup.groupSortingAlgorithm.groupName.text=Group Name
|
FileGroup.groupSortingAlgorithm.groupName.text=Group Name
|
||||||
@ -26,39 +24,6 @@ FileSearch.HashHitsGroupKey.noHashHits=None
|
|||||||
FileSearch.InterestingItemGroupKey.noSets=None
|
FileSearch.InterestingItemGroupKey.noSets=None
|
||||||
FileSearch.KeywordListGroupKey.noKeywords=None
|
FileSearch.KeywordListGroupKey.noKeywords=None
|
||||||
FileSearch.ObjectDetectedGroupKey.noSets=None
|
FileSearch.ObjectDetectedGroupKey.noSets=None
|
||||||
FileSearchData.FileSize.100kbto1mb=: 100KB-1MB
|
|
||||||
FileSearchData.FileSize.100mbto1gb=: 100MB-1GB
|
|
||||||
FileSearchData.FileSize.10PlusGb=: 10GB+
|
|
||||||
FileSearchData.FileSize.16kbto100kb=: 16-100KB
|
|
||||||
FileSearchData.FileSize.1gbto5gb=: 1-5GB
|
|
||||||
FileSearchData.FileSize.1mbto50mb=: 1-50MB
|
|
||||||
FileSearchData.FileSize.200PlusMb=: 200MB+
|
|
||||||
FileSearchData.FileSize.500kbto100mb=: 500KB-100MB
|
|
||||||
FileSearchData.FileSize.50mbto200mb=: 50-200MB
|
|
||||||
FileSearchData.FileSize.5gbto10gb=: 5-10GB
|
|
||||||
FileSearchData.FileSize.LARGE.displayName=Large
|
|
||||||
FileSearchData.FileSize.MEDIUM.displayName=Medium
|
|
||||||
FileSearchData.FileSize.SMALL.displayName=Small
|
|
||||||
FileSearchData.FileSize.upTo16kb=: 0-16KB
|
|
||||||
FileSearchData.FileSize.upTo500kb=: 0-500KB
|
|
||||||
FileSearchData.FileSize.XLARGE.displayName=XLarge
|
|
||||||
FileSearchData.FileSize.XSMALL.displayName=XSmall
|
|
||||||
FileSearchData.FileSize.XXLARGE.displayName=XXLarge
|
|
||||||
FileSearchData.FileType.Audio.displayName=Audio
|
|
||||||
FileSearchData.FileType.Documents.displayName=Documents
|
|
||||||
FileSearchData.FileType.Executables.displayName=Executables
|
|
||||||
FileSearchData.FileType.Image.displayName=Image
|
|
||||||
FileSearchData.FileType.Other.displayName=Other/Unknown
|
|
||||||
FileSearchData.FileType.Video.displayName=Video
|
|
||||||
FileSearchData.Frequency.common.displayName=Common (11 - 100)
|
|
||||||
FileSearchData.Frequency.known.displayName=Known (NSRL)
|
|
||||||
FileSearchData.Frequency.rare.displayName=Rare (2-10)
|
|
||||||
FileSearchData.Frequency.unique.displayName=Unique (1)
|
|
||||||
FileSearchData.Frequency.unknown.displayName=Unknown
|
|
||||||
FileSearchData.Frequency.verycommon.displayName=Very Common (100+)
|
|
||||||
FileSearchData.Score.interesting.displayName=Interesting
|
|
||||||
FileSearchData.Score.notable.displayName=Notable
|
|
||||||
FileSearchData.Score.unknown.displayName=Unknown
|
|
||||||
FileSearchFiltering.concatenateSetNamesForDisplay.comma=,
|
FileSearchFiltering.concatenateSetNamesForDisplay.comma=,
|
||||||
# {0} - filters
|
# {0} - filters
|
||||||
FileSearchFiltering.HashSetFilter.desc=Hash set hits in set(s): {0}
|
FileSearchFiltering.HashSetFilter.desc=Hash set hits in set(s): {0}
|
||||||
@ -79,6 +44,40 @@ ResultFile.score.interestingResult.description=At least one instance of the file
|
|||||||
ResultFile.score.notableFile.description=At least one instance of the file was recognized as notable.
|
ResultFile.score.notableFile.description=At least one instance of the file was recognized as notable.
|
||||||
ResultFile.score.notableTaggedFile.description=At least one instance of the file is tagged with a notable tag.
|
ResultFile.score.notableTaggedFile.description=At least one instance of the file is tagged with a notable tag.
|
||||||
ResultFile.score.taggedFile.description=At least one instance of the file has been tagged.
|
ResultFile.score.taggedFile.description=At least one instance of the file has been tagged.
|
||||||
|
SearchData.AttributeType.Domain.displayName=Domains
|
||||||
|
SearchData.FileSize.100kbto1mb=: 100KB-1MB
|
||||||
|
SearchData.FileSize.100mbto1gb=: 100MB-1GB
|
||||||
|
SearchData.FileSize.10PlusGb=: 10GB+
|
||||||
|
SearchData.FileSize.16kbto100kb=: 16-100KB
|
||||||
|
SearchData.FileSize.1gbto5gb=: 1-5GB
|
||||||
|
SearchData.FileSize.1mbto50mb=: 1-50MB
|
||||||
|
SearchData.FileSize.200PlusMb=: 200MB+
|
||||||
|
SearchData.FileSize.500kbto100mb=: 500KB-100MB
|
||||||
|
SearchData.FileSize.50mbto200mb=: 50-200MB
|
||||||
|
SearchData.FileSize.5gbto10gb=: 5-10GB
|
||||||
|
SearchData.FileSize.LARGE.displayName=Large
|
||||||
|
SearchData.FileSize.MEDIUM.displayName=Medium
|
||||||
|
SearchData.FileSize.SMALL.displayName=Small
|
||||||
|
SearchData.FileSize.upTo16kb=: 0-16KB
|
||||||
|
SearchData.FileSize.upTo500kb=: 0-500KB
|
||||||
|
SearchData.FileSize.XLARGE.displayName=XLarge
|
||||||
|
SearchData.FileSize.XSMALL.displayName=XSmall
|
||||||
|
SearchData.FileSize.XXLARGE.displayName=XXLarge
|
||||||
|
SearchData.FileType.Audio.displayName=Audio
|
||||||
|
SearchData.FileType.Documents.displayName=Documents
|
||||||
|
SearchData.FileType.Executables.displayName=Executables
|
||||||
|
SearchData.FileType.Image.displayName=Image
|
||||||
|
SearchData.FileType.Other.displayName=Other/Unknown
|
||||||
|
SearchData.FileType.Video.displayName=Video
|
||||||
|
SearchData.Frequency.common.displayName=Common (11 - 100)
|
||||||
|
SearchData.Frequency.known.displayName=Known (NSRL)
|
||||||
|
SearchData.Frequency.rare.displayName=Rare (2-10)
|
||||||
|
SearchData.Frequency.unique.displayName=Unique (1)
|
||||||
|
SearchData.Frequency.unknown.displayName=Unknown
|
||||||
|
SearchData.Frequency.verycommon.displayName=Very Common (100+)
|
||||||
|
SearchData.Score.interesting.displayName=Interesting
|
||||||
|
SearchData.Score.notable.displayName=Notable
|
||||||
|
SearchData.Score.unknown.displayName=Unknown
|
||||||
# {0} - Data source name
|
# {0} - Data source name
|
||||||
# {1} - Data source ID
|
# {1} - Data source ID
|
||||||
SearchFiltering.DataSourceFilter.datasource={0}({1})
|
SearchFiltering.DataSourceFilter.datasource={0}({1})
|
||||||
|
@ -0,0 +1,653 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package org.sleuthkit.autopsy.discovery.search;
|
||||||
|
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import org.openide.util.NbBundle;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoDbUtil;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.InstanceTableCallback;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
|
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||||
|
import org.sleuthkit.datamodel.CaseDbAccessManager;
|
||||||
|
import org.sleuthkit.datamodel.ContentTag;
|
||||||
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
import org.sleuthkit.datamodel.TskData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author wschaefer
|
||||||
|
*/
|
||||||
|
public class DiscoveryAttributes {
|
||||||
|
|
||||||
|
private final static Logger logger = Logger.getLogger(DiscoveryAttributes.class.getName());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for the grouping attributes.
|
||||||
|
*/
|
||||||
|
public abstract static class AttributeType {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For a given file, return the key for the group it belongs to for this
|
||||||
|
* attribute type.
|
||||||
|
*
|
||||||
|
* @param file the result file to be grouped
|
||||||
|
*
|
||||||
|
* @return the key for the group this file goes in
|
||||||
|
*/
|
||||||
|
public abstract DiscoveryKeyUtils.GroupKey getGroupKey(ResultFile file);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add any extra data to the ResultFile object from this attribute.
|
||||||
|
*
|
||||||
|
* @param files The list of files to enhance
|
||||||
|
* @param caseDb The case database
|
||||||
|
* @param centralRepoDb The central repository database. Can be null if
|
||||||
|
* not needed.
|
||||||
|
*
|
||||||
|
* @throws DiscoveryException
|
||||||
|
*/
|
||||||
|
public void addAttributeToResultFiles(List<ResultFile> files, SleuthkitCase caseDb, CentralRepository centralRepoDb) throws DiscoveryException {
|
||||||
|
// Default is to do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attribute for grouping/sorting by file size
|
||||||
|
*/
|
||||||
|
public static class FileSizeAttribute extends AttributeType {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DiscoveryKeyUtils.GroupKey getGroupKey(ResultFile file) {
|
||||||
|
return new DiscoveryKeyUtils.FileSizeGroupKey(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attribute for grouping/sorting by parent path
|
||||||
|
*/
|
||||||
|
public static class ParentPathAttribute extends AttributeType {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DiscoveryKeyUtils.GroupKey getGroupKey(ResultFile file) {
|
||||||
|
return new DiscoveryKeyUtils.ParentPathGroupKey(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default attribute used to make one group
|
||||||
|
*/
|
||||||
|
static class NoGroupingAttribute extends AttributeType {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DiscoveryKeyUtils.GroupKey getGroupKey(ResultFile file) {
|
||||||
|
return new DiscoveryKeyUtils.NoGroupingGroupKey();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attribute for grouping/sorting by data source
|
||||||
|
*/
|
||||||
|
static class DataSourceAttribute extends AttributeType {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DiscoveryKeyUtils.GroupKey getGroupKey(ResultFile file) {
|
||||||
|
return new DiscoveryKeyUtils.DataSourceGroupKey(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attribute for grouping/sorting by file type
|
||||||
|
*/
|
||||||
|
static class FileTypeAttribute extends AttributeType {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DiscoveryKeyUtils.GroupKey getGroupKey(ResultFile file) {
|
||||||
|
return new DiscoveryKeyUtils.FileTypeGroupKey(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attribute for grouping/sorting by keyword lists
|
||||||
|
*/
|
||||||
|
static class KeywordListAttribute extends AttributeType {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DiscoveryKeyUtils.GroupKey getGroupKey(ResultFile file) {
|
||||||
|
return new DiscoveryKeyUtils.KeywordListGroupKey(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addAttributeToResultFiles(List<ResultFile> files, SleuthkitCase caseDb,
|
||||||
|
CentralRepository centralRepoDb) throws DiscoveryException {
|
||||||
|
|
||||||
|
// Get pairs of (object ID, keyword list name) for all files in the list of files that have
|
||||||
|
// keyword list hits.
|
||||||
|
String selectQuery = createSetNameClause(files, BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID(),
|
||||||
|
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID());
|
||||||
|
|
||||||
|
SetKeywordListNamesCallback callback = new SetKeywordListNamesCallback(files);
|
||||||
|
try {
|
||||||
|
caseDb.getCaseDbAccessManager().select(selectQuery, callback);
|
||||||
|
} catch (TskCoreException ex) {
|
||||||
|
throw new DiscoveryException("Error looking up keyword list attributes", ex); // NON-NLS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback to process the results of the CaseDbAccessManager select
|
||||||
|
* query. Will add the keyword list names to the list of ResultFile
|
||||||
|
* objects.
|
||||||
|
*/
|
||||||
|
private static class SetKeywordListNamesCallback implements CaseDbAccessManager.CaseDbAccessQueryCallback {
|
||||||
|
|
||||||
|
List<ResultFile> resultFiles;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the callback.
|
||||||
|
*
|
||||||
|
* @param resultFiles List of files to add keyword list names to
|
||||||
|
*/
|
||||||
|
SetKeywordListNamesCallback(List<ResultFile> resultFiles) {
|
||||||
|
this.resultFiles = resultFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(ResultSet rs) {
|
||||||
|
try {
|
||||||
|
// Create a temporary map of object ID to ResultFile
|
||||||
|
Map<Long, ResultFile> tempMap = new HashMap<>();
|
||||||
|
for (ResultFile file : resultFiles) {
|
||||||
|
tempMap.put(file.getFirstInstance().getId(), file);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (rs.next()) {
|
||||||
|
try {
|
||||||
|
Long objId = rs.getLong("object_id"); // NON-NLS
|
||||||
|
String keywordListName = rs.getString("set_name"); // NON-NLS
|
||||||
|
|
||||||
|
tempMap.get(objId).addKeywordListName(keywordListName);
|
||||||
|
|
||||||
|
} catch (SQLException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Unable to get object_id or set_name from result set", ex); // NON-NLS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (SQLException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Failed to get keyword list names", ex); // NON-NLS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attribute for grouping/sorting by frequency in the central repository
|
||||||
|
*/
|
||||||
|
static class FrequencyAttribute extends AttributeType {
|
||||||
|
|
||||||
|
static final int BATCH_SIZE = 50; // Number of hashes to look up at one time
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DiscoveryKeyUtils.GroupKey getGroupKey(ResultFile file) {
|
||||||
|
return new DiscoveryKeyUtils.FrequencyGroupKey(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addAttributeToResultFiles(List<ResultFile> files, SleuthkitCase caseDb,
|
||||||
|
CentralRepository centralRepoDb) throws DiscoveryException {
|
||||||
|
if (centralRepoDb == null) {
|
||||||
|
for (ResultFile file : files) {
|
||||||
|
if (file.getFrequency() == SearchData.Frequency.UNKNOWN && file.getFirstInstance().getKnown() == TskData.FileKnown.KNOWN) {
|
||||||
|
file.setFrequency(SearchData.Frequency.KNOWN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
processResultFilesForCR(files, centralRepoDb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private helper method for adding Frequency attribute when CR is
|
||||||
|
* enabled.
|
||||||
|
*
|
||||||
|
* @param files The list of ResultFiles to caluclate frequency
|
||||||
|
* for.
|
||||||
|
* @param centralRepoDb The central repository currently in use.
|
||||||
|
*/
|
||||||
|
private void processResultFilesForCR(List<ResultFile> files,
|
||||||
|
CentralRepository centralRepoDb) {
|
||||||
|
List<ResultFile> currentFiles = new ArrayList<>();
|
||||||
|
Set<String> hashesToLookUp = new HashSet<>();
|
||||||
|
for (ResultFile file : files) {
|
||||||
|
if (file.getFirstInstance().getKnown() == TskData.FileKnown.KNOWN) {
|
||||||
|
file.setFrequency(SearchData.Frequency.KNOWN);
|
||||||
|
}
|
||||||
|
if (file.getFrequency() == SearchData.Frequency.UNKNOWN
|
||||||
|
&& file.getFirstInstance().getMd5Hash() != null
|
||||||
|
&& !file.getFirstInstance().getMd5Hash().isEmpty()) {
|
||||||
|
hashesToLookUp.add(file.getFirstInstance().getMd5Hash());
|
||||||
|
currentFiles.add(file);
|
||||||
|
}
|
||||||
|
if (hashesToLookUp.size() >= BATCH_SIZE) {
|
||||||
|
computeFrequency(hashesToLookUp, currentFiles, centralRepoDb);
|
||||||
|
|
||||||
|
hashesToLookUp.clear();
|
||||||
|
currentFiles.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
computeFrequency(hashesToLookUp, currentFiles, centralRepoDb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback to use with findInterCaseValuesByCount which generates a list of
|
||||||
|
* values for common property search
|
||||||
|
*/
|
||||||
|
private static class FrequencyCallback implements InstanceTableCallback {
|
||||||
|
|
||||||
|
private final List<ResultFile> files;
|
||||||
|
|
||||||
|
private FrequencyCallback(List<ResultFile> files) {
|
||||||
|
this.files = new ArrayList<>(files);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(ResultSet resultSet) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
while (resultSet.next()) {
|
||||||
|
String hash = resultSet.getString(1);
|
||||||
|
int count = resultSet.getInt(2);
|
||||||
|
for (Iterator<ResultFile> iterator = files.iterator(); iterator.hasNext();) {
|
||||||
|
ResultFile file = iterator.next();
|
||||||
|
if (file.getFirstInstance().getMd5Hash().equalsIgnoreCase(hash)) {
|
||||||
|
file.setFrequency(SearchData.Frequency.fromCount(count));
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The files left had no matching entries in the CR, so mark them as unique
|
||||||
|
for (ResultFile file : files) {
|
||||||
|
file.setFrequency(SearchData.Frequency.UNIQUE);
|
||||||
|
}
|
||||||
|
} catch (SQLException ex) {
|
||||||
|
logger.log(Level.WARNING, "Error getting frequency counts from Central Repository", ex); // NON-NLS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attribute for grouping/sorting by hash set lists
|
||||||
|
*/
|
||||||
|
static class HashHitsAttribute extends AttributeType {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DiscoveryKeyUtils.GroupKey getGroupKey(ResultFile file) {
|
||||||
|
return new DiscoveryKeyUtils.HashHitsGroupKey(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addAttributeToResultFiles(List<ResultFile> files, SleuthkitCase caseDb,
|
||||||
|
CentralRepository centralRepoDb) throws DiscoveryException {
|
||||||
|
|
||||||
|
// Get pairs of (object ID, hash set name) for all files in the list of files that have
|
||||||
|
// hash set hits.
|
||||||
|
String selectQuery = createSetNameClause(files, BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID(),
|
||||||
|
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID());
|
||||||
|
|
||||||
|
HashSetNamesCallback callback = new HashSetNamesCallback(files);
|
||||||
|
try {
|
||||||
|
caseDb.getCaseDbAccessManager().select(selectQuery, callback);
|
||||||
|
} catch (TskCoreException ex) {
|
||||||
|
throw new DiscoveryException("Error looking up hash set attributes", ex); // NON-NLS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback to process the results of the CaseDbAccessManager select
|
||||||
|
* query. Will add the hash set names to the list of ResultFile objects.
|
||||||
|
*/
|
||||||
|
private static class HashSetNamesCallback implements CaseDbAccessManager.CaseDbAccessQueryCallback {
|
||||||
|
|
||||||
|
List<ResultFile> resultFiles;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the callback.
|
||||||
|
*
|
||||||
|
* @param resultFiles List of files to add hash set names to
|
||||||
|
*/
|
||||||
|
HashSetNamesCallback(List<ResultFile> resultFiles) {
|
||||||
|
this.resultFiles = resultFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(ResultSet rs) {
|
||||||
|
try {
|
||||||
|
// Create a temporary map of object ID to ResultFile
|
||||||
|
Map<Long, ResultFile> tempMap = new HashMap<>();
|
||||||
|
for (ResultFile file : resultFiles) {
|
||||||
|
tempMap.put(file.getFirstInstance().getId(), file);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (rs.next()) {
|
||||||
|
try {
|
||||||
|
Long objId = rs.getLong("object_id"); // NON-NLS
|
||||||
|
String hashSetName = rs.getString("set_name"); // NON-NLS
|
||||||
|
|
||||||
|
tempMap.get(objId).addHashSetName(hashSetName);
|
||||||
|
|
||||||
|
} catch (SQLException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Unable to get object_id or set_name from result set", ex); // NON-NLS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (SQLException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Failed to get hash set names", ex); // NON-NLS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attribute for grouping/sorting by interesting item set lists
|
||||||
|
*/
|
||||||
|
static class InterestingItemAttribute extends AttributeType {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DiscoveryKeyUtils.GroupKey getGroupKey(ResultFile file) {
|
||||||
|
return new DiscoveryKeyUtils.InterestingItemGroupKey(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addAttributeToResultFiles(List<ResultFile> files, SleuthkitCase caseDb,
|
||||||
|
CentralRepository centralRepoDb) throws DiscoveryException {
|
||||||
|
|
||||||
|
// Get pairs of (object ID, interesting item set name) for all files in the list of files that have
|
||||||
|
// interesting file set hits.
|
||||||
|
String selectQuery = createSetNameClause(files, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID(),
|
||||||
|
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID());
|
||||||
|
|
||||||
|
InterestingFileSetNamesCallback callback = new InterestingFileSetNamesCallback(files);
|
||||||
|
try {
|
||||||
|
caseDb.getCaseDbAccessManager().select(selectQuery, callback);
|
||||||
|
} catch (TskCoreException ex) {
|
||||||
|
throw new DiscoveryException("Error looking up interesting file set attributes", ex); // NON-NLS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback to process the results of the CaseDbAccessManager select
|
||||||
|
* query. Will add the interesting file set names to the list of
|
||||||
|
* ResultFile objects.
|
||||||
|
*/
|
||||||
|
private static class InterestingFileSetNamesCallback implements CaseDbAccessManager.CaseDbAccessQueryCallback {
|
||||||
|
|
||||||
|
List<ResultFile> resultFiles;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the callback.
|
||||||
|
*
|
||||||
|
* @param resultFiles List of files to add interesting file set
|
||||||
|
* names to
|
||||||
|
*/
|
||||||
|
InterestingFileSetNamesCallback(List<ResultFile> resultFiles) {
|
||||||
|
this.resultFiles = resultFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(ResultSet rs) {
|
||||||
|
try {
|
||||||
|
// Create a temporary map of object ID to ResultFile
|
||||||
|
Map<Long, ResultFile> tempMap = new HashMap<>();
|
||||||
|
for (ResultFile file : resultFiles) {
|
||||||
|
tempMap.put(file.getFirstInstance().getId(), file);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (rs.next()) {
|
||||||
|
try {
|
||||||
|
Long objId = rs.getLong("object_id"); // NON-NLS
|
||||||
|
String setName = rs.getString("set_name"); // NON-NLS
|
||||||
|
|
||||||
|
tempMap.get(objId).addInterestingSetName(setName);
|
||||||
|
|
||||||
|
} catch (SQLException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Unable to get object_id or set_name from result set", ex); // NON-NLS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (SQLException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Failed to get interesting file set names", ex); // NON-NLS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attribute for grouping/sorting by objects detected
|
||||||
|
*/
|
||||||
|
static class ObjectDetectedAttribute extends AttributeType {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DiscoveryKeyUtils.GroupKey getGroupKey(ResultFile file) {
|
||||||
|
return new DiscoveryKeyUtils.ObjectDetectedGroupKey(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addAttributeToResultFiles(List<ResultFile> files, SleuthkitCase caseDb,
|
||||||
|
CentralRepository centralRepoDb) throws DiscoveryException {
|
||||||
|
|
||||||
|
// Get pairs of (object ID, object type name) for all files in the list of files that have
|
||||||
|
// objects detected
|
||||||
|
String selectQuery = createSetNameClause(files, BlackboardArtifact.ARTIFACT_TYPE.TSK_OBJECT_DETECTED.getTypeID(),
|
||||||
|
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION.getTypeID());
|
||||||
|
|
||||||
|
ObjectDetectedNamesCallback callback = new ObjectDetectedNamesCallback(files);
|
||||||
|
try {
|
||||||
|
caseDb.getCaseDbAccessManager().select(selectQuery, callback);
|
||||||
|
} catch (TskCoreException ex) {
|
||||||
|
throw new DiscoveryException("Error looking up object detected attributes", ex); // NON-NLS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback to process the results of the CaseDbAccessManager select
|
||||||
|
* query. Will add the object type names to the list of ResultFile
|
||||||
|
* objects.
|
||||||
|
*/
|
||||||
|
private static class ObjectDetectedNamesCallback implements CaseDbAccessManager.CaseDbAccessQueryCallback {
|
||||||
|
|
||||||
|
List<ResultFile> resultFiles;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the callback.
|
||||||
|
*
|
||||||
|
* @param resultFiles List of files to add object detected names to
|
||||||
|
*/
|
||||||
|
ObjectDetectedNamesCallback(List<ResultFile> resultFiles) {
|
||||||
|
this.resultFiles = resultFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(ResultSet rs) {
|
||||||
|
try {
|
||||||
|
// Create a temporary map of object ID to ResultFile
|
||||||
|
Map<Long, ResultFile> tempMap = new HashMap<>();
|
||||||
|
for (ResultFile file : resultFiles) {
|
||||||
|
tempMap.put(file.getFirstInstance().getId(), file);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (rs.next()) {
|
||||||
|
try {
|
||||||
|
Long objId = rs.getLong("object_id"); // NON-NLS
|
||||||
|
String setName = rs.getString("set_name"); // NON-NLS
|
||||||
|
|
||||||
|
tempMap.get(objId).addObjectDetectedName(setName);
|
||||||
|
|
||||||
|
} catch (SQLException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Unable to get object_id or set_name from result set", ex); // NON-NLS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (SQLException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Failed to get object detected names", ex); // NON-NLS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attribute for grouping/sorting by tag name
|
||||||
|
*/
|
||||||
|
static class FileTagAttribute extends AttributeType {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DiscoveryKeyUtils.GroupKey getGroupKey(ResultFile file) {
|
||||||
|
return new DiscoveryKeyUtils.FileTagGroupKey(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addAttributeToResultFiles(List<ResultFile> files, SleuthkitCase caseDb,
|
||||||
|
CentralRepository centralRepoDb) throws DiscoveryException {
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (ResultFile resultFile : files) {
|
||||||
|
List<ContentTag> contentTags = caseDb.getContentTagsByContent(resultFile.getFirstInstance());
|
||||||
|
|
||||||
|
for (ContentTag tag : contentTags) {
|
||||||
|
resultFile.addTagName(tag.getName().getDisplayName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (TskCoreException ex) {
|
||||||
|
throw new DiscoveryException("Error looking up file tag attributes", ex); // NON-NLS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enum for the attribute types that can be used for grouping.
|
||||||
|
*/
|
||||||
|
@NbBundle.Messages({
|
||||||
|
"DiscoveryAttributes.GroupingAttributeType.fileType.displayName=File Type",
|
||||||
|
"DiscoveryAttributes.GroupingAttributeType.frequency.displayName=Past Occurrences",
|
||||||
|
"DiscoveryAttributes.GroupingAttributeType.keywordList.displayName=Keyword",
|
||||||
|
"DiscoveryAttributes.GroupingAttributeType.size.displayName=File Size",
|
||||||
|
"DiscoveryAttributes.GroupingAttributeType.datasource.displayName=Data Source",
|
||||||
|
"DiscoveryAttributes.GroupingAttributeType.parent.displayName=Parent Folder",
|
||||||
|
"DiscoveryAttributes.GroupingAttributeType.hash.displayName=Hash Set",
|
||||||
|
"DiscoveryAttributes.GroupingAttributeType.interestingItem.displayName=Interesting Item",
|
||||||
|
"DiscoveryAttributes.GroupingAttributeType.tag.displayName=Tag",
|
||||||
|
"DiscoveryAttributes.GroupingAttributeType.object.displayName=Object Detected",
|
||||||
|
"DiscoveryAttributes.GroupingAttributeType.none.displayName=None"})
|
||||||
|
public enum GroupingAttributeType {
|
||||||
|
FILE_SIZE(new FileSizeAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_size_displayName()),
|
||||||
|
FREQUENCY(new FrequencyAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_frequency_displayName()),
|
||||||
|
KEYWORD_LIST_NAME(new KeywordListAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_keywordList_displayName()),
|
||||||
|
DATA_SOURCE(new DataSourceAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_datasource_displayName()),
|
||||||
|
PARENT_PATH(new ParentPathAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_parent_displayName()),
|
||||||
|
HASH_LIST_NAME(new HashHitsAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_hash_displayName()),
|
||||||
|
INTERESTING_ITEM_SET(new InterestingItemAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_interestingItem_displayName()),
|
||||||
|
FILE_TAG(new FileTagAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_tag_displayName()),
|
||||||
|
OBJECT_DETECTED(new ObjectDetectedAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_object_displayName()),
|
||||||
|
NO_GROUPING(new NoGroupingAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_none_displayName());
|
||||||
|
|
||||||
|
private final AttributeType attributeType;
|
||||||
|
private final String displayName;
|
||||||
|
|
||||||
|
GroupingAttributeType(AttributeType attributeType, String displayName) {
|
||||||
|
this.attributeType = attributeType;
|
||||||
|
this.displayName = displayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return displayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AttributeType getAttributeType() {
|
||||||
|
return attributeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of enums that are valid for grouping images.
|
||||||
|
*
|
||||||
|
* @return enums that can be used to group images
|
||||||
|
*/
|
||||||
|
public static List<GroupingAttributeType> getOptionsForGrouping() {
|
||||||
|
return Arrays.asList(FILE_SIZE, FREQUENCY, PARENT_PATH, OBJECT_DETECTED, HASH_LIST_NAME, INTERESTING_ITEM_SET);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the CR frequency of all the given hashes and updates the list of
|
||||||
|
* files.
|
||||||
|
*
|
||||||
|
* @param hashesToLookUp Hashes to find the frequency of
|
||||||
|
* @param currentFiles List of files to update with frequencies
|
||||||
|
*/
|
||||||
|
private static void computeFrequency(Set<String> hashesToLookUp, List<ResultFile> currentFiles, CentralRepository centralRepoDb) {
|
||||||
|
|
||||||
|
if (hashesToLookUp.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String hashes = String.join("','", hashesToLookUp);
|
||||||
|
hashes = "'" + hashes + "'";
|
||||||
|
try {
|
||||||
|
CorrelationAttributeInstance.Type attributeType = centralRepoDb.getCorrelationTypeById(CorrelationAttributeInstance.FILES_TYPE_ID);
|
||||||
|
String tableName = CentralRepoDbUtil.correlationTypeToInstanceTableName(attributeType);
|
||||||
|
|
||||||
|
String selectClause = " value, COUNT(value) FROM "
|
||||||
|
+ "(SELECT DISTINCT case_id, value FROM " + tableName
|
||||||
|
+ " WHERE value IN ("
|
||||||
|
+ hashes
|
||||||
|
+ ")) AS foo GROUP BY value";
|
||||||
|
|
||||||
|
FrequencyCallback callback = new FrequencyCallback(currentFiles);
|
||||||
|
centralRepoDb.processSelectClause(selectClause, callback);
|
||||||
|
|
||||||
|
} catch (CentralRepoException ex) {
|
||||||
|
logger.log(Level.WARNING, "Error getting frequency counts from Central Repository", ex); // NON-NLS
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String createSetNameClause(List<ResultFile> files,
|
||||||
|
int artifactTypeID, int setNameAttrID) throws DiscoveryException {
|
||||||
|
|
||||||
|
// Concatenate the object IDs in the list of files
|
||||||
|
String objIdList = ""; // NON-NLS
|
||||||
|
for (ResultFile file : files) {
|
||||||
|
if (!objIdList.isEmpty()) {
|
||||||
|
objIdList += ","; // NON-NLS
|
||||||
|
}
|
||||||
|
objIdList += "\'" + file.getFirstInstance().getId() + "\'"; // NON-NLS
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get pairs of (object ID, set name) for all files in the list of files that have
|
||||||
|
// the given artifact type.
|
||||||
|
return "blackboard_artifacts.obj_id AS object_id, blackboard_attributes.value_text AS set_name "
|
||||||
|
+ "FROM blackboard_artifacts "
|
||||||
|
+ "INNER JOIN blackboard_attributes ON blackboard_artifacts.artifact_id=blackboard_attributes.artifact_id "
|
||||||
|
+ "WHERE blackboard_attributes.artifact_type_id=\'" + artifactTypeID + "\' "
|
||||||
|
+ "AND blackboard_attributes.attribute_type_id=\'" + setNameAttrID + "\' "
|
||||||
|
+ "AND blackboard_artifacts.obj_id IN (" + objIdList + ") "; // NON-NLS
|
||||||
|
}
|
||||||
|
|
||||||
|
private DiscoveryAttributes() {
|
||||||
|
// Class should not be instantiated
|
||||||
|
}
|
||||||
|
}
|
@ -119,7 +119,7 @@ public final class DiscoveryEventUtils {
|
|||||||
|
|
||||||
private final Map<GroupKey, Integer> groupMap;
|
private final Map<GroupKey, Integer> groupMap;
|
||||||
private final List<AbstractFilter> searchFilters;
|
private final List<AbstractFilter> searchFilters;
|
||||||
private final FileSearch.AttributeType groupingAttribute;
|
private final DiscoveryAttributes.AttributeType groupingAttribute;
|
||||||
private final Group.GroupSortingAlgorithm groupSort;
|
private final Group.GroupSortingAlgorithm groupSort;
|
||||||
private final FileSorter.SortingMethod fileSortMethod;
|
private final FileSorter.SortingMethod fileSortMethod;
|
||||||
|
|
||||||
@ -135,7 +135,7 @@ public final class DiscoveryEventUtils {
|
|||||||
* @param fileSortMethod The sorting method used for files.
|
* @param fileSortMethod The sorting method used for files.
|
||||||
*/
|
*/
|
||||||
public SearchCompleteEvent(Map<GroupKey, Integer> groupMap, List<AbstractFilter> searchfilters,
|
public SearchCompleteEvent(Map<GroupKey, Integer> groupMap, List<AbstractFilter> searchfilters,
|
||||||
FileSearch.AttributeType groupingAttribute, Group.GroupSortingAlgorithm groupSort,
|
DiscoveryAttributes.AttributeType groupingAttribute, Group.GroupSortingAlgorithm groupSort,
|
||||||
FileSorter.SortingMethod fileSortMethod) {
|
FileSorter.SortingMethod fileSortMethod) {
|
||||||
this.groupMap = groupMap;
|
this.groupMap = groupMap;
|
||||||
this.searchFilters = searchfilters;
|
this.searchFilters = searchfilters;
|
||||||
@ -167,7 +167,7 @@ public final class DiscoveryEventUtils {
|
|||||||
*
|
*
|
||||||
* @return The grouping attribute used by the search.
|
* @return The grouping attribute used by the search.
|
||||||
*/
|
*/
|
||||||
public FileSearch.AttributeType getGroupingAttr() {
|
public DiscoveryAttributes.AttributeType getGroupingAttr() {
|
||||||
return groupingAttribute;
|
return groupingAttribute;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -278,7 +278,7 @@ public final class DiscoveryEventUtils {
|
|||||||
private final GroupKey groupKey;
|
private final GroupKey groupKey;
|
||||||
private final int groupSize;
|
private final int groupSize;
|
||||||
private final List<AbstractFilter> searchfilters;
|
private final List<AbstractFilter> searchfilters;
|
||||||
private final FileSearch.AttributeType groupingAttribute;
|
private final DiscoveryAttributes.AttributeType groupingAttribute;
|
||||||
private final Group.GroupSortingAlgorithm groupSort;
|
private final Group.GroupSortingAlgorithm groupSort;
|
||||||
private final FileSorter.SortingMethod fileSortMethod;
|
private final FileSorter.SortingMethod fileSortMethod;
|
||||||
|
|
||||||
@ -297,7 +297,7 @@ public final class DiscoveryEventUtils {
|
|||||||
* @param resultType The type of files which exist in the group.
|
* @param resultType The type of files which exist in the group.
|
||||||
*/
|
*/
|
||||||
public GroupSelectedEvent(List<AbstractFilter> searchfilters,
|
public GroupSelectedEvent(List<AbstractFilter> searchfilters,
|
||||||
FileSearch.AttributeType groupingAttribute, Group.GroupSortingAlgorithm groupSort,
|
DiscoveryAttributes.AttributeType groupingAttribute, Group.GroupSortingAlgorithm groupSort,
|
||||||
FileSorter.SortingMethod fileSortMethod, GroupKey groupKey, int groupSize, Type resultType) {
|
FileSorter.SortingMethod fileSortMethod, GroupKey groupKey, int groupSize, Type resultType) {
|
||||||
this.searchfilters = searchfilters;
|
this.searchfilters = searchfilters;
|
||||||
this.groupingAttribute = groupingAttribute;
|
this.groupingAttribute = groupingAttribute;
|
||||||
@ -369,7 +369,7 @@ public final class DiscoveryEventUtils {
|
|||||||
*
|
*
|
||||||
* @return The grouping attribute used by the search.
|
* @return The grouping attribute used by the search.
|
||||||
*/
|
*/
|
||||||
public FileSearch.AttributeType getGroupingAttr() {
|
public DiscoveryAttributes.AttributeType getGroupingAttr() {
|
||||||
return groupingAttribute;
|
return groupingAttribute;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ public class DiscoveryKeyUtils {
|
|||||||
* @param fileSortingMethod The method to sort the files by.
|
* @param fileSortingMethod The method to sort the files by.
|
||||||
*/
|
*/
|
||||||
SearchKey(String userName, List<AbstractFilter> filters,
|
SearchKey(String userName, List<AbstractFilter> filters,
|
||||||
FileSearch.AttributeType groupAttributeType,
|
DiscoveryAttributes.AttributeType groupAttributeType,
|
||||||
Group.GroupSortingAlgorithm groupSortingType,
|
Group.GroupSortingAlgorithm groupSortingType,
|
||||||
FileSorter.SortingMethod fileSortingMethod) {
|
FileSorter.SortingMethod fileSortingMethod) {
|
||||||
StringBuilder searchStringBuilder = new StringBuilder();
|
StringBuilder searchStringBuilder = new StringBuilder();
|
||||||
|
@ -21,35 +21,18 @@ package org.sleuthkit.autopsy.discovery.search;
|
|||||||
import com.google.common.cache.Cache;
|
import com.google.common.cache.Cache;
|
||||||
import com.google.common.cache.CacheBuilder;
|
import com.google.common.cache.CacheBuilder;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
|
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException;
|
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoDbUtil;
|
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.InstanceTableCallback;
|
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.discovery.search.SearchData.Frequency;
|
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
|
||||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
|
||||||
import org.sleuthkit.datamodel.CaseDbAccessManager;
|
|
||||||
import org.sleuthkit.datamodel.ContentTag;
|
|
||||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
|
||||||
import org.sleuthkit.datamodel.TskData;
|
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
||||||
|
import org.sleuthkit.autopsy.discovery.search.DiscoveryAttributes.AttributeType;
|
||||||
import org.sleuthkit.autopsy.discovery.search.DiscoveryKeyUtils.GroupKey;
|
import org.sleuthkit.autopsy.discovery.search.DiscoveryKeyUtils.GroupKey;
|
||||||
import org.sleuthkit.autopsy.discovery.search.DiscoveryKeyUtils.SearchKey;
|
import org.sleuthkit.autopsy.discovery.search.DiscoveryKeyUtils.SearchKey;
|
||||||
import org.sleuthkit.autopsy.textsummarizer.TextSummarizer;
|
import org.sleuthkit.autopsy.textsummarizer.TextSummarizer;
|
||||||
@ -322,615 +305,9 @@ public class FileSearch {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Computes the CR frequency of all the given hashes and updates the list of
|
|
||||||
* files.
|
|
||||||
*
|
|
||||||
* @param hashesToLookUp Hashes to find the frequency of
|
|
||||||
* @param currentFiles List of files to update with frequencies
|
|
||||||
*/
|
|
||||||
private static void computeFrequency(Set<String> hashesToLookUp, List<ResultFile> currentFiles, CentralRepository centralRepoDb) {
|
|
||||||
|
|
||||||
if (hashesToLookUp.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String hashes = String.join("','", hashesToLookUp);
|
|
||||||
hashes = "'" + hashes + "'";
|
|
||||||
try {
|
|
||||||
CorrelationAttributeInstance.Type attributeType = centralRepoDb.getCorrelationTypeById(CorrelationAttributeInstance.FILES_TYPE_ID);
|
|
||||||
String tableName = CentralRepoDbUtil.correlationTypeToInstanceTableName(attributeType);
|
|
||||||
|
|
||||||
String selectClause = " value, COUNT(value) FROM "
|
|
||||||
+ "(SELECT DISTINCT case_id, value FROM " + tableName
|
|
||||||
+ " WHERE value IN ("
|
|
||||||
+ hashes
|
|
||||||
+ ")) AS foo GROUP BY value";
|
|
||||||
|
|
||||||
FrequencyCallback callback = new FrequencyCallback(currentFiles);
|
|
||||||
centralRepoDb.processSelectClause(selectClause, callback);
|
|
||||||
|
|
||||||
} catch (CentralRepoException ex) {
|
|
||||||
logger.log(Level.WARNING, "Error getting frequency counts from Central Repository", ex); // NON-NLS
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String createSetNameClause(List<ResultFile> files,
|
|
||||||
int artifactTypeID, int setNameAttrID) throws DiscoveryException {
|
|
||||||
|
|
||||||
// Concatenate the object IDs in the list of files
|
|
||||||
String objIdList = ""; // NON-NLS
|
|
||||||
for (ResultFile file : files) {
|
|
||||||
if (!objIdList.isEmpty()) {
|
|
||||||
objIdList += ","; // NON-NLS
|
|
||||||
}
|
|
||||||
objIdList += "\'" + file.getFirstInstance().getId() + "\'"; // NON-NLS
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get pairs of (object ID, set name) for all files in the list of files that have
|
|
||||||
// the given artifact type.
|
|
||||||
return "blackboard_artifacts.obj_id AS object_id, blackboard_attributes.value_text AS set_name "
|
|
||||||
+ "FROM blackboard_artifacts "
|
|
||||||
+ "INNER JOIN blackboard_attributes ON blackboard_artifacts.artifact_id=blackboard_attributes.artifact_id "
|
|
||||||
+ "WHERE blackboard_attributes.artifact_type_id=\'" + artifactTypeID + "\' "
|
|
||||||
+ "AND blackboard_attributes.attribute_type_id=\'" + setNameAttrID + "\' "
|
|
||||||
+ "AND blackboard_artifacts.obj_id IN (" + objIdList + ") "; // NON-NLS
|
|
||||||
}
|
|
||||||
|
|
||||||
private FileSearch() {
|
private FileSearch() {
|
||||||
// Class should not be instantiated
|
// Class should not be instantiated
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Base class for the grouping attributes.
|
|
||||||
*/
|
|
||||||
public abstract static class AttributeType {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For a given file, return the key for the group it belongs to for this
|
|
||||||
* attribute type.
|
|
||||||
*
|
|
||||||
* @param file the result file to be grouped
|
|
||||||
*
|
|
||||||
* @return the key for the group this file goes in
|
|
||||||
*/
|
|
||||||
public abstract GroupKey getGroupKey(ResultFile file);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add any extra data to the ResultFile object from this attribute.
|
|
||||||
*
|
|
||||||
* @param files The list of files to enhance
|
|
||||||
* @param caseDb The case database
|
|
||||||
* @param centralRepoDb The central repository database. Can be null if
|
|
||||||
* not needed.
|
|
||||||
*
|
|
||||||
* @throws DiscoveryException
|
|
||||||
*/
|
|
||||||
public void addAttributeToResultFiles(List<ResultFile> files, SleuthkitCase caseDb, CentralRepository centralRepoDb) throws DiscoveryException {
|
|
||||||
// Default is to do nothing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attribute for grouping/sorting by file size
|
|
||||||
*/
|
|
||||||
public static class FileSizeAttribute extends AttributeType {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GroupKey getGroupKey(ResultFile file) {
|
|
||||||
return new DiscoveryKeyUtils.FileSizeGroupKey(file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attribute for grouping/sorting by parent path
|
|
||||||
*/
|
|
||||||
public static class ParentPathAttribute extends AttributeType {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GroupKey getGroupKey(ResultFile file) {
|
|
||||||
return new DiscoveryKeyUtils.ParentPathGroupKey(file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default attribute used to make one group
|
|
||||||
*/
|
|
||||||
static class NoGroupingAttribute extends FileSearch.AttributeType {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GroupKey getGroupKey(ResultFile file) {
|
|
||||||
return new DiscoveryKeyUtils.NoGroupingGroupKey();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attribute for grouping/sorting by data source
|
|
||||||
*/
|
|
||||||
static class DataSourceAttribute extends AttributeType {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GroupKey getGroupKey(ResultFile file) {
|
|
||||||
return new DiscoveryKeyUtils.DataSourceGroupKey(file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attribute for grouping/sorting by file type
|
|
||||||
*/
|
|
||||||
static class FileTypeAttribute extends AttributeType {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GroupKey getGroupKey(ResultFile file) {
|
|
||||||
return new DiscoveryKeyUtils.FileTypeGroupKey(file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attribute for grouping/sorting by keyword lists
|
|
||||||
*/
|
|
||||||
static class KeywordListAttribute extends AttributeType {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GroupKey getGroupKey(ResultFile file) {
|
|
||||||
return new DiscoveryKeyUtils.KeywordListGroupKey(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addAttributeToResultFiles(List<ResultFile> files, SleuthkitCase caseDb,
|
|
||||||
CentralRepository centralRepoDb) throws DiscoveryException {
|
|
||||||
|
|
||||||
// Get pairs of (object ID, keyword list name) for all files in the list of files that have
|
|
||||||
// keyword list hits.
|
|
||||||
String selectQuery = createSetNameClause(files, BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID(),
|
|
||||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID());
|
|
||||||
|
|
||||||
SetKeywordListNamesCallback callback = new SetKeywordListNamesCallback(files);
|
|
||||||
try {
|
|
||||||
caseDb.getCaseDbAccessManager().select(selectQuery, callback);
|
|
||||||
} catch (TskCoreException ex) {
|
|
||||||
throw new DiscoveryException("Error looking up keyword list attributes", ex); // NON-NLS
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback to process the results of the CaseDbAccessManager select
|
|
||||||
* query. Will add the keyword list names to the list of ResultFile
|
|
||||||
* objects.
|
|
||||||
*/
|
|
||||||
private static class SetKeywordListNamesCallback implements CaseDbAccessManager.CaseDbAccessQueryCallback {
|
|
||||||
|
|
||||||
List<ResultFile> resultFiles;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create the callback.
|
|
||||||
*
|
|
||||||
* @param resultFiles List of files to add keyword list names to
|
|
||||||
*/
|
|
||||||
SetKeywordListNamesCallback(List<ResultFile> resultFiles) {
|
|
||||||
this.resultFiles = resultFiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void process(ResultSet rs) {
|
|
||||||
try {
|
|
||||||
// Create a temporary map of object ID to ResultFile
|
|
||||||
Map<Long, ResultFile> tempMap = new HashMap<>();
|
|
||||||
for (ResultFile file : resultFiles) {
|
|
||||||
tempMap.put(file.getFirstInstance().getId(), file);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (rs.next()) {
|
|
||||||
try {
|
|
||||||
Long objId = rs.getLong("object_id"); // NON-NLS
|
|
||||||
String keywordListName = rs.getString("set_name"); // NON-NLS
|
|
||||||
|
|
||||||
tempMap.get(objId).addKeywordListName(keywordListName);
|
|
||||||
|
|
||||||
} catch (SQLException ex) {
|
|
||||||
logger.log(Level.SEVERE, "Unable to get object_id or set_name from result set", ex); // NON-NLS
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (SQLException ex) {
|
|
||||||
logger.log(Level.SEVERE, "Failed to get keyword list names", ex); // NON-NLS
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attribute for grouping/sorting by frequency in the central repository
|
|
||||||
*/
|
|
||||||
static class FrequencyAttribute extends AttributeType {
|
|
||||||
|
|
||||||
static final int BATCH_SIZE = 50; // Number of hashes to look up at one time
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GroupKey getGroupKey(ResultFile file) {
|
|
||||||
return new DiscoveryKeyUtils.FrequencyGroupKey(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addAttributeToResultFiles(List<ResultFile> files, SleuthkitCase caseDb,
|
|
||||||
CentralRepository centralRepoDb) throws DiscoveryException {
|
|
||||||
if (centralRepoDb == null) {
|
|
||||||
for (ResultFile file : files) {
|
|
||||||
if (file.getFrequency() == Frequency.UNKNOWN && file.getFirstInstance().getKnown() == TskData.FileKnown.KNOWN) {
|
|
||||||
file.setFrequency(Frequency.KNOWN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
processResultFilesForCR(files, centralRepoDb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private helper method for adding Frequency attribute when CR is
|
|
||||||
* enabled.
|
|
||||||
*
|
|
||||||
* @param files The list of ResultFiles to caluclate frequency
|
|
||||||
* for.
|
|
||||||
* @param centralRepoDb The central repository currently in use.
|
|
||||||
*/
|
|
||||||
private void processResultFilesForCR(List<ResultFile> files,
|
|
||||||
CentralRepository centralRepoDb) {
|
|
||||||
List<ResultFile> currentFiles = new ArrayList<>();
|
|
||||||
Set<String> hashesToLookUp = new HashSet<>();
|
|
||||||
for (ResultFile file : files) {
|
|
||||||
if (file.getFirstInstance().getKnown() == TskData.FileKnown.KNOWN) {
|
|
||||||
file.setFrequency(Frequency.KNOWN);
|
|
||||||
}
|
|
||||||
if (file.getFrequency() == Frequency.UNKNOWN
|
|
||||||
&& file.getFirstInstance().getMd5Hash() != null
|
|
||||||
&& !file.getFirstInstance().getMd5Hash().isEmpty()) {
|
|
||||||
hashesToLookUp.add(file.getFirstInstance().getMd5Hash());
|
|
||||||
currentFiles.add(file);
|
|
||||||
}
|
|
||||||
if (hashesToLookUp.size() >= BATCH_SIZE) {
|
|
||||||
computeFrequency(hashesToLookUp, currentFiles, centralRepoDb);
|
|
||||||
|
|
||||||
hashesToLookUp.clear();
|
|
||||||
currentFiles.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
computeFrequency(hashesToLookUp, currentFiles, centralRepoDb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback to use with findInterCaseValuesByCount which generates a list of
|
|
||||||
* values for common property search
|
|
||||||
*/
|
|
||||||
private static class FrequencyCallback implements InstanceTableCallback {
|
|
||||||
|
|
||||||
private final List<ResultFile> files;
|
|
||||||
|
|
||||||
private FrequencyCallback(List<ResultFile> files) {
|
|
||||||
this.files = new ArrayList<>(files);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void process(ResultSet resultSet) {
|
|
||||||
try {
|
|
||||||
|
|
||||||
while (resultSet.next()) {
|
|
||||||
String hash = resultSet.getString(1);
|
|
||||||
int count = resultSet.getInt(2);
|
|
||||||
for (Iterator<ResultFile> iterator = files.iterator(); iterator.hasNext();) {
|
|
||||||
ResultFile file = iterator.next();
|
|
||||||
if (file.getFirstInstance().getMd5Hash().equalsIgnoreCase(hash)) {
|
|
||||||
file.setFrequency(Frequency.fromCount(count));
|
|
||||||
iterator.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The files left had no matching entries in the CR, so mark them as unique
|
|
||||||
for (ResultFile file : files) {
|
|
||||||
file.setFrequency(Frequency.UNIQUE);
|
|
||||||
}
|
|
||||||
} catch (SQLException ex) {
|
|
||||||
logger.log(Level.WARNING, "Error getting frequency counts from Central Repository", ex); // NON-NLS
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attribute for grouping/sorting by hash set lists
|
|
||||||
*/
|
|
||||||
static class HashHitsAttribute extends AttributeType {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GroupKey getGroupKey(ResultFile file) {
|
|
||||||
return new DiscoveryKeyUtils.HashHitsGroupKey(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addAttributeToResultFiles(List<ResultFile> files, SleuthkitCase caseDb,
|
|
||||||
CentralRepository centralRepoDb) throws DiscoveryException {
|
|
||||||
|
|
||||||
// Get pairs of (object ID, hash set name) for all files in the list of files that have
|
|
||||||
// hash set hits.
|
|
||||||
String selectQuery = createSetNameClause(files, BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID(),
|
|
||||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID());
|
|
||||||
|
|
||||||
HashSetNamesCallback callback = new HashSetNamesCallback(files);
|
|
||||||
try {
|
|
||||||
caseDb.getCaseDbAccessManager().select(selectQuery, callback);
|
|
||||||
} catch (TskCoreException ex) {
|
|
||||||
throw new DiscoveryException("Error looking up hash set attributes", ex); // NON-NLS
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback to process the results of the CaseDbAccessManager select
|
|
||||||
* query. Will add the hash set names to the list of ResultFile objects.
|
|
||||||
*/
|
|
||||||
private static class HashSetNamesCallback implements CaseDbAccessManager.CaseDbAccessQueryCallback {
|
|
||||||
|
|
||||||
List<ResultFile> resultFiles;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create the callback.
|
|
||||||
*
|
|
||||||
* @param resultFiles List of files to add hash set names to
|
|
||||||
*/
|
|
||||||
HashSetNamesCallback(List<ResultFile> resultFiles) {
|
|
||||||
this.resultFiles = resultFiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void process(ResultSet rs) {
|
|
||||||
try {
|
|
||||||
// Create a temporary map of object ID to ResultFile
|
|
||||||
Map<Long, ResultFile> tempMap = new HashMap<>();
|
|
||||||
for (ResultFile file : resultFiles) {
|
|
||||||
tempMap.put(file.getFirstInstance().getId(), file);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (rs.next()) {
|
|
||||||
try {
|
|
||||||
Long objId = rs.getLong("object_id"); // NON-NLS
|
|
||||||
String hashSetName = rs.getString("set_name"); // NON-NLS
|
|
||||||
|
|
||||||
tempMap.get(objId).addHashSetName(hashSetName);
|
|
||||||
|
|
||||||
} catch (SQLException ex) {
|
|
||||||
logger.log(Level.SEVERE, "Unable to get object_id or set_name from result set", ex); // NON-NLS
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (SQLException ex) {
|
|
||||||
logger.log(Level.SEVERE, "Failed to get hash set names", ex); // NON-NLS
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attribute for grouping/sorting by interesting item set lists
|
|
||||||
*/
|
|
||||||
static class InterestingItemAttribute extends AttributeType {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GroupKey getGroupKey(ResultFile file) {
|
|
||||||
return new DiscoveryKeyUtils.InterestingItemGroupKey(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addAttributeToResultFiles(List<ResultFile> files, SleuthkitCase caseDb,
|
|
||||||
CentralRepository centralRepoDb) throws DiscoveryException {
|
|
||||||
|
|
||||||
// Get pairs of (object ID, interesting item set name) for all files in the list of files that have
|
|
||||||
// interesting file set hits.
|
|
||||||
String selectQuery = createSetNameClause(files, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID(),
|
|
||||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID());
|
|
||||||
|
|
||||||
InterestingFileSetNamesCallback callback = new InterestingFileSetNamesCallback(files);
|
|
||||||
try {
|
|
||||||
caseDb.getCaseDbAccessManager().select(selectQuery, callback);
|
|
||||||
} catch (TskCoreException ex) {
|
|
||||||
throw new DiscoveryException("Error looking up interesting file set attributes", ex); // NON-NLS
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback to process the results of the CaseDbAccessManager select
|
|
||||||
* query. Will add the interesting file set names to the list of
|
|
||||||
* ResultFile objects.
|
|
||||||
*/
|
|
||||||
private static class InterestingFileSetNamesCallback implements CaseDbAccessManager.CaseDbAccessQueryCallback {
|
|
||||||
|
|
||||||
List<ResultFile> resultFiles;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create the callback.
|
|
||||||
*
|
|
||||||
* @param resultFiles List of files to add interesting file set
|
|
||||||
* names to
|
|
||||||
*/
|
|
||||||
InterestingFileSetNamesCallback(List<ResultFile> resultFiles) {
|
|
||||||
this.resultFiles = resultFiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void process(ResultSet rs) {
|
|
||||||
try {
|
|
||||||
// Create a temporary map of object ID to ResultFile
|
|
||||||
Map<Long, ResultFile> tempMap = new HashMap<>();
|
|
||||||
for (ResultFile file : resultFiles) {
|
|
||||||
tempMap.put(file.getFirstInstance().getId(), file);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (rs.next()) {
|
|
||||||
try {
|
|
||||||
Long objId = rs.getLong("object_id"); // NON-NLS
|
|
||||||
String setName = rs.getString("set_name"); // NON-NLS
|
|
||||||
|
|
||||||
tempMap.get(objId).addInterestingSetName(setName);
|
|
||||||
|
|
||||||
} catch (SQLException ex) {
|
|
||||||
logger.log(Level.SEVERE, "Unable to get object_id or set_name from result set", ex); // NON-NLS
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (SQLException ex) {
|
|
||||||
logger.log(Level.SEVERE, "Failed to get interesting file set names", ex); // NON-NLS
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attribute for grouping/sorting by objects detected
|
|
||||||
*/
|
|
||||||
static class ObjectDetectedAttribute extends AttributeType {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GroupKey getGroupKey(ResultFile file) {
|
|
||||||
return new DiscoveryKeyUtils.ObjectDetectedGroupKey(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addAttributeToResultFiles(List<ResultFile> files, SleuthkitCase caseDb,
|
|
||||||
CentralRepository centralRepoDb) throws DiscoveryException {
|
|
||||||
|
|
||||||
// Get pairs of (object ID, object type name) for all files in the list of files that have
|
|
||||||
// objects detected
|
|
||||||
String selectQuery = createSetNameClause(files, BlackboardArtifact.ARTIFACT_TYPE.TSK_OBJECT_DETECTED.getTypeID(),
|
|
||||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION.getTypeID());
|
|
||||||
|
|
||||||
ObjectDetectedNamesCallback callback = new ObjectDetectedNamesCallback(files);
|
|
||||||
try {
|
|
||||||
caseDb.getCaseDbAccessManager().select(selectQuery, callback);
|
|
||||||
} catch (TskCoreException ex) {
|
|
||||||
throw new DiscoveryException("Error looking up object detected attributes", ex); // NON-NLS
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback to process the results of the CaseDbAccessManager select
|
|
||||||
* query. Will add the object type names to the list of ResultFile
|
|
||||||
* objects.
|
|
||||||
*/
|
|
||||||
private static class ObjectDetectedNamesCallback implements CaseDbAccessManager.CaseDbAccessQueryCallback {
|
|
||||||
|
|
||||||
List<ResultFile> resultFiles;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create the callback.
|
|
||||||
*
|
|
||||||
* @param resultFiles List of files to add object detected names to
|
|
||||||
*/
|
|
||||||
ObjectDetectedNamesCallback(List<ResultFile> resultFiles) {
|
|
||||||
this.resultFiles = resultFiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void process(ResultSet rs) {
|
|
||||||
try {
|
|
||||||
// Create a temporary map of object ID to ResultFile
|
|
||||||
Map<Long, ResultFile> tempMap = new HashMap<>();
|
|
||||||
for (ResultFile file : resultFiles) {
|
|
||||||
tempMap.put(file.getFirstInstance().getId(), file);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (rs.next()) {
|
|
||||||
try {
|
|
||||||
Long objId = rs.getLong("object_id"); // NON-NLS
|
|
||||||
String setName = rs.getString("set_name"); // NON-NLS
|
|
||||||
|
|
||||||
tempMap.get(objId).addObjectDetectedName(setName);
|
|
||||||
|
|
||||||
} catch (SQLException ex) {
|
|
||||||
logger.log(Level.SEVERE, "Unable to get object_id or set_name from result set", ex); // NON-NLS
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (SQLException ex) {
|
|
||||||
logger.log(Level.SEVERE, "Failed to get object detected names", ex); // NON-NLS
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attribute for grouping/sorting by tag name
|
|
||||||
*/
|
|
||||||
static class FileTagAttribute extends AttributeType {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GroupKey getGroupKey(ResultFile file) {
|
|
||||||
return new DiscoveryKeyUtils.FileTagGroupKey(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addAttributeToResultFiles(List<ResultFile> files, SleuthkitCase caseDb,
|
|
||||||
CentralRepository centralRepoDb) throws DiscoveryException {
|
|
||||||
|
|
||||||
try {
|
|
||||||
for (ResultFile resultFile : files) {
|
|
||||||
List<ContentTag> contentTags = caseDb.getContentTagsByContent(resultFile.getFirstInstance());
|
|
||||||
|
|
||||||
for (ContentTag tag : contentTags) {
|
|
||||||
resultFile.addTagName(tag.getName().getDisplayName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (TskCoreException ex) {
|
|
||||||
throw new DiscoveryException("Error looking up file tag attributes", ex); // NON-NLS
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enum for the attribute types that can be used for grouping.
|
|
||||||
*/
|
|
||||||
@NbBundle.Messages({
|
|
||||||
"FileSearch.GroupingAttributeType.fileType.displayName=File Type",
|
|
||||||
"FileSearch.GroupingAttributeType.frequency.displayName=Past Occurrences",
|
|
||||||
"FileSearch.GroupingAttributeType.keywordList.displayName=Keyword",
|
|
||||||
"FileSearch.GroupingAttributeType.size.displayName=File Size",
|
|
||||||
"FileSearch.GroupingAttributeType.datasource.displayName=Data Source",
|
|
||||||
"FileSearch.GroupingAttributeType.parent.displayName=Parent Folder",
|
|
||||||
"FileSearch.GroupingAttributeType.hash.displayName=Hash Set",
|
|
||||||
"FileSearch.GroupingAttributeType.interestingItem.displayName=Interesting Item",
|
|
||||||
"FileSearch.GroupingAttributeType.tag.displayName=Tag",
|
|
||||||
"FileSearch.GroupingAttributeType.object.displayName=Object Detected",
|
|
||||||
"FileSearch.GroupingAttributeType.none.displayName=None"})
|
|
||||||
public enum GroupingAttributeType {
|
|
||||||
FILE_SIZE(new FileSizeAttribute(), Bundle.FileSearch_GroupingAttributeType_size_displayName()),
|
|
||||||
FREQUENCY(new FrequencyAttribute(), Bundle.FileSearch_GroupingAttributeType_frequency_displayName()),
|
|
||||||
KEYWORD_LIST_NAME(new KeywordListAttribute(), Bundle.FileSearch_GroupingAttributeType_keywordList_displayName()),
|
|
||||||
DATA_SOURCE(new DataSourceAttribute(), Bundle.FileSearch_GroupingAttributeType_datasource_displayName()),
|
|
||||||
PARENT_PATH(new ParentPathAttribute(), Bundle.FileSearch_GroupingAttributeType_parent_displayName()),
|
|
||||||
HASH_LIST_NAME(new HashHitsAttribute(), Bundle.FileSearch_GroupingAttributeType_hash_displayName()),
|
|
||||||
INTERESTING_ITEM_SET(new InterestingItemAttribute(), Bundle.FileSearch_GroupingAttributeType_interestingItem_displayName()),
|
|
||||||
FILE_TAG(new FileTagAttribute(), Bundle.FileSearch_GroupingAttributeType_tag_displayName()),
|
|
||||||
OBJECT_DETECTED(new ObjectDetectedAttribute(), Bundle.FileSearch_GroupingAttributeType_object_displayName()),
|
|
||||||
NO_GROUPING(new NoGroupingAttribute(), Bundle.FileSearch_GroupingAttributeType_none_displayName());
|
|
||||||
|
|
||||||
private final AttributeType attributeType;
|
|
||||||
private final String displayName;
|
|
||||||
|
|
||||||
GroupingAttributeType(AttributeType attributeType, String displayName) {
|
|
||||||
this.attributeType = attributeType;
|
|
||||||
this.displayName = displayName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return displayName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AttributeType getAttributeType() {
|
|
||||||
return attributeType;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the list of enums that are valid for grouping images.
|
|
||||||
*
|
|
||||||
* @return enums that can be used to group images
|
|
||||||
*/
|
|
||||||
public static List<GroupingAttributeType> getOptionsForGrouping() {
|
|
||||||
return Arrays.asList(FILE_SIZE, FREQUENCY, PARENT_PATH, OBJECT_DETECTED, HASH_LIST_NAME, INTERESTING_ITEM_SET);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -254,19 +254,19 @@ public class FileSorter implements Comparator<ResultFile> {
|
|||||||
Bundle.FileSorter_SortingMethod_datasource_displayName()), // Sort in increasing order of data source ID
|
Bundle.FileSorter_SortingMethod_datasource_displayName()), // Sort in increasing order of data source ID
|
||||||
BY_FILE_SIZE(new ArrayList<>(),
|
BY_FILE_SIZE(new ArrayList<>(),
|
||||||
Bundle.FileSorter_SortingMethod_filesize_displayName()), // Sort in decreasing order of size
|
Bundle.FileSorter_SortingMethod_filesize_displayName()), // Sort in decreasing order of size
|
||||||
BY_FILE_TYPE(Arrays.asList(new FileSearch.FileTypeAttribute()),
|
BY_FILE_TYPE(Arrays.asList(new DiscoveryAttributes.FileTypeAttribute()),
|
||||||
Bundle.FileSorter_SortingMethod_filetype_displayName()), // Sort in order of file type (defined in FileType enum), with secondary sort on MIME type
|
Bundle.FileSorter_SortingMethod_filetype_displayName()), // Sort in order of file type (defined in FileType enum), with secondary sort on MIME type
|
||||||
BY_FREQUENCY(Arrays.asList(new FileSearch.FrequencyAttribute()),
|
BY_FREQUENCY(Arrays.asList(new DiscoveryAttributes.FrequencyAttribute()),
|
||||||
Bundle.FileSorter_SortingMethod_frequency_displayName()), // Sort by decreasing rarity in the central repository
|
Bundle.FileSorter_SortingMethod_frequency_displayName()), // Sort by decreasing rarity in the central repository
|
||||||
BY_KEYWORD_LIST_NAMES(Arrays.asList(new FileSearch.KeywordListAttribute()),
|
BY_KEYWORD_LIST_NAMES(Arrays.asList(new DiscoveryAttributes.KeywordListAttribute()),
|
||||||
Bundle.FileSorter_SortingMethod_keywordlist_displayName()), // Sort alphabetically by list of keyword list names found
|
Bundle.FileSorter_SortingMethod_keywordlist_displayName()), // Sort alphabetically by list of keyword list names found
|
||||||
BY_FULL_PATH(new ArrayList<>(),
|
BY_FULL_PATH(new ArrayList<>(),
|
||||||
Bundle.FileSorter_SortingMethod_fullPath_displayName()); // Sort alphabetically by path
|
Bundle.FileSorter_SortingMethod_fullPath_displayName()); // Sort alphabetically by path
|
||||||
|
|
||||||
private final String displayName;
|
private final String displayName;
|
||||||
private final List<FileSearch.AttributeType> requiredAttributes;
|
private final List<DiscoveryAttributes.AttributeType> requiredAttributes;
|
||||||
|
|
||||||
SortingMethod(List<FileSearch.AttributeType> attributes, String displayName) {
|
SortingMethod(List<DiscoveryAttributes.AttributeType> attributes, String displayName) {
|
||||||
this.requiredAttributes = attributes;
|
this.requiredAttributes = attributes;
|
||||||
this.displayName = displayName;
|
this.displayName = displayName;
|
||||||
}
|
}
|
||||||
@ -276,7 +276,7 @@ public class FileSorter implements Comparator<ResultFile> {
|
|||||||
return displayName;
|
return displayName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<FileSearch.AttributeType> getRequiredAttributes() {
|
public List<DiscoveryAttributes.AttributeType> getRequiredAttributes() {
|
||||||
return Collections.unmodifiableList(requiredAttributes);
|
return Collections.unmodifiableList(requiredAttributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -524,7 +524,7 @@ public class SearchFiltering {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set the frequency for each file
|
// Set the frequency for each file
|
||||||
FileSearch.FrequencyAttribute freqAttr = new FileSearch.FrequencyAttribute();
|
DiscoveryAttributes.FrequencyAttribute freqAttr = new DiscoveryAttributes.FrequencyAttribute();
|
||||||
freqAttr.addAttributeToResultFiles(currentResults, caseDb, centralRepoDb);
|
freqAttr.addAttributeToResultFiles(currentResults, caseDb, centralRepoDb);
|
||||||
|
|
||||||
// If the frequency matches the filter, add the file to the results
|
// If the frequency matches the filter, add the file to the results
|
||||||
|
@ -33,7 +33,7 @@ import org.sleuthkit.autopsy.discovery.search.DiscoveryKeyUtils.GroupKey;
|
|||||||
class SearchResults {
|
class SearchResults {
|
||||||
|
|
||||||
private final Group.GroupSortingAlgorithm groupSortingType;
|
private final Group.GroupSortingAlgorithm groupSortingType;
|
||||||
private final FileSearch.AttributeType attrType;
|
private final DiscoveryAttributes.AttributeType attrType;
|
||||||
private final FileSorter fileSorter;
|
private final FileSorter fileSorter;
|
||||||
|
|
||||||
private final Map<GroupKey, Group> groupMap = new HashMap<>();
|
private final Map<GroupKey, Group> groupMap = new HashMap<>();
|
||||||
@ -50,7 +50,7 @@ class SearchResults {
|
|||||||
* @param fileSortingMethod The method that should be used to
|
* @param fileSortingMethod The method that should be used to
|
||||||
* sortGroupsAndFiles the files in each group.
|
* sortGroupsAndFiles the files in each group.
|
||||||
*/
|
*/
|
||||||
SearchResults(Group.GroupSortingAlgorithm groupSortingType, FileSearch.AttributeType attrType,
|
SearchResults(Group.GroupSortingAlgorithm groupSortingType, DiscoveryAttributes.AttributeType attrType,
|
||||||
FileSorter.SortingMethod fileSortingMethod) {
|
FileSorter.SortingMethod fileSortingMethod) {
|
||||||
this.groupSortingType = groupSortingType;
|
this.groupSortingType = groupSortingType;
|
||||||
this.attrType = attrType;
|
this.attrType = attrType;
|
||||||
@ -63,7 +63,7 @@ class SearchResults {
|
|||||||
*/
|
*/
|
||||||
SearchResults() {
|
SearchResults() {
|
||||||
this.groupSortingType = Group.GroupSortingAlgorithm.BY_GROUP_NAME;
|
this.groupSortingType = Group.GroupSortingAlgorithm.BY_GROUP_NAME;
|
||||||
this.attrType = new FileSearch.FileSizeAttribute();
|
this.attrType = new DiscoveryAttributes.FileSizeAttribute();
|
||||||
this.fileSorter = new FileSorter(FileSorter.SortingMethod.BY_FILE_NAME);
|
this.fileSorter = new FileSorter(FileSorter.SortingMethod.BY_FILE_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,13 +37,13 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
|||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException;
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException;
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.autopsy.discovery.search.DiscoveryAttributes;
|
||||||
import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils;
|
import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils;
|
||||||
import org.sleuthkit.autopsy.discovery.search.Group;
|
import org.sleuthkit.autopsy.discovery.search.Group;
|
||||||
import org.sleuthkit.autopsy.discovery.search.Group.GroupSortingAlgorithm;
|
import org.sleuthkit.autopsy.discovery.search.Group.GroupSortingAlgorithm;
|
||||||
import static org.sleuthkit.autopsy.discovery.search.Group.GroupSortingAlgorithm.BY_GROUP_SIZE;
|
import static org.sleuthkit.autopsy.discovery.search.Group.GroupSortingAlgorithm.BY_GROUP_SIZE;
|
||||||
import org.sleuthkit.autopsy.discovery.search.FileSearch;
|
import org.sleuthkit.autopsy.discovery.search.DiscoveryAttributes.GroupingAttributeType;
|
||||||
import org.sleuthkit.autopsy.discovery.search.FileSearch.GroupingAttributeType;
|
import static org.sleuthkit.autopsy.discovery.search.DiscoveryAttributes.GroupingAttributeType.PARENT_PATH;
|
||||||
import static org.sleuthkit.autopsy.discovery.search.FileSearch.GroupingAttributeType.PARENT_PATH;
|
|
||||||
import org.sleuthkit.autopsy.discovery.search.FileSorter;
|
import org.sleuthkit.autopsy.discovery.search.FileSorter;
|
||||||
import org.sleuthkit.autopsy.discovery.search.FileSorter.SortingMethod;
|
import org.sleuthkit.autopsy.discovery.search.FileSorter.SortingMethod;
|
||||||
import static org.sleuthkit.autopsy.discovery.search.FileSorter.SortingMethod.BY_FILE_NAME;
|
import static org.sleuthkit.autopsy.discovery.search.FileSorter.SortingMethod.BY_FILE_NAME;
|
||||||
@ -169,7 +169,7 @@ final class DiscoveryDialog extends javax.swing.JDialog {
|
|||||||
private void updateComboBoxes() {
|
private void updateComboBoxes() {
|
||||||
groupByCombobox.removeAllItems();
|
groupByCombobox.removeAllItems();
|
||||||
// Set up the grouping attributes
|
// Set up the grouping attributes
|
||||||
for (FileSearch.GroupingAttributeType groupingType : FileSearch.GroupingAttributeType.getOptionsForGrouping()) {
|
for (DiscoveryAttributes.GroupingAttributeType groupingType : DiscoveryAttributes.GroupingAttributeType.getOptionsForGrouping()) {
|
||||||
addTypeToGroupByComboBox(groupingType);
|
addTypeToGroupByComboBox(groupingType);
|
||||||
}
|
}
|
||||||
groupByCombobox.setSelectedItem(PARENT_PATH);
|
groupByCombobox.setSelectedItem(PARENT_PATH);
|
||||||
@ -554,7 +554,7 @@ final class DiscoveryDialog extends javax.swing.JDialog {
|
|||||||
DiscoveryEventUtils.getDiscoveryEventBus().post(new DiscoveryEventUtils.SearchStartedEvent(type));
|
DiscoveryEventUtils.getDiscoveryEventBus().post(new DiscoveryEventUtils.SearchStartedEvent(type));
|
||||||
|
|
||||||
// Get the grouping attribute and group sorting method
|
// Get the grouping attribute and group sorting method
|
||||||
FileSearch.AttributeType groupingAttr = groupByCombobox.getItemAt(groupByCombobox.getSelectedIndex()).getAttributeType();
|
DiscoveryAttributes.AttributeType groupingAttr = groupByCombobox.getItemAt(groupByCombobox.getSelectedIndex()).getAttributeType();
|
||||||
Group.GroupSortingAlgorithm groupSortAlgorithm = groupSortingComboBox.getItemAt(groupSortingComboBox.getSelectedIndex());
|
Group.GroupSortingAlgorithm groupSortAlgorithm = groupSortingComboBox.getItemAt(groupSortingComboBox.getSelectedIndex());
|
||||||
|
|
||||||
// Get the file sorting method
|
// Get the file sorting method
|
||||||
|
@ -29,10 +29,10 @@ import javax.swing.JList;
|
|||||||
import javax.swing.JOptionPane;
|
import javax.swing.JOptionPane;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import org.openide.util.NbBundle.Messages;
|
import org.openide.util.NbBundle.Messages;
|
||||||
|
import org.sleuthkit.autopsy.discovery.search.DiscoveryAttributes;
|
||||||
import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils;
|
import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils;
|
||||||
import org.sleuthkit.autopsy.discovery.search.DiscoveryKeyUtils.GroupKey;
|
import org.sleuthkit.autopsy.discovery.search.DiscoveryKeyUtils.GroupKey;
|
||||||
import org.sleuthkit.autopsy.discovery.search.Group;
|
import org.sleuthkit.autopsy.discovery.search.Group;
|
||||||
import org.sleuthkit.autopsy.discovery.search.FileSearch;
|
|
||||||
import org.sleuthkit.autopsy.discovery.search.SearchData.Type;
|
import org.sleuthkit.autopsy.discovery.search.SearchData.Type;
|
||||||
import org.sleuthkit.autopsy.discovery.search.FileSorter;
|
import org.sleuthkit.autopsy.discovery.search.FileSorter;
|
||||||
|
|
||||||
@ -45,7 +45,7 @@ final class GroupListPanel extends javax.swing.JPanel {
|
|||||||
private Type type = null;
|
private Type type = null;
|
||||||
private Map<GroupKey, Integer> groupMap = null;
|
private Map<GroupKey, Integer> groupMap = null;
|
||||||
private List<AbstractFilter> searchfilters;
|
private List<AbstractFilter> searchfilters;
|
||||||
private FileSearch.AttributeType groupingAttribute;
|
private DiscoveryAttributes.AttributeType groupingAttribute;
|
||||||
private Group.GroupSortingAlgorithm groupSort;
|
private Group.GroupSortingAlgorithm groupSort;
|
||||||
private FileSorter.SortingMethod fileSortMethod;
|
private FileSorter.SortingMethod fileSortMethod;
|
||||||
private GroupKey selectedGroupKey;
|
private GroupKey selectedGroupKey;
|
||||||
@ -210,7 +210,7 @@ final class GroupListPanel extends javax.swing.JPanel {
|
|||||||
String valueString = newValue.toString();
|
String valueString = newValue.toString();
|
||||||
setToolTipText(valueString);
|
setToolTipText(valueString);
|
||||||
//if paths would be longer than 37 characters shorten them to be 37 characters
|
//if paths would be longer than 37 characters shorten them to be 37 characters
|
||||||
if (groupingAttribute instanceof FileSearch.ParentPathAttribute && valueString.length() > 37) {
|
if (groupingAttribute instanceof DiscoveryAttributes.ParentPathAttribute && valueString.length() > 37) {
|
||||||
valueString = valueString.substring(0, 16) + " ... " + valueString.substring(valueString.length() - 16);
|
valueString = valueString.substring(0, 16) + " ... " + valueString.substring(valueString.length() - 16);
|
||||||
}
|
}
|
||||||
newValue = valueString + " (" + groupMap.get(newValue) + ")";
|
newValue = valueString + " (" + groupMap.get(newValue) + ")";
|
||||||
|
@ -26,6 +26,7 @@ import javax.swing.SwingWorker;
|
|||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
||||||
|
import org.sleuthkit.autopsy.discovery.search.DiscoveryAttributes;
|
||||||
import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils;
|
import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils;
|
||||||
import org.sleuthkit.autopsy.discovery.search.DiscoveryKeyUtils.GroupKey;
|
import org.sleuthkit.autopsy.discovery.search.DiscoveryKeyUtils.GroupKey;
|
||||||
import org.sleuthkit.autopsy.discovery.search.Group;
|
import org.sleuthkit.autopsy.discovery.search.Group;
|
||||||
@ -43,7 +44,7 @@ final class PageWorker extends SwingWorker<Void, Void> {
|
|||||||
private final static Logger logger = Logger.getLogger(PageWorker.class.getName());
|
private final static Logger logger = Logger.getLogger(PageWorker.class.getName());
|
||||||
private static final String USER_NAME_PROPERTY = "user.name"; //NON-NLS
|
private static final String USER_NAME_PROPERTY = "user.name"; //NON-NLS
|
||||||
private final List<AbstractFilter> searchfilters;
|
private final List<AbstractFilter> searchfilters;
|
||||||
private final FileSearch.AttributeType groupingAttribute;
|
private final DiscoveryAttributes.AttributeType groupingAttribute;
|
||||||
private final Group.GroupSortingAlgorithm groupSort;
|
private final Group.GroupSortingAlgorithm groupSort;
|
||||||
private final FileSorter.SortingMethod fileSortMethod;
|
private final FileSorter.SortingMethod fileSortMethod;
|
||||||
private final GroupKey groupKey;
|
private final GroupKey groupKey;
|
||||||
@ -69,7 +70,7 @@ final class PageWorker extends SwingWorker<Void, Void> {
|
|||||||
* @param resultType The type of files which exist in the group.
|
* @param resultType The type of files which exist in the group.
|
||||||
* @param centralRepo The central repository to be used.
|
* @param centralRepo The central repository to be used.
|
||||||
*/
|
*/
|
||||||
PageWorker(List<AbstractFilter> searchfilters, FileSearch.AttributeType groupingAttribute,
|
PageWorker(List<AbstractFilter> searchfilters, DiscoveryAttributes.AttributeType groupingAttribute,
|
||||||
Group.GroupSortingAlgorithm groupSort, FileSorter.SortingMethod fileSortMethod, GroupKey groupKey,
|
Group.GroupSortingAlgorithm groupSort, FileSorter.SortingMethod fileSortMethod, GroupKey groupKey,
|
||||||
int startingEntry, int pageSize, SearchData.Type resultType, CentralRepository centralRepo) {
|
int startingEntry, int pageSize, SearchData.Type resultType, CentralRepository centralRepo) {
|
||||||
this.searchfilters = searchfilters;
|
this.searchfilters = searchfilters;
|
||||||
|
@ -38,6 +38,7 @@ import org.sleuthkit.autopsy.coreutils.ImageUtils;
|
|||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
||||||
|
import org.sleuthkit.autopsy.discovery.search.DiscoveryAttributes;
|
||||||
import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils;
|
import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils;
|
||||||
import org.sleuthkit.autopsy.discovery.search.DiscoveryKeyUtils.GroupKey;
|
import org.sleuthkit.autopsy.discovery.search.DiscoveryKeyUtils.GroupKey;
|
||||||
import org.sleuthkit.autopsy.discovery.search.Group;
|
import org.sleuthkit.autopsy.discovery.search.Group;
|
||||||
@ -59,7 +60,7 @@ final class ResultsPanel extends javax.swing.JPanel {
|
|||||||
private final ImageThumbnailViewer imageThumbnailViewer;
|
private final ImageThumbnailViewer imageThumbnailViewer;
|
||||||
private final DocumentPreviewViewer documentPreviewViewer;
|
private final DocumentPreviewViewer documentPreviewViewer;
|
||||||
private List<AbstractFilter> searchFilters;
|
private List<AbstractFilter> searchFilters;
|
||||||
private FileSearch.AttributeType groupingAttribute;
|
private DiscoveryAttributes.AttributeType groupingAttribute;
|
||||||
private Group.GroupSortingAlgorithm groupSort;
|
private Group.GroupSortingAlgorithm groupSort;
|
||||||
private FileSorter.SortingMethod fileSortMethod;
|
private FileSorter.SortingMethod fileSortMethod;
|
||||||
private GroupKey selectedGroupKey;
|
private GroupKey selectedGroupKey;
|
||||||
|
@ -27,6 +27,7 @@ import java.util.logging.Level;
|
|||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
||||||
|
import org.sleuthkit.autopsy.discovery.search.DiscoveryAttributes;
|
||||||
import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils;
|
import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils;
|
||||||
import org.sleuthkit.autopsy.discovery.search.DiscoveryKeyUtils.GroupKey;
|
import org.sleuthkit.autopsy.discovery.search.DiscoveryKeyUtils.GroupKey;
|
||||||
import org.sleuthkit.autopsy.discovery.search.Group;
|
import org.sleuthkit.autopsy.discovery.search.Group;
|
||||||
@ -42,7 +43,7 @@ final class SearchWorker extends SwingWorker<Void, Void> {
|
|||||||
private final static Logger logger = Logger.getLogger(SearchWorker.class.getName());
|
private final static Logger logger = Logger.getLogger(SearchWorker.class.getName());
|
||||||
private static final String USER_NAME_PROPERTY = "user.name"; //NON-NLS
|
private static final String USER_NAME_PROPERTY = "user.name"; //NON-NLS
|
||||||
private final List<AbstractFilter> filters;
|
private final List<AbstractFilter> filters;
|
||||||
private final FileSearch.AttributeType groupingAttr;
|
private final DiscoveryAttributes.AttributeType groupingAttr;
|
||||||
private final FileSorter.SortingMethod fileSort;
|
private final FileSorter.SortingMethod fileSort;
|
||||||
private final Group.GroupSortingAlgorithm groupSortAlgorithm;
|
private final Group.GroupSortingAlgorithm groupSortAlgorithm;
|
||||||
private final CentralRepository centralRepoDb;
|
private final CentralRepository centralRepoDb;
|
||||||
@ -58,7 +59,7 @@ final class SearchWorker extends SwingWorker<Void, Void> {
|
|||||||
* @param groupSort The Algorithm to sort groups by.
|
* @param groupSort The Algorithm to sort groups by.
|
||||||
* @param fileSortMethod The SortingMethod to use for files.
|
* @param fileSortMethod The SortingMethod to use for files.
|
||||||
*/
|
*/
|
||||||
SearchWorker(CentralRepository centralRepo, List<AbstractFilter> searchfilters, FileSearch.AttributeType groupingAttribute, Group.GroupSortingAlgorithm groupSort, FileSorter.SortingMethod fileSortMethod) {
|
SearchWorker(CentralRepository centralRepo, List<AbstractFilter> searchfilters, DiscoveryAttributes.AttributeType groupingAttribute, Group.GroupSortingAlgorithm groupSort, FileSorter.SortingMethod fileSortMethod) {
|
||||||
centralRepoDb = centralRepo;
|
centralRepoDb = centralRepo;
|
||||||
filters = searchfilters;
|
filters = searchfilters;
|
||||||
groupingAttr = groupingAttribute;
|
groupingAttr = groupingAttribute;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user