mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-17 02:07:42 +00:00
6711 add ResultDomain object
This commit is contained in:
parent
1b73edee7d
commit
e9b80d09a1
@ -61,7 +61,7 @@ public abstract class AbstractFilter {
|
||||
*
|
||||
* @throws DiscoveryException
|
||||
*/
|
||||
public List<ResultFile> applyAlternateFilter(List<ResultFile> currentResults, SleuthkitCase caseDb,
|
||||
public List<Result> applyAlternateFilter(List<Result> currentResults, SleuthkitCase caseDb,
|
||||
CentralRepository centralRepoDb) throws DiscoveryException {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
@ -52,19 +52,19 @@ public class DiscoveryAttributes {
|
||||
*
|
||||
* @return the key for the group this file goes in
|
||||
*/
|
||||
public abstract DiscoveryKeyUtils.GroupKey getGroupKey(ResultFile file);
|
||||
public abstract DiscoveryKeyUtils.GroupKey getGroupKey(Result file);
|
||||
|
||||
/**
|
||||
* Add any extra data to the ResultFile object from this attribute.
|
||||
*
|
||||
* @param files The list of files to enhance
|
||||
* @param files The list of results 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 {
|
||||
public void addAttributeToResultFiles(List<Result> results, SleuthkitCase caseDb, CentralRepository centralRepoDb) throws DiscoveryException {
|
||||
// Default is to do nothing
|
||||
}
|
||||
}
|
||||
@ -75,8 +75,8 @@ public class DiscoveryAttributes {
|
||||
public static class FileSizeAttribute extends AttributeType {
|
||||
|
||||
@Override
|
||||
public DiscoveryKeyUtils.GroupKey getGroupKey(ResultFile file) {
|
||||
return new DiscoveryKeyUtils.FileSizeGroupKey(file);
|
||||
public DiscoveryKeyUtils.GroupKey getGroupKey(Result file) {
|
||||
return new DiscoveryKeyUtils.FileSizeGroupKey((ResultFile) file);
|
||||
}
|
||||
}
|
||||
|
||||
@ -86,8 +86,8 @@ public class DiscoveryAttributes {
|
||||
public static class ParentPathAttribute extends AttributeType {
|
||||
|
||||
@Override
|
||||
public DiscoveryKeyUtils.GroupKey getGroupKey(ResultFile file) {
|
||||
return new DiscoveryKeyUtils.ParentPathGroupKey(file);
|
||||
public DiscoveryKeyUtils.GroupKey getGroupKey(Result file) {
|
||||
return new DiscoveryKeyUtils.ParentPathGroupKey((ResultFile) file);
|
||||
}
|
||||
}
|
||||
|
||||
@ -97,7 +97,7 @@ public class DiscoveryAttributes {
|
||||
static class NoGroupingAttribute extends AttributeType {
|
||||
|
||||
@Override
|
||||
public DiscoveryKeyUtils.GroupKey getGroupKey(ResultFile file) {
|
||||
public DiscoveryKeyUtils.GroupKey getGroupKey(Result result) {
|
||||
return new DiscoveryKeyUtils.NoGroupingGroupKey();
|
||||
}
|
||||
}
|
||||
@ -108,8 +108,8 @@ public class DiscoveryAttributes {
|
||||
static class DataSourceAttribute extends AttributeType {
|
||||
|
||||
@Override
|
||||
public DiscoveryKeyUtils.GroupKey getGroupKey(ResultFile file) {
|
||||
return new DiscoveryKeyUtils.DataSourceGroupKey(file);
|
||||
public DiscoveryKeyUtils.GroupKey getGroupKey(Result result) {
|
||||
return new DiscoveryKeyUtils.DataSourceGroupKey(result);
|
||||
}
|
||||
}
|
||||
|
||||
@ -119,7 +119,7 @@ public class DiscoveryAttributes {
|
||||
static class FileTypeAttribute extends AttributeType {
|
||||
|
||||
@Override
|
||||
public DiscoveryKeyUtils.GroupKey getGroupKey(ResultFile file) {
|
||||
public DiscoveryKeyUtils.GroupKey getGroupKey(Result file) {
|
||||
return new DiscoveryKeyUtils.FileTypeGroupKey(file);
|
||||
}
|
||||
}
|
||||
@ -130,20 +130,20 @@ public class DiscoveryAttributes {
|
||||
static class KeywordListAttribute extends AttributeType {
|
||||
|
||||
@Override
|
||||
public DiscoveryKeyUtils.GroupKey getGroupKey(ResultFile file) {
|
||||
return new DiscoveryKeyUtils.KeywordListGroupKey(file);
|
||||
public DiscoveryKeyUtils.GroupKey getGroupKey(Result file) {
|
||||
return new DiscoveryKeyUtils.KeywordListGroupKey((ResultFile) file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAttributeToResultFiles(List<ResultFile> files, SleuthkitCase caseDb,
|
||||
public void addAttributeToResultFiles(List<Result> results, 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(),
|
||||
String selectQuery = createSetNameClause(results, BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID(),
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID());
|
||||
|
||||
SetKeywordListNamesCallback callback = new SetKeywordListNamesCallback(files);
|
||||
SetKeywordListNamesCallback callback = new SetKeywordListNamesCallback(results);
|
||||
try {
|
||||
caseDb.getCaseDbAccessManager().select(selectQuery, callback);
|
||||
} catch (TskCoreException ex) {
|
||||
@ -158,14 +158,14 @@ public class DiscoveryAttributes {
|
||||
*/
|
||||
private static class SetKeywordListNamesCallback implements CaseDbAccessManager.CaseDbAccessQueryCallback {
|
||||
|
||||
List<ResultFile> resultFiles;
|
||||
List<Result> resultFiles;
|
||||
|
||||
/**
|
||||
* Create the callback.
|
||||
*
|
||||
* @param resultFiles List of files to add keyword list names to
|
||||
*/
|
||||
SetKeywordListNamesCallback(List<ResultFile> resultFiles) {
|
||||
SetKeywordListNamesCallback(List<Result> resultFiles) {
|
||||
this.resultFiles = resultFiles;
|
||||
}
|
||||
|
||||
@ -174,7 +174,11 @@ public class DiscoveryAttributes {
|
||||
try {
|
||||
// Create a temporary map of object ID to ResultFile
|
||||
Map<Long, ResultFile> tempMap = new HashMap<>();
|
||||
for (ResultFile file : resultFiles) {
|
||||
for (Result result : resultFiles) {
|
||||
if (result.getType() == SearchData.Type.DOMAIN) {
|
||||
break;
|
||||
}
|
||||
ResultFile file = (ResultFile) result;
|
||||
tempMap.put(file.getFirstInstance().getId(), file);
|
||||
}
|
||||
|
||||
@ -204,21 +208,21 @@ public class DiscoveryAttributes {
|
||||
static final int BATCH_SIZE = 50; // Number of hashes to look up at one time
|
||||
|
||||
@Override
|
||||
public DiscoveryKeyUtils.GroupKey getGroupKey(ResultFile file) {
|
||||
public DiscoveryKeyUtils.GroupKey getGroupKey(Result file) {
|
||||
return new DiscoveryKeyUtils.FrequencyGroupKey(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAttributeToResultFiles(List<ResultFile> files, SleuthkitCase caseDb,
|
||||
public void addAttributeToResultFiles(List<Result> results, 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);
|
||||
for (Result result : results) {
|
||||
if (result.getFrequency() == SearchData.Frequency.UNKNOWN && result.getKnown() == TskData.FileKnown.KNOWN) {
|
||||
result.setFrequency(SearchData.Frequency.KNOWN);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
processResultFilesForCR(files, centralRepoDb);
|
||||
processResultFilesForCR(results, centralRepoDb);
|
||||
}
|
||||
}
|
||||
|
||||
@ -230,19 +234,22 @@ public class DiscoveryAttributes {
|
||||
* for.
|
||||
* @param centralRepoDb The central repository currently in use.
|
||||
*/
|
||||
private void processResultFilesForCR(List<ResultFile> files,
|
||||
private void processResultFilesForCR(List<Result> results,
|
||||
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);
|
||||
for (Result result : results) {
|
||||
if (result.getKnown() == TskData.FileKnown.KNOWN) {
|
||||
result.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 (result.getType() != SearchData.Type.DOMAIN) {
|
||||
ResultFile file = (ResultFile) result;
|
||||
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);
|
||||
@ -299,20 +306,23 @@ public class DiscoveryAttributes {
|
||||
static class HashHitsAttribute extends AttributeType {
|
||||
|
||||
@Override
|
||||
public DiscoveryKeyUtils.GroupKey getGroupKey(ResultFile file) {
|
||||
return new DiscoveryKeyUtils.HashHitsGroupKey(file);
|
||||
public DiscoveryKeyUtils.GroupKey getGroupKey(Result result) {
|
||||
if (result.getType() == SearchData.Type.DOMAIN) {
|
||||
return null;
|
||||
}
|
||||
return new DiscoveryKeyUtils.HashHitsGroupKey((ResultFile) result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAttributeToResultFiles(List<ResultFile> files, SleuthkitCase caseDb,
|
||||
public void addAttributeToResultFiles(List<Result> results, 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(),
|
||||
String selectQuery = createSetNameClause(results, BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID(),
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID());
|
||||
|
||||
HashSetNamesCallback callback = new HashSetNamesCallback(files);
|
||||
HashSetNamesCallback callback = new HashSetNamesCallback(results);
|
||||
try {
|
||||
caseDb.getCaseDbAccessManager().select(selectQuery, callback);
|
||||
} catch (TskCoreException ex) {
|
||||
@ -326,15 +336,15 @@ public class DiscoveryAttributes {
|
||||
*/
|
||||
private static class HashSetNamesCallback implements CaseDbAccessManager.CaseDbAccessQueryCallback {
|
||||
|
||||
List<ResultFile> resultFiles;
|
||||
List<Result> results;
|
||||
|
||||
/**
|
||||
* Create the callback.
|
||||
*
|
||||
* @param resultFiles List of files to add hash set names to
|
||||
*/
|
||||
HashSetNamesCallback(List<ResultFile> resultFiles) {
|
||||
this.resultFiles = resultFiles;
|
||||
HashSetNamesCallback(List<Result> results) {
|
||||
this.results = results;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -342,7 +352,11 @@ public class DiscoveryAttributes {
|
||||
try {
|
||||
// Create a temporary map of object ID to ResultFile
|
||||
Map<Long, ResultFile> tempMap = new HashMap<>();
|
||||
for (ResultFile file : resultFiles) {
|
||||
for (Result result : results) {
|
||||
if (result.getType() == SearchData.Type.DOMAIN) {
|
||||
return;
|
||||
}
|
||||
ResultFile file = (ResultFile) result;
|
||||
tempMap.put(file.getFirstInstance().getId(), file);
|
||||
}
|
||||
|
||||
@ -370,20 +384,20 @@ public class DiscoveryAttributes {
|
||||
static class InterestingItemAttribute extends AttributeType {
|
||||
|
||||
@Override
|
||||
public DiscoveryKeyUtils.GroupKey getGroupKey(ResultFile file) {
|
||||
return new DiscoveryKeyUtils.InterestingItemGroupKey(file);
|
||||
public DiscoveryKeyUtils.GroupKey getGroupKey(Result file) {
|
||||
return new DiscoveryKeyUtils.InterestingItemGroupKey((ResultFile) file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAttributeToResultFiles(List<ResultFile> files, SleuthkitCase caseDb,
|
||||
public void addAttributeToResultFiles(List<Result> results, 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(),
|
||||
String selectQuery = createSetNameClause(results, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID(),
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID());
|
||||
|
||||
InterestingFileSetNamesCallback callback = new InterestingFileSetNamesCallback(files);
|
||||
InterestingFileSetNamesCallback callback = new InterestingFileSetNamesCallback(results);
|
||||
try {
|
||||
caseDb.getCaseDbAccessManager().select(selectQuery, callback);
|
||||
} catch (TskCoreException ex) {
|
||||
@ -398,7 +412,7 @@ public class DiscoveryAttributes {
|
||||
*/
|
||||
private static class InterestingFileSetNamesCallback implements CaseDbAccessManager.CaseDbAccessQueryCallback {
|
||||
|
||||
List<ResultFile> resultFiles;
|
||||
List<Result> results;
|
||||
|
||||
/**
|
||||
* Create the callback.
|
||||
@ -406,8 +420,8 @@ public class DiscoveryAttributes {
|
||||
* @param resultFiles List of files to add interesting file set
|
||||
* names to
|
||||
*/
|
||||
InterestingFileSetNamesCallback(List<ResultFile> resultFiles) {
|
||||
this.resultFiles = resultFiles;
|
||||
InterestingFileSetNamesCallback(List<Result> results) {
|
||||
this.results = results;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -415,7 +429,11 @@ public class DiscoveryAttributes {
|
||||
try {
|
||||
// Create a temporary map of object ID to ResultFile
|
||||
Map<Long, ResultFile> tempMap = new HashMap<>();
|
||||
for (ResultFile file : resultFiles) {
|
||||
for (Result result : results) {
|
||||
if (result.getType() == SearchData.Type.DOMAIN) {
|
||||
return;
|
||||
}
|
||||
ResultFile file = (ResultFile) result;
|
||||
tempMap.put(file.getFirstInstance().getId(), file);
|
||||
}
|
||||
|
||||
@ -443,20 +461,20 @@ public class DiscoveryAttributes {
|
||||
static class ObjectDetectedAttribute extends AttributeType {
|
||||
|
||||
@Override
|
||||
public DiscoveryKeyUtils.GroupKey getGroupKey(ResultFile file) {
|
||||
return new DiscoveryKeyUtils.ObjectDetectedGroupKey(file);
|
||||
public DiscoveryKeyUtils.GroupKey getGroupKey(Result file) {
|
||||
return new DiscoveryKeyUtils.ObjectDetectedGroupKey((ResultFile) file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAttributeToResultFiles(List<ResultFile> files, SleuthkitCase caseDb,
|
||||
public void addAttributeToResultFiles(List<Result> results, 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(),
|
||||
String selectQuery = createSetNameClause(results, BlackboardArtifact.ARTIFACT_TYPE.TSK_OBJECT_DETECTED.getTypeID(),
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION.getTypeID());
|
||||
|
||||
ObjectDetectedNamesCallback callback = new ObjectDetectedNamesCallback(files);
|
||||
ObjectDetectedNamesCallback callback = new ObjectDetectedNamesCallback(results);
|
||||
try {
|
||||
caseDb.getCaseDbAccessManager().select(selectQuery, callback);
|
||||
} catch (TskCoreException ex) {
|
||||
@ -471,15 +489,15 @@ public class DiscoveryAttributes {
|
||||
*/
|
||||
private static class ObjectDetectedNamesCallback implements CaseDbAccessManager.CaseDbAccessQueryCallback {
|
||||
|
||||
List<ResultFile> resultFiles;
|
||||
List<Result> results;
|
||||
|
||||
/**
|
||||
* Create the callback.
|
||||
*
|
||||
* @param resultFiles List of files to add object detected names to
|
||||
*/
|
||||
ObjectDetectedNamesCallback(List<ResultFile> resultFiles) {
|
||||
this.resultFiles = resultFiles;
|
||||
ObjectDetectedNamesCallback(List<Result> results) {
|
||||
this.results = results;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -487,7 +505,11 @@ public class DiscoveryAttributes {
|
||||
try {
|
||||
// Create a temporary map of object ID to ResultFile
|
||||
Map<Long, ResultFile> tempMap = new HashMap<>();
|
||||
for (ResultFile file : resultFiles) {
|
||||
for (Result result : results) {
|
||||
if (result.getType() == SearchData.Type.DOMAIN) {
|
||||
return;
|
||||
}
|
||||
ResultFile file = (ResultFile) result;
|
||||
tempMap.put(file.getFirstInstance().getId(), file);
|
||||
}
|
||||
|
||||
@ -515,20 +537,24 @@ public class DiscoveryAttributes {
|
||||
static class FileTagAttribute extends AttributeType {
|
||||
|
||||
@Override
|
||||
public DiscoveryKeyUtils.GroupKey getGroupKey(ResultFile file) {
|
||||
return new DiscoveryKeyUtils.FileTagGroupKey(file);
|
||||
public DiscoveryKeyUtils.GroupKey getGroupKey(Result file) {
|
||||
return new DiscoveryKeyUtils.FileTagGroupKey((ResultFile) file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAttributeToResultFiles(List<ResultFile> files, SleuthkitCase caseDb,
|
||||
public void addAttributeToResultFiles(List<Result> results, SleuthkitCase caseDb,
|
||||
CentralRepository centralRepoDb) throws DiscoveryException {
|
||||
|
||||
try {
|
||||
for (ResultFile resultFile : files) {
|
||||
List<ContentTag> contentTags = caseDb.getContentTagsByContent(resultFile.getFirstInstance());
|
||||
for (Result result : results) {
|
||||
if (result.getType() == SearchData.Type.DOMAIN) {
|
||||
return;
|
||||
}
|
||||
ResultFile file = (ResultFile) result;
|
||||
List<ContentTag> contentTags = caseDb.getContentTagsByContent(file.getFirstInstance());
|
||||
|
||||
for (ContentTag tag : contentTags) {
|
||||
resultFile.addTagName(tag.getName().getDisplayName());
|
||||
result.addTagName(tag.getName().getDisplayName());
|
||||
}
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
@ -625,12 +651,16 @@ public class DiscoveryAttributes {
|
||||
|
||||
}
|
||||
|
||||
private static String createSetNameClause(List<ResultFile> files,
|
||||
private static String createSetNameClause(List<Result> results,
|
||||
int artifactTypeID, int setNameAttrID) throws DiscoveryException {
|
||||
|
||||
// Concatenate the object IDs in the list of files
|
||||
String objIdList = ""; // NON-NLS
|
||||
for (ResultFile file : files) {
|
||||
for (Result result : results) {
|
||||
if (result.getType() == SearchData.Type.DOMAIN) {
|
||||
break;
|
||||
}
|
||||
ResultFile file = (ResultFile) result;
|
||||
if (!objIdList.isEmpty()) {
|
||||
objIdList += ","; // NON-NLS
|
||||
}
|
||||
@ -644,7 +674,8 @@ public class DiscoveryAttributes {
|
||||
+ "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
|
||||
+ "AND blackboard_artifacts.obj_id IN (" + objIdList
|
||||
+ ") "; // NON-NLS
|
||||
}
|
||||
|
||||
private DiscoveryAttributes() {
|
||||
|
@ -197,7 +197,7 @@ public final class DiscoveryEventUtils {
|
||||
*/
|
||||
public static final class PageRetrievedEvent {
|
||||
|
||||
private final List<ResultFile> results;
|
||||
private final List<Result> results;
|
||||
private final int page;
|
||||
private final Type resultType;
|
||||
|
||||
@ -208,7 +208,7 @@ public final class DiscoveryEventUtils {
|
||||
* @param page The number of the page which was retrieved.
|
||||
* @param results The list of files in the page retrieved.
|
||||
*/
|
||||
public PageRetrievedEvent(Type resultType, int page, List<ResultFile> results) {
|
||||
public PageRetrievedEvent(Type resultType, int page, List<Result> results) {
|
||||
this.results = results;
|
||||
this.page = page;
|
||||
this.resultType = resultType;
|
||||
@ -219,7 +219,7 @@ public final class DiscoveryEventUtils {
|
||||
*
|
||||
* @return The list of files in the page retrieved.
|
||||
*/
|
||||
public List<ResultFile> getSearchResults() {
|
||||
public List<Result> getSearchResults() {
|
||||
return Collections.unmodifiableList(results);
|
||||
}
|
||||
|
||||
|
@ -155,11 +155,12 @@ public class DiscoveryKeyUtils {
|
||||
|
||||
private final SearchData.FileSize fileSize;
|
||||
|
||||
FileSizeGroupKey(ResultFile file) {
|
||||
if (file.getFileType() == SearchData.Type.VIDEO) {
|
||||
fileSize = SearchData.FileSize.fromVideoSize(file.getFirstInstance().getSize());
|
||||
FileSizeGroupKey(Result file) {
|
||||
ResultFile resultFile = (ResultFile) file;
|
||||
if (resultFile.getFileType() == SearchData.Type.VIDEO) {
|
||||
fileSize = SearchData.FileSize.fromVideoSize(resultFile.getFirstInstance().getSize());
|
||||
} else {
|
||||
fileSize = SearchData.FileSize.fromImageSize(file.getFirstInstance().getSize());
|
||||
fileSize = SearchData.FileSize.fromImageSize(resultFile.getFirstInstance().getSize());
|
||||
}
|
||||
}
|
||||
|
||||
@ -212,8 +213,8 @@ public class DiscoveryKeyUtils {
|
||||
|
||||
private final SearchData.Type fileType;
|
||||
|
||||
FileTypeGroupKey(ResultFile file) {
|
||||
fileType = file.getFileType();
|
||||
FileTypeGroupKey(Result file) {
|
||||
fileType = ((ResultFile) file).getFileType();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -539,19 +540,19 @@ public class DiscoveryKeyUtils {
|
||||
@NbBundle.Messages({
|
||||
"# {0} - Data source name",
|
||||
"# {1} - Data source ID",
|
||||
"FileSearch.DataSourceGroupKey.datasourceAndID={0}(ID: {1})",
|
||||
"DiscoveryKeyUtils.DataSourceGroupKey.datasourceAndID={0}(ID: {1})",
|
||||
"# {0} - Data source ID",
|
||||
"FileSearch.DataSourceGroupKey.idOnly=Data source (ID: {0})"})
|
||||
DataSourceGroupKey(ResultFile file) {
|
||||
dataSourceID = file.getFirstInstance().getDataSourceObjectId();
|
||||
|
||||
"DiscoveryKeyUtils.DataSourceGroupKey.idOnly=Data source (ID: {0})"})
|
||||
DataSourceGroupKey(Result result) {
|
||||
//get the id first so that it can be used when logging if necessary
|
||||
dataSourceID = result.getDataSourceObjectId();
|
||||
try {
|
||||
// The data source should be cached so this won't actually be a database query.
|
||||
Content ds = file.getFirstInstance().getDataSource();
|
||||
displayName = Bundle.FileSearch_DataSourceGroupKey_datasourceAndID(ds.getName(), ds.getId());
|
||||
Content ds = result.getDataSource();
|
||||
displayName = Bundle.DiscoveryKeyUtils_DataSourceGroupKey_datasourceAndID(ds.getName(), ds.getId());
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Error looking up data source with ID " + dataSourceID, ex); // NON-NLS
|
||||
displayName = Bundle.FileSearch_DataSourceGroupKey_idOnly(dataSourceID);
|
||||
displayName = Bundle.DiscoveryKeyUtils_DataSourceGroupKey_idOnly(dataSourceID);
|
||||
}
|
||||
}
|
||||
|
||||
@ -646,7 +647,7 @@ public class DiscoveryKeyUtils {
|
||||
|
||||
private final SearchData.Frequency frequency;
|
||||
|
||||
FrequencyGroupKey(ResultFile file) {
|
||||
FrequencyGroupKey(Result file) {
|
||||
frequency = file.getFrequency();
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@ public class FileSearch {
|
||||
|
||||
private final static Logger logger = Logger.getLogger(FileSearch.class.getName());
|
||||
private static final int MAXIMUM_CACHE_SIZE = 10;
|
||||
private static final Cache<SearchKey, Map<GroupKey, List<ResultFile>>> searchCache = CacheBuilder.newBuilder()
|
||||
private static final Cache<SearchKey, Map<GroupKey, List<Result>>> searchCache = CacheBuilder.newBuilder()
|
||||
.maximumSize(MAXIMUM_CACHE_SIZE)
|
||||
.build();
|
||||
|
||||
@ -82,18 +82,18 @@ public class FileSearch {
|
||||
attributesNeededForGroupingOrSorting.addAll(fileSortingMethod.getRequiredAttributes());
|
||||
|
||||
// Run the queries for each filter
|
||||
List<ResultFile> resultFiles = SearchFiltering.runQueries(filters, caseDb, centralRepoDb);
|
||||
List<Result> results = SearchFiltering.runQueries(filters, caseDb, centralRepoDb);
|
||||
|
||||
// Add the data to resultFiles for any attributes needed for sorting and grouping
|
||||
addAttributes(attributesNeededForGroupingOrSorting, resultFiles, caseDb, centralRepoDb);
|
||||
addAttributes(attributesNeededForGroupingOrSorting, results, caseDb, centralRepoDb);
|
||||
|
||||
// Collect everything in the search results
|
||||
SearchResults searchResults = new SearchResults(groupSortingType, groupAttributeType, fileSortingMethod);
|
||||
searchResults.add(resultFiles);
|
||||
searchResults.add(results);
|
||||
|
||||
// Sort and group the results
|
||||
searchResults.sortGroupsAndFiles();
|
||||
Map<GroupKey, List<ResultFile>> resultHashMap = searchResults.toLinkedHashMap();
|
||||
Map<GroupKey, List<Result>> resultHashMap = searchResults.toLinkedHashMap();
|
||||
SearchKey searchKey = new SearchKey(userName, filters, groupAttributeType, groupSortingType, fileSortingMethod);
|
||||
synchronized (searchCache) {
|
||||
searchCache.put(searchKey, resultHashMap);
|
||||
@ -125,7 +125,7 @@ public class FileSearch {
|
||||
Group.GroupSortingAlgorithm groupSortingType,
|
||||
FileSorter.SortingMethod fileSortingMethod,
|
||||
SleuthkitCase caseDb, CentralRepository centralRepoDb) throws DiscoveryException {
|
||||
Map<GroupKey, List<ResultFile>> searchResults = runFileSearch(userName, filters,
|
||||
Map<GroupKey, List<Result>> searchResults = runFileSearch(userName, filters,
|
||||
groupAttributeType, groupSortingType, fileSortingMethod, caseDb, centralRepoDb);
|
||||
LinkedHashMap<GroupKey, Integer> groupSizes = new LinkedHashMap<>();
|
||||
for (GroupKey groupKey : searchResults.keySet()) {
|
||||
@ -156,7 +156,7 @@ public class FileSearch {
|
||||
*
|
||||
* @throws DiscoveryException
|
||||
*/
|
||||
public static List<ResultFile> getFilesInGroup(String userName,
|
||||
public static List<Result> getFilesInGroup(String userName,
|
||||
List<AbstractFilter> filters,
|
||||
AttributeType groupAttributeType,
|
||||
Group.GroupSortingAlgorithm groupSortingType,
|
||||
@ -166,16 +166,16 @@ public class FileSearch {
|
||||
int numberOfEntries,
|
||||
SleuthkitCase caseDb, CentralRepository centralRepoDb) throws DiscoveryException {
|
||||
//the group should be in the cache at this point
|
||||
List<ResultFile> filesInGroup = null;
|
||||
List<Result> filesInGroup = null;
|
||||
SearchKey searchKey = new SearchKey(userName, filters, groupAttributeType, groupSortingType, fileSortingMethod);
|
||||
Map<GroupKey, List<ResultFile>> resultsMap;
|
||||
Map<GroupKey, List<Result>> resultsMap;
|
||||
synchronized (searchCache) {
|
||||
resultsMap = searchCache.getIfPresent(searchKey);
|
||||
}
|
||||
if (resultsMap != null) {
|
||||
filesInGroup = resultsMap.get(groupKey);
|
||||
}
|
||||
List<ResultFile> page = new ArrayList<>();
|
||||
List<Result> page = new ArrayList<>();
|
||||
if (filesInGroup == null) {
|
||||
logger.log(Level.INFO, "Group {0} was not cached, performing search to cache all groups again", groupKey);
|
||||
runFileSearch(userName, filters, groupAttributeType, groupSortingType, fileSortingMethod, caseDb, centralRepoDb);
|
||||
@ -252,7 +252,7 @@ public class FileSearch {
|
||||
*
|
||||
* @throws DiscoveryException
|
||||
*/
|
||||
private static Map<GroupKey, List<ResultFile>> runFileSearch(String userName,
|
||||
private static Map<GroupKey, List<Result>> runFileSearch(String userName,
|
||||
List<AbstractFilter> filters,
|
||||
AttributeType groupAttributeType,
|
||||
Group.GroupSortingAlgorithm groupSortingType,
|
||||
@ -268,15 +268,15 @@ public class FileSearch {
|
||||
attributesNeededForGroupingOrSorting.addAll(fileSortingMethod.getRequiredAttributes());
|
||||
|
||||
// Run the queries for each filter
|
||||
List<ResultFile> resultFiles = SearchFiltering.runQueries(filters, caseDb, centralRepoDb);
|
||||
List<Result> results = SearchFiltering.runQueries(filters, caseDb, centralRepoDb);
|
||||
|
||||
// Add the data to resultFiles for any attributes needed for sorting and grouping
|
||||
addAttributes(attributesNeededForGroupingOrSorting, resultFiles, caseDb, centralRepoDb);
|
||||
addAttributes(attributesNeededForGroupingOrSorting, results, caseDb, centralRepoDb);
|
||||
|
||||
// Collect everything in the search results
|
||||
SearchResults searchResults = new SearchResults(groupSortingType, groupAttributeType, fileSortingMethod);
|
||||
searchResults.add(resultFiles);
|
||||
Map<GroupKey, List<ResultFile>> resultHashMap = searchResults.toLinkedHashMap();
|
||||
searchResults.add(results);
|
||||
Map<GroupKey, List<Result>> resultHashMap = searchResults.toLinkedHashMap();
|
||||
SearchKey searchKey = new SearchKey(userName, filters, groupAttributeType, groupSortingType, fileSortingMethod);
|
||||
synchronized (searchCache) {
|
||||
searchCache.put(searchKey, resultHashMap);
|
||||
@ -298,10 +298,10 @@ public class FileSearch {
|
||||
*
|
||||
* @throws DiscoveryException
|
||||
*/
|
||||
private static void addAttributes(List<AttributeType> attrs, List<ResultFile> resultFiles, SleuthkitCase caseDb, CentralRepository centralRepoDb)
|
||||
private static void addAttributes(List<AttributeType> attrs, List<Result> results, SleuthkitCase caseDb, CentralRepository centralRepoDb)
|
||||
throws DiscoveryException {
|
||||
for (AttributeType attr : attrs) {
|
||||
attr.addAttributeToResultFiles(resultFiles, caseDb, centralRepoDb);
|
||||
attr.addAttributeToResultFiles(results, caseDb, centralRepoDb);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,9 +29,9 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
/**
|
||||
* Class used to sort ResultFiles using the supplied method.
|
||||
*/
|
||||
public class FileSorter implements Comparator<ResultFile> {
|
||||
public class FileSorter implements Comparator<Result> {
|
||||
|
||||
private final List<Comparator<ResultFile>> comparators = new ArrayList<>();
|
||||
private final List<Comparator<Result>> comparators = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Set up the sorter using the supplied sorting method. The sorting is
|
||||
@ -51,7 +51,7 @@ public class FileSorter implements Comparator<ResultFile> {
|
||||
comparators.add(getFileSizeComparator());
|
||||
break;
|
||||
case BY_FILE_TYPE:
|
||||
comparators.add(getFileTypeComparator());
|
||||
comparators.add(getTypeComparator());
|
||||
comparators.add(getMIMETypeComparator());
|
||||
break;
|
||||
case BY_FREQUENCY:
|
||||
@ -77,11 +77,11 @@ public class FileSorter implements Comparator<ResultFile> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(ResultFile file1, ResultFile file2) {
|
||||
public int compare(Result result1, Result result2) {
|
||||
|
||||
int result = 0;
|
||||
for (Comparator<ResultFile> comp : comparators) {
|
||||
result = comp.compare(file1, file2);
|
||||
for (Comparator<Result> comp : comparators) {
|
||||
result = comp.compare(result1, result2);
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
@ -96,8 +96,8 @@ public class FileSorter implements Comparator<ResultFile> {
|
||||
*
|
||||
* @return -1 if file1 has the lower data source ID, 0 if equal, 1 otherwise
|
||||
*/
|
||||
private static Comparator<ResultFile> getDataSourceComparator() {
|
||||
return (ResultFile file1, ResultFile file2) -> Long.compare(file1.getFirstInstance().getDataSourceObjectId(), file2.getFirstInstance().getDataSourceObjectId());
|
||||
private static Comparator<Result> getDataSourceComparator() {
|
||||
return (Result result1, Result result2) -> Long.compare(result1.getDataSourceObjectId(), result2.getDataSourceObjectId());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -106,8 +106,8 @@ public class FileSorter implements Comparator<ResultFile> {
|
||||
*
|
||||
* @return -1 if file1 has the lower FileType value, 0 if equal, 1 otherwise
|
||||
*/
|
||||
private static Comparator<ResultFile> getFileTypeComparator() {
|
||||
return (ResultFile file1, ResultFile file2) -> Integer.compare(file1.getFileType().getRanking(), file2.getFileType().getRanking());
|
||||
private static Comparator<Result> getTypeComparator() {
|
||||
return (Result result1, Result result2) -> Integer.compare(result1.getType().getRanking(), result2.getType().getRanking());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -118,9 +118,14 @@ public class FileSorter implements Comparator<ResultFile> {
|
||||
* @return -1 if file1 has the earliest combined keyword list name, 0 if
|
||||
* equal, 1 otherwise
|
||||
*/
|
||||
private static Comparator<ResultFile> getKeywordListNameComparator() {
|
||||
return (ResultFile file1, ResultFile file2) -> {
|
||||
private static Comparator<Result> getKeywordListNameComparator() {
|
||||
return (Result result1, Result result2) -> {
|
||||
// Put empty lists at the bottom
|
||||
if (result1.getType() == SearchData.Type.DOMAIN) {
|
||||
return 0;
|
||||
}
|
||||
ResultFile file1 = (ResultFile) result1;
|
||||
ResultFile file2 = (ResultFile) result2;
|
||||
if (file1.getKeywordListNames().isEmpty()) {
|
||||
if (file2.getKeywordListNames().isEmpty()) {
|
||||
return 0;
|
||||
@ -142,11 +147,16 @@ public class FileSorter implements Comparator<ResultFile> {
|
||||
* @return -1 if file1's path comes first alphabetically, 0 if equal, 1
|
||||
* otherwise
|
||||
*/
|
||||
private static Comparator<ResultFile> getParentPathComparator() {
|
||||
private static Comparator<Result> getParentPathComparator() {
|
||||
|
||||
return new Comparator<ResultFile>() {
|
||||
return new Comparator<Result>() {
|
||||
@Override
|
||||
public int compare(ResultFile file1, ResultFile file2) {
|
||||
public int compare(Result result1, Result result2) {
|
||||
if (result1.getType() == SearchData.Type.DOMAIN) {
|
||||
return 0;
|
||||
}
|
||||
ResultFile file1 = (ResultFile) result1;
|
||||
ResultFile file2 = (ResultFile) result2;
|
||||
String file1ParentPath;
|
||||
try {
|
||||
file1ParentPath = file1.getFirstInstance().getParent().getUniquePath();
|
||||
@ -170,8 +180,8 @@ public class FileSorter implements Comparator<ResultFile> {
|
||||
*
|
||||
* @return -1 if file1's rarity is lower than file2, 0 if equal, 1 otherwise
|
||||
*/
|
||||
private static Comparator<ResultFile> getFrequencyComparator() {
|
||||
return (ResultFile file1, ResultFile file2) -> Integer.compare(file1.getFrequency().getRanking(), file2.getFrequency().getRanking());
|
||||
private static Comparator<Result> getFrequencyComparator() {
|
||||
return (Result result1, Result result2) -> Integer.compare(result1.getFrequency().getRanking(), result2.getFrequency().getRanking());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -180,8 +190,13 @@ public class FileSorter implements Comparator<ResultFile> {
|
||||
* @return -1 if file1's MIME type comes before file2's, 0 if equal, 1
|
||||
* otherwise
|
||||
*/
|
||||
private static Comparator<ResultFile> getMIMETypeComparator() {
|
||||
return (ResultFile file1, ResultFile file2) -> compareStrings(file1.getFirstInstance().getMIMEType(), file2.getFirstInstance().getMIMEType());
|
||||
private static Comparator<Result> getMIMETypeComparator() {
|
||||
return (Result result1, Result result2) -> {
|
||||
if (result1.getType() == SearchData.Type.DOMAIN) {
|
||||
return 0;
|
||||
}
|
||||
return compareStrings(((ResultFile) result1).getFirstInstance().getMIMEType(), ((ResultFile) result2).getFirstInstance().getMIMEType());
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -189,9 +204,13 @@ public class FileSorter implements Comparator<ResultFile> {
|
||||
*
|
||||
* @return -1 if file1 is larger than file2, 0 if equal, 1 otherwise
|
||||
*/
|
||||
private static Comparator<ResultFile> getFileSizeComparator() {
|
||||
return (ResultFile file1, ResultFile file2) -> -1 * Long.compare(file1.getFirstInstance().getSize(), file2.getFirstInstance().getSize()) // Sort large to small
|
||||
;
|
||||
private static Comparator<Result> getFileSizeComparator() {
|
||||
return (Result result1, Result result2) -> {
|
||||
if (result1.getType() == SearchData.Type.DOMAIN) {
|
||||
return 0;
|
||||
}
|
||||
return -1 * Long.compare(((ResultFile) result1).getFirstInstance().getSize(), ((ResultFile) result2).getFirstInstance().getSize()); // Sort large to small
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -199,8 +218,13 @@ public class FileSorter implements Comparator<ResultFile> {
|
||||
*
|
||||
* @return -1 if file1 comes before file2, 0 if equal, 1 otherwise
|
||||
*/
|
||||
private static Comparator<ResultFile> getFileNameComparator() {
|
||||
return (ResultFile file1, ResultFile file2) -> compareStrings(file1.getFirstInstance().getName().toLowerCase(), file2.getFirstInstance().getName().toLowerCase());
|
||||
private static Comparator<Result> getFileNameComparator() {
|
||||
return (Result result1, Result result2) -> {
|
||||
if (result1.getType() == SearchData.Type.DOMAIN) {
|
||||
return 0;
|
||||
}
|
||||
return compareStrings(((ResultFile) result1).getFirstInstance().getName().toLowerCase(), (((ResultFile) result2).getFirstInstance().getName().toLowerCase()));
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -211,14 +235,21 @@ public class FileSorter implements Comparator<ResultFile> {
|
||||
*
|
||||
* @return -1 if file1 comes before file2, 0 if equal, 1 otherwise
|
||||
*/
|
||||
private static Comparator<ResultFile> getDefaultComparator() {
|
||||
return (ResultFile file1, ResultFile file2) -> {
|
||||
private static Comparator<Result> getDefaultComparator() {
|
||||
return (Result result1, Result result2) -> {
|
||||
// Compare file names and then object ID (to ensure a consistent sort)
|
||||
int result = getFileNameComparator().compare(file1, file2);
|
||||
if (result == 0) {
|
||||
return Long.compare(file1.getFirstInstance().getId(), file2.getFirstInstance().getId());
|
||||
if (result1.getType() == SearchData.Type.DOMAIN) {
|
||||
return getFrequencyComparator().compare(result1, result2);
|
||||
} else {
|
||||
ResultFile file1 = (ResultFile) result1;
|
||||
ResultFile file2 = (ResultFile) result2;
|
||||
int result = getFileNameComparator().compare(file1, file2);
|
||||
if (result == 0) {
|
||||
return Long.compare(file1.getFirstInstance().getId(), file2.getFirstInstance().getId());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@ -234,6 +265,7 @@ public class FileSorter implements Comparator<ResultFile> {
|
||||
String string1 = s1 == null ? "" : s1;
|
||||
String string2 = s2 == null ? "" : s2;
|
||||
return string1.compareTo(string2);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -247,7 +279,7 @@ public class FileSorter implements Comparator<ResultFile> {
|
||||
"FileSorter.SortingMethod.frequency.displayName=Central Repo Frequency",
|
||||
"FileSorter.SortingMethod.keywordlist.displayName=Keyword List Names",
|
||||
"FileSorter.SortingMethod.fullPath.displayName=Full Path"})
|
||||
public enum SortingMethod {
|
||||
public enum SortingMethod {
|
||||
BY_FILE_NAME(new ArrayList<>(),
|
||||
Bundle.FileSorter_SortingMethod_filename_displayName()), // Sort alphabetically by file name
|
||||
BY_DATA_SOURCE(new ArrayList<>(),
|
||||
|
@ -30,7 +30,7 @@ public class Group implements Comparable<Group> {
|
||||
|
||||
private final Group.GroupSortingAlgorithm groupSortingType;
|
||||
private final DiscoveryKeyUtils.GroupKey groupKey;
|
||||
private final List<ResultFile> files;
|
||||
private final List<Result> results;
|
||||
private final String displayName;
|
||||
|
||||
/**
|
||||
@ -42,21 +42,23 @@ public class Group implements Comparable<Group> {
|
||||
public Group(Group.GroupSortingAlgorithm groupSortingType, DiscoveryKeyUtils.GroupKey groupKey) {
|
||||
this.groupSortingType = groupSortingType;
|
||||
this.groupKey = groupKey;
|
||||
files = new ArrayList<>();
|
||||
results = new ArrayList<>();
|
||||
this.displayName = groupKey.getDisplayName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a ResultFile to the group. Will not be sorted at this time.
|
||||
* Add a Result to the group. Will not be sorted at this time.
|
||||
*
|
||||
* @param file The ResultFile to add to the FileGroup
|
||||
* @param result The Result to add to the FileGroup
|
||||
*/
|
||||
void addFile(ResultFile file) {
|
||||
if (files.contains(file)) {
|
||||
ResultFile existingCopy = files.get(files.indexOf(file)); //get the copy of this which exists in the list
|
||||
existingCopy.addDuplicate(file.getFirstInstance());
|
||||
void addResult(Result result) {
|
||||
if (result.getType() != SearchData.Type.DOMAIN && results.contains(result)) {
|
||||
//dedupe files and show instances
|
||||
ResultFile existingCopy = (ResultFile)results.get(results.indexOf(result)); //get the copy of this which exists in the list
|
||||
existingCopy.addDuplicate(((ResultFile)result).getFirstInstance());
|
||||
} else {
|
||||
files.add(file);
|
||||
//Domains and non files are not being deduped currently
|
||||
results.add(result);
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,7 +84,7 @@ public class Group implements Comparable<Group> {
|
||||
* Sort all the files in the group
|
||||
*/
|
||||
public void sortFiles(FileSorter sorter) {
|
||||
Collections.sort(files, sorter);
|
||||
Collections.sort(results, sorter);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -128,8 +130,8 @@ public class Group implements Comparable<Group> {
|
||||
* @return -1 if group1 should be displayed before group2, 1 otherwise
|
||||
*/
|
||||
private static int compareGroupsBySize(Group group1, Group group2) {
|
||||
if (group1.getFiles().size() != group2.getFiles().size()) {
|
||||
return -1 * Long.compare(group1.getFiles().size(), group2.getFiles().size()); // High to low
|
||||
if (group1.getResults().size() != group2.getResults().size()) {
|
||||
return -1 * Long.compare(group1.getResults().size(), group2.getResults().size()); // High to low
|
||||
} else {
|
||||
// If the groups have the same size, fall through to the BY_GROUP_NAME sorting
|
||||
return compareGroupsByGroupKey(group1, group2);
|
||||
@ -168,8 +170,8 @@ public class Group implements Comparable<Group> {
|
||||
*
|
||||
* @return List of ResultFile objects
|
||||
*/
|
||||
public List<ResultFile> getFiles() {
|
||||
return Collections.unmodifiableList(files);
|
||||
public List<Result> getResults() {
|
||||
return Collections.unmodifiableList(results);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -18,9 +18,67 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.discovery.search;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
|
||||
/**
|
||||
* Interface implemented by all types of results.
|
||||
*/
|
||||
public interface Result {
|
||||
public abstract class Result {
|
||||
|
||||
private SearchData.Frequency frequency;
|
||||
private final List<String> tagNames = new ArrayList<>();
|
||||
|
||||
public abstract long getDataSourceObjectId();
|
||||
|
||||
/**
|
||||
* Get the frequency of this result in the central repository.
|
||||
*
|
||||
* @return The Frequency enum.
|
||||
*/
|
||||
public SearchData.Frequency getFrequency() {
|
||||
return frequency;
|
||||
}
|
||||
|
||||
public abstract TskData.FileKnown getKnown();
|
||||
|
||||
/**
|
||||
* Set the frequency of this result in the central repository.
|
||||
*
|
||||
* @param frequency The frequency of the result as an enum.
|
||||
*/
|
||||
final public void setFrequency(SearchData.Frequency frequency) {
|
||||
this.frequency = frequency;
|
||||
}
|
||||
|
||||
public abstract Content getDataSource() throws TskCoreException;
|
||||
|
||||
public abstract SearchData.Type getType();
|
||||
|
||||
/**
|
||||
* Add a tag name that matched this file.
|
||||
*
|
||||
* @param tagName
|
||||
*/
|
||||
public void addTagName(String tagName) {
|
||||
if (!tagNames.contains(tagName)) {
|
||||
tagNames.add(tagName);
|
||||
}
|
||||
|
||||
// Sort the list so the getTagNames() will be consistent regardless of the order added
|
||||
Collections.sort(tagNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tag names for this file
|
||||
*
|
||||
* @return the tag names that matched this file.
|
||||
*/
|
||||
public List<String> getTagNames() {
|
||||
return Collections.unmodifiableList(tagNames);
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,34 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.discovery.search;
|
||||
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
|
||||
public class ResultDomain extends Result {
|
||||
|
||||
ResultDomain() {
|
||||
this.setFrequency(SearchData.Frequency.UNKNOWN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDataSourceObjectId() {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public Content getDataSource() throws TskCoreException {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public TskData.FileKnown getKnown() {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public SearchData.Type getType() {
|
||||
return SearchData.Type.DOMAIN;
|
||||
}
|
||||
|
||||
public class ResultDomain implements Result {
|
||||
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import static org.sleuthkit.autopsy.discovery.search.SearchData.Type.OTHER;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.ContentTag;
|
||||
import org.sleuthkit.datamodel.HashUtility;
|
||||
import org.sleuthkit.datamodel.Tag;
|
||||
@ -40,13 +41,11 @@ import org.sleuthkit.datamodel.TskData;
|
||||
/**
|
||||
* Container for files that holds all necessary data for grouping and sorting.
|
||||
*/
|
||||
public class ResultFile implements Result{
|
||||
public class ResultFile extends Result {
|
||||
|
||||
private final static Logger logger = Logger.getLogger(ResultFile.class.getName());
|
||||
private SearchData.Frequency frequency;
|
||||
private final List<String> keywordListNames;
|
||||
private final List<String> hashSetNames;
|
||||
private final List<String> tagNames;
|
||||
private final List<String> interestingSetNames;
|
||||
private final List<String> objectDetectedNames;
|
||||
private final List<AbstractFile> instances = new ArrayList<>();
|
||||
@ -73,33 +72,13 @@ public class ResultFile implements Result{
|
||||
deleted = true;
|
||||
}
|
||||
updateScoreAndDescription(abstractFile);
|
||||
this.frequency = SearchData.Frequency.UNKNOWN;
|
||||
keywordListNames = new ArrayList<>();
|
||||
hashSetNames = new ArrayList<>();
|
||||
tagNames = new ArrayList<>();
|
||||
interestingSetNames = new ArrayList<>();
|
||||
objectDetectedNames = new ArrayList<>();
|
||||
fileType = fromMIMEtype(abstractFile.getMIMEType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the frequency of this file in the central repository
|
||||
*
|
||||
* @return The Frequency enum
|
||||
*/
|
||||
public SearchData.Frequency getFrequency() {
|
||||
return frequency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the frequency of this file from the central repository
|
||||
*
|
||||
* @param frequency The frequency of the file as an enum
|
||||
*/
|
||||
public void setFrequency(SearchData.Frequency frequency) {
|
||||
this.frequency = frequency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an AbstractFile to the list of files which are instances of this
|
||||
* file.
|
||||
@ -218,29 +197,6 @@ public class ResultFile implements Result{
|
||||
return Collections.unmodifiableList(hashSetNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a tag name that matched this file.
|
||||
*
|
||||
* @param tagName
|
||||
*/
|
||||
public void addTagName(String tagName) {
|
||||
if (!tagNames.contains(tagName)) {
|
||||
tagNames.add(tagName);
|
||||
}
|
||||
|
||||
// Sort the list so the getTagNames() will be consistent regardless of the order added
|
||||
Collections.sort(tagNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tag names for this file
|
||||
*
|
||||
* @return the tag names that matched this file.
|
||||
*/
|
||||
public List<String> getTagNames() {
|
||||
return Collections.unmodifiableList(tagNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an interesting file set name that matched this file.
|
||||
*
|
||||
@ -300,7 +256,7 @@ public class ResultFile implements Result{
|
||||
public String toString() {
|
||||
return getFirstInstance().getName() + "(" + getFirstInstance().getId() + ") - "
|
||||
+ getFirstInstance().getSize() + ", " + getFirstInstance().getParentPath() + ", "
|
||||
+ getFirstInstance().getDataSourceObjectId() + ", " + frequency.toString() + ", "
|
||||
+ getFirstInstance().getDataSourceObjectId() + ", " + getFrequency().toString() + ", "
|
||||
+ String.join(",", keywordListNames) + ", " + getFirstInstance().getMIMEType();
|
||||
}
|
||||
|
||||
@ -397,4 +353,24 @@ public class ResultFile implements Result{
|
||||
}
|
||||
return OTHER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDataSourceObjectId() {
|
||||
return getFirstInstance().getDataSourceObjectId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Content getDataSource() throws TskCoreException {
|
||||
return getFirstInstance().getDataSource();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TskData.FileKnown getKnown() {
|
||||
return getFirstInstance().getKnown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return fileType;
|
||||
}
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ public class SearchFiltering {
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
static List<ResultFile> runQueries(List<AbstractFilter> filters, SleuthkitCase caseDb, CentralRepository centralRepoDb) throws DiscoveryException {
|
||||
static List<Result> runQueries(List<AbstractFilter> filters, SleuthkitCase caseDb, CentralRepository centralRepoDb) throws DiscoveryException {
|
||||
if (caseDb == null) {
|
||||
throw new DiscoveryException("Case DB parameter is null"); // NON-NLS
|
||||
}
|
||||
@ -94,9 +94,9 @@ public class SearchFiltering {
|
||||
* @throws TskCoreException
|
||||
* @throws DiscoveryException
|
||||
*/
|
||||
private static List<ResultFile> getResultList(List<AbstractFilter> filters, String combinedQuery, SleuthkitCase caseDb, CentralRepository centralRepoDb) throws TskCoreException, DiscoveryException {
|
||||
private static List<Result> getResultList(List<AbstractFilter> filters, String combinedQuery, SleuthkitCase caseDb, CentralRepository centralRepoDb) throws TskCoreException, DiscoveryException {
|
||||
// Get all matching abstract files
|
||||
List<ResultFile> resultList = new ArrayList<>();
|
||||
List<Result> resultList = new ArrayList<>();
|
||||
List<AbstractFile> sqlResults = caseDb.findAllFilesWhere(combinedQuery);
|
||||
|
||||
// If there are no results, return now
|
||||
@ -329,7 +329,7 @@ public class SearchFiltering {
|
||||
desc += searchTerm.getSearchStr() + Bundle.SearchFiltering_ParentFilter_substring();
|
||||
}
|
||||
if (searchTerm.isIncluded()) {
|
||||
desc += Bundle.SearchFiltering_ParentFilter_included();
|
||||
desc += Bundle.SearchFiltering_ParentFilter_included();
|
||||
} else {
|
||||
desc += Bundle.SearchFiltering_ParentFilter_excluded();
|
||||
}
|
||||
@ -393,7 +393,7 @@ public class SearchFiltering {
|
||||
* A filter for specifying keyword list names. A file must contain a keyword
|
||||
* from one of the given lists to pass.
|
||||
*/
|
||||
public static class KeywordListFilter extends AbstractFilter {
|
||||
public static class KeywordListFilter extends AbstractFilter {
|
||||
|
||||
private final List<String> listNames;
|
||||
|
||||
@ -514,7 +514,7 @@ public class SearchFiltering {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ResultFile> applyAlternateFilter(List<ResultFile> currentResults, SleuthkitCase caseDb,
|
||||
public List<Result> applyAlternateFilter(List<Result> currentResults, SleuthkitCase caseDb,
|
||||
CentralRepository centralRepoDb) throws DiscoveryException {
|
||||
|
||||
// We have to have run some kind of SQL filter before getting to this point,
|
||||
@ -528,8 +528,8 @@ public class SearchFiltering {
|
||||
freqAttr.addAttributeToResultFiles(currentResults, caseDb, centralRepoDb);
|
||||
|
||||
// If the frequency matches the filter, add the file to the results
|
||||
List<ResultFile> frequencyResults = new ArrayList<>();
|
||||
for (ResultFile file : currentResults) {
|
||||
List<Result> frequencyResults = new ArrayList<>();
|
||||
for (Result file : currentResults) {
|
||||
if (frequencies.contains(file.getFrequency())) {
|
||||
frequencyResults.add(file);
|
||||
}
|
||||
@ -834,7 +834,7 @@ public class SearchFiltering {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ResultFile> applyAlternateFilter(List<ResultFile> currentResults, SleuthkitCase caseDb,
|
||||
public List<Result> applyAlternateFilter(List<Result> currentResults, SleuthkitCase caseDb,
|
||||
CentralRepository centralRepoDb) throws DiscoveryException {
|
||||
|
||||
if (centralRepoDb == null) {
|
||||
@ -848,18 +848,21 @@ public class SearchFiltering {
|
||||
}
|
||||
|
||||
// The matching files
|
||||
List<ResultFile> notableResults = new ArrayList<>();
|
||||
List<Result> notableResults = new ArrayList<>();
|
||||
|
||||
try {
|
||||
CorrelationAttributeInstance.Type type = CorrelationAttributeInstance.getDefaultCorrelationTypes().get(CorrelationAttributeInstance.FILES_TYPE_ID);
|
||||
|
||||
for (ResultFile file : currentResults) {
|
||||
for (Result result : currentResults) {
|
||||
ResultFile file = (ResultFile) result;
|
||||
if (result.getType() == SearchData.Type.DOMAIN) {
|
||||
break;
|
||||
}
|
||||
if (file.getFirstInstance().getMd5Hash() != null && !file.getFirstInstance().getMd5Hash().isEmpty()) {
|
||||
|
||||
// Check if this file hash is marked as notable in the CR
|
||||
String value = file.getFirstInstance().getMd5Hash();
|
||||
if (centralRepoDb.getCountArtifactInstancesKnownBad(type, value) > 0) {
|
||||
notableResults.add(file);
|
||||
notableResults.add(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -927,7 +930,7 @@ public class SearchFiltering {
|
||||
return result;
|
||||
}
|
||||
|
||||
private SearchFiltering(){
|
||||
private SearchFiltering() {
|
||||
// Class should not be instantiated
|
||||
}
|
||||
}
|
||||
|
@ -72,15 +72,15 @@ class SearchResults {
|
||||
*
|
||||
* @param files The list of ResultFiles to add.
|
||||
*/
|
||||
void add(List<ResultFile> files) {
|
||||
for (ResultFile file : files) {
|
||||
void add(List<Result> results) {
|
||||
for (Result result : results) {
|
||||
// Add the file to the appropriate group, creating it if necessary
|
||||
GroupKey groupKey = attrType.getGroupKey(file);
|
||||
GroupKey groupKey = attrType.getGroupKey(result);
|
||||
|
||||
if (!groupMap.containsKey(groupKey)) {
|
||||
groupMap.put(groupKey, new Group(groupSortingType, groupKey));
|
||||
}
|
||||
groupMap.get(groupKey).addFile(file);
|
||||
groupMap.get(groupKey).addResult(result);
|
||||
}
|
||||
}
|
||||
|
||||
@ -102,25 +102,25 @@ class SearchResults {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String result = "";
|
||||
String resultString = "";
|
||||
if (groupList == null) {
|
||||
return result;
|
||||
return resultString;
|
||||
}
|
||||
|
||||
long count = 0;
|
||||
for (Group group : groupList) {
|
||||
result += group.getDisplayName() + "\n";
|
||||
resultString += group.getDisplayName() + "\n";
|
||||
|
||||
for (ResultFile file : group.getFiles()) {
|
||||
result += " " + file.toString() + "\n";
|
||||
for (Result result : group.getResults()) {
|
||||
resultString += " " + result.toString() + "\n";
|
||||
count++;
|
||||
if (count > MAX_OUTPUT_FILES) {
|
||||
result += "(truncated)";
|
||||
return result;
|
||||
resultString += "(truncated)";
|
||||
return resultString;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return resultString;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -129,7 +129,7 @@ class SearchResults {
|
||||
* @return The list of group names.
|
||||
*/
|
||||
List<String> getGroupNamesWithCounts() {
|
||||
return groupList.stream().map(p -> p.getDisplayName() + " (" + p.getFiles().size() + ")").collect(Collectors.toList());
|
||||
return groupList.stream().map(p -> p.getDisplayName() + " (" + p.getResults().size() + ")").collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -139,13 +139,13 @@ class SearchResults {
|
||||
*
|
||||
* @return The list of result files.
|
||||
*/
|
||||
List<ResultFile> getResultFilesInGroup(String groupName) {
|
||||
List<Result> getResultFilesInGroup(String groupName) {
|
||||
if (groupName != null) {
|
||||
final String modifiedGroupName = groupName.replaceAll(" \\([0-9]+\\)$", "");
|
||||
|
||||
java.util.Optional<Group> fileGroup = groupList.stream().filter(p -> p.getDisplayName().equals(modifiedGroupName)).findFirst();
|
||||
if (fileGroup.isPresent()) {
|
||||
return fileGroup.get().getFiles();
|
||||
java.util.Optional<Group> group = groupList.stream().filter(p -> p.getDisplayName().equals(modifiedGroupName)).findFirst();
|
||||
if (group.isPresent()) {
|
||||
return group.get().getResults();
|
||||
}
|
||||
}
|
||||
return new ArrayList<>();
|
||||
@ -156,15 +156,15 @@ class SearchResults {
|
||||
*
|
||||
* @return The grouped and sorted results.
|
||||
*/
|
||||
Map<GroupKey, List<ResultFile>> toLinkedHashMap() throws DiscoveryException {
|
||||
Map<GroupKey, List<ResultFile>> map = new LinkedHashMap<>();
|
||||
Map<GroupKey, List<Result>> toLinkedHashMap() throws DiscoveryException {
|
||||
Map<GroupKey, List<Result>> map = new LinkedHashMap<>();
|
||||
|
||||
// Sort the groups and files
|
||||
sortGroupsAndFiles();
|
||||
|
||||
// groupList is sorted and a LinkedHashMap will preserve that order.
|
||||
for (Group group : groupList) {
|
||||
map.put(group.getGroupKey(), group.getFiles());
|
||||
map.put(group.getGroupKey(), group.getResults());
|
||||
}
|
||||
|
||||
return map;
|
||||
|
@ -232,6 +232,7 @@ final class DiscoveryUiUtils {
|
||||
* Helper method to display an error message when the results of the
|
||||
* Discovery Top component may be incomplete.
|
||||
*/
|
||||
@NbBundle.Messages({"DiscoveryUiUtils.resultsIncomplete.text=Discovery results may be incomplete"})
|
||||
static void displayErrorMessage(DiscoveryDialog dialog) {
|
||||
//check if modules run and assemble message
|
||||
try {
|
||||
@ -258,7 +259,7 @@ final class DiscoveryUiUtils {
|
||||
messageScrollPane.setMaximumSize(new Dimension(600, 100));
|
||||
messageScrollPane.setPreferredSize(new Dimension(600, 100));
|
||||
messageScrollPane.setViewportView(messageTextPane);
|
||||
JOptionPane.showMessageDialog(dialog, messageScrollPane, Bundle.OpenDiscoveryAction_resultsIncomplete_text(), JOptionPane.PLAIN_MESSAGE);
|
||||
JOptionPane.showMessageDialog(dialog, messageScrollPane, Bundle.DiscoveryUiUtils_resultsIncomplete_text(), JOptionPane.PLAIN_MESSAGE);
|
||||
}
|
||||
} catch (NoCurrentCaseException | TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Exception while determining which modules have been run for Discovery", ex);
|
||||
|
@ -62,8 +62,6 @@ public final class OpenDiscoveryAction extends CallableSystemAction implements P
|
||||
return Case.isCaseOpen();
|
||||
}
|
||||
|
||||
@NbBundle.Messages({"OpenDiscoveryAction.resultsIncomplete.text=Discovery results may be incomplete"})
|
||||
|
||||
@Override
|
||||
public void performAction() {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
|
@ -34,7 +34,7 @@ import org.sleuthkit.autopsy.discovery.search.FileSearch;
|
||||
import org.sleuthkit.autopsy.discovery.search.SearchData;
|
||||
import org.sleuthkit.autopsy.discovery.search.DiscoveryException;
|
||||
import org.sleuthkit.autopsy.discovery.search.FileSorter;
|
||||
import org.sleuthkit.autopsy.discovery.search.ResultFile;
|
||||
import org.sleuthkit.autopsy.discovery.search.Result;
|
||||
|
||||
/**
|
||||
* SwingWorker to retrieve the contents of a page.
|
||||
@ -52,7 +52,7 @@ final class PageWorker extends SwingWorker<Void, Void> {
|
||||
private final int pageSize;
|
||||
private final SearchData.Type resultType;
|
||||
private final CentralRepository centralRepo;
|
||||
private final List<ResultFile> results = new ArrayList<>();
|
||||
private final List<Result> results = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Construct a new PageWorker.
|
||||
|
Loading…
x
Reference in New Issue
Block a user