6610 refactor and move search related discovery files

This commit is contained in:
William Schaefer 2020-08-17 13:42:39 -04:00
parent 881b31bb60
commit 3eee575d66
50 changed files with 1203 additions and 1197 deletions

View File

@ -1,65 +0,0 @@
FileSearchDialog.jLabel1.text=File Type
FileSearchDialog.dsCheckBox.text=Data source
FileSearchDialog.cancelButton.text=Cancel
FileSearchDialog.freqCheckBox.text=CR Frequency
FileSearchDialog.sizeCheckBox.text=Size
FileSearchDialog.kwCheckBox.text=Keyword
FileSearchDialog.addParentButton.text=Add
FileSearchDialog.deleteParentButton.text=Delete
FileSearchDialog.parentFullRadioButton.text=Full
FileSearchDialog.parentSubstringRadioButton.text=Substring
FileSearchDialog.jLabel2.text=(All will be used)
FileSearchDialog.jLabel3.text=Group by attribute:
FileSearchDialog.jLabel4.text=Order groups by:
FileSearchDialog.orderAttrRadioButton.text=Attribute
FileSearchDialog.orderSizeRadioButton.text=Group Size
FileSearchDialog.jLabel5.text=Order files by:
FileSearchDialog.parentCheckBox.text=Parent
FileSearchPanel.sortingPanel.border.title=Grouping
FileSearchPanel.addButton.text=Add
FileSearchPanel.substringRadioButton.text=Substring
FileSearchPanel.fullRadioButton.text=Full
FileSearchPanel.parentCheckbox.text=Parent Folder:
FileSearchPanel.keywordCheckbox.text=Keyword:
FileSearchPanel.crFrequencyCheckbox.text=Past Occurrences:
FileSearchPanel.dataSourceCheckbox.text=Data Source:
FileSearchPanel.sizeCheckbox.text=File Size:
FileSearchPanel.orderGroupsByLabel.text=Order Groups By:
FileSearchPanel.filtersScrollPane.border.title=Filters
FileSearchPanel.parentLabel.text=(All will be used)
FileSearchPanel.deleteButton.text=Delete
FileSearchPanel.orderByLabel.text=Order Within Groups By:
FileSearchPanel.groupByLabel.text=Group By:
FileSearchDialog.searchButton.text=Search
FileSearchDialog.hashCheckBox.text=Hash Set
FileSearchDialog.intCheckBox.text=Interesting Items
FileSearchDialog.tagsCheckBox.text=Tags
FileSearchDialog.objCheckBox.text=Objects
FileSearchDialog.exifCheckBox.text=Must contain EXIF data
FileSearchDialog.notableCheckBox.text=Must have been tagged as notable
FileSearchDialog.scoreCheckBox.text=Has score
FileSearchPanel.hashSetCheckbox.text=Hash Set:
FileSearchPanel.tagsCheckbox.text=Tag:
FileSearchPanel.interestingItemsCheckbox.text=Interesting Item:
FileSearchPanel.scoreCheckbox.text=Has Score:
FileSearchPanel.notableCheckbox.text=Must have been tagged as notable
FileSearchPanel.objectsCheckbox.text=Object Detected:
DiscoveryExtractAction.title.extractFiles.text=Extract File
FileSearchPanel.includeRadioButton.text=Include
FileSearchPanel.excludeRadioButton.text=Exclude
FileSearchPanel.knownFilesCheckbox.toolTipText=
FileSearchPanel.knownFilesCheckbox.text=Hide known files
FileSearchPanel.stepThreeLabel.text=Step 3: Choose display settings
FileSearchPanel.userCreatedCheckbox.text=Possibly User Created
UserCreatedFilterPanel.userCreatedCheckbox.text=Possibly User Created
InterestingItemFilterPanel.interestingItemsCheckbox.text=Interesting Item:
ParentFolderFilterPanel.parentCheckbox.text=Parent Folder:
ParentFolderFilterPanel.deleteButton.text=Delete
ParentFolderFilterPanel.excludeRadioButton.text=Exclude
ParentFolderFilterPanel.includeRadioButton.text=Include
ParentFolderFilterPanel.substringRadioButton.text=Substring
ParentFolderFilterPanel.fullRadioButton.text=Full
ParentFolderFilterPanel.parentLabel.text=(All will be used)
ParentFolderFilterPanel.addButton.text=Add
ObjectDetectedFilterPanel.text=Object Detected:
DomainUniquenessFilterPanel.domainUniquenessCheckbox.text=Domain Uniqueness:

View File

@ -16,19 +16,17 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.discovery.ui; package org.sleuthkit.autopsy.discovery.search;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
import org.sleuthkit.autopsy.discovery.FileSearchException;
import org.sleuthkit.autopsy.discovery.ResultFile;
import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.SleuthkitCase;
/** /**
* Base class for the filters. * Base class for the filters.
*/ */
abstract class AbstractFilter { public abstract class AbstractFilter {
/** /**
* Returns part of a query on the table that can be AND-ed with * Returns part of a query on the table that can be AND-ed with
@ -37,7 +35,7 @@ abstract class AbstractFilter {
* @return the SQL query or an empty string if there is no SQL query for * @return the SQL query or an empty string if there is no SQL query for
* this filter. * this filter.
*/ */
abstract String getWhereClause(); public abstract String getWhereClause();
/** /**
* Indicates whether this filter needs to use the secondary, non-SQL method * Indicates whether this filter needs to use the secondary, non-SQL method
@ -45,7 +43,7 @@ abstract class AbstractFilter {
* *
* @return false by default * @return false by default
*/ */
boolean useAlternateFilter() { public boolean useAlternateFilter() {
return false; return false;
} }
@ -63,7 +61,7 @@ abstract class AbstractFilter {
* *
* @throws FileSearchException * @throws FileSearchException
*/ */
List<ResultFile> applyAlternateFilter(List<ResultFile> currentResults, SleuthkitCase caseDb, public List<ResultFile> applyAlternateFilter(List<ResultFile> currentResults, SleuthkitCase caseDb,
CentralRepository centralRepoDb) throws FileSearchException { CentralRepository centralRepoDb) throws FileSearchException {
return new ArrayList<>(); return new ArrayList<>();
} }
@ -73,5 +71,5 @@ abstract class AbstractFilter {
* *
* @return A description of the filter * @return A description of the filter
*/ */
abstract String getDesc(); public abstract String getDesc();
} }

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.discovery; package org.sleuthkit.autopsy.discovery.search;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@ -29,22 +29,22 @@ import org.sleuthkit.datamodel.BlackboardArtifact;
/** /**
* Utility enums for searches made for attributes with Discovery. * Utility enums for searches made for attributes with Discovery.
*/ */
public class AttributeSearchData extends SearchData { public class AttributeSearchData implements SearchData {
private static final Set<BlackboardArtifact.ARTIFACT_TYPE> DOMAIN_ARTIFACT_TYPES = EnumSet.of(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK, BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE, BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE, BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY, BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY, BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG); private static final Set<BlackboardArtifact.ARTIFACT_TYPE> DOMAIN_ARTIFACT_TYPES = EnumSet.of(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK, BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE, BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE, BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY, BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY, BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG);
@Override @Override
ResultType getResultType() { public ResultType getResultType() {
return ResultType.ATTRIBUTE; return ResultType.ATTRIBUTE;
} }
/** /**
* Enum representing the attribute type. * Enum representing the attribute type.
*/ */
@NbBundle.Messages({ @NbBundle.Messages({
"AttributeSearchData.AttributeType.Domain.displayName=Domain", "AttributeSearchData.AttributeType.Domain.displayName=Domain",
"AttributeSearchData.AttributeType.Other.displayName=Other"}) "AttributeSearchData.AttributeType.Other.displayName=Other"})
enum AttributeType { public enum AttributeType {
DOMAIN(0, Bundle.AttributeSearchData_AttributeType_Domain_displayName(), DOMAIN_ARTIFACT_TYPES), DOMAIN(0, Bundle.AttributeSearchData_AttributeType_Domain_displayName(), DOMAIN_ARTIFACT_TYPES),
OTHER(1, Bundle.AttributeSearchData_AttributeType_Other_displayName(), new HashSet<>()); OTHER(1, Bundle.AttributeSearchData_AttributeType_Other_displayName(), new HashSet<>());
@ -64,7 +64,7 @@ public class AttributeSearchData extends SearchData {
* *
* @return Collection of BlackboardArtifact types. * @return Collection of BlackboardArtifact types.
*/ */
Collection<BlackboardArtifact.ARTIFACT_TYPE> getBlackboardTypes() { public Collection<BlackboardArtifact.ARTIFACT_TYPE> getBlackboardTypes() {
return Collections.unmodifiableCollection(artifactTypes); return Collections.unmodifiableCollection(artifactTypes);
} }
@ -78,11 +78,11 @@ public class AttributeSearchData extends SearchData {
* *
* @return the rank (lower should be displayed first) * @return the rank (lower should be displayed first)
*/ */
int getRanking() { public int getRanking() {
return ranking; return ranking;
} }
static AttributeType fromBlackboardArtifact(final BlackboardArtifact.ARTIFACT_TYPE type) { public static AttributeType fromBlackboardArtifact(final BlackboardArtifact.ARTIFACT_TYPE type) {
switch (type) { switch (type) {
case TSK_WEB_BOOKMARK: case TSK_WEB_BOOKMARK:
return DOMAIN; return DOMAIN;

View File

@ -16,23 +16,22 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.discovery; package org.sleuthkit.autopsy.discovery.search;
import org.sleuthkit.autopsy.discovery.ui.AbstractFilter;
import com.google.common.eventbus.EventBus; import com.google.common.eventbus.EventBus;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.sleuthkit.autopsy.discovery.AttributeSearchData.AttributeType; import org.sleuthkit.autopsy.discovery.search.AttributeSearchData.AttributeType;
import org.sleuthkit.autopsy.discovery.FileSearch.GroupKey; import org.sleuthkit.autopsy.discovery.search.DiscoveryKeyUtils.GroupKey;
import org.sleuthkit.autopsy.discovery.FileSearchData.FileType; import org.sleuthkit.autopsy.discovery.search.FileSearchData.FileType;
import org.sleuthkit.autopsy.discovery.SearchData.ResultType; import org.sleuthkit.autopsy.discovery.search.SearchData.ResultType;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
/** /**
* Class to handle event bus and events for discovery tool. * Class to handle event bus and events for discovery tool.
*/ */
final class DiscoveryEventUtils { public final class DiscoveryEventUtils {
private final static EventBus discoveryEventBus = new EventBus(); private final static EventBus discoveryEventBus = new EventBus();
@ -41,7 +40,7 @@ final class DiscoveryEventUtils {
* *
* @return The discovery event bus. * @return The discovery event bus.
*/ */
static EventBus getDiscoveryEventBus() { public static EventBus getDiscoveryEventBus() {
return discoveryEventBus; return discoveryEventBus;
} }
@ -55,7 +54,7 @@ final class DiscoveryEventUtils {
/** /**
* Event to signal the start of a search being performed. * Event to signal the start of a search being performed.
*/ */
static final class SearchStartedEvent { public static final class SearchStartedEvent {
private final ResultType resultType; private final ResultType resultType;
private final FileType fileType; private final FileType fileType;
@ -66,7 +65,7 @@ final class DiscoveryEventUtils {
* *
* @param type The type of file the search event is for. * @param type The type of file the search event is for.
*/ */
SearchStartedEvent(ResultType resultType, FileType fileType, AttributeType attributeType) { public SearchStartedEvent(ResultType resultType, FileType fileType, AttributeType attributeType) {
this.resultType = resultType; this.resultType = resultType;
this.fileType = fileType; this.fileType = fileType;
this.attributeType = attributeType; this.attributeType = attributeType;
@ -77,7 +76,7 @@ final class DiscoveryEventUtils {
* *
* @return The result type, either FILES, or ATTRIBUTES. * @return The result type, either FILES, or ATTRIBUTES.
*/ */
ResultType getResultType() { public ResultType getResultType() {
return resultType; return resultType;
} }
@ -86,7 +85,7 @@ final class DiscoveryEventUtils {
* *
* @return The type of files being searched for. * @return The type of files being searched for.
*/ */
FileType getFileType() { public FileType getFileType() {
return fileType; return fileType;
} }
@ -95,7 +94,7 @@ final class DiscoveryEventUtils {
* *
* @return The type of attribute being searched for. * @return The type of attribute being searched for.
*/ */
AttributeType getAttributeType() { public AttributeType getAttributeType() {
return attributeType; return attributeType;
} }
} }
@ -103,12 +102,12 @@ final class DiscoveryEventUtils {
/** /**
* Event to signal that the Instances list should have selection cleared. * Event to signal that the Instances list should have selection cleared.
*/ */
static final class ClearInstanceSelectionEvent { public static final class ClearInstanceSelectionEvent {
/** /**
* Construct a new ClearInstanceSelectionEvent. * Construct a new ClearInstanceSelectionEvent.
*/ */
ClearInstanceSelectionEvent() { public ClearInstanceSelectionEvent() {
//no arg constructor //no arg constructor
} }
} }
@ -116,21 +115,21 @@ final class DiscoveryEventUtils {
/** /**
* Event to signal that the Instances list should be populated. * Event to signal that the Instances list should be populated.
*/ */
static final class PopulateInstancesListEvent { public static final class PopulateInstancesListEvent {
private final List<AbstractFile> instances; private final List<AbstractFile> instances;
/** /**
* Construct a new PopulateInstancesListEvent. * Construct a new PopulateInstancesListEvent.
*/ */
PopulateInstancesListEvent(List<AbstractFile> files) { public PopulateInstancesListEvent(List<AbstractFile> files) {
instances = files; instances = files;
} }
/** /**
* @return the instances * @return the instances
*/ */
List<AbstractFile> getInstances() { public List<AbstractFile> getInstances() {
return Collections.unmodifiableList(instances); return Collections.unmodifiableList(instances);
} }
} }
@ -138,7 +137,7 @@ final class DiscoveryEventUtils {
/** /**
* Event to signal the completion of a search being performed. * Event to signal the completion of a search being performed.
*/ */
static final class SearchCompleteEvent { public static final class SearchCompleteEvent {
private final Map<GroupKey, Integer> groupMap; private final Map<GroupKey, Integer> groupMap;
private final List<AbstractFilter> searchFilters; private final List<AbstractFilter> searchFilters;
@ -157,7 +156,7 @@ final class DiscoveryEventUtils {
* @param groupSort The sorting algorithm used for groups. * @param groupSort The sorting algorithm used for groups.
* @param fileSortMethod The sorting method used for files. * @param fileSortMethod The sorting method used for files.
*/ */
SearchCompleteEvent(Map<GroupKey, Integer> groupMap, List<AbstractFilter> searchfilters, public SearchCompleteEvent(Map<GroupKey, Integer> groupMap, List<AbstractFilter> searchfilters,
FileSearch.AttributeType groupingAttribute, FileGroup.GroupSortingAlgorithm groupSort, FileSearch.AttributeType groupingAttribute, FileGroup.GroupSortingAlgorithm groupSort,
FileSorter.SortingMethod fileSortMethod) { FileSorter.SortingMethod fileSortMethod) {
this.groupMap = groupMap; this.groupMap = groupMap;
@ -172,7 +171,7 @@ final class DiscoveryEventUtils {
* *
* @return The map of groups which were found by the search. * @return The map of groups which were found by the search.
*/ */
Map<GroupKey, Integer> getGroupMap() { public Map<GroupKey, Integer> getGroupMap() {
return Collections.unmodifiableMap(groupMap); return Collections.unmodifiableMap(groupMap);
} }
@ -181,7 +180,7 @@ final class DiscoveryEventUtils {
* *
* @return The search filters which were used by the search. * @return The search filters which were used by the search.
*/ */
List<AbstractFilter> getFilters() { public List<AbstractFilter> getFilters() {
return Collections.unmodifiableList(searchFilters); return Collections.unmodifiableList(searchFilters);
} }
@ -190,7 +189,7 @@ final class DiscoveryEventUtils {
* *
* @return The grouping attribute used by the search. * @return The grouping attribute used by the search.
*/ */
FileSearch.AttributeType getGroupingAttr() { public FileSearch.AttributeType getGroupingAttr() {
return groupingAttribute; return groupingAttribute;
} }
@ -199,7 +198,7 @@ final class DiscoveryEventUtils {
* *
* @return The sorting algorithm used for groups. * @return The sorting algorithm used for groups.
*/ */
FileGroup.GroupSortingAlgorithm getGroupSort() { public FileGroup.GroupSortingAlgorithm getGroupSort() {
return groupSort; return groupSort;
} }
@ -208,7 +207,7 @@ final class DiscoveryEventUtils {
* *
* @return The sorting method used for files. * @return The sorting method used for files.
*/ */
FileSorter.SortingMethod getFileSort() { public FileSorter.SortingMethod getFileSort() {
return fileSortMethod; return fileSortMethod;
} }
@ -218,7 +217,7 @@ final class DiscoveryEventUtils {
* Event to signal the completion of page retrieval and include the page * Event to signal the completion of page retrieval and include the page
* contents. * contents.
*/ */
static final class PageRetrievedEvent { public static final class PageRetrievedEvent {
private final List<ResultFile> results; private final List<ResultFile> results;
private final int page; private final int page;
@ -231,7 +230,7 @@ final class DiscoveryEventUtils {
* @param page The number of the page which was retrieved. * @param page The number of the page which was retrieved.
* @param results The list of files in the page retrieved. * @param results The list of files in the page retrieved.
*/ */
PageRetrievedEvent(FileType resultType, int page, List<ResultFile> results) { public PageRetrievedEvent(FileType resultType, int page, List<ResultFile> results) {
this.results = results; this.results = results;
this.page = page; this.page = page;
this.resultType = resultType; this.resultType = resultType;
@ -242,7 +241,7 @@ final class DiscoveryEventUtils {
* *
* @return The list of files in the page retrieved. * @return The list of files in the page retrieved.
*/ */
List<ResultFile> getSearchResults() { public List<ResultFile> getSearchResults() {
return Collections.unmodifiableList(results); return Collections.unmodifiableList(results);
} }
@ -251,7 +250,7 @@ final class DiscoveryEventUtils {
* *
* @return The number of the page which was retrieved. * @return The number of the page which was retrieved.
*/ */
int getPageNumber() { public int getPageNumber() {
return page; return page;
} }
@ -260,7 +259,7 @@ final class DiscoveryEventUtils {
* *
* @return The type of files which exist in the page. * @return The type of files which exist in the page.
*/ */
FileType getType() { public FileType getType() {
return resultType; return resultType;
} }
} }
@ -268,12 +267,12 @@ final class DiscoveryEventUtils {
/** /**
* Event to signal that there were no results for the search. * Event to signal that there were no results for the search.
*/ */
static final class NoResultsEvent { public static final class NoResultsEvent {
/** /**
* Construct a new NoResultsEvent. * Construct a new NoResultsEvent.
*/ */
NoResultsEvent() { public NoResultsEvent() {
//no arg constructor //no arg constructor
} }
} }
@ -281,12 +280,12 @@ final class DiscoveryEventUtils {
/** /**
* Event to signal that a search has been cancelled * Event to signal that a search has been cancelled
*/ */
static final class SearchCancelledEvent { public static final class SearchCancelledEvent {
/** /**
* Construct a new SearchCancelledEvent. * Construct a new SearchCancelledEvent.
*/ */
SearchCancelledEvent() { public SearchCancelledEvent() {
//no arg constructor //no arg constructor
} }
@ -295,7 +294,7 @@ final class DiscoveryEventUtils {
/** /**
* Event to signal that a group has been selected. * Event to signal that a group has been selected.
*/ */
static final class GroupSelectedEvent { public static final class GroupSelectedEvent {
private final FileType resultType; private final FileType resultType;
private final GroupKey groupKey; private final GroupKey groupKey;
@ -319,7 +318,7 @@ final class DiscoveryEventUtils {
* selected. * selected.
* @param resultType The type of files which exist in the group. * @param resultType The type of files which exist in the group.
*/ */
GroupSelectedEvent(List<AbstractFilter> searchfilters, public GroupSelectedEvent(List<AbstractFilter> searchfilters,
FileSearch.AttributeType groupingAttribute, FileGroup.GroupSortingAlgorithm groupSort, FileSearch.AttributeType groupingAttribute, FileGroup.GroupSortingAlgorithm groupSort,
FileSorter.SortingMethod fileSortMethod, GroupKey groupKey, int groupSize, FileType resultType) { FileSorter.SortingMethod fileSortMethod, GroupKey groupKey, int groupSize, FileType resultType) {
this.searchfilters = searchfilters; this.searchfilters = searchfilters;
@ -336,7 +335,7 @@ final class DiscoveryEventUtils {
* *
* @return The type of files which exist in the group. * @return The type of files which exist in the group.
*/ */
FileType getResultType() { public FileType getResultType() {
return resultType; return resultType;
} }
@ -347,7 +346,7 @@ final class DiscoveryEventUtils {
* @return The group key which is used to uniquely identify the group * @return The group key which is used to uniquely identify the group
* selected. * selected.
*/ */
GroupKey getGroupKey() { public GroupKey getGroupKey() {
return groupKey; return groupKey;
} }
@ -356,7 +355,7 @@ final class DiscoveryEventUtils {
* *
* @return The number of files in the group which was selected. * @return The number of files in the group which was selected.
*/ */
int getGroupSize() { public int getGroupSize() {
return groupSize; return groupSize;
} }
@ -365,7 +364,7 @@ final class DiscoveryEventUtils {
* *
* @return The sorting algorithm used for groups. * @return The sorting algorithm used for groups.
*/ */
FileGroup.GroupSortingAlgorithm getGroupSort() { public FileGroup.GroupSortingAlgorithm getGroupSort() {
return groupSort; return groupSort;
} }
@ -374,7 +373,7 @@ final class DiscoveryEventUtils {
* *
* @return The sorting method used for files. * @return The sorting method used for files.
*/ */
FileSorter.SortingMethod getFileSort() { public FileSorter.SortingMethod getFileSort() {
return fileSortMethod; return fileSortMethod;
} }
@ -383,7 +382,7 @@ final class DiscoveryEventUtils {
* *
* @return The search filters which were used by the search. * @return The search filters which were used by the search.
*/ */
List<AbstractFilter> getFilters() { public List<AbstractFilter> getFilters() {
return Collections.unmodifiableList(searchfilters); return Collections.unmodifiableList(searchfilters);
} }
@ -392,7 +391,7 @@ final class DiscoveryEventUtils {
* *
* @return The grouping attribute used by the search. * @return The grouping attribute used by the search.
*/ */
FileSearch.AttributeType getGroupingAttr() { public FileSearch.AttributeType getGroupingAttr() {
return groupingAttribute; return groupingAttribute;
} }
@ -401,7 +400,7 @@ final class DiscoveryEventUtils {
/** /**
* Event to signal that the visibility of the Details area should change. * Event to signal that the visibility of the Details area should change.
*/ */
static class DetailsVisibleEvent { public static class DetailsVisibleEvent {
private final boolean showDetailsArea; private final boolean showDetailsArea;
@ -411,7 +410,7 @@ final class DiscoveryEventUtils {
* @param isVisible True if the details area should be visible, false * @param isVisible True if the details area should be visible, false
* otherwise. * otherwise.
*/ */
DetailsVisibleEvent(boolean isVisible) { public DetailsVisibleEvent(boolean isVisible) {
showDetailsArea = isVisible; showDetailsArea = isVisible;
} }
@ -420,7 +419,7 @@ final class DiscoveryEventUtils {
* *
* @return True if the details area should be visible, false otherwise. * @return True if the details area should be visible, false otherwise.
*/ */
boolean isShowDetailsArea() { public boolean isShowDetailsArea() {
return showDetailsArea; return showDetailsArea;
} }
} }

View File

@ -0,0 +1,341 @@
/*
* Autopsy
*
* Copyright 2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.discovery.search;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import org.openide.util.NbBundle;
/**
* Utility class for constructing keys for groups and searches.
*/
public class DiscoveryKeyUtils {
/**
* The key used for grouping for each attribute type.
*/
public abstract static class GroupKey implements Comparable<GroupKey> {
/**
* Get the string version of the group key for display. Each display
* name should correspond to a unique GroupKey object.
*
* @return The display name for this key
*/
abstract String getDisplayName();
/**
* Subclasses must implement equals().
*
* @param otherKey
*
* @return true if the keys are equal, false otherwise
*/
@Override
abstract public boolean equals(Object otherKey);
/**
* Subclasses must implement hashCode().
*
* @return the hash code
*/
@Override
abstract public int hashCode();
/**
* It should not happen with the current setup, but we need to cover the
* case where two different GroupKey subclasses are compared against
* each other. Use a lexicographic comparison on the class names.
*
* @param otherGroupKey The other group key
*
* @return result of alphabetical comparison on the class name
*/
int compareClassNames(GroupKey otherGroupKey) {
return this.getClass().getName().compareTo(otherGroupKey.getClass().getName());
}
@Override
public String toString() {
return getDisplayName();
}
}
/**
* Key representing a file size group
*/
static class FileSizeGroupKey extends GroupKey {
private final FileSearchData.FileSize fileSize;
FileSizeGroupKey(ResultFile file) {
if (file.getFileType() == FileSearchData.FileType.VIDEO) {
fileSize = FileSearchData.FileSize.fromVideoSize(file.getFirstInstance().getSize());
} else {
fileSize = FileSearchData.FileSize.fromImageSize(file.getFirstInstance().getSize());
}
}
@Override
String getDisplayName() {
return getFileSize().toString();
}
@Override
public int compareTo(GroupKey otherGroupKey) {
if (otherGroupKey instanceof FileSizeGroupKey) {
FileSizeGroupKey otherFileSizeGroupKey = (FileSizeGroupKey) otherGroupKey;
return Integer.compare(getFileSize().getRanking(), otherFileSizeGroupKey.getFileSize().getRanking());
} else {
return compareClassNames(otherGroupKey);
}
}
@Override
public boolean equals(Object otherKey) {
if (otherKey == this) {
return true;
}
if (!(otherKey instanceof FileSizeGroupKey)) {
return false;
}
FileSizeGroupKey otherFileSizeGroupKey = (FileSizeGroupKey) otherKey;
return getFileSize().equals(otherFileSizeGroupKey.getFileSize());
}
@Override
public int hashCode() {
return Objects.hash(getFileSize().getRanking());
}
/**
* @return the fileSize
*/
FileSearchData.FileSize getFileSize() {
return fileSize;
}
}
/**
* Key representing a file tag group
*/
static class FileTagGroupKey extends GroupKey {
private final List<String> tagNames;
private final String tagNamesString;
@NbBundle.Messages({
"DiscoveryKeyUtils.FileTagGroupKey.noSets=None"})
FileTagGroupKey(ResultFile file) {
tagNames = file.getTagNames();
if (tagNames.isEmpty()) {
tagNamesString = Bundle.DiscoveryKeyUtils_FileTagGroupKey_noSets();
} else {
tagNamesString = String.join(",", tagNames); // NON-NLS
}
}
@Override
String getDisplayName() {
return getTagNamesString();
}
@Override
public int compareTo(GroupKey otherGroupKey) {
if (otherGroupKey instanceof FileTagGroupKey) {
FileTagGroupKey otherFileTagGroupKey = (FileTagGroupKey) otherGroupKey;
// Put the empty list at the end
if (getTagNames().isEmpty()) {
if (otherFileTagGroupKey.getTagNames().isEmpty()) {
return 0;
} else {
return 1;
}
} else if (otherFileTagGroupKey.getTagNames().isEmpty()) {
return -1;
}
return getTagNamesString().compareTo(otherFileTagGroupKey.getTagNamesString());
} else {
return compareClassNames(otherGroupKey);
}
}
@Override
public boolean equals(Object otherKey) {
if (otherKey == this) {
return true;
}
if (!(otherKey instanceof FileTagGroupKey)) {
return false;
}
FileTagGroupKey otherFileTagGroupKey = (FileTagGroupKey) otherKey;
return getTagNamesString().equals(otherFileTagGroupKey.getTagNamesString());
}
@Override
public int hashCode() {
return Objects.hash(getTagNamesString());
}
/**
* @return the tagNames
*/
List<String> getTagNames() {
return Collections.unmodifiableList(tagNames);
}
/**
* @return the tagNamesString
*/
String getTagNamesString() {
return tagNamesString;
}
}
/**
* Default attribute used to make one group
*/
static class NoGroupingAttribute extends FileSearch.AttributeType {
@Override
public GroupKey getGroupKey(ResultFile file) {
return new NoGroupingGroupKey();
}
}
/**
* Dummy key for when there is no grouping. All files will have the same
* key.
*/
static class NoGroupingGroupKey extends GroupKey {
NoGroupingGroupKey() {
// Nothing to save - all files will get the same GroupKey
}
@NbBundle.Messages({
"DiscoveryKeyUtils.NoGroupingGroupKey.allFiles=All Files"})
@Override
String getDisplayName() {
return Bundle.DiscoveryKeyUtils_NoGroupingGroupKey_allFiles();
}
@Override
public int compareTo(GroupKey otherGroupKey) {
// As long as the other key is the same type, they are equal
if (otherGroupKey instanceof NoGroupingGroupKey) {
return 0;
} else {
return compareClassNames(otherGroupKey);
}
}
@Override
public boolean equals(Object otherKey) {
if (otherKey == this) {
return true;
}
// As long as the other key is the same type, they are equal
return otherKey instanceof NoGroupingGroupKey;
}
@Override
public int hashCode() {
return 0;
}
}
/**
* Represents a key for a specific search for a specific user.
*/
static class SearchKey implements Comparable<SearchKey> {
private final String keyString;
/**
* Construct a new SearchKey with all information that defines a search.
*
* @param userName The name of the user performing the search.
* @param filters The FileFilters being used for the search.
* @param groupAttributeType The AttributeType to group by.
* @param groupSortingType The algorithm to sort the groups by.
* @param fileSortingMethod The method to sort the files by.
*/
SearchKey(String userName, List<AbstractFilter> filters,
FileSearch.AttributeType groupAttributeType,
FileGroup.GroupSortingAlgorithm groupSortingType,
FileSorter.SortingMethod fileSortingMethod) {
StringBuilder searchStringBuilder = new StringBuilder();
searchStringBuilder.append(userName);
for (AbstractFilter filter : filters) {
searchStringBuilder.append(filter.toString());
}
searchStringBuilder.append(groupAttributeType).append(groupSortingType).append(fileSortingMethod);
keyString = searchStringBuilder.toString();
}
@Override
public int compareTo(SearchKey otherSearchKey) {
return getKeyString().compareTo(otherSearchKey.getKeyString());
}
@Override
public boolean equals(Object otherKey) {
if (otherKey == this) {
return true;
}
if (!(otherKey instanceof SearchKey)) {
return false;
}
SearchKey otherSearchKey = (SearchKey) otherKey;
return getKeyString().equals(otherSearchKey.getKeyString());
}
@Override
public int hashCode() {
int hash = 5;
hash = 79 * hash + Objects.hashCode(getKeyString());
return hash;
}
/**
* @return the keyString
*/
String getKeyString() {
return keyString;
}
}
/**
* Private constructor for GroupKeyUtils utility class.
*/
private DiscoveryKeyUtils() {
//private constructor in a utility class intentionally left blank
}
}

View File

@ -16,21 +16,20 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.discovery; package org.sleuthkit.autopsy.discovery.search;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.discovery.FileSearch.GroupKey;
/** /**
* Class for storing files that belong to a particular group. * Class for storing files that belong to a particular group.
*/ */
class FileGroup implements Comparable<FileGroup> { public class FileGroup implements Comparable<FileGroup> {
private final FileGroup.GroupSortingAlgorithm groupSortingType; private final FileGroup.GroupSortingAlgorithm groupSortingType;
private final GroupKey groupKey; private final DiscoveryKeyUtils.GroupKey groupKey;
private final List<ResultFile> files; private final List<ResultFile> files;
private final String displayName; private final String displayName;
@ -40,7 +39,7 @@ class FileGroup implements Comparable<FileGroup> {
* @param groupSortingType The method for sorting the group * @param groupSortingType The method for sorting the group
* @param groupKey The GroupKey for this group * @param groupKey The GroupKey for this group
*/ */
FileGroup(FileGroup.GroupSortingAlgorithm groupSortingType, GroupKey groupKey) { public FileGroup(FileGroup.GroupSortingAlgorithm groupSortingType, DiscoveryKeyUtils.GroupKey groupKey) {
this.groupSortingType = groupSortingType; this.groupSortingType = groupSortingType;
this.groupKey = groupKey; this.groupKey = groupKey;
files = new ArrayList<>(); files = new ArrayList<>();
@ -66,7 +65,7 @@ class FileGroup implements Comparable<FileGroup> {
* *
* @return The display name of the group. * @return The display name of the group.
*/ */
String getDisplayName() { public String getDisplayName() {
return displayName; // NON-NLS return displayName; // NON-NLS
} }
@ -75,14 +74,14 @@ class FileGroup implements Comparable<FileGroup> {
* *
* @return The unique key for the group. * @return The unique key for the group.
*/ */
GroupKey getGroupKey() { public DiscoveryKeyUtils.GroupKey getGroupKey() {
return groupKey; return groupKey;
} }
/** /**
* Sort all the files in the group * Sort all the files in the group
*/ */
void sortFiles(FileSorter sorter) { public void sortFiles(FileSorter sorter) {
Collections.sort(files, sorter); Collections.sort(files, sorter);
} }
@ -142,7 +141,7 @@ class FileGroup implements Comparable<FileGroup> {
*/ */
@Messages({"FileGroup.groupSortingAlgorithm.groupSize.text=Group Size", @Messages({"FileGroup.groupSortingAlgorithm.groupSize.text=Group Size",
"FileGroup.groupSortingAlgorithm.groupName.text=Group Name"}) "FileGroup.groupSortingAlgorithm.groupName.text=Group Name"})
enum GroupSortingAlgorithm { public enum GroupSortingAlgorithm {
BY_GROUP_NAME(Bundle.FileGroup_groupSortingAlgorithm_groupName_text()), // Sort using the group key (for example, if grouping by size sort from largest to smallest value) BY_GROUP_NAME(Bundle.FileGroup_groupSortingAlgorithm_groupName_text()), // Sort using the group key (for example, if grouping by size sort from largest to smallest value)
BY_GROUP_SIZE(Bundle.FileGroup_groupSortingAlgorithm_groupSize_text()); // Sort from largest to smallest group BY_GROUP_SIZE(Bundle.FileGroup_groupSortingAlgorithm_groupSize_text()); // Sort from largest to smallest group
@ -169,7 +168,7 @@ class FileGroup implements Comparable<FileGroup> {
* *
* @return List of ResultFile objects * @return List of ResultFile objects
*/ */
List<ResultFile> getFiles() { public List<ResultFile> getFiles() {
return Collections.unmodifiableList(files); return Collections.unmodifiableList(files);
} }

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.discovery; package org.sleuthkit.autopsy.discovery.search;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import java.util.ArrayList; import java.util.ArrayList;
@ -30,12 +30,12 @@ import org.sleuthkit.autopsy.coreutils.FileTypeUtils;
/** /**
* Utility enums for searches made for files with Discovery. * Utility enums for searches made for files with Discovery.
*/ */
final class FileSearchData extends SearchData { public final class FileSearchData implements SearchData {
private final static long BYTES_PER_MB = 1000000; private final static long BYTES_PER_MB = 1000000;
@Override @Override
ResultType getResultType() { public ResultType getResultType() {
return ResultType.FILE; return ResultType.FILE;
} }
@ -49,7 +49,7 @@ final class FileSearchData extends SearchData {
"FileSearchData.Frequency.verycommon.displayName=Very Common (100+)", "FileSearchData.Frequency.verycommon.displayName=Very Common (100+)",
"FileSearchData.Frequency.known.displayName=Known (NSRL)", "FileSearchData.Frequency.known.displayName=Known (NSRL)",
"FileSearchData.Frequency.unknown.displayName=Unknown",}) "FileSearchData.Frequency.unknown.displayName=Unknown",})
enum Frequency { public enum Frequency {
UNIQUE(0, 1, Bundle.FileSearchData_Frequency_unique_displayName()), UNIQUE(0, 1, Bundle.FileSearchData_Frequency_unique_displayName()),
RARE(1, 10, Bundle.FileSearchData_Frequency_rare_displayName()), RARE(1, 10, Bundle.FileSearchData_Frequency_rare_displayName()),
COMMON(2, 100, Bundle.FileSearchData_Frequency_common_displayName()), COMMON(2, 100, Bundle.FileSearchData_Frequency_common_displayName()),
@ -72,7 +72,7 @@ final class FileSearchData extends SearchData {
* *
* @return the rank (lower should be displayed first) * @return the rank (lower should be displayed first)
*/ */
int getRanking() { public int getRanking() {
return ranking; return ranking;
} }
@ -83,7 +83,7 @@ final class FileSearchData extends SearchData {
* *
* @return the corresponding enum * @return the corresponding enum
*/ */
static Frequency fromCount(long count) { public static Frequency fromCount(long count) {
if (count <= UNIQUE.getMaxOccur()) { if (count <= UNIQUE.getMaxOccur()) {
return UNIQUE; return UNIQUE;
} else if (count <= RARE.getMaxOccur()) { } else if (count <= RARE.getMaxOccur()) {
@ -100,7 +100,7 @@ final class FileSearchData extends SearchData {
* *
* @return enums that can be used to filter with a CR. * @return enums that can be used to filter with a CR.
*/ */
static List<Frequency> getOptionsForFilteringWithCr() { public static List<Frequency> getOptionsForFilteringWithCr() {
return Arrays.asList(UNIQUE, RARE, COMMON, VERY_COMMON, KNOWN); return Arrays.asList(UNIQUE, RARE, COMMON, VERY_COMMON, KNOWN);
} }
@ -110,7 +110,7 @@ final class FileSearchData extends SearchData {
* *
* @return enums that can be used to filter without a CR. * @return enums that can be used to filter without a CR.
*/ */
static List<Frequency> getOptionsForFilteringWithoutCr() { public static List<Frequency> getOptionsForFilteringWithoutCr() {
return Arrays.asList(KNOWN, UNKNOWN); return Arrays.asList(KNOWN, UNKNOWN);
} }
@ -122,7 +122,7 @@ final class FileSearchData extends SearchData {
/** /**
* @return the maxOccur * @return the maxOccur
*/ */
int getMaxOccur() { public int getMaxOccur() {
return maxOccur; return maxOccur;
} }
} }
@ -149,7 +149,7 @@ final class FileSearchData extends SearchData {
"FileSearchData.FileSize.16kbto100kb=: 16-100KB", "FileSearchData.FileSize.16kbto100kb=: 16-100KB",
"FileSearchData.FileSize.upTo500kb=: 0-500KB", "FileSearchData.FileSize.upTo500kb=: 0-500KB",
"FileSearchData.FileSize.upTo16kb=: 0-16KB",}) "FileSearchData.FileSize.upTo16kb=: 0-16KB",})
enum FileSize { public enum FileSize {
XXLARGE_VIDEO(0, 10000 * BYTES_PER_MB, -1, Bundle.FileSearchData_FileSize_XXLARGE_displayName(), Bundle.FileSearchData_FileSize_10PlusGb()), XXLARGE_VIDEO(0, 10000 * BYTES_PER_MB, -1, Bundle.FileSearchData_FileSize_XXLARGE_displayName(), Bundle.FileSearchData_FileSize_10PlusGb()),
XLARGE_VIDEO(1, 5000 * BYTES_PER_MB, 10000 * BYTES_PER_MB, Bundle.FileSearchData_FileSize_XLARGE_displayName(), Bundle.FileSearchData_FileSize_5gbto10gb()), XLARGE_VIDEO(1, 5000 * BYTES_PER_MB, 10000 * BYTES_PER_MB, Bundle.FileSearchData_FileSize_XLARGE_displayName(), Bundle.FileSearchData_FileSize_5gbto10gb()),
LARGE_VIDEO(2, 1000 * BYTES_PER_MB, 5000 * BYTES_PER_MB, Bundle.FileSearchData_FileSize_LARGE_displayName(), Bundle.FileSearchData_FileSize_1gbto5gb()), LARGE_VIDEO(2, 1000 * BYTES_PER_MB, 5000 * BYTES_PER_MB, Bundle.FileSearchData_FileSize_LARGE_displayName(), Bundle.FileSearchData_FileSize_1gbto5gb()),
@ -190,7 +190,7 @@ final class FileSearchData extends SearchData {
* *
* @return the enum whose range contains the file size * @return the enum whose range contains the file size
*/ */
static FileSize fromImageSize(long size) { public static FileSize fromImageSize(long size) {
if (size > XXLARGE_IMAGE.getMinBytes()) { if (size > XXLARGE_IMAGE.getMinBytes()) {
return XXLARGE_IMAGE; return XXLARGE_IMAGE;
} else if (size > XLARGE_IMAGE.getMinBytes()) { } else if (size > XLARGE_IMAGE.getMinBytes()) {
@ -214,7 +214,7 @@ final class FileSearchData extends SearchData {
* *
* @return the enum whose range contains the file size * @return the enum whose range contains the file size
*/ */
static FileSize fromVideoSize(long size) { public static FileSize fromVideoSize(long size) {
if (size > XXLARGE_VIDEO.getMinBytes()) { if (size > XXLARGE_VIDEO.getMinBytes()) {
return XXLARGE_VIDEO; return XXLARGE_VIDEO;
} else if (size > XLARGE_VIDEO.getMinBytes()) { } else if (size > XLARGE_VIDEO.getMinBytes()) {
@ -235,7 +235,7 @@ final class FileSearchData extends SearchData {
* *
* @return the maximum file size that will fit in this range. * @return the maximum file size that will fit in this range.
*/ */
long getMaxBytes() { public long getMaxBytes() {
return maxBytes; return maxBytes;
} }
@ -244,7 +244,7 @@ final class FileSearchData extends SearchData {
* *
* @return the maximum file size that is not part of this range * @return the maximum file size that is not part of this range
*/ */
long getMinBytes() { public long getMinBytes() {
return minBytes; return minBytes;
} }
@ -253,7 +253,7 @@ final class FileSearchData extends SearchData {
* *
* @return the rank (lower should be displayed first) * @return the rank (lower should be displayed first)
*/ */
int getRanking() { public int getRanking() {
return ranking; return ranking;
} }
@ -262,7 +262,7 @@ final class FileSearchData extends SearchData {
return sizeGroup + displaySize; return sizeGroup + displaySize;
} }
String getSizeGroup() { public String getSizeGroup() {
return sizeGroup; return sizeGroup;
} }
@ -272,7 +272,7 @@ final class FileSearchData extends SearchData {
* @return Enums that can be used to filter most file including images * @return Enums that can be used to filter most file including images
* by size. * by size.
*/ */
static List<FileSize> getDefaultSizeOptions() { public static List<FileSize> getDefaultSizeOptions() {
return Arrays.asList(XXLARGE_IMAGE, XLARGE_IMAGE, LARGE_IMAGE, MEDIUM_IMAGE, SMALL_IMAGE, XSMALL_IMAGE); return Arrays.asList(XXLARGE_IMAGE, XLARGE_IMAGE, LARGE_IMAGE, MEDIUM_IMAGE, SMALL_IMAGE, XSMALL_IMAGE);
} }
@ -281,7 +281,7 @@ final class FileSearchData extends SearchData {
* *
* @return enums that can be used to filter videos by size. * @return enums that can be used to filter videos by size.
*/ */
static List<FileSize> getOptionsForVideos() { public static List<FileSize> getOptionsForVideos() {
return Arrays.asList(XXLARGE_VIDEO, XLARGE_VIDEO, LARGE_VIDEO, MEDIUM_VIDEO, SMALL_VIDEO, XSMALL_VIDEO); return Arrays.asList(XXLARGE_VIDEO, XLARGE_VIDEO, LARGE_VIDEO, MEDIUM_VIDEO, SMALL_VIDEO, XSMALL_VIDEO);
} }
} }
@ -314,7 +314,7 @@ final class FileSearchData extends SearchData {
.add("application/pdf", //NON-NLS .add("application/pdf", //NON-NLS
"application/xhtml+xml").build(); //NON-NLS "application/xhtml+xml").build(); //NON-NLS
static Collection<String> getDocTypesWithoutImageExtraction() { public static Collection<String> getDocTypesWithoutImageExtraction() {
return Collections.unmodifiableCollection(IMAGE_UNSUPPORTED_DOC_TYPES); return Collections.unmodifiableCollection(IMAGE_UNSUPPORTED_DOC_TYPES);
} }
@ -331,7 +331,7 @@ final class FileSearchData extends SearchData {
"FileSearchData.FileType.Documents.displayName=Documents", "FileSearchData.FileType.Documents.displayName=Documents",
"FileSearchData.FileType.Executables.displayName=Executables", "FileSearchData.FileType.Executables.displayName=Executables",
"FileSearchData.FileType.Other.displayName=Other/Unknown"}) "FileSearchData.FileType.Other.displayName=Other/Unknown"})
enum FileType { public enum FileType {
IMAGE(0, Bundle.FileSearchData_FileType_Image_displayName(), FileTypeUtils.FileTypeCategory.IMAGE.getMediaTypes()), IMAGE(0, Bundle.FileSearchData_FileType_Image_displayName(), FileTypeUtils.FileTypeCategory.IMAGE.getMediaTypes()),
AUDIO(1, Bundle.FileSearchData_FileType_Audio_displayName(), FileTypeUtils.FileTypeCategory.AUDIO.getMediaTypes()), AUDIO(1, Bundle.FileSearchData_FileType_Audio_displayName(), FileTypeUtils.FileTypeCategory.AUDIO.getMediaTypes()),
@ -355,7 +355,7 @@ final class FileSearchData extends SearchData {
* *
* @return Collection of MIME type strings * @return Collection of MIME type strings
*/ */
Collection<String> getMediaTypes() { public Collection<String> getMediaTypes() {
return Collections.unmodifiableCollection(mediaTypes); return Collections.unmodifiableCollection(mediaTypes);
} }
@ -369,7 +369,7 @@ final class FileSearchData extends SearchData {
* *
* @return the rank (lower should be displayed first) * @return the rank (lower should be displayed first)
*/ */
int getRanking() { public int getRanking() {
return ranking; return ranking;
} }
@ -380,7 +380,7 @@ final class FileSearchData extends SearchData {
* *
* @return the corresponding enum (will be OTHER if no types matched) * @return the corresponding enum (will be OTHER if no types matched)
*/ */
static FileType fromMIMEtype(String mimeType) { public static FileType fromMIMEtype(String mimeType) {
for (FileType type : FileType.values()) { for (FileType type : FileType.values()) {
if (type.getMediaTypes().contains(mimeType)) { if (type.getMediaTypes().contains(mimeType)) {
return type; return type;
@ -398,7 +398,7 @@ final class FileSearchData extends SearchData {
"FileSearchData.Score.notable.displayName=Notable", "FileSearchData.Score.notable.displayName=Notable",
"FileSearchData.Score.interesting.displayName=Interesting", "FileSearchData.Score.interesting.displayName=Interesting",
"FileSearchData.Score.unknown.displayName=Unknown",}) "FileSearchData.Score.unknown.displayName=Unknown",})
enum Score { public enum Score {
NOTABLE(0, Bundle.FileSearchData_Score_notable_displayName()), NOTABLE(0, Bundle.FileSearchData_Score_notable_displayName()),
INTERESTING(1, Bundle.FileSearchData_Score_interesting_displayName()), INTERESTING(1, Bundle.FileSearchData_Score_interesting_displayName()),
UNKNOWN(2, Bundle.FileSearchData_Score_unknown_displayName()); UNKNOWN(2, Bundle.FileSearchData_Score_unknown_displayName());
@ -416,7 +416,7 @@ final class FileSearchData extends SearchData {
* *
* @return the rank (lower should be displayed first) * @return the rank (lower should be displayed first)
*/ */
int getRanking() { public int getRanking() {
return ranking; return ranking;
} }
@ -425,7 +425,7 @@ final class FileSearchData extends SearchData {
* *
* @return enums that can be used to filter * @return enums that can be used to filter
*/ */
static List<Score> getOptionsForFiltering() { public static List<Score> getOptionsForFiltering() {
return Arrays.asList(NOTABLE, INTERESTING); return Arrays.asList(NOTABLE, INTERESTING);
} }

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.discovery; package org.sleuthkit.autopsy.discovery.search;
/** /**
* Exception type used for FileSearch. * Exception type used for FileSearch.

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.discovery; package org.sleuthkit.autopsy.discovery.search;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -29,7 +29,7 @@ import org.sleuthkit.datamodel.TskCoreException;
/** /**
* Class used to sort ResultFiles using the supplied method. * Class used to sort ResultFiles using the supplied method.
*/ */
class FileSorter implements Comparator<ResultFile> { public class FileSorter implements Comparator<ResultFile> {
private final List<Comparator<ResultFile>> comparators = new ArrayList<>(); private final List<Comparator<ResultFile>> comparators = new ArrayList<>();
@ -40,7 +40,7 @@ class FileSorter implements Comparator<ResultFile> {
* *
* @param method The method that should be used to sort the files * @param method The method that should be used to sort the files
*/ */
FileSorter(SortingMethod method) { public FileSorter(SortingMethod method) {
// Set up the primary comparators that should applied to the files // Set up the primary comparators that should applied to the files
switch (method) { switch (method) {
@ -247,7 +247,7 @@ class FileSorter implements Comparator<ResultFile> {
"FileSorter.SortingMethod.frequency.displayName=Central Repo Frequency", "FileSorter.SortingMethod.frequency.displayName=Central Repo Frequency",
"FileSorter.SortingMethod.keywordlist.displayName=Keyword List Names", "FileSorter.SortingMethod.keywordlist.displayName=Keyword List Names",
"FileSorter.SortingMethod.fullPath.displayName=Full Path"}) "FileSorter.SortingMethod.fullPath.displayName=Full Path"})
enum SortingMethod { public enum SortingMethod {
BY_FILE_NAME(new ArrayList<>(), BY_FILE_NAME(new ArrayList<>(),
Bundle.FileSorter_SortingMethod_filename_displayName()), // Sort alphabetically by file name Bundle.FileSorter_SortingMethod_filename_displayName()), // Sort alphabetically by file name
BY_DATA_SOURCE(new ArrayList<>(), BY_DATA_SOURCE(new ArrayList<>(),
@ -276,7 +276,7 @@ class FileSorter implements Comparator<ResultFile> {
return displayName; return displayName;
} }
List<FileSearch.AttributeType> getRequiredAttributes() { public List<FileSearch.AttributeType> getRequiredAttributes() {
return Collections.unmodifiableList(requiredAttributes); return Collections.unmodifiableList(requiredAttributes);
} }
@ -285,7 +285,7 @@ class FileSorter implements Comparator<ResultFile> {
* *
* @return enums that can be used to ordering images. * @return enums that can be used to ordering images.
*/ */
static List<SortingMethod> getOptionsForOrdering() { public static List<SortingMethod> getOptionsForOrdering() {
return Arrays.asList(BY_FILE_SIZE, BY_FULL_PATH, BY_FILE_NAME, BY_DATA_SOURCE); return Arrays.asList(BY_FILE_SIZE, BY_FULL_PATH, BY_FILE_NAME, BY_DATA_SOURCE);
} }
} }

View File

@ -16,9 +16,9 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.discovery; package org.sleuthkit.autopsy.discovery.search;
import org.sleuthkit.autopsy.discovery.FileSearchData.FileType; import org.sleuthkit.autopsy.discovery.search.FileSearchData.FileType;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -39,7 +39,7 @@ import org.sleuthkit.datamodel.TskData;
/** /**
* Container for files that holds all necessary data for grouping and sorting. * Container for files that holds all necessary data for grouping and sorting.
*/ */
class ResultFile { public class ResultFile {
private final static Logger logger = Logger.getLogger(ResultFile.class.getName()); private final static Logger logger = Logger.getLogger(ResultFile.class.getName());
private FileSearchData.Frequency frequency; private FileSearchData.Frequency frequency;
@ -59,7 +59,7 @@ class ResultFile {
* *
* @param abstractFile * @param abstractFile
*/ */
ResultFile(AbstractFile abstractFile) { public ResultFile(AbstractFile abstractFile) {
try { try {
//call get uniquePath to cache the path //call get uniquePath to cache the path
abstractFile.getUniquePath(); abstractFile.getUniquePath();
@ -86,7 +86,7 @@ class ResultFile {
* *
* @return The Frequency enum * @return The Frequency enum
*/ */
FileSearchData.Frequency getFrequency() { public FileSearchData.Frequency getFrequency() {
return frequency; return frequency;
} }
@ -95,7 +95,7 @@ class ResultFile {
* *
* @param frequency The frequency of the file as an enum * @param frequency The frequency of the file as an enum
*/ */
void setFrequency(FileSearchData.Frequency frequency) { public void setFrequency(FileSearchData.Frequency frequency) {
this.frequency = frequency; this.frequency = frequency;
} }
@ -105,7 +105,7 @@ class ResultFile {
* *
* @param duplicate The abstract file to add as a duplicate. * @param duplicate The abstract file to add as a duplicate.
*/ */
void addDuplicate(AbstractFile duplicate) { public void addDuplicate(AbstractFile duplicate) {
if (deleted && !duplicate.isDirNameFlagSet(TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC)) { if (deleted && !duplicate.isDirNameFlagSet(TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC)) {
deleted = false; deleted = false;
} }
@ -128,7 +128,7 @@ class ResultFile {
* *
* @return The score of this ResultFile. * @return The score of this ResultFile.
*/ */
DataResultViewerTable.Score getScore() { public DataResultViewerTable.Score getScore() {
return currentScore; return currentScore;
} }
@ -137,7 +137,7 @@ class ResultFile {
* *
* @return The score description of this ResultFile. * @return The score description of this ResultFile.
*/ */
String getScoreDescription() { public String getScoreDescription() {
return scoreDescription; return scoreDescription;
} }
@ -147,7 +147,7 @@ class ResultFile {
* *
* @return The deleted status of this ResultFile. * @return The deleted status of this ResultFile.
*/ */
boolean isDeleted() { public boolean isDeleted() {
return deleted; return deleted;
} }
@ -158,7 +158,7 @@ class ResultFile {
* @return The list of AbstractFiles which have been identified as instances * @return The list of AbstractFiles which have been identified as instances
* of this file. * of this file.
*/ */
List<AbstractFile> getAllInstances() { public List<AbstractFile> getAllInstances() {
return Collections.unmodifiableList(instances); return Collections.unmodifiableList(instances);
} }
@ -167,7 +167,7 @@ class ResultFile {
* *
* @return The FileType enum. * @return The FileType enum.
*/ */
FileType getFileType() { public FileType getFileType() {
return fileType; return fileType;
} }
@ -176,7 +176,7 @@ class ResultFile {
* *
* @param keywordListName * @param keywordListName
*/ */
void addKeywordListName(String keywordListName) { public void addKeywordListName(String keywordListName) {
if (!keywordListNames.contains(keywordListName)) { if (!keywordListNames.contains(keywordListName)) {
keywordListNames.add(keywordListName); keywordListNames.add(keywordListName);
} }
@ -190,7 +190,7 @@ class ResultFile {
* *
* @return the keyword list names that matched this file. * @return the keyword list names that matched this file.
*/ */
List<String> getKeywordListNames() { public List<String> getKeywordListNames() {
return Collections.unmodifiableList(keywordListNames); return Collections.unmodifiableList(keywordListNames);
} }
@ -199,7 +199,7 @@ class ResultFile {
* *
* @param hashSetName * @param hashSetName
*/ */
void addHashSetName(String hashSetName) { public void addHashSetName(String hashSetName) {
if (!hashSetNames.contains(hashSetName)) { if (!hashSetNames.contains(hashSetName)) {
hashSetNames.add(hashSetName); hashSetNames.add(hashSetName);
} }
@ -213,7 +213,7 @@ class ResultFile {
* *
* @return The hash set names that matched this file. * @return The hash set names that matched this file.
*/ */
List<String> getHashSetNames() { public List<String> getHashSetNames() {
return Collections.unmodifiableList(hashSetNames); return Collections.unmodifiableList(hashSetNames);
} }
@ -222,7 +222,7 @@ class ResultFile {
* *
* @param tagName * @param tagName
*/ */
void addTagName(String tagName) { public void addTagName(String tagName) {
if (!tagNames.contains(tagName)) { if (!tagNames.contains(tagName)) {
tagNames.add(tagName); tagNames.add(tagName);
} }
@ -236,7 +236,7 @@ class ResultFile {
* *
* @return the tag names that matched this file. * @return the tag names that matched this file.
*/ */
List<String> getTagNames() { public List<String> getTagNames() {
return Collections.unmodifiableList(tagNames); return Collections.unmodifiableList(tagNames);
} }
@ -245,7 +245,7 @@ class ResultFile {
* *
* @param interestingSetName * @param interestingSetName
*/ */
void addInterestingSetName(String interestingSetName) { public void addInterestingSetName(String interestingSetName) {
if (!interestingSetNames.contains(interestingSetName)) { if (!interestingSetNames.contains(interestingSetName)) {
interestingSetNames.add(interestingSetName); interestingSetNames.add(interestingSetName);
} }
@ -259,7 +259,7 @@ class ResultFile {
* *
* @return the interesting item set names that matched this file. * @return the interesting item set names that matched this file.
*/ */
List<String> getInterestingSetNames() { public List<String> getInterestingSetNames() {
return Collections.unmodifiableList(interestingSetNames); return Collections.unmodifiableList(interestingSetNames);
} }
@ -268,7 +268,7 @@ class ResultFile {
* *
* @param objectDetectedName * @param objectDetectedName
*/ */
void addObjectDetectedName(String objectDetectedName) { public void addObjectDetectedName(String objectDetectedName) {
if (!objectDetectedNames.contains(objectDetectedName)) { if (!objectDetectedNames.contains(objectDetectedName)) {
objectDetectedNames.add(objectDetectedName); objectDetectedNames.add(objectDetectedName);
} }
@ -282,7 +282,7 @@ class ResultFile {
* *
* @return the objects detected in this file. * @return the objects detected in this file.
*/ */
List<String> getObjectDetectedNames() { public List<String> getObjectDetectedNames() {
return Collections.unmodifiableList(objectDetectedNames); return Collections.unmodifiableList(objectDetectedNames);
} }
@ -291,7 +291,7 @@ class ResultFile {
* *
* @return the AbstractFile object * @return the AbstractFile object
*/ */
AbstractFile getFirstInstance() { public AbstractFile getFirstInstance() {
return instances.get(0); return instances.get(0);
} }

View File

@ -16,17 +16,17 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.discovery; package org.sleuthkit.autopsy.discovery.search;
/** /**
* Abstract class to contain data that is common to all result types. * Abstract class to contain data that is common to all result types.
*/ */
abstract class SearchData { public interface SearchData {
/** /**
* Enum of the broad result type categories. * Enum of the broad result type categories.
*/ */
enum ResultType { public enum ResultType {
FILE, FILE,
ATTRIBUTE; ATTRIBUTE;
} }
@ -34,6 +34,6 @@ abstract class SearchData {
/** /**
* Get the broad result type. * Get the broad result type.
*/ */
abstract ResultType getResultType(); public abstract ResultType getResultType();
} }

View File

@ -16,16 +16,15 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.discovery; package org.sleuthkit.autopsy.discovery.search;
import org.sleuthkit.autopsy.discovery.ui.AbstractFilter;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeNormalizationException; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeNormalizationException;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException;
import org.sleuthkit.autopsy.discovery.FileSearchData.FileSize; import org.sleuthkit.autopsy.discovery.search.FileSearchData.FileSize;
import org.sleuthkit.autopsy.discovery.FileSearchData.FileType; import org.sleuthkit.autopsy.discovery.search.FileSearchData.FileType;
import org.sleuthkit.autopsy.discovery.FileSearchData.Frequency; import org.sleuthkit.autopsy.discovery.search.FileSearchData.Frequency;
import org.sleuthkit.autopsy.discovery.FileSearchData.Score; import org.sleuthkit.autopsy.discovery.search.FileSearchData.Score;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.DataSource;
import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.SleuthkitCase;
@ -43,7 +42,7 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
/** /**
* Run various filters to return a subset of files from the current case. * Run various filters to return a subset of files from the current case.
*/ */
class SearchFiltering { public class SearchFiltering {
/** /**
* Run the given filters to get a list of matching files. * Run the given filters to get a list of matching files.
@ -126,7 +125,7 @@ class SearchFiltering {
/** /**
* A filter for specifying the file size * A filter for specifying the file size
*/ */
static class SizeFilter extends AbstractFilter { public static class SizeFilter extends AbstractFilter {
private final List<FileSize> fileSizes; private final List<FileSize> fileSizes;
@ -135,12 +134,12 @@ class SearchFiltering {
* *
* @param fileSizes the file sizes that should match * @param fileSizes the file sizes that should match
*/ */
SizeFilter(List<FileSize> fileSizes) { public SizeFilter(List<FileSize> fileSizes) {
this.fileSizes = fileSizes; this.fileSizes = fileSizes;
} }
@Override @Override
String getWhereClause() { public String getWhereClause() {
String queryStr = ""; // NON-NLS String queryStr = ""; // NON-NLS
for (FileSize size : fileSizes) { for (FileSize size : fileSizes) {
if (!queryStr.isEmpty()) { if (!queryStr.isEmpty()) {
@ -160,7 +159,7 @@ class SearchFiltering {
"SearchFiltering.SizeFilter.desc=Size(s): {0}", "SearchFiltering.SizeFilter.desc=Size(s): {0}",
"SearchFiltering.SizeFilter.or=, "}) "SearchFiltering.SizeFilter.or=, "})
@Override @Override
String getDesc() { public String getDesc() {
String desc = ""; // NON-NLS String desc = ""; // NON-NLS
for (FileSize size : fileSizes) { for (FileSize size : fileSizes) {
if (!desc.isEmpty()) { if (!desc.isEmpty()) {
@ -177,7 +176,7 @@ class SearchFiltering {
* A utility class for the ParentFilter to store the search string and * A utility class for the ParentFilter to store the search string and
* whether it is a full path or a substring. * whether it is a full path or a substring.
*/ */
static class ParentSearchTerm { public static class ParentSearchTerm {
private final String searchStr; private final String searchStr;
private final boolean fullPath; private final boolean fullPath;
@ -192,7 +191,7 @@ class SearchFiltering {
* @param isIncluded True if the results must include the path, false if * @param isIncluded True if the results must include the path, false if
* the path should be excluded from the results. * the path should be excluded from the results.
*/ */
ParentSearchTerm(String searchStr, boolean isFullPath, boolean isIncluded) { public ParentSearchTerm(String searchStr, boolean isFullPath, boolean isIncluded) {
this.searchStr = searchStr; this.searchStr = searchStr;
this.fullPath = isFullPath; this.fullPath = isFullPath;
this.included = isIncluded; this.included = isIncluded;
@ -203,7 +202,7 @@ class SearchFiltering {
* *
* @return The SQL for a where clause to search for a matching path * @return The SQL for a where clause to search for a matching path
*/ */
String getSQLForTerm() { public String getSQLForTerm() {
// TODO - these should really be prepared statements // TODO - these should really be prepared statements
if (isIncluded()) { if (isIncluded()) {
if (isFullPath()) { if (isFullPath()) {
@ -244,21 +243,21 @@ class SearchFiltering {
/** /**
* @return the fullPath * @return the fullPath
*/ */
boolean isFullPath() { public boolean isFullPath() {
return fullPath; return fullPath;
} }
/** /**
* @return the included * @return the included
*/ */
boolean isIncluded() { public boolean isIncluded() {
return included; return included;
} }
/** /**
* @return the searchStr * @return the searchStr
*/ */
String getSearchStr() { public String getSearchStr() {
return searchStr; return searchStr;
} }
} }
@ -266,7 +265,7 @@ class SearchFiltering {
/** /**
* A filter for specifying parent path (either full path or substring) * A filter for specifying parent path (either full path or substring)
*/ */
static class ParentFilter extends AbstractFilter { public static class ParentFilter extends AbstractFilter {
private final List<ParentSearchTerm> parentSearchTerms; private final List<ParentSearchTerm> parentSearchTerms;
@ -275,12 +274,12 @@ class SearchFiltering {
* *
* @param parentSearchTerms Full paths or substrings to filter on * @param parentSearchTerms Full paths or substrings to filter on
*/ */
ParentFilter(List<ParentSearchTerm> parentSearchTerms) { public ParentFilter(List<ParentSearchTerm> parentSearchTerms) {
this.parentSearchTerms = parentSearchTerms; this.parentSearchTerms = parentSearchTerms;
} }
@Override @Override
String getWhereClause() { public String getWhereClause() {
String includeQueryStr = ""; // NON-NLS String includeQueryStr = ""; // NON-NLS
String excludeQueryStr = ""; String excludeQueryStr = "";
for (ParentSearchTerm searchTerm : parentSearchTerms) { for (ParentSearchTerm searchTerm : parentSearchTerms) {
@ -318,7 +317,7 @@ class SearchFiltering {
"SearchFiltering.ParentFilter.included=(included)", "SearchFiltering.ParentFilter.included=(included)",
"SearchFiltering.ParentFilter.excluded=(excluded)"}) "SearchFiltering.ParentFilter.excluded=(excluded)"})
@Override @Override
String getDesc() { public String getDesc() {
String desc = ""; // NON-NLS String desc = ""; // NON-NLS
for (ParentSearchTerm searchTerm : parentSearchTerms) { for (ParentSearchTerm searchTerm : parentSearchTerms) {
if (!desc.isEmpty()) { if (!desc.isEmpty()) {
@ -343,7 +342,7 @@ class SearchFiltering {
/** /**
* A filter for specifying data sources * A filter for specifying data sources
*/ */
static class DataSourceFilter extends AbstractFilter { public static class DataSourceFilter extends AbstractFilter {
private final List<DataSource> dataSources; private final List<DataSource> dataSources;
@ -352,12 +351,12 @@ class SearchFiltering {
* *
* @param dataSources the data sources to filter on * @param dataSources the data sources to filter on
*/ */
DataSourceFilter(List<DataSource> dataSources) { public DataSourceFilter(List<DataSource> dataSources) {
this.dataSources = dataSources; this.dataSources = dataSources;
} }
@Override @Override
String getWhereClause() { public String getWhereClause() {
String queryStr = ""; // NON-NLS String queryStr = ""; // NON-NLS
for (DataSource ds : dataSources) { for (DataSource ds : dataSources) {
if (!queryStr.isEmpty()) { if (!queryStr.isEmpty()) {
@ -377,7 +376,7 @@ class SearchFiltering {
"# {1} - Data source ID", "# {1} - Data source ID",
"SearchFiltering.DataSourceFilter.datasource={0}({1})",}) "SearchFiltering.DataSourceFilter.datasource={0}({1})",})
@Override @Override
String getDesc() { public String getDesc() {
String desc = ""; // NON-NLS String desc = ""; // NON-NLS
for (DataSource ds : dataSources) { for (DataSource ds : dataSources) {
if (!desc.isEmpty()) { if (!desc.isEmpty()) {
@ -394,7 +393,7 @@ class SearchFiltering {
* A filter for specifying keyword list names. A file must contain a keyword * A filter for specifying keyword list names. A file must contain a keyword
* from one of the given lists to pass. * from one of the given lists to pass.
*/ */
static class KeywordListFilter extends AbstractFilter { public static class KeywordListFilter extends AbstractFilter {
private final List<String> listNames; private final List<String> listNames;
@ -403,12 +402,12 @@ class SearchFiltering {
* *
* @param listNames * @param listNames
*/ */
KeywordListFilter(List<String> listNames) { public KeywordListFilter(List<String> listNames) {
this.listNames = listNames; this.listNames = listNames;
} }
@Override @Override
String getWhereClause() { public String getWhereClause() {
String keywordListPart = concatenateNamesForSQL(listNames); String keywordListPart = concatenateNamesForSQL(listNames);
String queryStr = "(obj_id IN (SELECT obj_id from blackboard_artifacts WHERE artifact_id IN " String queryStr = "(obj_id IN (SELECT obj_id from blackboard_artifacts WHERE artifact_id IN "
@ -422,7 +421,7 @@ class SearchFiltering {
"# {0} - filters", "# {0} - filters",
"SearchFiltering.KeywordListFilter.desc=Keywords in list(s): {0}",}) "SearchFiltering.KeywordListFilter.desc=Keywords in list(s): {0}",})
@Override @Override
String getDesc() { public String getDesc() {
return Bundle.SearchFiltering_KeywordListFilter_desc(concatenateSetNamesForDisplay(listNames)); return Bundle.SearchFiltering_KeywordListFilter_desc(concatenateSetNamesForDisplay(listNames));
} }
} }
@ -430,7 +429,7 @@ class SearchFiltering {
/** /**
* A filter for specifying file types. * A filter for specifying file types.
*/ */
static class FileTypeFilter extends AbstractFilter { public static class FileTypeFilter extends AbstractFilter {
private final List<FileType> categories; private final List<FileType> categories;
@ -439,7 +438,7 @@ class SearchFiltering {
* *
* @param categories List of file types to filter on * @param categories List of file types to filter on
*/ */
FileTypeFilter(List<FileType> categories) { public FileTypeFilter(List<FileType> categories) {
this.categories = categories; this.categories = categories;
} }
@ -448,13 +447,13 @@ class SearchFiltering {
* *
* @param category the file type to filter on * @param category the file type to filter on
*/ */
FileTypeFilter(FileType category) { public FileTypeFilter(FileType category) {
this.categories = new ArrayList<>(); this.categories = new ArrayList<>();
this.categories.add(category); this.categories.add(category);
} }
@Override @Override
String getWhereClause() { public String getWhereClause() {
String queryStr = ""; // NON-NLS String queryStr = ""; // NON-NLS
for (FileType cat : categories) { for (FileType cat : categories) {
for (String type : cat.getMediaTypes()) { for (String type : cat.getMediaTypes()) {
@ -473,7 +472,7 @@ class SearchFiltering {
"SearchFiltering.FileTypeFilter.desc=Type: {0}", "SearchFiltering.FileTypeFilter.desc=Type: {0}",
"SearchFiltering.FileTypeFilter.or=, ",}) "SearchFiltering.FileTypeFilter.or=, ",})
@Override @Override
String getDesc() { public String getDesc() {
String desc = ""; String desc = "";
for (FileType cat : categories) { for (FileType cat : categories) {
if (!desc.isEmpty()) { if (!desc.isEmpty()) {
@ -489,7 +488,7 @@ class SearchFiltering {
/** /**
* A filter for specifying frequency in the central repository. * A filter for specifying frequency in the central repository.
*/ */
static class FrequencyFilter extends AbstractFilter { public static class FrequencyFilter extends AbstractFilter {
private final List<Frequency> frequencies; private final List<Frequency> frequencies;
@ -498,24 +497,24 @@ class SearchFiltering {
* *
* @param frequencies List of frequencies that will pass the filter * @param frequencies List of frequencies that will pass the filter
*/ */
FrequencyFilter(List<Frequency> frequencies) { public FrequencyFilter(List<Frequency> frequencies) {
this.frequencies = frequencies; this.frequencies = frequencies;
} }
@Override @Override
String getWhereClause() { public String getWhereClause() {
// Since this relies on the central repository database, there is no // Since this relies on the central repository database, there is no
// query on the case database. // query on the case database.
return ""; // NON-NLS return ""; // NON-NLS
} }
@Override @Override
boolean useAlternateFilter() { public boolean useAlternateFilter() {
return true; return true;
} }
@Override @Override
List<ResultFile> applyAlternateFilter(List<ResultFile> currentResults, SleuthkitCase caseDb, public List<ResultFile> applyAlternateFilter(List<ResultFile> currentResults, SleuthkitCase caseDb,
CentralRepository centralRepoDb) throws FileSearchException { CentralRepository centralRepoDb) throws FileSearchException {
// We have to have run some kind of SQL filter before getting to this point, // We have to have run some kind of SQL filter before getting to this point,
@ -543,7 +542,7 @@ class SearchFiltering {
"SearchFiltering.FrequencyFilter.desc=Past occurrences: {0}", "SearchFiltering.FrequencyFilter.desc=Past occurrences: {0}",
"SearchFiltering.FrequencyFilter.or=, ",}) "SearchFiltering.FrequencyFilter.or=, ",})
@Override @Override
String getDesc() { public String getDesc() {
String desc = ""; // NON-NLS String desc = ""; // NON-NLS
for (Frequency freq : frequencies) { for (Frequency freq : frequencies) {
if (!desc.isEmpty()) { if (!desc.isEmpty()) {
@ -559,7 +558,7 @@ class SearchFiltering {
* A filter for specifying hash set names. A file must match one of the * A filter for specifying hash set names. A file must match one of the
* given sets to pass. * given sets to pass.
*/ */
static class HashSetFilter extends AbstractFilter { public static class HashSetFilter extends AbstractFilter {
private final List<String> setNames; private final List<String> setNames;
@ -568,12 +567,12 @@ class SearchFiltering {
* *
* @param setNames * @param setNames
*/ */
HashSetFilter(List<String> setNames) { public HashSetFilter(List<String> setNames) {
this.setNames = setNames; this.setNames = setNames;
} }
@Override @Override
String getWhereClause() { public String getWhereClause() {
String hashSetPart = concatenateNamesForSQL(setNames); String hashSetPart = concatenateNamesForSQL(setNames);
String queryStr = "(obj_id IN (SELECT obj_id from blackboard_artifacts WHERE artifact_id IN " String queryStr = "(obj_id IN (SELECT obj_id from blackboard_artifacts WHERE artifact_id IN "
@ -588,7 +587,7 @@ class SearchFiltering {
"# {0} - filters", "# {0} - filters",
"FileSearchFiltering.HashSetFilter.desc=Hash set hits in set(s): {0}",}) "FileSearchFiltering.HashSetFilter.desc=Hash set hits in set(s): {0}",})
@Override @Override
String getDesc() { public String getDesc() {
return Bundle.FileSearchFiltering_HashSetFilter_desc(concatenateSetNamesForDisplay(setNames)); return Bundle.FileSearchFiltering_HashSetFilter_desc(concatenateSetNamesForDisplay(setNames));
} }
} }
@ -597,7 +596,7 @@ class SearchFiltering {
* A filter for specifying interesting file set names. A file must match one * A filter for specifying interesting file set names. A file must match one
* of the given sets to pass. * of the given sets to pass.
*/ */
static class InterestingFileSetFilter extends AbstractFilter { public static class InterestingFileSetFilter extends AbstractFilter {
private final List<String> setNames; private final List<String> setNames;
@ -606,12 +605,12 @@ class SearchFiltering {
* *
* @param setNames * @param setNames
*/ */
InterestingFileSetFilter(List<String> setNames) { public InterestingFileSetFilter(List<String> setNames) {
this.setNames = setNames; this.setNames = setNames;
} }
@Override @Override
String getWhereClause() { public String getWhereClause() {
String intItemSetPart = concatenateNamesForSQL(setNames); String intItemSetPart = concatenateNamesForSQL(setNames);
String queryStr = "(obj_id IN (SELECT obj_id from blackboard_artifacts WHERE artifact_id IN " String queryStr = "(obj_id IN (SELECT obj_id from blackboard_artifacts WHERE artifact_id IN "
@ -626,7 +625,7 @@ class SearchFiltering {
"# {0} - filters", "# {0} - filters",
"SearchFiltering.InterestingItemSetFilter.desc=Interesting item hits in set(s): {0}",}) "SearchFiltering.InterestingItemSetFilter.desc=Interesting item hits in set(s): {0}",})
@Override @Override
String getDesc() { public String getDesc() {
return Bundle.SearchFiltering_InterestingItemSetFilter_desc(concatenateSetNamesForDisplay(setNames)); return Bundle.SearchFiltering_InterestingItemSetFilter_desc(concatenateSetNamesForDisplay(setNames));
} }
} }
@ -635,7 +634,7 @@ class SearchFiltering {
* A filter for specifying object types detected. A file must match one of * A filter for specifying object types detected. A file must match one of
* the given types to pass. * the given types to pass.
*/ */
static class ObjectDetectionFilter extends AbstractFilter { public static class ObjectDetectionFilter extends AbstractFilter {
private final List<String> typeNames; private final List<String> typeNames;
@ -644,12 +643,12 @@ class SearchFiltering {
* *
* @param typeNames * @param typeNames
*/ */
ObjectDetectionFilter(List<String> typeNames) { public ObjectDetectionFilter(List<String> typeNames) {
this.typeNames = typeNames; this.typeNames = typeNames;
} }
@Override @Override
String getWhereClause() { public String getWhereClause() {
String objTypePart = concatenateNamesForSQL(typeNames); String objTypePart = concatenateNamesForSQL(typeNames);
String queryStr = "(obj_id IN (SELECT obj_id from blackboard_artifacts WHERE artifact_id IN " String queryStr = "(obj_id IN (SELECT obj_id from blackboard_artifacts WHERE artifact_id IN "
@ -664,7 +663,7 @@ class SearchFiltering {
"# {0} - filters", "# {0} - filters",
"SearchFiltering.ObjectDetectionFilter.desc=Objects detected in set(s): {0}",}) "SearchFiltering.ObjectDetectionFilter.desc=Objects detected in set(s): {0}",})
@Override @Override
String getDesc() { public String getDesc() {
return Bundle.SearchFiltering_ObjectDetectionFilter_desc(concatenateSetNamesForDisplay(typeNames)); return Bundle.SearchFiltering_ObjectDetectionFilter_desc(concatenateSetNamesForDisplay(typeNames));
} }
} }
@ -673,7 +672,7 @@ class SearchFiltering {
* A filter for specifying the score. A file must have one of the given * A filter for specifying the score. A file must have one of the given
* scores to pass * scores to pass
*/ */
static class ScoreFilter extends AbstractFilter { public static class ScoreFilter extends AbstractFilter {
private final List<Score> scores; private final List<Score> scores;
@ -682,12 +681,12 @@ class SearchFiltering {
* *
* @param typeNames * @param typeNames
*/ */
ScoreFilter(List<Score> scores) { public ScoreFilter(List<Score> scores) {
this.scores = scores; this.scores = scores;
} }
@Override @Override
String getWhereClause() { public String getWhereClause() {
// Current algorithm: // Current algorithm:
// "Notable" if the file is a match for a notable hashset or has been tagged with a notable tag. // "Notable" if the file is a match for a notable hashset or has been tagged with a notable tag.
@ -740,7 +739,7 @@ class SearchFiltering {
"# {0} - filters", "# {0} - filters",
"SearchFiltering.ScoreFilter.desc=Score(s) of : {0}",}) "SearchFiltering.ScoreFilter.desc=Score(s) of : {0}",})
@Override @Override
String getDesc() { public String getDesc() {
return Bundle.SearchFiltering_ScoreFilter_desc( return Bundle.SearchFiltering_ScoreFilter_desc(
concatenateSetNamesForDisplay(scores.stream().map(p -> p.toString()).collect(Collectors.toList()))); concatenateSetNamesForDisplay(scores.stream().map(p -> p.toString()).collect(Collectors.toList())));
} }
@ -750,7 +749,7 @@ class SearchFiltering {
* A filter for specifying tag names. A file must contain one of the given * A filter for specifying tag names. A file must contain one of the given
* tags to pass. * tags to pass.
*/ */
static class TagsFilter extends AbstractFilter { public static class TagsFilter extends AbstractFilter {
private final List<TagName> tagNames; private final List<TagName> tagNames;
@ -759,12 +758,12 @@ class SearchFiltering {
* *
* @param tagNames * @param tagNames
*/ */
TagsFilter(List<TagName> tagNames) { public TagsFilter(List<TagName> tagNames) {
this.tagNames = tagNames; this.tagNames = tagNames;
} }
@Override @Override
String getWhereClause() { public String getWhereClause() {
String tagIDs = ""; // NON-NLS String tagIDs = ""; // NON-NLS
for (TagName tagName : tagNames) { for (TagName tagName : tagNames) {
if (!tagIDs.isEmpty()) { if (!tagIDs.isEmpty()) {
@ -783,7 +782,7 @@ class SearchFiltering {
"FileSearchFiltering.TagsFilter.desc=Tagged {0}", "FileSearchFiltering.TagsFilter.desc=Tagged {0}",
"FileSearchFiltering.TagsFilter.or=, ",}) "FileSearchFiltering.TagsFilter.or=, ",})
@Override @Override
String getDesc() { public String getDesc() {
String desc = ""; // NON-NLS String desc = ""; // NON-NLS
for (TagName name : tagNames) { for (TagName name : tagNames) {
if (!desc.isEmpty()) { if (!desc.isEmpty()) {
@ -799,17 +798,10 @@ class SearchFiltering {
* A filter for specifying that the file must have user content suspected * A filter for specifying that the file must have user content suspected
* data. * data.
*/ */
static class UserCreatedFilter extends AbstractFilter { public static class UserCreatedFilter extends AbstractFilter {
/**
* Create the ExifFilter
*/
UserCreatedFilter() {
// Nothing to save
}
@Override @Override
String getWhereClause() { public String getWhereClause() {
return "(obj_id IN (SELECT obj_id from blackboard_artifacts WHERE artifact_id IN " return "(obj_id IN (SELECT obj_id from blackboard_artifacts WHERE artifact_id IN "
+ "(SELECT artifact_id FROM blackboard_attributes WHERE artifact_type_id = " + "(SELECT artifact_id FROM blackboard_attributes WHERE artifact_type_id = "
+ BlackboardArtifact.ARTIFACT_TYPE.TSK_USER_CONTENT_SUSPECTED.getTypeID() + ")))"; + BlackboardArtifact.ARTIFACT_TYPE.TSK_USER_CONTENT_SUSPECTED.getTypeID() + ")))";
@ -818,7 +810,7 @@ class SearchFiltering {
@NbBundle.Messages({ @NbBundle.Messages({
"FileSearchFiltering.UserCreatedFilter.desc=that contain EXIF data",}) "FileSearchFiltering.UserCreatedFilter.desc=that contain EXIF data",})
@Override @Override
String getDesc() { public String getDesc() {
return Bundle.FileSearchFiltering_UserCreatedFilter_desc(); return Bundle.FileSearchFiltering_UserCreatedFilter_desc();
} }
} }
@ -827,29 +819,22 @@ class SearchFiltering {
* A filter for specifying that the file must have been marked as notable in * A filter for specifying that the file must have been marked as notable in
* the CR. * the CR.
*/ */
static class NotableFilter extends AbstractFilter { public static class NotableFilter extends AbstractFilter {
/**
* Create the NotableFilter
*/
NotableFilter() {
// Nothing to save
}
@Override @Override
String getWhereClause() { public String getWhereClause() {
// Since this relies on the central repository database, there is no // Since this relies on the central repository database, there is no
// query on the case database. // query on the case database.
return ""; // NON-NLS return ""; // NON-NLS
} }
@Override @Override
boolean useAlternateFilter() { public boolean useAlternateFilter() {
return true; return true;
} }
@Override @Override
List<ResultFile> applyAlternateFilter(List<ResultFile> currentResults, SleuthkitCase caseDb, public List<ResultFile> applyAlternateFilter(List<ResultFile> currentResults, SleuthkitCase caseDb,
CentralRepository centralRepoDb) throws FileSearchException { CentralRepository centralRepoDb) throws FileSearchException {
if (centralRepoDb == null) { if (centralRepoDb == null) {
@ -887,7 +872,7 @@ class SearchFiltering {
@NbBundle.Messages({ @NbBundle.Messages({
"FileSearchFiltering.PreviouslyNotableFilter.desc=that were previously marked as notable",}) "FileSearchFiltering.PreviouslyNotableFilter.desc=that were previously marked as notable",})
@Override @Override
String getDesc() { public String getDesc() {
return Bundle.FileSearchFiltering_PreviouslyNotableFilter_desc(); return Bundle.FileSearchFiltering_PreviouslyNotableFilter_desc();
} }
} }
@ -895,17 +880,17 @@ class SearchFiltering {
/** /**
* A filter for specifying if known files should be included. * A filter for specifying if known files should be included.
*/ */
static class KnownFilter extends AbstractFilter { public static class KnownFilter extends AbstractFilter {
@Override @Override
String getWhereClause() { public String getWhereClause() {
return "known!=" + TskData.FileKnown.KNOWN.getFileKnownValue(); // NON-NLS return "known!=" + TskData.FileKnown.KNOWN.getFileKnownValue(); // NON-NLS
} }
@NbBundle.Messages({ @NbBundle.Messages({
"FileSearchFiltering.KnownFilter.desc=which are not known"}) "FileSearchFiltering.KnownFilter.desc=which are not known"})
@Override @Override
String getDesc() { public String getDesc() {
return Bundle.FileSearchFiltering_KnownFilter_desc(); return Bundle.FileSearchFiltering_KnownFilter_desc();
} }
} }

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.discovery; package org.sleuthkit.autopsy.discovery.search;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -25,7 +25,7 @@ import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.sleuthkit.autopsy.discovery.FileSearch.GroupKey; import org.sleuthkit.autopsy.discovery.search.DiscoveryKeyUtils.GroupKey;
/** /**
* Class to hold the results of the filtering/grouping/sorting operations. * Class to hold the results of the filtering/grouping/sorting operations.
@ -36,7 +36,7 @@ class SearchResults {
private final FileSearch.AttributeType attrType; private final FileSearch.AttributeType attrType;
private final FileSorter fileSorter; private final FileSorter fileSorter;
private final Map<FileSearch.GroupKey, FileGroup> groupMap = new HashMap<>(); private final Map<GroupKey, FileGroup> groupMap = new HashMap<>();
private List<FileGroup> groupList = new ArrayList<>(); private List<FileGroup> groupList = new ArrayList<>();
private static final long MAX_OUTPUT_FILES = 2000; // For debug UI - maximum number of lines to print private static final long MAX_OUTPUT_FILES = 2000; // For debug UI - maximum number of lines to print
@ -75,7 +75,7 @@ class SearchResults {
void add(List<ResultFile> files) { void add(List<ResultFile> files) {
for (ResultFile file : files) { for (ResultFile file : files) {
// Add the file to the appropriate group, creating it if necessary // Add the file to the appropriate group, creating it if necessary
FileSearch.GroupKey groupKey = attrType.getGroupKey(file); GroupKey groupKey = attrType.getGroupKey(file);
if (!groupMap.containsKey(groupKey)) { if (!groupMap.containsKey(groupKey)) {
groupMap.put(groupKey, new FileGroup(groupSortingType, groupKey)); groupMap.put(groupKey, new FileGroup(groupSortingType, groupKey));

View File

@ -0,0 +1,236 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.discovery.search;
import com.google.common.io.Files;
import java.awt.Image;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.logging.Level;
import org.apache.commons.lang.StringUtils;
import org.openide.util.Lookup;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.coreutils.ImageUtils;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.textextractors.TextExtractor;
import org.sleuthkit.autopsy.textextractors.TextExtractorFactory;
import org.sleuthkit.autopsy.textsummarizer.TextSummarizer;
import org.sleuthkit.autopsy.textsummarizer.TextSummary;
import org.sleuthkit.autopsy.texttranslation.NoServiceProviderException;
import org.sleuthkit.autopsy.texttranslation.TextTranslationService;
import org.sleuthkit.autopsy.texttranslation.TranslationException;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException;
/**
* Utility class for code which helps create summaries for Discovery.
*/
class SummaryHelpers {
private static final int PREVIEW_SIZE = 256;
private final static Logger logger = Logger.getLogger(SummaryHelpers.class.getName());
private static volatile TextSummarizer summarizerToUse = null;
private SummaryHelpers() {
// Class should not be instantiated
}
static TextSummary getDefaultSummary(AbstractFile file) {
Image image = null;
int countOfImages = 0;
try {
Content largestChild = null;
for (Content child : file.getChildren()) {
if (child instanceof AbstractFile && ImageUtils.isImageThumbnailSupported((AbstractFile) child)) {
countOfImages++;
if (largestChild == null || child.getSize() > largestChild.getSize()) {
largestChild = child;
}
}
}
if (largestChild != null) {
image = ImageUtils.getThumbnail(largestChild, ImageUtils.ICON_SIZE_LARGE);
}
} catch (TskCoreException ex) {
logger.log(Level.WARNING, "Error getting children for file: " + file.getId(), ex);
}
image = image == null ? image : image.getScaledInstance(ImageUtils.ICON_SIZE_MEDIUM, ImageUtils.ICON_SIZE_MEDIUM,
Image.SCALE_SMOOTH);
String summaryText = null;
if (file.getMd5Hash() != null) {
try {
summaryText = getSavedSummary(Paths.get(Case.getCurrentCaseThrows().getCacheDirectory(), "summaries", file.getMd5Hash() + "-default-" + PREVIEW_SIZE + "-translated.txt").toString());
} catch (NoCurrentCaseException ex) {
logger.log(Level.WARNING, "Unable to retrieve saved summary. No case is open.", ex);
}
}
if (StringUtils.isBlank(summaryText)) {
String firstLines = getFirstLines(file);
String translatedFirstLines = getTranslatedVersion(firstLines);
if (!StringUtils.isBlank(translatedFirstLines)) {
summaryText = translatedFirstLines;
if (file.getMd5Hash() != null) {
try {
saveSummary(summaryText, Paths.get(Case.getCurrentCaseThrows().getCacheDirectory(), "summaries", file.getMd5Hash() + "-default-" + PREVIEW_SIZE + "-translated.txt").toString());
} catch (NoCurrentCaseException ex) {
logger.log(Level.WARNING, "Unable to save translated summary. No case is open.", ex);
}
}
} else {
summaryText = firstLines;
}
}
return new TextSummary(summaryText, image, countOfImages);
}
/**
* Provide an English version of the specified String if it is not English,
* translation is enabled, and it can be translated.
*
* @param documentString The String to provide an English version of.
*
* @return The English version of the provided String, or null if no
* translation occurred.
*/
static String getTranslatedVersion(String documentString) {
try {
TextTranslationService translatorInstance = TextTranslationService.getInstance();
if (translatorInstance.hasProvider()) {
String translatedResult = translatorInstance.translate(documentString);
if (translatedResult.isEmpty() == false) {
return translatedResult;
}
}
} catch (NoServiceProviderException | TranslationException ex) {
logger.log(Level.INFO, "Error translating string for summary", ex);
}
return null;
}
/**
* Find and load a saved summary from the case folder for the specified
* file.
*
* @param summarySavePath The full path for the saved summary file.
*
* @return The summary found given the specified path, null if no summary
* was found.
*/
static String getSavedSummary(String summarySavePath) {
if (summarySavePath == null) {
return null;
}
File savedFile = new File(summarySavePath);
if (savedFile.exists()) {
try (BufferedReader bReader = new BufferedReader(new FileReader(savedFile))) {
// pass the path to the file as a parameter
StringBuilder sBuilder = new StringBuilder(PREVIEW_SIZE);
String sCurrentLine = bReader.readLine();
while (sCurrentLine != null) {
sBuilder.append(sCurrentLine).append('\n');
sCurrentLine = bReader.readLine();
}
return sBuilder.toString();
} catch (IOException ingored) {
//summary file may not exist or may be incomplete in which case return null so a summary can be generated
return null; //no saved summary was able to be found
}
} else {
try { //if the file didn't exist make sure the parent directories exist before we move on to creating a summary
Files.createParentDirs(savedFile);
} catch (IOException ex) {
logger.log(Level.WARNING, "Unable to create summaries directory in case folder for file at: " + summarySavePath, ex);
}
return null; //no saved summary was able to be found
}
}
/**
* Save a summary at the specified location.
*
* @param summary The text of the summary being saved.
* @param summarySavePath The full path for the saved summary file.
*/
static void saveSummary(String summary, String summarySavePath) {
if (summarySavePath == null) {
return; //can't save a summary if we don't have a path
}
try (FileWriter myWriter = new FileWriter(summarySavePath)) {
myWriter.write(summary);
} catch (IOException ex) {
logger.log(Level.WARNING, "Unable to save summary at: " + summarySavePath, ex);
}
}
/**
* Get the beginning of text from the specified AbstractFile.
*
* @param file The AbstractFile to get text from.
*
* @return The beginning of text from the specified AbstractFile.
*/
static String getFirstLines(AbstractFile file) {
TextExtractor extractor;
try {
extractor = TextExtractorFactory.getExtractor(file, null);
} catch (TextExtractorFactory.NoTextExtractorFound ignored) {
//no extractor found, use Strings Extractor
extractor = TextExtractorFactory.getStringsExtractor(file, null);
}
try (Reader reader = extractor.getReader()) {
char[] cbuf = new char[PREVIEW_SIZE];
reader.read(cbuf, 0, PREVIEW_SIZE);
return new String(cbuf);
} catch (IOException ex) {
return Bundle.FileSearch_documentSummary_noBytes();
} catch (TextExtractor.InitReaderException ex) {
return Bundle.FileSearch_documentSummary_noPreview();
}
}
/**
* Get the first TextSummarizer found by a lookup of TextSummarizers.
*
* @return The first TextSummarizer found by a lookup of TextSummarizers.
*
* @throws IOException
*/
static TextSummarizer getLocalSummarizer() {
if (summarizerToUse == null) {
Collection<? extends TextSummarizer> summarizers
= Lookup.getDefault().lookupAll(TextSummarizer.class
);
if (!summarizers.isEmpty()) {
summarizerToUse = summarizers.iterator().next();
}
}
return summarizerToUse;
}
}

View File

@ -18,6 +18,7 @@
*/ */
package org.sleuthkit.autopsy.discovery.ui; package org.sleuthkit.autopsy.discovery.ui;
import org.sleuthkit.autopsy.discovery.search.AbstractFilter;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import javax.swing.JCheckBox; import javax.swing.JCheckBox;
import javax.swing.JLabel; import javax.swing.JLabel;

View File

@ -18,6 +18,7 @@
*/ */
package org.sleuthkit.autopsy.discovery.ui; package org.sleuthkit.autopsy.discovery.ui;
import org.sleuthkit.autopsy.discovery.search.AbstractFilter;
import java.awt.Component; import java.awt.Component;
import java.awt.GridBagConstraints; import java.awt.GridBagConstraints;
import java.awt.GridBagLayout; import java.awt.GridBagLayout;
@ -31,10 +32,10 @@ import javax.swing.JSplitPane;
import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener; import javax.swing.event.ListSelectionListener;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.sleuthkit.autopsy.discovery.AttributeSearchData; import org.sleuthkit.autopsy.discovery.search.AttributeSearchData;
import org.sleuthkit.autopsy.discovery.FileSearchData; import org.sleuthkit.autopsy.discovery.search.FileSearchData;
import org.sleuthkit.autopsy.discovery.SearchData; import org.sleuthkit.autopsy.discovery.search.SearchData;
import org.sleuthkit.autopsy.discovery.SearchFiltering; import org.sleuthkit.autopsy.discovery.search.SearchFiltering;
/** /**
* Abstract class extending JPanel for displaying all the filters associated * Abstract class extending JPanel for displaying all the filters associated

View File

@ -18,11 +18,12 @@
*/ */
package org.sleuthkit.autopsy.discovery.ui; package org.sleuthkit.autopsy.discovery.ui;
import org.sleuthkit.autopsy.discovery.search.AbstractFilter;
import javax.swing.DefaultListModel; import javax.swing.DefaultListModel;
import javax.swing.JCheckBox; import javax.swing.JCheckBox;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JList; import javax.swing.JList;
import org.sleuthkit.autopsy.discovery.AttributeSearchData; import org.sleuthkit.autopsy.discovery.search.AttributeSearchData;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
/** /**

View File

@ -18,6 +18,7 @@
*/ */
package org.sleuthkit.autopsy.discovery.ui; package org.sleuthkit.autopsy.discovery.ui;
import org.sleuthkit.autopsy.discovery.search.AbstractFilter;
import java.util.List; import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -27,7 +28,7 @@ import javax.swing.JLabel;
import javax.swing.JList; import javax.swing.JList;
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.discovery.SearchFiltering; import org.sleuthkit.autopsy.discovery.search.SearchFiltering;
import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.DataSource;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;

View File

@ -19,7 +19,6 @@
package org.sleuthkit.autopsy.discovery.ui; package org.sleuthkit.autopsy.discovery.ui;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.discovery.Bundle;
import org.sleuthkit.autopsy.modules.exif.ExifParserModuleFactory; import org.sleuthkit.autopsy.modules.exif.ExifParserModuleFactory;
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeIdModuleFactory; import org.sleuthkit.autopsy.modules.filetypeid.FileTypeIdModuleFactory;
import org.sleuthkit.autopsy.modules.hashdatabase.HashLookupModuleFactory; import org.sleuthkit.autopsy.modules.hashdatabase.HashLookupModuleFactory;

View File

@ -18,13 +18,13 @@
*/ */
package org.sleuthkit.autopsy.discovery.ui; package org.sleuthkit.autopsy.discovery.ui;
import org.sleuthkit.autopsy.discovery.search.AbstractFilter;
import javax.swing.JCheckBox; import javax.swing.JCheckBox;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JList; import javax.swing.JList;
import javax.swing.SpinnerNumberModel; import javax.swing.SpinnerNumberModel;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.communications.Utils; import org.sleuthkit.autopsy.communications.Utils;
import org.sleuthkit.autopsy.discovery.Bundle;
/** /**
* Filter panel for allowing the user to filter on date. * Filter panel for allowing the user to filter on date.

View File

@ -40,7 +40,7 @@ import org.sleuthkit.autopsy.datamodel.FileNode;
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction; import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
import org.sleuthkit.autopsy.directorytree.ViewContextAction; import org.sleuthkit.autopsy.directorytree.ViewContextAction;
import org.sleuthkit.autopsy.discovery.Bundle; import org.sleuthkit.autopsy.discovery.Bundle;
import org.sleuthkit.autopsy.discovery.DiscoveryEventUtils; import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils;
import org.sleuthkit.autopsy.modules.hashdatabase.AddContentToHashDbAction; import org.sleuthkit.autopsy.modules.hashdatabase.AddContentToHashDbAction;
import org.sleuthkit.autopsy.timeline.actions.ViewFileInTimelineAction; import org.sleuthkit.autopsy.timeline.actions.ViewFileInTimelineAction;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;

View File

@ -18,6 +18,7 @@
*/ */
package org.sleuthkit.autopsy.discovery.ui; package org.sleuthkit.autopsy.discovery.ui;
import org.sleuthkit.autopsy.discovery.search.AbstractFilter;
import static java.awt.BorderLayout.CENTER; import static java.awt.BorderLayout.CENTER;
import java.awt.Color; import java.awt.Color;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
@ -36,25 +37,24 @@ 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.AttributeSearchData; import org.sleuthkit.autopsy.discovery.search.AttributeSearchData;
import org.sleuthkit.autopsy.discovery.Bundle; import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils;
import org.sleuthkit.autopsy.discovery.DiscoveryEventUtils; import org.sleuthkit.autopsy.discovery.search.FileGroup;
import org.sleuthkit.autopsy.discovery.FileGroup; import org.sleuthkit.autopsy.discovery.search.FileGroup.GroupSortingAlgorithm;
import org.sleuthkit.autopsy.discovery.FileGroup.GroupSortingAlgorithm; import static org.sleuthkit.autopsy.discovery.search.FileGroup.GroupSortingAlgorithm.BY_GROUP_SIZE;
import org.sleuthkit.autopsy.discovery.FileSearch; import org.sleuthkit.autopsy.discovery.search.FileSearch;
import static org.sleuthkit.autopsy.discovery.FileGroup.GroupSortingAlgorithm.BY_GROUP_SIZE; import org.sleuthkit.autopsy.discovery.search.FileSearch.GroupingAttributeType;
import org.sleuthkit.autopsy.discovery.FileSearch.GroupingAttributeType; import static org.sleuthkit.autopsy.discovery.search.FileSearch.GroupingAttributeType.PARENT_PATH;
import org.sleuthkit.autopsy.discovery.FileSearchData; import org.sleuthkit.autopsy.discovery.search.FileSearchData;
import org.sleuthkit.autopsy.discovery.FileSorter; import org.sleuthkit.autopsy.discovery.search.FileSorter;
import static org.sleuthkit.autopsy.discovery.FileSearch.GroupingAttributeType.PARENT_PATH; import org.sleuthkit.autopsy.discovery.search.FileSorter.SortingMethod;
import org.sleuthkit.autopsy.discovery.FileSorter.SortingMethod; import static org.sleuthkit.autopsy.discovery.search.FileSorter.SortingMethod.BY_FILE_NAME;
import org.sleuthkit.autopsy.discovery.SearchData; import org.sleuthkit.autopsy.discovery.search.SearchData;
import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.ingest.ModuleDataEvent; import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
import static org.sleuthkit.autopsy.discovery.FileSorter.SortingMethod.BY_FILE_NAME;
/** /**
* Dialog for displaying the controls and filters for configuration of a * Dialog for displaying the controls and filters for configuration of a

View File

@ -106,7 +106,7 @@
<Component class="javax.swing.JButton" name="newSearchButton"> <Component class="javax.swing.JButton" name="newSearchButton">
<Properties> <Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/discovery/Bundle.properties" key="FileSearchDialog.cancelButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/discovery/ui/Bundle_1.properties" key="FileSearchDialog.cancelButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor"> <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[110, 26]"/> <Dimension value="[110, 26]"/>

View File

@ -18,6 +18,7 @@
*/ */
package org.sleuthkit.autopsy.discovery.ui; package org.sleuthkit.autopsy.discovery.ui;
import org.sleuthkit.autopsy.discovery.search.AbstractFilter;
import com.google.common.eventbus.Subscribe; import com.google.common.eventbus.Subscribe;
import java.awt.BorderLayout; import java.awt.BorderLayout;
import java.awt.Color; import java.awt.Color;
@ -36,9 +37,8 @@ import org.openide.windows.RetainLocation;
import org.openide.windows.TopComponent; import org.openide.windows.TopComponent;
import org.openide.windows.WindowManager; import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.coreutils.ThreadConfined;
import org.sleuthkit.autopsy.discovery.Bundle; import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils;
import org.sleuthkit.autopsy.discovery.DiscoveryEventUtils; import org.sleuthkit.autopsy.discovery.search.SearchData.ResultType;
import org.sleuthkit.autopsy.discovery.SearchData.ResultType;
/** /**
* Create a dialog for displaying the Discovery results. * Create a dialog for displaying the Discovery results.

View File

@ -18,27 +18,43 @@
*/ */
package org.sleuthkit.autopsy.discovery.ui; package org.sleuthkit.autopsy.discovery.ui;
import com.google.common.io.Files;
import java.awt.Component; import java.awt.Component;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Image;
import java.awt.Point; import java.awt.Point;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon; import javax.swing.ImageIcon;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.JScrollPane; import javax.swing.JScrollPane;
import javax.swing.JTextPane; import javax.swing.JTextPane;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.imgscalr.Scalr;
import org.netbeans.api.progress.ProgressHandle;
import org.opencv.core.Mat;
import org.opencv.highgui.VideoCapture;
import org.openide.util.ImageUtilities; import org.openide.util.ImageUtilities;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.corelibs.ScalrWrapper;
import org.sleuthkit.autopsy.coreutils.ImageUtils;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.discovery.Bundle; import static org.sleuthkit.autopsy.coreutils.VideoUtils.getVideoFileInTempDir;
import org.sleuthkit.autopsy.discovery.ResultFile; import org.sleuthkit.autopsy.datamodel.ContentUtils;
import org.sleuthkit.autopsy.discovery.search.ResultFile;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.DataSource;
@ -62,6 +78,9 @@ final class DiscoveryUiUtils {
private static final ImageIcon NOTABLE_SCORE_ICON = new ImageIcon(ImageUtilities.loadImage(RED_CIRCLE_ICON_PATH, false)); private static final ImageIcon NOTABLE_SCORE_ICON = new ImageIcon(ImageUtilities.loadImage(RED_CIRCLE_ICON_PATH, false));
private static final ImageIcon DELETED_ICON = new ImageIcon(ImageUtilities.loadImage(DELETE_ICON_PATH, false)); private static final ImageIcon DELETED_ICON = new ImageIcon(ImageUtilities.loadImage(DELETE_ICON_PATH, false));
private static final ImageIcon UNSUPPORTED_DOCUMENT_THUMBNAIL = new ImageIcon(ImageUtilities.loadImage(UNSUPPORTED_DOC_PATH, false)); private static final ImageIcon UNSUPPORTED_DOCUMENT_THUMBNAIL = new ImageIcon(ImageUtilities.loadImage(UNSUPPORTED_DOC_PATH, false));
private static final String THUMBNAIL_FORMAT = "png"; //NON-NLS
private static final String VIDEO_THUMBNAIL_DIR = "video-thumbnails"; //NON-NLS
private static final BufferedImage VIDEO_DEFAULT_IMAGE = getDefaultVideoThumbnail();
@NbBundle.Messages({"# {0} - fileSize", @NbBundle.Messages({"# {0} - fileSize",
"# {1} - units", "# {1} - units",
@ -166,10 +185,11 @@ final class DiscoveryUiUtils {
* false otherwise. * false otherwise.
* @param isDeletedLabel The label to set the icon and tooltip for. * @param isDeletedLabel The label to set the icon and tooltip for.
*/ */
@NbBundle.Messages({"DiscoveryUiUtils.isDeleted.text=All instances of file are deleted."})
static void setDeletedIcon(boolean isDeleted, javax.swing.JLabel isDeletedLabel) { static void setDeletedIcon(boolean isDeleted, javax.swing.JLabel isDeletedLabel) {
if (isDeleted) { if (isDeleted) {
isDeletedLabel.setIcon(DELETED_ICON); isDeletedLabel.setIcon(DELETED_ICON);
isDeletedLabel.setToolTipText(Bundle.ImageThumbnailPanel_isDeleted_text()); isDeletedLabel.setToolTipText(Bundle.DiscoveryUiUtils_isDeleted_text());
} else { } else {
isDeletedLabel.setIcon(null); isDeletedLabel.setIcon(null);
isDeletedLabel.setToolTipText(null); isDeletedLabel.setToolTipText(null);
@ -246,6 +266,272 @@ final class DiscoveryUiUtils {
dialog.validateDialog(); dialog.validateDialog();
} }
/**
* Get the video thumbnails for a file which exists in a
* VideoThumbnailsWrapper and update the VideoThumbnailsWrapper to include
* them.
*
* @param thumbnailWrapper the object which contains the file to generate
* thumbnails for.
*
*/
@NbBundle.Messages({"# {0} - file name",
"DiscoveryUiUtils.genVideoThumb.progress.text=extracting temporary file {0}"})
static void getVideoThumbnails(VideoThumbnailsWrapper thumbnailWrapper) {
AbstractFile file = thumbnailWrapper.getResultFile().getFirstInstance();
String cacheDirectory;
try {
cacheDirectory = Case.getCurrentCaseThrows().getCacheDirectory();
} catch (NoCurrentCaseException ex) {
cacheDirectory = null;
logger.log(Level.WARNING, "Unable to get cache directory, video thumbnails will not be saved", ex);
}
if (cacheDirectory == null || file.getMd5Hash() == null || !Paths.get(cacheDirectory, VIDEO_THUMBNAIL_DIR, file.getMd5Hash()).toFile().exists()) {
java.io.File tempFile;
try {
tempFile = getVideoFileInTempDir(file);
} catch (NoCurrentCaseException ex) {
logger.log(Level.WARNING, "Exception while getting open case.", ex); //NON-NLS
int[] framePositions = new int[]{
0,
0,
0,
0};
thumbnailWrapper.setThumbnails(createDefaultThumbnailList(VIDEO_DEFAULT_IMAGE), framePositions);
return;
}
if (tempFile.exists() == false || tempFile.length() < file.getSize()) {
ProgressHandle progress = ProgressHandle.createHandle(Bundle.DiscoveryUiUtils_genVideoThumb_progress_text(file.getName()));
progress.start(100);
try {
Files.createParentDirs(tempFile);
if (Thread.interrupted()) {
int[] framePositions = new int[]{
0,
0,
0,
0};
thumbnailWrapper.setThumbnails(createDefaultThumbnailList(VIDEO_DEFAULT_IMAGE), framePositions);
return;
}
ContentUtils.writeToFile(file, tempFile, progress, null, true);
} catch (IOException ex) {
logger.log(Level.WARNING, "Error extracting temporary file for " + file.getParentPath() + "/" + file.getName(), ex); //NON-NLS
} finally {
progress.finish();
}
}
VideoCapture videoFile = new VideoCapture(); // will contain the video
BufferedImage bufferedImage = null;
try {
if (!videoFile.open(tempFile.toString())) {
logger.log(Level.WARNING, "Error opening {0} for preview generation.", file.getParentPath() + "/" + file.getName()); //NON-NLS
int[] framePositions = new int[]{
0,
0,
0,
0};
thumbnailWrapper.setThumbnails(createDefaultThumbnailList(VIDEO_DEFAULT_IMAGE), framePositions);
return;
}
double fps = videoFile.get(5); // gets frame per second
double totalFrames = videoFile.get(7); // gets total frames
if (fps <= 0 || totalFrames <= 0) {
logger.log(Level.WARNING, "Error getting fps or total frames for {0}", file.getParentPath() + "/" + file.getName()); //NON-NLS
int[] framePositions = new int[]{
0,
0,
0,
0};
thumbnailWrapper.setThumbnails(createDefaultThumbnailList(VIDEO_DEFAULT_IMAGE), framePositions);
return;
}
if (Thread.interrupted()) {
int[] framePositions = new int[]{
0,
0,
0,
0};
thumbnailWrapper.setThumbnails(createDefaultThumbnailList(VIDEO_DEFAULT_IMAGE), framePositions);
return;
}
double duration = 1000 * (totalFrames / fps); //total milliseconds
int[] framePositions = new int[]{
(int) (duration * .01),
(int) (duration * .25),
(int) (duration * .5),
(int) (duration * .75),};
Mat imageMatrix = new Mat();
List<Image> videoThumbnails = new ArrayList<>();
if (cacheDirectory == null || file.getMd5Hash() == null) {
cacheDirectory = null;
} else {
try {
FileUtils.forceMkdir(Paths.get(cacheDirectory, VIDEO_THUMBNAIL_DIR, file.getMd5Hash()).toFile());
} catch (IOException ex) {
cacheDirectory = null;
logger.log(Level.WARNING, "Unable to make video thumbnails directory, thumbnails will not be saved", ex);
}
}
for (int i = 0; i < framePositions.length; i++) {
if (!videoFile.set(0, framePositions[i])) {
logger.log(Level.WARNING, "Error seeking to " + framePositions[i] + "ms in {0}", file.getParentPath() + "/" + file.getName()); //NON-NLS
// If we can't set the time, continue to the next frame position and try again.
videoThumbnails.add(VIDEO_DEFAULT_IMAGE);
if (cacheDirectory != null) {
try {
ImageIO.write(VIDEO_DEFAULT_IMAGE, THUMBNAIL_FORMAT,
Paths.get(cacheDirectory, VIDEO_THUMBNAIL_DIR, file.getMd5Hash(), i + "-" + framePositions[i] + "." + THUMBNAIL_FORMAT).toFile()); //NON-NLS)
} catch (IOException ex) {
logger.log(Level.WARNING, "Unable to save default video thumbnail for " + file.getMd5Hash() + " at frame position " + framePositions[i], ex);
}
}
continue;
}
// Read the frame into the image/matrix.
if (!videoFile.read(imageMatrix)) {
logger.log(Level.WARNING, "Error reading frame at " + framePositions[i] + "ms from {0}", file.getParentPath() + "/" + file.getName()); //NON-NLS
// If the image is bad for some reason, continue to the next frame position and try again.
videoThumbnails.add(VIDEO_DEFAULT_IMAGE);
if (cacheDirectory != null) {
try {
ImageIO.write(VIDEO_DEFAULT_IMAGE, THUMBNAIL_FORMAT,
Paths.get(cacheDirectory, VIDEO_THUMBNAIL_DIR, file.getMd5Hash(), i + "-" + framePositions[i] + "." + THUMBNAIL_FORMAT).toFile()); //NON-NLS)
} catch (IOException ex) {
logger.log(Level.WARNING, "Unable to save default video thumbnail for " + file.getMd5Hash() + " at frame position " + framePositions[i], ex);
}
}
continue;
}
// If the image is empty, return since no buffered image can be created.
if (imageMatrix.empty()) {
videoThumbnails.add(VIDEO_DEFAULT_IMAGE);
if (cacheDirectory != null) {
try {
ImageIO.write(VIDEO_DEFAULT_IMAGE, THUMBNAIL_FORMAT,
Paths.get(cacheDirectory, VIDEO_THUMBNAIL_DIR, file.getMd5Hash(), i + "-" + framePositions[i] + "." + THUMBNAIL_FORMAT).toFile()); //NON-NLS)
} catch (IOException ex) {
logger.log(Level.WARNING, "Unable to save default video thumbnail for " + file.getMd5Hash() + " at frame position " + framePositions[i], ex);
}
}
continue;
}
int matrixColumns = imageMatrix.cols();
int matrixRows = imageMatrix.rows();
// Convert the matrix that contains the frame to a buffered image.
if (bufferedImage == null) {
bufferedImage = new BufferedImage(matrixColumns, matrixRows, BufferedImage.TYPE_3BYTE_BGR);
}
byte[] data = new byte[matrixRows * matrixColumns * (int) (imageMatrix.elemSize())];
imageMatrix.get(0, 0, data); //copy the image to data
if (imageMatrix.channels() == 3) {
for (int k = 0; k < data.length; k += 3) {
byte temp = data[k];
data[k] = data[k + 2];
data[k + 2] = temp;
}
}
bufferedImage.getRaster().setDataElements(0, 0, matrixColumns, matrixRows, data);
if (Thread.interrupted()) {
thumbnailWrapper.setThumbnails(videoThumbnails, framePositions);
try {
FileUtils.forceDelete(Paths.get(cacheDirectory, VIDEO_THUMBNAIL_DIR, file.getMd5Hash()).toFile());
} catch (IOException ex) {
logger.log(Level.WARNING, "Unable to delete directory for cancelled video thumbnail process", ex);
}
return;
}
BufferedImage thumbnail = ScalrWrapper.resize(bufferedImage, Scalr.Method.SPEED, Scalr.Mode.FIT_TO_HEIGHT, ImageUtils.ICON_SIZE_LARGE, ImageUtils.ICON_SIZE_MEDIUM, Scalr.OP_ANTIALIAS);
//We are height limited here so it can be wider than it can be tall.Scalr maintains the aspect ratio.
videoThumbnails.add(thumbnail);
if (cacheDirectory != null) {
try {
ImageIO.write(thumbnail, THUMBNAIL_FORMAT,
Paths.get(cacheDirectory, VIDEO_THUMBNAIL_DIR, file.getMd5Hash(), i + "-" + framePositions[i] + "." + THUMBNAIL_FORMAT).toFile()); //NON-NLS)
} catch (IOException ex) {
logger.log(Level.WARNING, "Unable to save video thumbnail for " + file.getMd5Hash() + " at frame position " + framePositions[i], ex);
}
}
}
thumbnailWrapper.setThumbnails(videoThumbnails, framePositions);
} finally {
videoFile.release(); // close the file}
}
} else {
loadSavedThumbnails(cacheDirectory, thumbnailWrapper, VIDEO_DEFAULT_IMAGE);
}
}
/**
* Get the default image to display when a thumbnail is not available.
*
* @return The default video thumbnail.
*/
private static BufferedImage getDefaultVideoThumbnail() {
try {
return ImageIO.read(ImageUtils.class
.getResourceAsStream("/org/sleuthkit/autopsy/images/failedToCreateVideoThumb.png"));//NON-NLS
} catch (IOException ex) {
logger.log(Level.SEVERE, "Failed to load 'failed to create video' placeholder.", ex); //NON-NLS
}
return null;
}
/**
* Load the thumbnails that exist in the cache directory for the specified
* video file.
*
* @param cacheDirectory The directory which exists for the video
* thumbnails.
* @param thumbnailWrapper The VideoThumbnailWrapper object which contains
* information about the file and the thumbnails
* associated with it.
*/
private static void loadSavedThumbnails(String cacheDirectory, VideoThumbnailsWrapper thumbnailWrapper, BufferedImage failedVideoThumbImage) {
int[] framePositions = new int[4];
List<Image> videoThumbnails = new ArrayList<>();
int thumbnailNumber = 0;
String md5 = thumbnailWrapper.getResultFile().getFirstInstance().getMd5Hash();
for (String fileName : Paths.get(cacheDirectory, VIDEO_THUMBNAIL_DIR, md5).toFile().list()) {
try {
videoThumbnails.add(ImageIO.read(Paths.get(cacheDirectory, VIDEO_THUMBNAIL_DIR, md5, fileName).toFile()));
} catch (IOException ex) {
videoThumbnails.add(failedVideoThumbImage);
logger.log(Level.WARNING, "Unable to read saved video thumbnail " + fileName + " for " + md5, ex);
}
int framePos = Integer.valueOf(FilenameUtils.getBaseName(fileName).substring(2));
framePositions[thumbnailNumber] = framePos;
thumbnailNumber++;
}
thumbnailWrapper.setThumbnails(videoThumbnails, framePositions);
}
/**
* Private helper method for creating video thumbnails, for use when no
* thumbnails are created.
*
* @return List containing the default thumbnail.
*/
private static List<Image> createDefaultThumbnailList(BufferedImage failedVideoThumbImage) {
List<Image> videoThumbnails = new ArrayList<>();
videoThumbnails.add(failedVideoThumbImage);
videoThumbnails.add(failedVideoThumbImage);
videoThumbnails.add(failedVideoThumbImage);
videoThumbnails.add(failedVideoThumbImage);
return videoThumbnails;
}
/** /**
* Private constructor for DiscoveryUiUtils utility class. * Private constructor for DiscoveryUiUtils utility class.
*/ */

View File

@ -19,9 +19,9 @@
package org.sleuthkit.autopsy.discovery.ui; package org.sleuthkit.autopsy.discovery.ui;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
import org.sleuthkit.autopsy.discovery.AttributeSearchData; import org.sleuthkit.autopsy.discovery.search.AttributeSearchData;
import org.sleuthkit.autopsy.discovery.FileSearchData; import org.sleuthkit.autopsy.discovery.search.FileSearchData;
import org.sleuthkit.autopsy.discovery.SearchData; import org.sleuthkit.autopsy.discovery.search.SearchData;
/** /**
* Class which displays all filters available for the Documents search type. * Class which displays all filters available for the Documents search type.

View File

@ -29,8 +29,7 @@ import javax.swing.JList;
import javax.swing.ListCellRenderer; import javax.swing.ListCellRenderer;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.corecomponents.AutoWrappingJTextPane; import org.sleuthkit.autopsy.corecomponents.AutoWrappingJTextPane;
import org.sleuthkit.autopsy.discovery.Bundle; import org.sleuthkit.autopsy.discovery.search.FileSearchData;
import org.sleuthkit.autopsy.discovery.FileSearchData;
/** /**
* Class which displays a preview and details about a document. * Class which displays a preview and details about a document.

View File

@ -19,8 +19,7 @@
package org.sleuthkit.autopsy.discovery.ui; package org.sleuthkit.autopsy.discovery.ui;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.discovery.Bundle; import org.sleuthkit.autopsy.discovery.search.ResultFile;
import org.sleuthkit.autopsy.discovery.ResultFile;
import org.sleuthkit.autopsy.textsummarizer.TextSummary; import org.sleuthkit.autopsy.textsummarizer.TextSummary;
/** /**

View File

@ -19,9 +19,9 @@
package org.sleuthkit.autopsy.discovery.ui; package org.sleuthkit.autopsy.discovery.ui;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
import org.sleuthkit.autopsy.discovery.AttributeSearchData; import org.sleuthkit.autopsy.discovery.search.AttributeSearchData;
import org.sleuthkit.autopsy.discovery.FileSearchData; import org.sleuthkit.autopsy.discovery.search.FileSearchData;
import org.sleuthkit.autopsy.discovery.SearchData; import org.sleuthkit.autopsy.discovery.search.SearchData;
/** /**
* Filter panel for searching domain attributes with Discovery. * Filter panel for searching domain attributes with Discovery.

View File

@ -18,6 +18,7 @@
*/ */
package org.sleuthkit.autopsy.discovery.ui; package org.sleuthkit.autopsy.discovery.ui;
import org.sleuthkit.autopsy.discovery.search.AbstractFilter;
import com.google.common.eventbus.Subscribe; import com.google.common.eventbus.Subscribe;
import java.awt.Cursor; import java.awt.Cursor;
import java.util.List; import java.util.List;
@ -28,13 +29,12 @@ 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.Bundle; import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils;
import org.sleuthkit.autopsy.discovery.DiscoveryEventUtils; import org.sleuthkit.autopsy.discovery.search.DiscoveryKeyUtils.GroupKey;
import org.sleuthkit.autopsy.discovery.FileGroup; import org.sleuthkit.autopsy.discovery.search.FileGroup;
import org.sleuthkit.autopsy.discovery.FileSearch; import org.sleuthkit.autopsy.discovery.search.FileSearch;
import org.sleuthkit.autopsy.discovery.FileSearch.GroupKey; import org.sleuthkit.autopsy.discovery.search.FileSearchData.FileType;
import org.sleuthkit.autopsy.discovery.FileSearchData.FileType; import org.sleuthkit.autopsy.discovery.search.FileSorter;
import org.sleuthkit.autopsy.discovery.FileSorter;
/** /**
* Panel to display the list of groups which are provided by a search. * Panel to display the list of groups which are provided by a search.

View File

@ -18,6 +18,7 @@
*/ */
package org.sleuthkit.autopsy.discovery.ui; package org.sleuthkit.autopsy.discovery.ui;
import org.sleuthkit.autopsy.discovery.search.AbstractFilter;
import java.util.List; import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.DefaultListModel; import javax.swing.DefaultListModel;
@ -25,7 +26,7 @@ import javax.swing.JCheckBox;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JList; import javax.swing.JList;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.discovery.SearchFiltering; import org.sleuthkit.autopsy.discovery.search.SearchFiltering;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;

View File

@ -19,9 +19,9 @@
package org.sleuthkit.autopsy.discovery.ui; package org.sleuthkit.autopsy.discovery.ui;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
import org.sleuthkit.autopsy.discovery.AttributeSearchData; import org.sleuthkit.autopsy.discovery.search.AttributeSearchData;
import org.sleuthkit.autopsy.discovery.FileSearchData; import org.sleuthkit.autopsy.discovery.search.FileSearchData;
import org.sleuthkit.autopsy.discovery.SearchData; import org.sleuthkit.autopsy.discovery.search.SearchData;
/** /**
* Panel for displaying all the filters associated with the Image type. * Panel for displaying all the filters associated with the Image type.

View File

@ -28,7 +28,6 @@ import javax.swing.JComponent;
import javax.swing.JList; import javax.swing.JList;
import javax.swing.ListCellRenderer; import javax.swing.ListCellRenderer;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.discovery.Bundle;
/** /**
* Class which displays a thumbnail and information for an image file. * Class which displays a thumbnail and information for an image file.

View File

@ -20,7 +20,7 @@ package org.sleuthkit.autopsy.discovery.ui;
import java.awt.Image; import java.awt.Image;
import org.sleuthkit.autopsy.coreutils.ImageUtils; import org.sleuthkit.autopsy.coreutils.ImageUtils;
import org.sleuthkit.autopsy.discovery.ResultFile; import org.sleuthkit.autopsy.discovery.search.ResultFile;
/** /**
* Class to wrap all the information necessary for an image thumbnail to be * Class to wrap all the information necessary for an image thumbnail to be

View File

@ -18,6 +18,7 @@
*/ */
package org.sleuthkit.autopsy.discovery.ui; package org.sleuthkit.autopsy.discovery.ui;
import org.sleuthkit.autopsy.discovery.search.AbstractFilter;
import java.util.List; import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.DefaultListModel; import javax.swing.DefaultListModel;
@ -25,7 +26,7 @@ import javax.swing.JCheckBox;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JList; import javax.swing.JList;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.discovery.SearchFiltering; import org.sleuthkit.autopsy.discovery.search.SearchFiltering;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;

View File

@ -18,6 +18,7 @@
*/ */
package org.sleuthkit.autopsy.discovery.ui; package org.sleuthkit.autopsy.discovery.ui;
import org.sleuthkit.autopsy.discovery.search.AbstractFilter;
import java.util.List; import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.DefaultListModel; import javax.swing.DefaultListModel;
@ -25,7 +26,7 @@ import javax.swing.JCheckBox;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JList; import javax.swing.JList;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.discovery.SearchFiltering; import org.sleuthkit.autopsy.discovery.search.SearchFiltering;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;

View File

@ -31,7 +31,6 @@ import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction; import org.openide.util.actions.CallableSystemAction;
import org.openide.util.actions.Presenter; import org.openide.util.actions.Presenter;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.discovery.Bundle;
/** /**
* Class to open the Discovery dialog. Allows the user to run searches and see * Class to open the Discovery dialog. Allows the user to run searches and see

View File

@ -18,21 +18,22 @@
*/ */
package org.sleuthkit.autopsy.discovery.ui; package org.sleuthkit.autopsy.discovery.ui;
import org.sleuthkit.autopsy.discovery.search.AbstractFilter;
import java.util.List; import java.util.List;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.SwingWorker; 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.discovery.FileSearch.GroupKey;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
import org.sleuthkit.autopsy.discovery.DiscoveryEventUtils; import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils;
import org.sleuthkit.autopsy.discovery.FileGroup; import org.sleuthkit.autopsy.discovery.search.DiscoveryKeyUtils.GroupKey;
import org.sleuthkit.autopsy.discovery.FileSearch; import org.sleuthkit.autopsy.discovery.search.FileGroup;
import org.sleuthkit.autopsy.discovery.FileSearchData; import org.sleuthkit.autopsy.discovery.search.FileSearch;
import org.sleuthkit.autopsy.discovery.FileSearchException; import org.sleuthkit.autopsy.discovery.search.FileSearchData;
import org.sleuthkit.autopsy.discovery.FileSorter; import org.sleuthkit.autopsy.discovery.search.FileSearchException;
import org.sleuthkit.autopsy.discovery.ResultFile; import org.sleuthkit.autopsy.discovery.search.FileSorter;
import org.sleuthkit.autopsy.discovery.search.ResultFile;
/** /**
* SwingWorker to retrieve the contents of a page. * SwingWorker to retrieve the contents of a page.

View File

@ -18,14 +18,15 @@
*/ */
package org.sleuthkit.autopsy.discovery.ui; package org.sleuthkit.autopsy.discovery.ui;
import org.sleuthkit.autopsy.discovery.search.AbstractFilter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.swing.DefaultListModel; import javax.swing.DefaultListModel;
import javax.swing.JCheckBox; import javax.swing.JCheckBox;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JList; import javax.swing.JList;
import org.sleuthkit.autopsy.discovery.SearchFiltering; import org.sleuthkit.autopsy.discovery.search.SearchFiltering;
import org.sleuthkit.autopsy.discovery.SearchFiltering.ParentSearchTerm; import org.sleuthkit.autopsy.discovery.search.SearchFiltering.ParentSearchTerm;
/** /**
* Panel to allow configuration of the Parent Folder filter. * Panel to allow configuration of the Parent Folder filter.

View File

@ -23,10 +23,6 @@ import javax.swing.JCheckBox;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JList; import javax.swing.JList;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
import org.sleuthkit.autopsy.discovery.FileSearchData;
import org.sleuthkit.autopsy.discovery.FileSearchData.Frequency;
import org.sleuthkit.autopsy.discovery.SearchData.ResultType;
import org.sleuthkit.autopsy.discovery.SearchFiltering;
/** /**
* Panel to allow configuration of the Past Occurrences filter. * Panel to allow configuration of the Past Occurrences filter.

View File

@ -18,6 +18,7 @@
*/ */
package org.sleuthkit.autopsy.discovery.ui; package org.sleuthkit.autopsy.discovery.ui;
import org.sleuthkit.autopsy.discovery.search.AbstractFilter;
import com.google.common.eventbus.Subscribe; import com.google.common.eventbus.Subscribe;
import java.awt.Cursor; import java.awt.Cursor;
import java.awt.Image; import java.awt.Image;
@ -35,16 +36,15 @@ import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException;
import org.sleuthkit.autopsy.coreutils.ImageUtils; import org.sleuthkit.autopsy.coreutils.ImageUtils;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.discovery.FileSearch.GroupKey;
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.Bundle; import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils;
import org.sleuthkit.autopsy.discovery.DiscoveryEventUtils; import org.sleuthkit.autopsy.discovery.search.DiscoveryKeyUtils.GroupKey;
import org.sleuthkit.autopsy.discovery.FileGroup; import org.sleuthkit.autopsy.discovery.search.FileGroup;
import org.sleuthkit.autopsy.discovery.FileSearch; import org.sleuthkit.autopsy.discovery.search.FileSearch;
import org.sleuthkit.autopsy.discovery.FileSearchData; import org.sleuthkit.autopsy.discovery.search.FileSearchData;
import org.sleuthkit.autopsy.discovery.FileSorter; import org.sleuthkit.autopsy.discovery.search.FileSorter;
import org.sleuthkit.autopsy.discovery.ResultFile; import org.sleuthkit.autopsy.discovery.search.ResultFile;
import org.sleuthkit.autopsy.textsummarizer.TextSummary; import org.sleuthkit.autopsy.textsummarizer.TextSummary;
/** /**
@ -653,7 +653,7 @@ final class ResultsPanel extends javax.swing.JPanel {
@Override @Override
protected Void doInBackground() throws Exception { protected Void doInBackground() throws Exception {
FileSearch.getVideoThumbnails(thumbnailWrapper); DiscoveryUiUtils.getVideoThumbnails(thumbnailWrapper);
return null; return null;
} }

View File

@ -19,7 +19,7 @@
package org.sleuthkit.autopsy.discovery.ui; package org.sleuthkit.autopsy.discovery.ui;
import java.awt.Cursor; import java.awt.Cursor;
import org.sleuthkit.autopsy.discovery.DiscoveryEventUtils; import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils;
/** /**
* Panel for separating the results list from the details area. * Panel for separating the results list from the details area.

View File

@ -18,6 +18,7 @@
*/ */
package org.sleuthkit.autopsy.discovery.ui; package org.sleuthkit.autopsy.discovery.ui;
import org.sleuthkit.autopsy.discovery.search.AbstractFilter;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import javax.swing.SwingWorker; import javax.swing.SwingWorker;
import java.util.List; import java.util.List;
@ -25,13 +26,13 @@ import java.util.Map;
import java.util.logging.Level; 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.discovery.FileSearch.GroupKey;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
import org.sleuthkit.autopsy.discovery.DiscoveryEventUtils; import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils;
import org.sleuthkit.autopsy.discovery.FileGroup; import org.sleuthkit.autopsy.discovery.search.DiscoveryKeyUtils.GroupKey;
import org.sleuthkit.autopsy.discovery.FileSearch; import org.sleuthkit.autopsy.discovery.search.FileGroup;
import org.sleuthkit.autopsy.discovery.FileSearchException; import org.sleuthkit.autopsy.discovery.search.FileSearch;
import org.sleuthkit.autopsy.discovery.FileSorter; import org.sleuthkit.autopsy.discovery.search.FileSearchException;
import org.sleuthkit.autopsy.discovery.search.FileSorter;
/** /**
* SwingWorker to perform search on a background thread. * SwingWorker to perform search on a background thread.

View File

@ -18,15 +18,16 @@
*/ */
package org.sleuthkit.autopsy.discovery.ui; package org.sleuthkit.autopsy.discovery.ui;
import org.sleuthkit.autopsy.discovery.search.AbstractFilter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.swing.DefaultListModel; import javax.swing.DefaultListModel;
import javax.swing.JCheckBox; import javax.swing.JCheckBox;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JList; import javax.swing.JList;
import org.sleuthkit.autopsy.discovery.FileSearchData; import org.sleuthkit.autopsy.discovery.search.FileSearchData;
import org.sleuthkit.autopsy.discovery.FileSearchData.FileSize; import org.sleuthkit.autopsy.discovery.search.FileSearchData.FileSize;
import org.sleuthkit.autopsy.discovery.SearchFiltering; import org.sleuthkit.autopsy.discovery.search.SearchFiltering;
/** /**
* Panel to allow configuration of the Size Filter. * Panel to allow configuration of the Size Filter.

View File

@ -18,10 +18,11 @@
*/ */
package org.sleuthkit.autopsy.discovery.ui; package org.sleuthkit.autopsy.discovery.ui;
import org.sleuthkit.autopsy.discovery.search.AbstractFilter;
import javax.swing.JCheckBox; import javax.swing.JCheckBox;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JList; import javax.swing.JList;
import org.sleuthkit.autopsy.discovery.SearchFiltering; import org.sleuthkit.autopsy.discovery.search.SearchFiltering;
/** /**
* Panel to allow configuration of the User Created Filter. * Panel to allow configuration of the User Created Filter.

View File

@ -19,9 +19,9 @@
package org.sleuthkit.autopsy.discovery.ui; package org.sleuthkit.autopsy.discovery.ui;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
import org.sleuthkit.autopsy.discovery.AttributeSearchData; import org.sleuthkit.autopsy.discovery.search.AttributeSearchData;
import org.sleuthkit.autopsy.discovery.FileSearchData; import org.sleuthkit.autopsy.discovery.search.FileSearchData;
import org.sleuthkit.autopsy.discovery.SearchData; import org.sleuthkit.autopsy.discovery.search.SearchData;
/** /**
* Panel for displaying all filters available for the searches of type Video. * Panel for displaying all filters available for the searches of type Video.

View File

@ -32,7 +32,6 @@ import javax.swing.JLabel;
import javax.swing.JList; import javax.swing.JList;
import javax.swing.ListCellRenderer; import javax.swing.ListCellRenderer;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.discovery.Bundle;
/** /**
* Class which displays thumbnails and information for a video file. * Class which displays thumbnails and information for a video file.

View File

@ -22,7 +22,7 @@ import java.awt.Image;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import org.sleuthkit.autopsy.discovery.ResultFile; import org.sleuthkit.autopsy.discovery.search.ResultFile;
/** /**
* Class to wrap all the information necessary for video thumbnails to be * Class to wrap all the information necessary for video thumbnails to be