diff --git a/Core/ivy.xml b/Core/ivy.xml
index 63fdd9ed92..4c4bef4f9a 100644
--- a/Core/ivy.xml
+++ b/Core/ivy.xml
@@ -50,6 +50,9 @@
+
+
+
diff --git a/Core/nbproject/project.xml b/Core/nbproject/project.xml
index 61e6a86b04..f82ab0c7af 100644
--- a/Core/nbproject/project.xml
+++ b/Core/nbproject/project.xml
@@ -479,6 +479,14 @@
ext/jxmapviewer2-2.4.jar
release/modules/ext/jxmapviewer2-2.4.jar
+
+ ext/jfreechart-1.0.19.jar
+ release/modules/ext/jfreechart-1.0.19.jar
+
+
+ ext/jcommon-1.0.23.jar
+ release/modules/ext/jcommon-1.0.23.jar
+
ext/jdom-2.0.5-contrib.jar
release/modules/ext/jdom-2.0.5-contrib.jar
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties
index 24a312f733..462d910dde 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties
@@ -33,7 +33,6 @@ DataSourceSummaryDetailsPanel.acquisitionDetailsTextArea.text=
DataSourceSummaryDetailsPanel.acquisitionDetailsLabel.text=Acquisition Details:
DataSourceSummaryDetailsPanel.unallocatedSizeLabel.text=Unallocated Space:
DataSourceSummaryDetailsPanel.unallocatedSizeValue.text=
-DataSourceSummaryCountsPanel.byMimeTypeLabel.text=Files by MIME Type
DataSourceSummaryCountsPanel.byCategoryLabel.text=Files by Category
-DataSourceSummaryCountsPanel.jLabel1.text=Results by Type
+DataSourceSummaryCountsPanel.resultsByTypeLabel.text=Results by Type
DataSourceSummaryUserActivityPanel.programsRunLabel.text=Top Programs Run
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties-MERGED
index ba0d3510c7..58c1fc4516 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties-MERGED
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties-MERGED
@@ -1,6 +1,7 @@
CTL_DataSourceSummaryAction=Data Source Summary
DataSourceSummaryCountsPanel.ArtifactCountsTableModel.count.header=Count
DataSourceSummaryCountsPanel.ArtifactCountsTableModel.type.header=Result Type
+DataSourceSummaryCountsPanel.byMimeTypeLabel.text=Files by MIME Type
DataSourceSummaryCountsPanel.FilesByCategoryTableModel.all.row=All
DataSourceSummaryCountsPanel.FilesByCategoryTableModel.allocated.row=Allocated
DataSourceSummaryCountsPanel.FilesByCategoryTableModel.count.header=Count
@@ -58,9 +59,11 @@ DataSourceSummaryDetailsPanel.acquisitionDetailsTextArea.text=
DataSourceSummaryDetailsPanel.acquisitionDetailsLabel.text=Acquisition Details:
DataSourceSummaryDetailsPanel.unallocatedSizeLabel.text=Unallocated Space:
DataSourceSummaryDetailsPanel.unallocatedSizeValue.text=
-DataSourceSummaryCountsPanel.byMimeTypeLabel.text=Files by MIME Type
DataSourceSummaryCountsPanel.byCategoryLabel.text=Files by Category
-DataSourceSummaryCountsPanel.jLabel1.text=Results by Type
+DataSourceSummaryCountsPanel.resultsByTypeLabel.text=Results by Type
+DataSourceSummaryDialog.countsTab.title=Counts
+DataSourceSummaryDialog.detailsTab.title=Details
+DataSourceSummaryDialog.ingestHistoryTab.title=Ingest History
DataSourceSummaryDialog.window.title=Data Sources Summary
DataSourceSummaryNode.column.dataSourceName.header=Data Source Name
DataSourceSummaryNode.column.files.header=Files
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceInfoUtilities.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceInfoUtilities.java
index 7e66e56682..12f4ad738d 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceInfoUtilities.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceInfoUtilities.java
@@ -45,6 +45,9 @@ import org.sleuthkit.datamodel.TskData;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
import org.sleuthkit.datamodel.DataSource;
+import org.sleuthkit.datamodel.TskData.TSK_DB_FILES_TYPE_ENUM;
+import org.sleuthkit.datamodel.TskData.TSK_FS_META_FLAG_ENUM;
+import org.sleuthkit.datamodel.TskData.TSK_FS_META_TYPE_ENUM;
/**
* Utilities for getting information about a data source or all data sources
@@ -55,8 +58,8 @@ final class DataSourceInfoUtilities {
private static final Logger logger = Logger.getLogger(DataSourceInfoUtilities.class.getName());
/**
- * Gets a count of files for a particular datasource where it is not a
- * virtual directory and has a name.
+ * Gets a count of tsk_files for a particular datasource where dir_type is
+ * not a virtual directory and has a name.
*
* @param currentDataSource The datasource.
* @param additionalWhere Additional sql where clauses.
@@ -64,15 +67,15 @@ final class DataSourceInfoUtilities {
*
* @return The count of files or null on error.
*/
- private static Long getCountOfFiles(DataSource currentDataSource, String additionalWhere, String onError) {
+ private static Long getCountOfTskFiles(DataSource currentDataSource, String additionalWhere, String onError) {
if (currentDataSource != null) {
try {
SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
return skCase.countFilesWhere(
- "dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue()
+ "data_source_obj_id=" + currentDataSource.getId()
+ + " AND dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue()
+ " AND name<>''"
- + " AND data_source_obj_id=" + currentDataSource.getId()
- + " AND " + additionalWhere);
+ + (StringUtils.isBlank(additionalWhere) ? "" : (" AND " + additionalWhere)));
} catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.WARNING, onError, ex);
//unable to get count of files for the specified types cell will be displayed as empty
@@ -82,18 +85,51 @@ final class DataSourceInfoUtilities {
}
/**
- * Get count of files in a data source.
+ * Gets a count of regular files for a particular datasource where the
+ * dir_type and type are not a virtual directory and has a name.
+ *
+ * @param currentDataSource The datasource.
+ * @param additionalWhere Additional sql where clauses.
+ * @param onError The message to log on error.
+ *
+ * @return The count of files or null on error.
+ */
+ private static Long getCountOfRegularFiles(DataSource currentDataSource, String additionalWhere, String onError) {
+ String whereClause = "meta_type=" + TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG.getValue()
+ + " AND type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType();
+
+ if (StringUtils.isNotBlank(additionalWhere)) {
+ whereClause += " AND " + additionalWhere;
+ }
+
+ return getCountOfTskFiles(currentDataSource, whereClause, onError);
+ }
+
+ /**
+ * Get count of regular files (not directories) in a data source.
*
* @param currentDataSource The data source.
*
* @return The count.
*/
static Long getCountOfFiles(DataSource currentDataSource) {
- return getCountOfFiles(currentDataSource,
- "type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType(),
+ return getCountOfRegularFiles(currentDataSource, null,
"Unable to get count of files, providing empty results");
}
+ /**
+ * Get count of allocated files in a data source.
+ *
+ * @param currentDataSource The data source.
+ *
+ * @return The count.
+ */
+ static Long getCountOfAllocatedFiles(DataSource currentDataSource) {
+ return getCountOfRegularFiles(currentDataSource,
+ getMetaFlagsContainsStatement(TSK_FS_META_FLAG_ENUM.ALLOC),
+ "Unable to get counts of unallocated files for datasource, providing empty results");
+ }
+
/**
* Get count of unallocated files in a data source.
*
@@ -102,9 +138,9 @@ final class DataSourceInfoUtilities {
* @return The count.
*/
static Long getCountOfUnallocatedFiles(DataSource currentDataSource) {
- return getCountOfFiles(currentDataSource,
- "type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType()
- + " AND dir_flags=" + TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC.getValue(),
+ return getCountOfRegularFiles(currentDataSource,
+ getMetaFlagsContainsStatement(TSK_FS_META_FLAG_ENUM.UNALLOC)
+ + " AND type<>" + TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType(),
"Unable to get counts of unallocated files for datasource, providing empty results");
}
@@ -116,9 +152,9 @@ final class DataSourceInfoUtilities {
* @return The count.
*/
static Long getCountOfDirectories(DataSource currentDataSource) {
- return getCountOfFiles(currentDataSource,
- "type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType()
- + " AND meta_type=" + TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR.getValue(),
+ return getCountOfTskFiles(currentDataSource,
+ "meta_type=" + TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR.getValue()
+ + " AND type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType(),
"Unable to get count of directories for datasource, providing empty results");
}
@@ -130,8 +166,9 @@ final class DataSourceInfoUtilities {
* @return The count.
*/
static Long getCountOfSlackFiles(DataSource currentDataSource) {
- return getCountOfFiles(currentDataSource,
- "type=" + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType(),
+ return getCountOfRegularFiles(currentDataSource,
+ getMetaFlagsContainsStatement(TSK_FS_META_FLAG_ENUM.UNALLOC)
+ + " AND type=" + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType(),
"Unable to get count of slack files for datasources, providing empty results");
}
@@ -183,9 +220,11 @@ final class DataSourceInfoUtilities {
final String valueParam = "value";
final String countParam = "count";
String query = "SELECT SUM(size) AS " + valueParam + ", COUNT(*) AS " + countParam
- + " FROM tsk_files WHERE type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType()
+ + " FROM tsk_files"
+ + " WHERE " + getMetaFlagsContainsStatement(TSK_FS_META_FLAG_ENUM.UNALLOC)
+ + " AND type<>" + TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType()
+ + " AND type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType()
+ " AND dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue()
- + " AND dir_flags=" + TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC.getValue()
+ " AND name<>''"
+ " AND data_source_obj_id=" + currentDataSource.getId();
@@ -700,10 +739,12 @@ final class DataSourceInfoUtilities {
*/
static Map getCountsOfFiles() {
try {
- final String countFilesQuery = "data_source_obj_id, COUNT(*) AS value"
- + " FROM tsk_files WHERE type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType()
+ final String countFilesQuery = "data_source_obj_id, COUNT(*) AS value FROM tsk_files"
+ + " WHERE meta_type=" + TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG.getValue()
+ + " AND type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType()
+ " AND dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue()
- + " AND name<>'' GROUP BY data_source_obj_id"; //NON-NLS
+ + " AND name<>''"
+ + " GROUP BY data_source_obj_id"; //NON-NLS
return getValuesMap(countFilesQuery);
} catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.WARNING, "Unable to get counts of files for all datasources, providing empty results", ex);
@@ -776,21 +817,75 @@ final class DataSourceInfoUtilities {
* source, null if no count was retrieved
*/
static Long getCountOfFilesForMimeTypes(DataSource currentDataSource, Set setOfMimeTypes) {
- if (currentDataSource != null) {
- try {
- String inClause = String.join("', '", setOfMimeTypes);
- SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
- return skCase.countFilesWhere("data_source_obj_id=" + currentDataSource.getId()
- + " AND type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType()
- + " AND dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue()
- + " AND mime_type IN ('" + inClause + "')"
- + " AND name<>''");
- } catch (TskCoreException | NoCurrentCaseException ex) {
- logger.log(Level.WARNING, "Unable to get count of files for specified mime types", ex);
- //unable to get count of files for the specified mimetypes cell will be displayed as empty
- }
- }
- return null;
+ return getCountOfRegularFiles(currentDataSource,
+ "mime_type IN " + getSqlSet(setOfMimeTypes),
+ "Unable to get count of files for specified mime types");
+ }
+
+ /**
+ * Get the number of files in the case database for the current data source
+ * which do not have the specified mimetypes.
+ *
+ * @param currentDataSource the data source which we are finding a file
+ * count
+ *
+ * @param setOfMimeTypes the set of mime types that should be excluded.
+ *
+ * @return a Long value which represents the number of files that do not
+ * have the specific mime type, but do have a mime type.
+ */
+ static Long getCountOfFilesNotInMimeTypes(DataSource currentDataSource, Set setOfMimeTypes) {
+ return getCountOfRegularFiles(currentDataSource,
+ "mime_type NOT IN " + getSqlSet(setOfMimeTypes)
+ + " AND mime_type IS NOT NULL AND mime_type <> '' ",
+ "Unable to get count of files without specified mime types");
+ }
+
+ /**
+ * Gets the number of files in the data source with no assigned mime type.
+ *
+ * @param currentDataSource The data source.
+ *
+ * @return The number of files with no mime type or null if there is an
+ * issue searching the data source.
+ *
+ */
+ static Long getCountOfFilesWithNoMimeType(DataSource currentDataSource) {
+ return getCountOfRegularFiles(currentDataSource,
+ "(mime_type IS NULL OR mime_type = '') ",
+ "Unable to get count of files without a mime type");
+ }
+
+ /**
+ * Derives a sql set string (i.e. "('val1', 'val2', 'val3')"). A naive
+ * attempt is made to sanitize the strings by removing single quotes from
+ * values.
+ *
+ * @param setValues The values that should be present in the set. Single
+ * quotes are removed.
+ *
+ * @return The sql set string.
+ */
+ private static String getSqlSet(Set setValues) {
+ List quotedValues = setValues
+ .stream()
+ .map(str -> String.format("'%s'", str.replace("'", "")))
+ .collect(Collectors.toList());
+
+ String commaSeparatedQuoted = String.join(", ", quotedValues);
+ return String.format("(%s) ", commaSeparatedQuoted);
+ }
+
+ /**
+ * Creates sql where clause that does a bitwise check to see if flag is
+ * present.
+ *
+ * @param flag The flag for which to check.
+ *
+ * @return The clause.
+ */
+ private static String getMetaFlagsContainsStatement(TSK_FS_META_FLAG_ENUM flag) {
+ return "meta_flags & " + flag.getValue() + " > 0";
}
/**
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.form
index 9a82746da6..f922bf9288 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.form
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.form
@@ -1,6 +1,6 @@
-