Merge pull request #6196 from sleuthkit/revert-6195-merge-develop-into-data-src-summaries

Revert "Merge develop into data src summaries"
This commit is contained in:
Richard Cordovano 2020-08-20 12:32:31 -04:00 committed by GitHub
commit 30edc43c20
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 1150 additions and 1738 deletions

View File

@ -50,9 +50,6 @@
<dependency conf="core->default" org="commons-validator" name="commons-validator" rev="1.6"/> <dependency conf="core->default" org="commons-validator" name="commons-validator" rev="1.6"/>
<dependency conf="core->default" org="net.htmlparser.jericho" name="jericho-html" rev="3.3"/> <dependency conf="core->default" org="net.htmlparser.jericho" name="jericho-html" rev="3.3"/>
<dependency org="com.squareup.okhttp" name="okhttp" rev="2.7.5"/> <dependency org="com.squareup.okhttp" name="okhttp" rev="2.7.5"/>
<!-- https://mvnrepository.com/artifact/jfree/jfreechart -->
<dependency org="org.jfree" name="jfreechart" rev="1.0.19"/>
<!-- map support for geolocation --> <!-- map support for geolocation -->
<dependency conf="core->default" org="org.jxmapviewer" name="jxmapviewer2" rev="2.4"/> <dependency conf="core->default" org="org.jxmapviewer" name="jxmapviewer2" rev="2.4"/>

View File

@ -479,14 +479,6 @@
<runtime-relative-path>ext/jxmapviewer2-2.4.jar</runtime-relative-path> <runtime-relative-path>ext/jxmapviewer2-2.4.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jxmapviewer2-2.4.jar</binary-origin> <binary-origin>release/modules/ext/jxmapviewer2-2.4.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jfreechart-1.0.19.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jfreechart-1.0.19.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jcommon-1.0.23.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jcommon-1.0.23.jar</binary-origin>
</class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/jdom-2.0.5-contrib.jar</runtime-relative-path> <runtime-relative-path>ext/jdom-2.0.5-contrib.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jdom-2.0.5-contrib.jar</binary-origin> <binary-origin>release/modules/ext/jdom-2.0.5-contrib.jar</binary-origin>

View File

@ -70,7 +70,7 @@ import org.sleuthkit.autopsy.actions.OpenOutputFolderAction;
import org.sleuthkit.autopsy.appservices.AutopsyService; import org.sleuthkit.autopsy.appservices.AutopsyService;
import org.sleuthkit.autopsy.appservices.AutopsyService.CaseContext; import org.sleuthkit.autopsy.appservices.AutopsyService.CaseContext;
import org.sleuthkit.autopsy.casemodule.CaseMetadata.CaseMetadataException; import org.sleuthkit.autopsy.casemodule.CaseMetadata.CaseMetadataException;
import org.sleuthkit.autopsy.datasourcesummary.ui.DataSourceSummaryAction; import org.sleuthkit.autopsy.casemodule.datasourcesummary.DataSourceSummaryAction;
import org.sleuthkit.autopsy.casemodule.events.AddingDataSourceEvent; import org.sleuthkit.autopsy.casemodule.events.AddingDataSourceEvent;
import org.sleuthkit.autopsy.casemodule.events.AddingDataSourceFailedEvent; import org.sleuthkit.autopsy.casemodule.events.AddingDataSourceFailedEvent;
import org.sleuthkit.autopsy.casemodule.events.BlackBoardArtifactTagAddedEvent; import org.sleuthkit.autopsy.casemodule.events.BlackBoardArtifactTagAddedEvent;

View File

@ -33,6 +33,7 @@ DataSourceSummaryDetailsPanel.acquisitionDetailsTextArea.text=
DataSourceSummaryDetailsPanel.acquisitionDetailsLabel.text=Acquisition Details: DataSourceSummaryDetailsPanel.acquisitionDetailsLabel.text=Acquisition Details:
DataSourceSummaryDetailsPanel.unallocatedSizeLabel.text=Unallocated Space: DataSourceSummaryDetailsPanel.unallocatedSizeLabel.text=Unallocated Space:
DataSourceSummaryDetailsPanel.unallocatedSizeValue.text= DataSourceSummaryDetailsPanel.unallocatedSizeValue.text=
DataSourceSummaryCountsPanel.byMimeTypeLabel.text=Files by MIME Type
DataSourceSummaryCountsPanel.byCategoryLabel.text=Files by Category DataSourceSummaryCountsPanel.byCategoryLabel.text=Files by Category
DataSourceSummaryCountsPanel.resultsByTypeLabel.text=Results by Type DataSourceSummaryCountsPanel.jLabel1.text=Results by Type
DataSourceSummaryUserActivityPanel.programsRunLabel.text=Top Programs Run DataSourceSummaryUserActivityPanel.programsRunLabel.text=Top Programs Run

View File

@ -1,7 +1,6 @@
CTL_DataSourceSummaryAction=Data Source Summary CTL_DataSourceSummaryAction=Data Source Summary
DataSourceSummaryCountsPanel.ArtifactCountsTableModel.count.header=Count DataSourceSummaryCountsPanel.ArtifactCountsTableModel.count.header=Count
DataSourceSummaryCountsPanel.ArtifactCountsTableModel.type.header=Result Type DataSourceSummaryCountsPanel.ArtifactCountsTableModel.type.header=Result Type
DataSourceSummaryCountsPanel.byMimeTypeLabel.text=Files by MIME Type
DataSourceSummaryCountsPanel.FilesByCategoryTableModel.all.row=All DataSourceSummaryCountsPanel.FilesByCategoryTableModel.all.row=All
DataSourceSummaryCountsPanel.FilesByCategoryTableModel.allocated.row=Allocated DataSourceSummaryCountsPanel.FilesByCategoryTableModel.allocated.row=Allocated
DataSourceSummaryCountsPanel.FilesByCategoryTableModel.count.header=Count DataSourceSummaryCountsPanel.FilesByCategoryTableModel.count.header=Count
@ -16,8 +15,6 @@ DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.executables.row=Executabl
DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.images.row=Images DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.images.row=Images
DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.type.header=File Type DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.type.header=File Type
DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.videos.row=Videos DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.videos.row=Videos
DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_notAnalyzed_label=Not Analyzed
DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_other_label=Other
DataSourceSummaryDetailsPanel.getDataSources.error.text=Failed to get the list of datasources for the current case. DataSourceSummaryDetailsPanel.getDataSources.error.text=Failed to get the list of datasources for the current case.
DataSourceSummaryDetailsPanel.getDataSources.error.title=Load Failure DataSourceSummaryDetailsPanel.getDataSources.error.title=Load Failure
DataSourceSummaryDetailsPanel.units.bytes=\ bytes DataSourceSummaryDetailsPanel.units.bytes=\ bytes
@ -61,8 +58,9 @@ DataSourceSummaryDetailsPanel.acquisitionDetailsTextArea.text=
DataSourceSummaryDetailsPanel.acquisitionDetailsLabel.text=Acquisition Details: DataSourceSummaryDetailsPanel.acquisitionDetailsLabel.text=Acquisition Details:
DataSourceSummaryDetailsPanel.unallocatedSizeLabel.text=Unallocated Space: DataSourceSummaryDetailsPanel.unallocatedSizeLabel.text=Unallocated Space:
DataSourceSummaryDetailsPanel.unallocatedSizeValue.text= DataSourceSummaryDetailsPanel.unallocatedSizeValue.text=
DataSourceSummaryCountsPanel.byMimeTypeLabel.text=Files by MIME Type
DataSourceSummaryCountsPanel.byCategoryLabel.text=Files by Category DataSourceSummaryCountsPanel.byCategoryLabel.text=Files by Category
DataSourceSummaryCountsPanel.resultsByTypeLabel.text=Results by Type DataSourceSummaryCountsPanel.jLabel1.text=Results by Type
DataSourceSummaryDialog.window.title=Data Sources Summary DataSourceSummaryDialog.window.title=Data Sources Summary
DataSourceSummaryNode.column.dataSourceName.header=Data Source Name DataSourceSummaryNode.column.dataSourceName.header=Data Source Name
DataSourceSummaryNode.column.files.header=Files DataSourceSummaryNode.column.files.header=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.datasourcesummary.ui; package org.sleuthkit.autopsy.casemodule.datasourcesummary;
import java.awt.EventQueue; import java.awt.EventQueue;
import java.beans.PropertyVetoException; import java.beans.PropertyVetoException;
@ -35,11 +35,10 @@ import javax.swing.event.ListSelectionListener;
import org.openide.nodes.Node; import org.openide.nodes.Node;
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.datasourcesummary.ui.DataSourceSummaryNode.DataSourceSummaryEntryNode; import org.sleuthkit.autopsy.casemodule.datasourcesummary.DataSourceSummaryNode.DataSourceSummaryEntryNode;
import static javax.swing.SwingConstants.RIGHT; import static javax.swing.SwingConstants.RIGHT;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import javax.swing.table.TableColumn; import javax.swing.table.TableColumn;
import org.sleuthkit.autopsy.datasourcesummary.datamodel.CaseDataSourcesSummary;
import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.DataSource;
import org.sleuthkit.datamodel.IngestJobInfo; import org.sleuthkit.datamodel.IngestJobInfo;
import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.SleuthkitCase;
@ -153,8 +152,8 @@ final class DataSourceBrowser extends javax.swing.JPanel implements ExplorerMana
private List<DataSourceSummary> getDataSourceSummaryList(Map<Long, String> usageMap, Map<Long, Long> fileCountsMap) { private List<DataSourceSummary> getDataSourceSummaryList(Map<Long, String> usageMap, Map<Long, Long> fileCountsMap) {
List<DataSourceSummary> summaryList = new ArrayList<>(); List<DataSourceSummary> summaryList = new ArrayList<>();
final Map<Long, Long> artifactCountsMap = CaseDataSourcesSummary.getCountsOfArtifacts(); final Map<Long, Long> artifactCountsMap = DataSourceInfoUtilities.getCountsOfArtifacts();
final Map<Long, Long> tagCountsMap = CaseDataSourcesSummary.getCountsOfTags(); final Map<Long, Long> tagCountsMap = DataSourceInfoUtilities.getCountsOfTags();
try { try {
SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase(); SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
for (DataSource dataSource : skCase.getDataSources()) { for (DataSource dataSource : skCase.getDataSources()) {

View File

@ -0,0 +1,819 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019 - 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.casemodule.datasourcesummary;
import java.io.File;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.apache.commons.lang.StringUtils;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
import org.sleuthkit.datamodel.TskData;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
import org.sleuthkit.datamodel.DataSource;
/**
* Utilities for getting information about a data source or all data sources
* from the case database.
*/
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.
*
* @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 getCountOfFiles(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()
+ " AND name<>''"
+ " AND data_source_obj_id=" + currentDataSource.getId()
+ " 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
}
}
return null;
}
/**
* Get count of files 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(),
"Unable to get count of files, providing empty results");
}
/**
* Get count of unallocated files in a data source.
*
* @param currentDataSource The data source.
*
* @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(),
"Unable to get counts of unallocated files for datasource, providing empty results");
}
/**
* Get count of directories in a data source.
*
* @param currentDataSource The data source.
*
* @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(),
"Unable to get count of directories for datasource, providing empty results");
}
/**
* Get count of slack files in a data source.
*
* @param currentDataSource The data source.
*
* @return The count.
*/
static Long getCountOfSlackFiles(DataSource currentDataSource) {
return getCountOfFiles(currentDataSource,
"type=" + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType(),
"Unable to get count of slack files for datasources, providing empty results");
}
/**
* An interface for handling a result set and returning a value.
*/
private interface ResultSetHandler<T> {
T process(ResultSet resultset) throws SQLException;
}
/**
* Retrieves a result based on the provided query.
*
* @param query The query.
* @param processor The result set handler.
* @param errorMessage The error message to display if there is an error
* retrieving the resultset.
*
* @return The ResultSetHandler value or null if no ResultSet could be
* obtained.
*/
private static <T> T getBaseQueryResult(String query, ResultSetHandler<T> processor, String errorMessage) {
try (SleuthkitCase.CaseDbQuery dbQuery = Case.getCurrentCaseThrows().getSleuthkitCase().executeQuery(query)) {
ResultSet resultSet = dbQuery.getResultSet();
try {
return processor.process(resultSet);
} catch (SQLException ex) {
logger.log(Level.WARNING, errorMessage, ex);
}
} catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.WARNING, errorMessage, ex);
}
return null;
}
/**
* Gets the size of unallocated files in a particular datasource.
*
* @param currentDataSource The data source.
*
* @return The size or null if the query could not be executed.
*/
static Long getSizeOfUnallocatedFiles(DataSource currentDataSource) {
if (currentDataSource == null) {
return null;
}
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()
+ " 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();
ResultSetHandler<Long> handler = (resultSet) -> {
if (resultSet.next()) {
// ensure that there is an unallocated count result that is attached to this data source
long resultCount = resultSet.getLong(valueParam);
return (resultCount > 0) ? resultSet.getLong(valueParam) : null;
} else {
return null;
}
};
String errorMessage = "Unable to get size of unallocated files; returning null.";
return getBaseQueryResult(query, handler, errorMessage);
}
/**
* Generates a result set handler that will return a map of string to long.
*
* @param keyParam The named parameter in the result set representing the
* key.
* @param valueParam The named parameter in the result set representing the
* value.
*
* @return The result set handler to generate the map of string to long.
*/
private static ResultSetHandler<LinkedHashMap<String, Long>> getStringLongResultSetHandler(String keyParam, String valueParam) {
return (resultSet) -> {
LinkedHashMap<String, Long> toRet = new LinkedHashMap<>();
while (resultSet.next()) {
try {
toRet.put(resultSet.getString(keyParam), resultSet.getLong(valueParam));
} catch (SQLException ex) {
logger.log(Level.WARNING, "Failed to get a result pair from the result set.", ex);
}
}
return toRet;
};
}
/**
* Retrieves counts for each artifact type in a data source.
*
* @param selectedDataSource The data source.
*
* @return A mapping of artifact type name to the counts or null if there
* was an error executing the query.
*/
static Map<String, Long> getCountsOfArtifactsByType(DataSource selectedDataSource) {
if (selectedDataSource == null) {
return Collections.emptyMap();
}
final String nameParam = "name";
final String valueParam = "value";
String query
= "SELECT bbt.display_name AS " + nameParam + ", COUNT(*) AS " + valueParam
+ " FROM blackboard_artifacts bba "
+ " INNER JOIN blackboard_artifact_types bbt ON bba.artifact_type_id = bbt.artifact_type_id"
+ " WHERE bba.data_source_obj_id =" + selectedDataSource.getId()
+ " GROUP BY bbt.display_name";
String errorMessage = "Unable to get artifact type counts; returning null.";
return getBaseQueryResult(query, getStringLongResultSetHandler(nameParam, valueParam), errorMessage);
}
/**
* Describes a result of a program run on a datasource.
*/
static class TopProgramsResult {
private final String programName;
private final String programPath;
private final Long runTimes;
private final Date lastRun;
/**
* Main constructor.
*
* @param programName The name of the program.
* @param programPath The path of the program.
* @param runTimes The number of runs.
*/
TopProgramsResult(String programName, String programPath, Long runTimes, Date lastRun) {
this.programName = programName;
this.programPath = programPath;
this.runTimes = runTimes;
this.lastRun = lastRun;
}
/**
* @return The name of the program
*/
String getProgramName() {
return programName;
}
/**
* @return The path of the program.
*/
String getProgramPath() {
return programPath;
}
/**
* @return The number of run times or null if not present.
*/
Long getRunTimes() {
return runTimes;
}
/**
* @return The last time the program was run or null if not present.
*/
public Date getLastRun() {
return lastRun;
}
}
/**
* A SQL join type.
*/
private enum JoinType {
LEFT,
RIGHT,
INNER,
OUTER
}
/**
* A blackboard attribute value column.
*/
private enum AttributeColumn {
value_text,
value_int32,
value_int64
}
/**
* The suffix joined to a key name for use as an identifier of a query.
*/
private static final String QUERY_SUFFIX = "_query";
/**
* Creates a sql statement querying the blackboard attributes table for a
* particular attribute type and returning a specified value. That query
* also joins with the blackboard artifact table.
*
* @param joinType The type of join statement to create.
* @param attributeColumn The blackboard attribute column that should be
* returned.
* @param attrType The attribute type to query for.
* @param keyName The aliased name of the attribute to return. This
* is also used to calculate the alias of the query
* same as getFullKey.
* @param bbaName The blackboard artifact table alias.
*
* @return The generated sql statement.
*/
private static String getAttributeJoin(JoinType joinType, AttributeColumn attributeColumn, ATTRIBUTE_TYPE attrType, String keyName, String bbaName) {
String queryName = keyName + QUERY_SUFFIX;
String innerQueryName = "inner_attribute_" + queryName;
return "\n" + joinType + " JOIN (\n"
+ " SELECT \n"
+ " " + innerQueryName + ".artifact_id,\n"
+ " " + innerQueryName + "." + attributeColumn + " AS " + keyName + "\n"
+ " FROM blackboard_attributes " + innerQueryName + "\n"
+ " WHERE " + innerQueryName + ".attribute_type_id = " + attrType.getTypeID() + " -- " + attrType.name() + "\n"
+ ") " + queryName + " ON " + queryName + ".artifact_id = " + bbaName + ".artifact_id\n";
}
/**
* Given a column key, creates the full name for the column key.
*
* @param key The column key.
*
* @return The full identifier for the column key.
*/
private static String getFullKey(String key) {
return key + QUERY_SUFFIX + "." + key;
}
/**
* Constructs a SQL 'where' statement from a list of clauses and puts
* parenthesis around each clause.
*
* @param clauses The clauses
*
* @return The generated 'where' statement.
*/
private static String getWhereString(List<String> clauses) {
if (clauses.isEmpty()) {
return "";
}
List<String> parenthesized = clauses.stream()
.map(c -> "(" + c + ")")
.collect(Collectors.toList());
return "\nWHERE " + String.join("\n AND ", parenthesized) + "\n";
}
/**
* Generates a [column] LIKE sql clause.
*
* @param column The column identifier.
* @param likeString The string that will be used as column comparison.
* @param isLike if false, the statement becomes NOT LIKE.
*
* @return The generated statement.
*/
private static String getLikeClause(String column, String likeString, boolean isLike) {
return column + (isLike ? "" : " NOT") + " LIKE '" + likeString + "'";
}
/**
* Retrieves a list of the top programs used on the data source. Currently
* determines this based off of which prefetch results return the highest
* count.
*
* @param dataSource The data source.
* @param count The number of programs to return.
*
* @return
*/
static List<TopProgramsResult> getTopPrograms(DataSource dataSource, int count) {
if (dataSource == null || count <= 0) {
return Collections.emptyList();
}
// ntosboot should be ignored
final String ntosBootIdentifier = "NTOSBOOT";
// programs in windows directory to be ignored
final String windowsDir = "/WINDOWS%";
final String nameParam = "name";
final String pathParam = "path";
final String runCountParam = "run_count";
final String lastRunParam = "last_run";
String bbaQuery = "bba";
final String query = "SELECT\n"
+ " " + getFullKey(nameParam) + " AS " + nameParam + ",\n"
+ " " + getFullKey(pathParam) + " AS " + pathParam + ",\n"
+ " MAX(" + getFullKey(runCountParam) + ") AS " + runCountParam + ",\n"
+ " MAX(" + getFullKey(lastRunParam) + ") AS " + lastRunParam + "\n"
+ "FROM blackboard_artifacts " + bbaQuery + "\n"
+ getAttributeJoin(JoinType.INNER, AttributeColumn.value_text, ATTRIBUTE_TYPE.TSK_PROG_NAME, nameParam, bbaQuery)
+ getAttributeJoin(JoinType.LEFT, AttributeColumn.value_text, ATTRIBUTE_TYPE.TSK_PATH, pathParam, bbaQuery)
+ getAttributeJoin(JoinType.LEFT, AttributeColumn.value_int32, ATTRIBUTE_TYPE.TSK_COUNT, runCountParam, bbaQuery)
+ getAttributeJoin(JoinType.LEFT, AttributeColumn.value_int64, ATTRIBUTE_TYPE.TSK_DATETIME, lastRunParam, bbaQuery)
+ getWhereString(Arrays.asList(
bbaQuery + ".artifact_type_id = " + ARTIFACT_TYPE.TSK_PROG_RUN.getTypeID(),
bbaQuery + ".data_source_obj_id = " + dataSource.getId(),
// exclude ntosBootIdentifier from results
getLikeClause(getFullKey(nameParam), ntosBootIdentifier, false),
// exclude windows directory items from results
getFullKey(pathParam) + " IS NULL OR " + getLikeClause(getFullKey(pathParam), windowsDir, false)
))
+ "GROUP BY " + getFullKey(nameParam) + ", " + getFullKey(pathParam) + "\n"
+ "ORDER BY \n"
+ " MAX(" + getFullKey(runCountParam) + ") DESC,\n"
+ " MAX(" + getFullKey(lastRunParam) + ") DESC,\n"
+ " " + getFullKey(nameParam) + " ASC";
final String errorMessage = "Unable to get top program results; returning null.";
ResultSetHandler<List<TopProgramsResult>> handler = (resultSet) -> {
List<TopProgramsResult> progResults = new ArrayList<>();
boolean quitAtCount = false;
while (resultSet.next() && (!quitAtCount || progResults.size() < count)) {
try {
long lastRunEpoch = resultSet.getLong(lastRunParam);
Date lastRun = (resultSet.wasNull()) ? null : new Date(lastRunEpoch * 1000);
Long runCount = resultSet.getLong(runCountParam);
if (resultSet.wasNull()) {
runCount = null;
}
if (lastRun != null || runCount != null) {
quitAtCount = true;
}
progResults.add(new TopProgramsResult(
resultSet.getString(nameParam),
resultSet.getString(pathParam),
runCount,
lastRun));
} catch (SQLException ex) {
logger.log(Level.WARNING, "Failed to get a top program result from the result set.", ex);
}
}
return progResults;
};
return getBaseQueryResult(query, handler, errorMessage);
}
/**
* Functions that determine the folder name of a list of path elements. If
* not matched, function returns null.
*/
private static final List<Function<List<String>, String>> SHORT_FOLDER_MATCHERS = Arrays.asList(
// handle Program Files and Program Files (x86) - if true, return the next folder
(pathList) -> {
if (pathList.size() < 2) {
return null;
}
String rootParent = pathList.get(0).toUpperCase();
if ("PROGRAM FILES".equals(rootParent) || "PROGRAM FILES (X86)".equals(rootParent)) {
return pathList.get(1);
} else {
return null;
}
},
// if there is a folder named "APPLICATION DATA" or "APPDATA"
(pathList) -> {
for (String pathEl : pathList) {
String uppered = pathEl.toUpperCase();
if ("APPLICATION DATA".equals(uppered) || "APPDATA".equals(uppered)) {
return "AppData";
}
}
return null;
}
);
/**
* Determines a short folder name if any. Otherwise, returns empty string.
*
* @param strPath The string path.
*
* @return The short folder name or empty string if not found.
*/
static String getShortFolderName(String strPath, String applicationName) {
if (strPath == null) {
return "";
}
List<String> pathEls = new ArrayList<>(Arrays.asList(applicationName));
File file = new File(strPath);
while (file != null && StringUtils.isNotBlank(file.getName())) {
pathEls.add(file.getName());
file = file.getParentFile();
}
Collections.reverse(pathEls);
for (Function<List<String>, String> matchEntry : SHORT_FOLDER_MATCHERS) {
String result = matchEntry.apply(pathEls);
if (StringUtils.isNotBlank(result)) {
return result;
}
}
return "";
}
/**
* Generates a string which is a concatenation of the value received from
* the result set.
*
* @param query The query.
* @param valueParam The parameter for the value in the result set.
* @param separator The string separator used in concatenation.
* @param errorMessage The error message if the result set could not
* be received.
* @param singleErrorMessage The error message if a single result could not
* be obtained.
*
* @return The concatenated string or null if the query could not be
* executed.
*/
private static String getConcattedStringsResult(String query, String valueParam, String separator, String errorMessage, String singleErrorMessage) {
ResultSetHandler<String> handler = (resultSet) -> {
String toRet = "";
boolean first = true;
while (resultSet.next()) {
try {
if (first) {
first = false;
} else {
toRet += separator;
}
toRet += resultSet.getString(valueParam);
} catch (SQLException ex) {
logger.log(Level.WARNING, singleErrorMessage, ex);
}
}
return toRet;
};
return getBaseQueryResult(query, handler, errorMessage);
}
/**
* Generates a concatenated string value based on the text value of a
* particular attribute in a particular artifact for a specific data source.
*
* @param dataSourceId The data source id.
* @param artifactTypeId The artifact type id.
* @param attributeTypeId The attribute type id.
*
* @return The concatenated value or null if the query could not be
* executed.
*/
private static String getConcattedAttrValue(long dataSourceId, int artifactTypeId, int attributeTypeId) {
final String valueParam = "concatted_attribute_value";
String query = "SELECT attr.value_text AS " + valueParam
+ " FROM blackboard_artifacts bba "
+ " INNER JOIN blackboard_attributes attr ON bba.artifact_id = attr.artifact_id "
+ " WHERE bba.data_source_obj_id = " + dataSourceId
+ " AND bba.artifact_type_id = " + artifactTypeId
+ " AND attr.attribute_type_id = " + attributeTypeId;
String errorMessage = "Unable to execute query to retrieve concatted attribute values.";
String singleErrorMessage = "There was an error retrieving one of the results. That result will be omitted from concatted value.";
String separator = ", ";
return getConcattedStringsResult(query, valueParam, separator, errorMessage, singleErrorMessage);
}
/**
* Retrieves the concatenation of operating system attributes for a
* particular data source.
*
* @param dataSource The data source.
*
* @return The concatenated value or null if the query could not be
* executed.
*/
static String getOperatingSystems(DataSource dataSource) {
if (dataSource == null) {
return null;
}
return getConcattedAttrValue(dataSource.getId(),
BlackboardArtifact.ARTIFACT_TYPE.TSK_OS_INFO.getTypeID(),
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID());
}
/**
* Retrieves the concatenation of data source usage for a particular data
* source.
*
* @param dataSource The data source.
*
* @return The concatenated value or null if the query could not be
* executed.
*/
static String getDataSourceType(DataSource dataSource) {
if (dataSource == null) {
return null;
}
return getConcattedAttrValue(dataSource.getId(),
BlackboardArtifact.ARTIFACT_TYPE.TSK_DATA_SOURCE_USAGE.getTypeID(),
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION.getTypeID());
}
/**
* Get a map containing the TSK_DATA_SOURCE_USAGE description attributes
* associated with each data source in the current case.
*
* @return Collection which maps datasource id to a String which displays a
* comma seperated list of values of data source usage types
* expected to be in the datasource
*/
static Map<Long, String> getDataSourceTypes() {
try {
SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
List<BlackboardArtifact> listOfArtifacts = skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_DATA_SOURCE_USAGE);
Map<Long, String> typeMap = new HashMap<>();
for (BlackboardArtifact typeArtifact : listOfArtifacts) {
BlackboardAttribute descriptionAttr = typeArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION));
if (typeArtifact.getDataSource() != null && descriptionAttr != null) {
long dsId = typeArtifact.getDataSource().getId();
String type = typeMap.get(typeArtifact.getDataSource().getId());
if (type == null) {
type = descriptionAttr.getValueString();
} else {
type = type + ", " + descriptionAttr.getValueString();
}
typeMap.put(dsId, type);
}
}
return typeMap;
} catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.WARNING, "Unable to get types of files for all datasources, providing empty results", ex);
return Collections.emptyMap();
}
}
/**
* Get a map containing the number of files in each data source in the
* current case.
*
* @return Collection which maps datasource id to a count for the number of
* files in the datasource, will only contain entries for
* datasources which have at least 1 file
*/
static Map<Long, Long> 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()
+ " AND dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue()
+ " 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);
return Collections.emptyMap();
}
}
/**
* Get a map containing the number of artifacts in each data source in the
* current case.
*
* @return Collection which maps datasource id to a count for the number of
* artifacts in the datasource, will only contain entries for
* datasources which have at least 1 artifact
*/
static Map<Long, Long> getCountsOfArtifacts() {
try {
final String countArtifactsQuery = "data_source_obj_id, COUNT(*) AS value"
+ " FROM blackboard_artifacts WHERE review_status_id !=" + BlackboardArtifact.ReviewStatus.REJECTED.getID()
+ " GROUP BY data_source_obj_id"; //NON-NLS
return getValuesMap(countArtifactsQuery);
} catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.WARNING, "Unable to get counts of artifacts for all datasources, providing empty results", ex);
return Collections.emptyMap();
}
}
/**
* Get a map containing the number of tags which have been applied in each
* data source in the current case. Not necessarily the same as the number
* of items tagged, as an item can have any number of tags.
*
* @return Collection which maps datasource id to a count for the number of
* tags which have been applied in the datasource, will only contain
* entries for datasources which have at least 1 item tagged.
*/
static Map<Long, Long> getCountsOfTags() {
try {
final String countFileTagsQuery = "data_source_obj_id, COUNT(*) AS value"
+ " FROM content_tags as content_tags, tsk_files as tsk_files"
+ " WHERE content_tags.obj_id = tsk_files.obj_id"
+ " GROUP BY data_source_obj_id"; //NON-NLS
//new hashmap so it can be modifiable
Map<Long, Long> tagCountMap = new HashMap<>(getValuesMap(countFileTagsQuery));
final String countArtifactTagsQuery = "data_source_obj_id, COUNT(*) AS value"
+ " FROM blackboard_artifact_tags as artifact_tags, blackboard_artifacts AS arts"
+ " WHERE artifact_tags.artifact_id = arts.artifact_id"
+ " GROUP BY data_source_obj_id"; //NON-NLS
//combine the results from the count artifact tags query into the copy of the mapped results from the count file tags query
getValuesMap(countArtifactTagsQuery).forEach((key, value) -> tagCountMap.merge(key, value, (value1, value2) -> value1 + value2));
return tagCountMap;
} catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.WARNING, "Unable to get counts of tags for all datasources, providing empty results", ex);
return Collections.emptyMap();
}
}
/**
* Get the number of files in the case database for the current data source
* which have the specified mimetypes.
*
* @param currentDataSource the data source which we are finding a file
* count
*
* @param setOfMimeTypes the set of mime types which we are finding the
* number of occurences of
*
* @return a Long value which represents the number of occurrences of the
* specified mime types in the current case for the specified data
* source, null if no count was retrieved
*/
static Long getCountOfFilesForMimeTypes(DataSource currentDataSource, Set<String> 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;
}
/**
* Helper method to execute a select query with a
* DataSourceSingleValueCallback.
*
* @param query the portion of the query which should follow the SELECT
*
* @return a map of datasource object ID to a value of type Long
*
* @throws TskCoreException
* @throws NoCurrentCaseException
*/
private static Map<Long, Long> getValuesMap(String query) throws TskCoreException, NoCurrentCaseException {
SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
DataSourceSingleValueCallback callback = new DataSourceSingleValueCallback();
skCase.getCaseDbAccessManager().select(query, callback);
return callback.getMapOfValues();
}
/**
* Empty private constructor
*/
private DataSourceInfoUtilities() {
}
}

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.datasourcesummary.datamodel; package org.sleuthkit.autopsy.casemodule.datasourcesummary;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;

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.datasourcesummary.datamodel; package org.sleuthkit.autopsy.casemodule.datasourcesummary;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;

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.datasourcesummary.ui; package org.sleuthkit.autopsy.casemodule.datasourcesummary;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;

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.datasourcesummary.ui; package org.sleuthkit.autopsy.casemodule.datasourcesummary;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
@ -28,7 +28,6 @@ import org.openide.util.HelpCtx;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.openide.util.actions.CallableSystemAction; import org.openide.util.actions.CallableSystemAction;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.datasourcesummary.ui.Bundle;
@ActionID(category = "Case", id = "org.sleuthkit.autopsy.casemodule.datasourcesummary.DataSourceSummaryAction") @ActionID(category = "Case", id = "org.sleuthkit.autopsy.casemodule.datasourcesummary.DataSourceSummaryAction")
@ActionRegistration(displayName = "#CTL_DataSourceSummaryAction", lazy = false) @ActionRegistration(displayName = "#CTL_DataSourceSummaryAction", lazy = false)

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="fileCountsByMimeTypeScrollPane" linkSize="1" pref="140" max="32767" attributes="0"/>
<Component id="byMimeTypeLabel" max="32767" attributes="0"/>
</Group>
<EmptySpace type="separate" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="byCategoryLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="fileCountsByCategoryScrollPane" linkSize="1" alignment="0" min="-2" pref="82" max="-2" attributes="0"/>
</Group>
<EmptySpace type="separate" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jLabel1" min="-2" pref="79" max="-2" attributes="0"/>
<Component id="artifactCountsScrollPane" min="-2" pref="244" max="-2" attributes="0"/>
</Group>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="byMimeTypeLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="byCategoryLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="artifactCountsScrollPane" alignment="1" pref="0" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="fileCountsByMimeTypeScrollPane" linkSize="2" min="-2" pref="107" max="-2" attributes="0"/>
<Component id="fileCountsByCategoryScrollPane" linkSize="2" min="-2" pref="86" max="-2" attributes="0"/>
</Group>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JScrollPane" name="fileCountsByMimeTypeScrollPane">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTable" name="fileCountsByMimeTypeTable">
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JLabel" name="byMimeTypeLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryCountsPanel.byMimeTypeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Container class="javax.swing.JScrollPane" name="fileCountsByCategoryScrollPane">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTable" name="fileCountsByCategoryTable">
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JLabel" name="byCategoryLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryCountsPanel.byCategoryLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel1">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryCountsPanel.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Container class="javax.swing.JScrollPane" name="artifactCountsScrollPane">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTable" name="artifactCountsTable">
</Component>
</SubComponents>
</Container>
</SubComponents>
</Form>

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.datasourcesummary.ui; package org.sleuthkit.autopsy.casemodule.datasourcesummary;
import java.util.Map; import java.util.Map;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
@ -24,8 +24,7 @@ import javax.swing.JLabel;
import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.DefaultTableCellRenderer;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceCountsSummary; import org.sleuthkit.autopsy.coreutils.FileTypeUtils;
import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.DataSource;
/** /**
@ -41,8 +40,6 @@ import org.sleuthkit.datamodel.DataSource;
}) })
class DataSourceSummaryCountsPanel extends javax.swing.JPanel { class DataSourceSummaryCountsPanel extends javax.swing.JPanel {
private static final long serialVersionUID = 1L;
// Result returned for a data model if no data found. // Result returned for a data model if no data found.
private static final Object[][] EMPTY_PAIRS = new Object[][]{}; private static final Object[][] EMPTY_PAIRS = new Object[][]{};
@ -64,11 +61,10 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel {
Bundle.DataSourceSummaryCountsPanel_ArtifactCountsTableModel_count_header() Bundle.DataSourceSummaryCountsPanel_ArtifactCountsTableModel_count_header()
}; };
private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(DataSourceSummaryCountsPanel.class.getName()); private static final Logger logger = Logger.getLogger(DataSourceSummaryCountsPanel.class.getName());
private final DefaultTableCellRenderer rightAlignedRenderer = new DefaultTableCellRenderer(); private final DefaultTableCellRenderer rightAlignedRenderer = new DefaultTableCellRenderer();
private final FileTypePieChart fileTypePieChart = new FileTypePieChart();
private DataSource dataSource; private DataSource dataSource;
/** /**
@ -77,6 +73,7 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel {
DataSourceSummaryCountsPanel() { DataSourceSummaryCountsPanel() {
rightAlignedRenderer.setHorizontalAlignment(JLabel.RIGHT); rightAlignedRenderer.setHorizontalAlignment(JLabel.RIGHT);
initComponents(); initComponents();
fileCountsByMimeTypeTable.getTableHeader().setReorderingAllowed(false);
fileCountsByCategoryTable.getTableHeader().setReorderingAllowed(false); fileCountsByCategoryTable.getTableHeader().setReorderingAllowed(false);
artifactCountsTable.getTableHeader().setReorderingAllowed(false); artifactCountsTable.getTableHeader().setReorderingAllowed(false);
setDataSource(null); setDataSource(null);
@ -99,20 +96,29 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel {
public void setDataSource(DataSource dataSource) { public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource; this.dataSource = dataSource;
if (dataSource == null || !Case.isCaseOpen()) { if (dataSource == null || !Case.isCaseOpen()) {
updateCountsTableData(EMPTY_PAIRS, EMPTY_PAIRS); updateCountsTableData(EMPTY_PAIRS,
EMPTY_PAIRS,
EMPTY_PAIRS);
} else { } else {
updateCountsTableData(getFileCategoryModel(dataSource), getArtifactCountsModel(dataSource)); updateCountsTableData(getMimeTypeModel(dataSource),
getFileCategoryModel(dataSource),
getArtifactCountsModel(dataSource));
} }
this.fileTypePieChart.setDataSource(dataSource);
} }
/** /**
* Specify the DataSource to display file information for. * Specify the DataSource to display file information for.
* *
* @param mimeTypeDataModel The mime type data model.
* @param fileCategoryDataModel The file category data model. * @param fileCategoryDataModel The file category data model.
* @param artifactDataModel The artifact type data model. * @param artifactDataModel The artifact type data model.
*/ */
private void updateCountsTableData(Object[][] fileCategoryDataModel, Object[][] artifactDataModel) { private void updateCountsTableData(Object[][] mimeTypeDataModel, Object[][] fileCategoryDataModel, Object[][] artifactDataModel) {
fileCountsByMimeTypeTable.setModel(new NonEditableTableModel(mimeTypeDataModel, MIME_TYPE_COLUMN_HEADERS));
fileCountsByMimeTypeTable.getColumnModel().getColumn(1).setCellRenderer(rightAlignedRenderer);
fileCountsByMimeTypeTable.getColumnModel().getColumn(0).setPreferredWidth(130);
fileCountsByCategoryTable.setModel(new NonEditableTableModel(fileCategoryDataModel, FILE_BY_CATEGORY_COLUMN_HEADERS)); fileCountsByCategoryTable.setModel(new NonEditableTableModel(fileCategoryDataModel, FILE_BY_CATEGORY_COLUMN_HEADERS));
fileCountsByCategoryTable.getColumnModel().getColumn(1).setCellRenderer(rightAlignedRenderer); fileCountsByCategoryTable.getColumnModel().getColumn(1).setCellRenderer(rightAlignedRenderer);
fileCountsByCategoryTable.getColumnModel().getColumn(0).setPreferredWidth(130); fileCountsByCategoryTable.getColumnModel().getColumn(0).setPreferredWidth(130);
@ -124,6 +130,48 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel {
this.repaint(); this.repaint();
} }
/**
* Determines the JTable data model for datasource mime types.
*
* @param dataSource The DataSource.
*
* @return The model to be used with a JTable.
*/
@Messages({
"DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.images.row=Images",
"DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.videos.row=Videos",
"DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.audio.row=Audio",
"DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.documents.row=Documents",
"DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.executables.row=Executables"
})
private static Object[][] getMimeTypeModel(DataSource dataSource) {
return new Object[][]{
new Object[]{Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_images_row(),
getCount(dataSource, FileTypeUtils.FileTypeCategory.IMAGE)},
new Object[]{Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_videos_row(),
getCount(dataSource, FileTypeUtils.FileTypeCategory.VIDEO)},
new Object[]{Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_audio_row(),
getCount(dataSource, FileTypeUtils.FileTypeCategory.AUDIO)},
new Object[]{Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_documents_row(),
getCount(dataSource, FileTypeUtils.FileTypeCategory.DOCUMENTS)},
new Object[]{Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_executables_row(),
getCount(dataSource, FileTypeUtils.FileTypeCategory.EXECUTABLE)}
};
}
/**
* Retrieves the counts of files of a particular mime type for a particular
* DataSource.
*
* @param dataSource The DataSource.
* @param category The mime type category.
*
* @return The count.
*/
private static Long getCount(DataSource dataSource, FileTypeUtils.FileTypeCategory category) {
return DataSourceInfoUtilities.getCountOfFilesForMimeTypes(dataSource, category.getMediaTypes());
}
/** /**
* Determines the JTable data model for datasource file categories. * Determines the JTable data model for datasource file categories.
* *
@ -139,11 +187,11 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel {
"DataSourceSummaryCountsPanel.FilesByCategoryTableModel.directory.row=Directory" "DataSourceSummaryCountsPanel.FilesByCategoryTableModel.directory.row=Directory"
}) })
private static Object[][] getFileCategoryModel(DataSource selectedDataSource) { private static Object[][] getFileCategoryModel(DataSource selectedDataSource) {
Long fileCount = zeroIfNull(DataSourceCountsSummary.getCountOfFiles(selectedDataSource)); Long fileCount = zeroIfNull(DataSourceInfoUtilities.getCountOfFiles(selectedDataSource));
Long unallocatedFiles = zeroIfNull(DataSourceCountsSummary.getCountOfUnallocatedFiles(selectedDataSource)); Long unallocatedFiles = zeroIfNull(DataSourceInfoUtilities.getCountOfUnallocatedFiles(selectedDataSource));
Long allocatedFiles = zeroIfNull(DataSourceCountsSummary.getCountOfAllocatedFiles(selectedDataSource)); Long allocatedFiles = zeroIfNull(getAllocatedCount(fileCount, unallocatedFiles));
Long slackFiles = zeroIfNull(DataSourceCountsSummary.getCountOfSlackFiles(selectedDataSource)); Long slackFiles = zeroIfNull(DataSourceInfoUtilities.getCountOfSlackFiles(selectedDataSource));
Long directories = zeroIfNull(DataSourceCountsSummary.getCountOfDirectories(selectedDataSource)); Long directories = zeroIfNull(DataSourceInfoUtilities.getCountOfDirectories(selectedDataSource));
return new Object[][]{ return new Object[][]{
new Object[]{Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_all_row(), fileCount}, new Object[]{Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_all_row(), fileCount},
@ -165,6 +213,24 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel {
return origValue == null ? 0 : origValue; return origValue == null ? 0 : origValue;
} }
/**
* Safely gets the allocated files count.
*
* @param allFilesCount The count of all files.
* @param unallocatedFilesCount The count of unallocated files.
*
* @return The count of allocated files.
*/
private static long getAllocatedCount(Long allFilesCount, Long unallocatedFilesCount) {
if (allFilesCount == null) {
return 0;
} else if (unallocatedFilesCount == null) {
return allFilesCount;
} else {
return allFilesCount - unallocatedFilesCount;
}
}
/** /**
* The counts of different artifact types found in a DataSource. * The counts of different artifact types found in a DataSource.
* *
@ -173,7 +239,7 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel {
* @return The JTable data model of counts of artifact types. * @return The JTable data model of counts of artifact types.
*/ */
private static Object[][] getArtifactCountsModel(DataSource selectedDataSource) { private static Object[][] getArtifactCountsModel(DataSource selectedDataSource) {
Map<String, Long> artifactMapping = DataSourceCountsSummary.getCountsOfArtifactsByType(selectedDataSource); Map<String, Long> artifactMapping = DataSourceInfoUtilities.getCountsOfArtifactsByType(selectedDataSource);
if (artifactMapping == null) { if (artifactMapping == null) {
return EMPTY_PAIRS; return EMPTY_PAIRS;
} }
@ -194,120 +260,83 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel {
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() { private void initComponents() {
javax.swing.JScrollPane scrollParent = new javax.swing.JScrollPane(); fileCountsByMimeTypeScrollPane = new javax.swing.JScrollPane();
javax.swing.JPanel parentPanel = new javax.swing.JPanel(); fileCountsByMimeTypeTable = new javax.swing.JTable();
javax.swing.JScrollPane fileCountsByCategoryScrollPane = new javax.swing.JScrollPane(); byMimeTypeLabel = new javax.swing.JLabel();
fileCountsByCategoryScrollPane = new javax.swing.JScrollPane();
fileCountsByCategoryTable = new javax.swing.JTable(); fileCountsByCategoryTable = new javax.swing.JTable();
javax.swing.JLabel byCategoryLabel = new javax.swing.JLabel(); byCategoryLabel = new javax.swing.JLabel();
javax.swing.JLabel resultsByTypeLabel = new javax.swing.JLabel(); jLabel1 = new javax.swing.JLabel();
javax.swing.JScrollPane artifactCountsScrollPane = new javax.swing.JScrollPane(); artifactCountsScrollPane = new javax.swing.JScrollPane();
artifactCountsTable = new javax.swing.JTable(); artifactCountsTable = new javax.swing.JTable();
javax.swing.JPanel fileTypePiePanel = fileTypePieChart;
javax.swing.JPanel filesByCatParent = new javax.swing.JPanel();
javax.swing.JPanel resultsByTypeParent = new javax.swing.JPanel();
parentPanel.setMinimumSize(new java.awt.Dimension(840, 320)); fileCountsByMimeTypeScrollPane.setViewportView(fileCountsByMimeTypeTable);
org.openide.awt.Mnemonics.setLocalizedText(byMimeTypeLabel, org.openide.util.NbBundle.getMessage(DataSourceSummaryCountsPanel.class, "DataSourceSummaryCountsPanel.byMimeTypeLabel.text")); // NOI18N
fileCountsByCategoryScrollPane.setViewportView(fileCountsByCategoryTable); fileCountsByCategoryScrollPane.setViewportView(fileCountsByCategoryTable);
org.openide.awt.Mnemonics.setLocalizedText(byCategoryLabel, org.openide.util.NbBundle.getMessage(DataSourceSummaryCountsPanel.class, "DataSourceSummaryCountsPanel.byCategoryLabel.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(byCategoryLabel, org.openide.util.NbBundle.getMessage(DataSourceSummaryCountsPanel.class, "DataSourceSummaryCountsPanel.byCategoryLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(resultsByTypeLabel, org.openide.util.NbBundle.getMessage(DataSourceSummaryCountsPanel.class, "DataSourceSummaryCountsPanel.resultsByTypeLabel.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(DataSourceSummaryCountsPanel.class, "DataSourceSummaryCountsPanel.jLabel1.text")); // NOI18N
artifactCountsTable.setAutoCreateRowSorter(true);
artifactCountsScrollPane.setViewportView(artifactCountsTable); artifactCountsScrollPane.setViewportView(artifactCountsTable);
fileTypePiePanel.setPreferredSize(new java.awt.Dimension(400, 300));
javax.swing.GroupLayout filesByCatParentLayout = new javax.swing.GroupLayout(filesByCatParent);
filesByCatParent.setLayout(filesByCatParentLayout);
filesByCatParentLayout.setHorizontalGroup(
filesByCatParentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 0, Short.MAX_VALUE)
);
filesByCatParentLayout.setVerticalGroup(
filesByCatParentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 0, Short.MAX_VALUE)
);
javax.swing.GroupLayout resultsByTypeParentLayout = new javax.swing.GroupLayout(resultsByTypeParent);
resultsByTypeParent.setLayout(resultsByTypeParentLayout);
resultsByTypeParentLayout.setHorizontalGroup(
resultsByTypeParentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 0, Short.MAX_VALUE)
);
resultsByTypeParentLayout.setVerticalGroup(
resultsByTypeParentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 0, Short.MAX_VALUE)
);
javax.swing.GroupLayout parentPanelLayout = new javax.swing.GroupLayout(parentPanel);
parentPanel.setLayout(parentPanelLayout);
parentPanelLayout.setHorizontalGroup(
parentPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(parentPanelLayout.createSequentialGroup()
.addContainerGap()
.addComponent(fileTypePiePanel, javax.swing.GroupLayout.PREFERRED_SIZE, 400, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addGroup(parentPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(fileCountsByCategoryScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 140, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(byCategoryLabel)
.addComponent(filesByCatParent, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(18, 18, 18)
.addGroup(parentPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(resultsByTypeLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(parentPanelLayout.createSequentialGroup()
.addComponent(artifactCountsScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 244, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(resultsByTypeParent, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
parentPanelLayout.setVerticalGroup(
parentPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(parentPanelLayout.createSequentialGroup()
.addContainerGap()
.addGroup(parentPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(parentPanelLayout.createSequentialGroup()
.addComponent(fileTypePiePanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGroup(parentPanelLayout.createSequentialGroup()
.addGroup(parentPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(byCategoryLabel)
.addComponent(resultsByTypeLabel))
.addGroup(parentPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, parentPanelLayout.createSequentialGroup()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(resultsByTypeParent, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(148, 148, 148))
.addGroup(parentPanelLayout.createSequentialGroup()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(parentPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(artifactCountsScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
.addGroup(parentPanelLayout.createSequentialGroup()
.addComponent(fileCountsByCategoryScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 107, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(31, 31, 31)
.addComponent(filesByCatParent, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())))))
);
scrollParent.setViewportView(parentPanel);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout); this.setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(scrollParent) .addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(fileCountsByMimeTypeScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 140, Short.MAX_VALUE)
.addComponent(byMimeTypeLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(byCategoryLabel)
.addComponent(fileCountsByCategoryScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 82, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(artifactCountsScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 244, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
); );
layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {fileCountsByCategoryScrollPane, fileCountsByMimeTypeScrollPane});
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(scrollParent) .addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(byMimeTypeLabel)
.addComponent(byCategoryLabel)
.addComponent(jLabel1))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(artifactCountsScrollPane, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(fileCountsByMimeTypeScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 107, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(fileCountsByCategoryScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 86, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())
); );
layout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {fileCountsByCategoryScrollPane, fileCountsByMimeTypeScrollPane});
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables // Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JScrollPane artifactCountsScrollPane;
private javax.swing.JTable artifactCountsTable; private javax.swing.JTable artifactCountsTable;
private javax.swing.JLabel byCategoryLabel;
private javax.swing.JLabel byMimeTypeLabel;
private javax.swing.JScrollPane fileCountsByCategoryScrollPane;
private javax.swing.JTable fileCountsByCategoryTable; private javax.swing.JTable fileCountsByCategoryTable;
private javax.swing.JScrollPane fileCountsByMimeTypeScrollPane;
private javax.swing.JTable fileCountsByMimeTypeTable;
private javax.swing.JLabel jLabel1;
// End of variables declaration//GEN-END:variables // End of variables declaration//GEN-END:variables
} }

View File

@ -40,7 +40,7 @@
<Component class="javax.swing.JLabel" name="operatingSystemLabel"> <Component class="javax.swing.JLabel" name="operatingSystemLabel">
<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/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.operatingSystemLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.operatingSystemLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Constraints> <Constraints>
@ -52,7 +52,7 @@
<Component class="javax.swing.JLabel" name="displayNameLabel"> <Component class="javax.swing.JLabel" name="displayNameLabel">
<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/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.displayNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.displayNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Constraints> <Constraints>
@ -64,7 +64,7 @@
<Component class="javax.swing.JLabel" name="originalNameLabel"> <Component class="javax.swing.JLabel" name="originalNameLabel">
<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/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.originalNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.originalNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Constraints> <Constraints>
@ -76,7 +76,7 @@
<Component class="javax.swing.JLabel" name="sha1HashValue"> <Component class="javax.swing.JLabel" name="sha1HashValue">
<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/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.sha1HashValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.sha1HashValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Constraints> <Constraints>
@ -88,10 +88,10 @@
<Component class="javax.swing.JLabel" name="operatingSystemValue"> <Component class="javax.swing.JLabel" name="operatingSystemValue">
<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/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.operatingSystemValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.operatingSystemValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.operatingSystemValue.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.operatingSystemValue.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Constraints> <Constraints>
@ -103,7 +103,7 @@
<Component class="javax.swing.JLabel" name="displayNameValue"> <Component class="javax.swing.JLabel" name="displayNameValue">
<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/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.displayNameValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.displayNameValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Constraints> <Constraints>
@ -115,7 +115,7 @@
<Component class="javax.swing.JLabel" name="sha256HashValue"> <Component class="javax.swing.JLabel" name="sha256HashValue">
<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/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.sha256HashValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.sha256HashValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Constraints> <Constraints>
@ -127,7 +127,7 @@
<Component class="javax.swing.JLabel" name="originalNameValue"> <Component class="javax.swing.JLabel" name="originalNameValue">
<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/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.originalNameValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.originalNameValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Constraints> <Constraints>
@ -139,10 +139,10 @@
<Component class="javax.swing.JLabel" name="deviceIdValue"> <Component class="javax.swing.JLabel" name="deviceIdValue">
<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/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.deviceIdValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.deviceIdValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.deviceIdValue.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.deviceIdValue.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Constraints> <Constraints>
@ -179,7 +179,7 @@
<TableColumnModel selectionModel="0"> <TableColumnModel selectionModel="0">
<Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true"> <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true">
<Title editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Title editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.filePathsTable.columnModel.title0" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.filePathsTable.columnModel.title0" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Title> </Title>
<Editor/> <Editor/>
<Renderer/> <Renderer/>
@ -196,7 +196,7 @@
<Component class="javax.swing.JLabel" name="dataSourceUsageValue"> <Component class="javax.swing.JLabel" name="dataSourceUsageValue">
<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/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.dataSourceUsageValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.dataSourceUsageValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Constraints> <Constraints>
@ -208,7 +208,7 @@
<Component class="javax.swing.JLabel" name="timeZoneValue"> <Component class="javax.swing.JLabel" name="timeZoneValue">
<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/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.timeZoneValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.timeZoneValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Constraints> <Constraints>
@ -220,10 +220,10 @@
<Component class="javax.swing.JLabel" name="imageTypeValue"> <Component class="javax.swing.JLabel" name="imageTypeValue">
<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/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.imageTypeValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.imageTypeValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.imageTypeValue.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.imageTypeValue.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Constraints> <Constraints>
@ -235,10 +235,10 @@
<Component class="javax.swing.JLabel" name="md5HashValue"> <Component class="javax.swing.JLabel" name="md5HashValue">
<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/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.md5HashValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.md5HashValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.md5HashValue.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.md5HashValue.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Constraints> <Constraints>
@ -250,7 +250,7 @@
<Component class="javax.swing.JLabel" name="sectorSizeValue"> <Component class="javax.swing.JLabel" name="sectorSizeValue">
<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/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.sectorSizeValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.sectorSizeValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Constraints> <Constraints>
@ -262,7 +262,7 @@
<Component class="javax.swing.JLabel" name="sizeValue"> <Component class="javax.swing.JLabel" name="sizeValue">
<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/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.sizeValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.sizeValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Constraints> <Constraints>
@ -274,7 +274,7 @@
<Component class="javax.swing.JLabel" name="filePathsLabel"> <Component class="javax.swing.JLabel" name="filePathsLabel">
<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/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.filePathsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.filePathsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Constraints> <Constraints>
@ -286,7 +286,7 @@
<Component class="javax.swing.JLabel" name="sha256HashLabel"> <Component class="javax.swing.JLabel" name="sha256HashLabel">
<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/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.sha256HashLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.sha256HashLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Constraints> <Constraints>
@ -298,7 +298,7 @@
<Component class="javax.swing.JLabel" name="sha1HashLabel"> <Component class="javax.swing.JLabel" name="sha1HashLabel">
<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/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.sha1HashLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.sha1HashLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Constraints> <Constraints>
@ -310,7 +310,7 @@
<Component class="javax.swing.JLabel" name="md5HashLabel"> <Component class="javax.swing.JLabel" name="md5HashLabel">
<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/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.md5HashLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.md5HashLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Constraints> <Constraints>
@ -322,7 +322,7 @@
<Component class="javax.swing.JLabel" name="sectorSizeLabel"> <Component class="javax.swing.JLabel" name="sectorSizeLabel">
<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/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.sectorSizeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.sectorSizeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Constraints> <Constraints>
@ -334,7 +334,7 @@
<Component class="javax.swing.JLabel" name="sizeLabel"> <Component class="javax.swing.JLabel" name="sizeLabel">
<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/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.sizeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.sizeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Constraints> <Constraints>
@ -346,7 +346,7 @@
<Component class="javax.swing.JLabel" name="imageTypeLabel"> <Component class="javax.swing.JLabel" name="imageTypeLabel">
<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/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.imageTypeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.imageTypeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Constraints> <Constraints>
@ -358,7 +358,7 @@
<Component class="javax.swing.JLabel" name="acquisitionDetailsLabel"> <Component class="javax.swing.JLabel" name="acquisitionDetailsLabel">
<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/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.acquisitionDetailsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.acquisitionDetailsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Constraints> <Constraints>
@ -370,7 +370,7 @@
<Component class="javax.swing.JLabel" name="timeZoneLabel"> <Component class="javax.swing.JLabel" name="timeZoneLabel">
<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/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.timeZoneLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.timeZoneLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Constraints> <Constraints>
@ -382,7 +382,7 @@
<Component class="javax.swing.JLabel" name="dataSourceUsageLabel"> <Component class="javax.swing.JLabel" name="dataSourceUsageLabel">
<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/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.dataSourceUsageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.dataSourceUsageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Constraints> <Constraints>
@ -394,7 +394,7 @@
<Component class="javax.swing.JLabel" name="deviceIdLabel"> <Component class="javax.swing.JLabel" name="deviceIdLabel">
<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/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.deviceIdLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.deviceIdLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Constraints> <Constraints>
@ -424,7 +424,7 @@
<Property name="columns" type="int" value="20"/> <Property name="columns" type="int" value="20"/>
<Property name="rows" type="int" value="4"/> <Property name="rows" type="int" value="4"/>
<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/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.acquisitionDetailsTextArea.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.acquisitionDetailsTextArea.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor"> <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="null"/> <Border info="null"/>
@ -466,7 +466,7 @@
<Component class="javax.swing.JLabel" name="unallocatedSizeLabel"> <Component class="javax.swing.JLabel" name="unallocatedSizeLabel">
<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/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.unallocatedSizeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.unallocatedSizeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Constraints> <Constraints>
@ -478,7 +478,7 @@
<Component class="javax.swing.JLabel" name="unallocatedSizeValue"> <Component class="javax.swing.JLabel" name="unallocatedSizeValue">
<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/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.unallocatedSizeValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.unallocatedSizeValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Constraints> <Constraints>

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.datasourcesummary.ui; package org.sleuthkit.autopsy.casemodule.datasourcesummary;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.logging.Level; import java.util.logging.Level;
@ -25,7 +25,6 @@ import javax.swing.table.DefaultTableModel;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceDetailsSummary;
import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.DataSource;
import org.sleuthkit.datamodel.Image; import org.sleuthkit.datamodel.Image;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
@ -74,9 +73,9 @@ class DataSourceSummaryDetailsPanel extends javax.swing.JPanel {
updateDetailsPanelData(null, null, null, null); updateDetailsPanelData(null, null, null, null);
} else { } else {
updateDetailsPanelData(dataSource, updateDetailsPanelData(dataSource,
DataSourceDetailsSummary.getSizeOfUnallocatedFiles(dataSource), DataSourceInfoUtilities.getSizeOfUnallocatedFiles(dataSource),
DataSourceDetailsSummary.getOperatingSystems(dataSource), DataSourceInfoUtilities.getOperatingSystems(dataSource),
DataSourceDetailsSummary.getDataSourceType(dataSource)); DataSourceInfoUtilities.getDataSourceType(dataSource));
} }
} }

View File

@ -22,7 +22,7 @@
<Group type="102" alignment="1" attributes="0"> <Group type="102" alignment="1" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0"> <Group type="103" groupAlignment="1" attributes="0">
<Component id="dataSourceSummarySplitPane" pref="860" max="32767" attributes="0"/> <Component id="dataSourceSummarySplitPane" pref="668" max="32767" attributes="0"/>
<Group type="102" attributes="0"> <Group type="102" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/> <EmptySpace min="0" pref="0" max="32767" attributes="0"/>
<Component id="closeButton" min="-2" max="-2" attributes="0"/> <Component id="closeButton" min="-2" max="-2" attributes="0"/>
@ -36,7 +36,7 @@
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="dataSourceSummarySplitPane" pref="540" max="32767" attributes="0"/> <Component id="dataSourceSummarySplitPane" pref="362" max="32767" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="closeButton" min="-2" max="-2" attributes="0"/> <Component id="closeButton" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
@ -48,7 +48,7 @@
<Component class="javax.swing.JButton" name="closeButton"> <Component class="javax.swing.JButton" name="closeButton">
<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/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDialog.closeButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDialog.closeButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Events> <Events>

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.datasourcesummary.ui; package org.sleuthkit.autopsy.casemodule.datasourcesummary;
import java.awt.Frame; import java.awt.Frame;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
@ -27,7 +27,6 @@ import java.util.Observer;
import java.util.Set; import java.util.Set;
import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionEvent;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.datasourcesummary.datamodel.CaseDataSourcesSummary;
import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.ingest.events.DataSourceAnalysisCompletedEvent; import org.sleuthkit.autopsy.ingest.events.DataSourceAnalysisCompletedEvent;
import org.sleuthkit.autopsy.ingest.events.DataSourceAnalysisCompletedEvent.Reason; import org.sleuthkit.autopsy.ingest.events.DataSourceAnalysisCompletedEvent.Reason;
@ -54,8 +53,8 @@ final class DataSourceSummaryDialog extends javax.swing.JDialog implements Obser
}) })
DataSourceSummaryDialog(Frame owner) { DataSourceSummaryDialog(Frame owner) {
super(owner, Bundle.DataSourceSummaryDialog_window_title(), true); super(owner, Bundle.DataSourceSummaryDialog_window_title(), true);
Map<Long, String> usageMap = CaseDataSourcesSummary.getDataSourceTypes(); Map<Long, String> usageMap = DataSourceInfoUtilities.getDataSourceTypes();
Map<Long, Long> fileCountsMap = CaseDataSourcesSummary.getCountsOfFiles(); Map<Long, Long> fileCountsMap = DataSourceInfoUtilities.getCountsOfFiles();
dataSourcesPanel = new DataSourceBrowser(usageMap, fileCountsMap); dataSourcesPanel = new DataSourceBrowser(usageMap, fileCountsMap);
dataSourceSummaryTabbedPane = new DataSourceSummaryTabbedPane(); dataSourceSummaryTabbedPane = new DataSourceSummaryTabbedPane();
initComponents(); initComponents();
@ -126,7 +125,7 @@ final class DataSourceSummaryDialog extends javax.swing.JDialog implements Obser
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(dataSourceSummarySplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 860, Short.MAX_VALUE) .addComponent(dataSourceSummarySplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 668, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE) .addGap(0, 0, Short.MAX_VALUE)
.addComponent(closeButton))) .addComponent(closeButton)))
@ -136,7 +135,7 @@ final class DataSourceSummaryDialog extends javax.swing.JDialog implements Obser
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addComponent(dataSourceSummarySplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 540, Short.MAX_VALUE) .addComponent(dataSourceSummarySplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 362, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(closeButton) .addComponent(closeButton)
.addContainerGap()) .addContainerGap())

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.datasourcesummary.ui; package org.sleuthkit.autopsy.casemodule.datasourcesummary;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.util.ArrayList; import java.util.ArrayList;
@ -30,7 +30,6 @@ import org.openide.nodes.Children;
import org.openide.nodes.Node; import org.openide.nodes.Node;
import org.openide.nodes.Sheet; import org.openide.nodes.Sheet;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.datasourcesummary.ui.Bundle;
import org.sleuthkit.autopsy.datamodel.NodeProperty; import org.sleuthkit.autopsy.datamodel.NodeProperty;
import org.sleuthkit.autopsy.directorytree.ViewContextAction; import org.sleuthkit.autopsy.directorytree.ViewContextAction;
import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.DataSource;

View File

@ -16,12 +16,11 @@
* 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.datasourcesummary.ui; package org.sleuthkit.autopsy.casemodule.datasourcesummary;
import javax.swing.JTabbedPane; import javax.swing.JTabbedPane;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.IngestJobInfoPanel; import org.sleuthkit.autopsy.casemodule.IngestJobInfoPanel;
import org.sleuthkit.autopsy.datasourcesummary.ui.Bundle;
import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.DataSource;
/** /**

View File

@ -42,7 +42,7 @@
<Component class="javax.swing.JLabel" name="programsRunLabel"> <Component class="javax.swing.JLabel" name="programsRunLabel">
<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/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryUserActivityPanel.programsRunLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryUserActivityPanel.programsRunLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<AuxValues> <AuxValues>

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.datasourcesummary.ui; package org.sleuthkit.autopsy.casemodule.datasourcesummary;
import java.awt.Component; import java.awt.Component;
import java.text.DateFormat; import java.text.DateFormat;
@ -32,8 +32,6 @@ import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer; import javax.swing.table.TableCellRenderer;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceTopProgramsSummary;
import org.sleuthkit.autopsy.datasourcesummary.datamodel.TopProgramsResult;
import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.DataSource;
/** /**
@ -116,8 +114,8 @@ public class DataSourceSummaryUserActivityPanel extends javax.swing.JPanel {
* @return The JTable data model of counts of program runs. * @return The JTable data model of counts of program runs.
*/ */
private static TopProgramsModel getTopProgramsModel(DataSource selectedDataSource) { private static TopProgramsModel getTopProgramsModel(DataSource selectedDataSource) {
List<TopProgramsResult> topProgramList List<DataSourceInfoUtilities.TopProgramsResult> topProgramList
= DataSourceTopProgramsSummary.getTopPrograms(selectedDataSource, TOP_PROGS_COUNT); = DataSourceInfoUtilities.getTopPrograms(selectedDataSource, TOP_PROGS_COUNT);
if (topProgramList == null) { if (topProgramList == null) {
return new TopProgramsModel(null); return new TopProgramsModel(null);
@ -196,14 +194,14 @@ public class DataSourceSummaryUserActivityPanel extends javax.swing.JPanel {
Bundle.DataSourceSummaryUserActivityPanel_TopProgramsTableModel_lastrun_header() Bundle.DataSourceSummaryUserActivityPanel_TopProgramsTableModel_lastrun_header()
}; };
private final List<TopProgramsResult> programResults; private final List<DataSourceInfoUtilities.TopProgramsResult> programResults;
/** /**
* Main constructor. * Main constructor.
* *
* @param programResults The results to display. * @param programResults The results to display.
*/ */
TopProgramsModel(List<TopProgramsResult> programResults) { TopProgramsModel(List<DataSourceInfoUtilities.TopProgramsResult> programResults) {
this.programResults = programResults == null ? new ArrayList<>() : Collections.unmodifiableList(programResults); this.programResults = programResults == null ? new ArrayList<>() : Collections.unmodifiableList(programResults);
} }
@ -228,12 +226,12 @@ public class DataSourceSummaryUserActivityPanel extends javax.swing.JPanel {
return null; return null;
} }
TopProgramsResult result = programResults.get(rowIndex); DataSourceInfoUtilities.TopProgramsResult result = programResults.get(rowIndex);
switch (columnIndex) { switch (columnIndex) {
case 0: case 0:
return new ProgramNameCellValue(result.getProgramName(), result.getProgramPath()); return new ProgramNameCellValue(result.getProgramName(), result.getProgramPath());
case 1: case 1:
return DataSourceTopProgramsSummary.getShortFolderName(result.getProgramPath(), result.getProgramName()); return DataSourceInfoUtilities.getShortFolderName(result.getProgramPath(), result.getProgramName());
case 2: case 2:
return result.getRunTimes(); return result.getRunTimes();
case 3: case 3:

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.datasourcesummary.ui; package org.sleuthkit.autopsy.casemodule.datasourcesummary;
import javax.swing.table.DefaultTableModel; import javax.swing.table.DefaultTableModel;

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.datasourcesummary.ui; package org.sleuthkit.autopsy.casemodule.datasourcesummary;
import java.awt.Component; import java.awt.Component;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;

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.datasourcesummary.ui; package org.sleuthkit.autopsy.casemodule.datasourcesummary;
import java.awt.Frame; import java.awt.Frame;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
@ -24,7 +24,6 @@ import javax.swing.AbstractAction;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.openide.windows.WindowManager; import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.datasourcesummary.ui.Bundle;
/** /**
* ViewSummaryInformationAction action for opening a Data Sources Summary Dialog * ViewSummaryInformationAction action for opening a Data Sources Summary Dialog

View File

@ -36,7 +36,7 @@ import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.DeleteDataSourceAction; import org.sleuthkit.autopsy.casemodule.DeleteDataSourceAction;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.datasourcesummary.ui.ViewSummaryInformationAction; import org.sleuthkit.autopsy.casemodule.datasourcesummary.ViewSummaryInformationAction;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable; import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;

View File

@ -24,7 +24,7 @@ import java.util.List;
import javax.swing.Action; import javax.swing.Action;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.DeleteDataSourceAction; import org.sleuthkit.autopsy.casemodule.DeleteDataSourceAction;
import org.sleuthkit.autopsy.datasourcesummary.ui.ViewSummaryInformationAction; import org.sleuthkit.autopsy.casemodule.datasourcesummary.ViewSummaryInformationAction;
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint; import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
import org.sleuthkit.autopsy.directorytree.ExportCSVAction; import org.sleuthkit.autopsy.directorytree.ExportCSVAction;
import org.sleuthkit.autopsy.directorytree.ExtractAction; import org.sleuthkit.autopsy.directorytree.ExtractAction;

View File

@ -1,168 +0,0 @@
/*
* 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.datasourcesummary.datamodel;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData;
/**
* Provides methods to query for information for all datasources in a case.
*/
public class CaseDataSourcesSummary {
private static final Logger logger = Logger.getLogger(CaseDataSourcesSummary.class.getName());
/**
* Get a map containing the TSK_DATA_SOURCE_USAGE description attributes
* associated with each data source in the current case.
*
* @return Collection which maps datasource id to a String which displays a
* comma seperated list of values of data source usage types
* expected to be in the datasource
*/
public static Map<Long, String> getDataSourceTypes() {
try {
SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
List<BlackboardArtifact> listOfArtifacts = skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_DATA_SOURCE_USAGE);
Map<Long, String> typeMap = new HashMap<>();
for (BlackboardArtifact typeArtifact : listOfArtifacts) {
BlackboardAttribute descriptionAttr = typeArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION));
if (typeArtifact.getDataSource() != null && descriptionAttr != null) {
long dsId = typeArtifact.getDataSource().getId();
String type = typeMap.get(typeArtifact.getDataSource().getId());
if (type == null) {
type = descriptionAttr.getValueString();
} else {
type = type + ", " + descriptionAttr.getValueString();
}
typeMap.put(dsId, type);
}
}
return typeMap;
} catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.WARNING, "Unable to get types of files for all datasources, providing empty results", ex);
return Collections.emptyMap();
}
}
/**
* Get a map containing the number of files in each data source in the
* current case.
*
* @return Collection which maps datasource id to a count for the number of
* files in the datasource, will only contain entries for
* datasources which have at least 1 file
*/
public static Map<Long, Long> getCountsOfFiles() {
try {
final String countFilesQuery = "data_source_obj_id, COUNT(*) AS value FROM tsk_files"
+ " WHERE meta_type=" + TskData.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
return getValuesMap(countFilesQuery);
} catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.WARNING, "Unable to get counts of files for all datasources, providing empty results", ex);
return Collections.emptyMap();
}
}
/**
* Get a map containing the number of artifacts in each data source in the
* current case.
*
* @return Collection which maps datasource id to a count for the number of
* artifacts in the datasource, will only contain entries for
* datasources which have at least 1 artifact
*/
public static Map<Long, Long> getCountsOfArtifacts() {
try {
final String countArtifactsQuery = "data_source_obj_id, COUNT(*) AS value"
+ " FROM blackboard_artifacts WHERE review_status_id !=" + BlackboardArtifact.ReviewStatus.REJECTED.getID()
+ " GROUP BY data_source_obj_id"; //NON-NLS
return getValuesMap(countArtifactsQuery);
} catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.WARNING, "Unable to get counts of artifacts for all datasources, providing empty results", ex);
return Collections.emptyMap();
}
}
/**
* Get a map containing the number of tags which have been applied in each
* data source in the current case. Not necessarily the same as the number
* of items tagged, as an item can have any number of tags.
*
* @return Collection which maps datasource id to a count for the number of
* tags which have been applied in the datasource, will only contain
* entries for datasources which have at least 1 item tagged.
*/
public static Map<Long, Long> getCountsOfTags() {
try {
final String countFileTagsQuery = "data_source_obj_id, COUNT(*) AS value"
+ " FROM content_tags as content_tags, tsk_files as tsk_files"
+ " WHERE content_tags.obj_id = tsk_files.obj_id"
+ " GROUP BY data_source_obj_id"; //NON-NLS
//new hashmap so it can be modifiable
Map<Long, Long> tagCountMap = new HashMap<>(getValuesMap(countFileTagsQuery));
final String countArtifactTagsQuery = "data_source_obj_id, COUNT(*) AS value"
+ " FROM blackboard_artifact_tags as artifact_tags, blackboard_artifacts AS arts"
+ " WHERE artifact_tags.artifact_id = arts.artifact_id"
+ " GROUP BY data_source_obj_id"; //NON-NLS
//combine the results from the count artifact tags query into the copy of the mapped results from the count file tags query
getValuesMap(countArtifactTagsQuery).forEach((key, value) -> tagCountMap.merge(key, value, (value1, value2) -> value1 + value2));
return tagCountMap;
} catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.WARNING, "Unable to get counts of tags for all datasources, providing empty results", ex);
return Collections.emptyMap();
}
}
/**
* Helper method to execute a select query with a
* DataSourceSingleValueCallback.
*
* @param query the portion of the query which should follow the SELECT
*
* @return a map of datasource object ID to a value of type Long
*
* @throws TskCoreException
* @throws NoCurrentCaseException
*/
private static Map<Long, Long> getValuesMap(String query) throws TskCoreException, NoCurrentCaseException {
SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
DataSourceSingleValueCallback callback = new DataSourceSingleValueCallback();
skCase.getCaseDbAccessManager().select(query, callback);
return callback.getMapOfValues();
}
private CaseDataSourcesSummary() {
}
}

View File

@ -1,160 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019 - 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.datasourcesummary.datamodel;
import java.sql.SQLException;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceInfoUtilities.ResultSetHandler;
import org.sleuthkit.datamodel.DataSource;
import org.sleuthkit.datamodel.TskData;
/**
* Provides information for the DataSourceSummaryCountsPanel.
*/
public class DataSourceCountsSummary {
private static final Logger logger = Logger.getLogger(DataSourceCountsSummary.class.getName());
/**
* Get count of regular files (not directories) in a data source.
*
* @param currentDataSource The data source.
*
* @return The count.
*/
public static Long getCountOfFiles(DataSource currentDataSource) {
return DataSourceInfoUtilities.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.
*/
public static Long getCountOfAllocatedFiles(DataSource currentDataSource) {
return DataSourceInfoUtilities.getCountOfRegularFiles(currentDataSource,
DataSourceInfoUtilities.getMetaFlagsContainsStatement(TskData.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.
*
* @param currentDataSource The data source.
*
* @return The count.
*/
public static Long getCountOfUnallocatedFiles(DataSource currentDataSource) {
return DataSourceInfoUtilities.getCountOfRegularFiles(currentDataSource,
DataSourceInfoUtilities.getMetaFlagsContainsStatement(TskData.TSK_FS_META_FLAG_ENUM.UNALLOC)
+ " AND type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType(),
"Unable to get counts of unallocated files for datasource, providing empty results");
}
/**
* Get count of directories in a data source.
*
* @param currentDataSource The data source.
*
* @return The count.
*/
public static Long getCountOfDirectories(DataSource currentDataSource) {
return DataSourceInfoUtilities.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");
}
/**
* Get count of slack files in a data source.
*
* @param currentDataSource The data source.
*
* @return The count.
*/
public static Long getCountOfSlackFiles(DataSource currentDataSource) {
return DataSourceInfoUtilities.getCountOfRegularFiles(currentDataSource,
DataSourceInfoUtilities.getMetaFlagsContainsStatement(TskData.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");
}
/**
* Retrieves counts for each artifact type in a data source.
*
* @param selectedDataSource The data source.
*
* @return A mapping of artifact type name to the counts or null if there
* was an error executing the query.
*/
public static Map<String, Long> getCountsOfArtifactsByType(DataSource selectedDataSource) {
if (selectedDataSource == null) {
return Collections.emptyMap();
}
final String nameParam = "name";
final String valueParam = "value";
String query
= "SELECT bbt.display_name AS " + nameParam + ", COUNT(*) AS " + valueParam
+ " FROM blackboard_artifacts bba "
+ " INNER JOIN blackboard_artifact_types bbt ON bba.artifact_type_id = bbt.artifact_type_id"
+ " WHERE bba.data_source_obj_id =" + selectedDataSource.getId()
+ " GROUP BY bbt.display_name";
String errorMessage = "Unable to get artifact type counts; returning null.";
return DataSourceInfoUtilities.getBaseQueryResult(query,
getStringLongResultSetHandler(nameParam, valueParam),
errorMessage);
}
/**
* Generates a result set handler that will return a map of string to long.
*
* @param keyParam The named parameter in the result set representing the
* key.
* @param valueParam The named parameter in the result set representing the
* value.
*
* @return The result set handler to generate the map of string to long.
*/
private static ResultSetHandler<LinkedHashMap<String, Long>> getStringLongResultSetHandler(String keyParam, String valueParam) {
return (resultSet) -> {
LinkedHashMap<String, Long> toRet = new LinkedHashMap<>();
while (resultSet.next()) {
try {
toRet.put(resultSet.getString(keyParam), resultSet.getLong(valueParam));
} catch (SQLException ex) {
logger.log(Level.WARNING, "Failed to get a result pair from the result set.", ex);
}
}
return toRet;
};
}
private DataSourceCountsSummary() {
}
}

View File

@ -1,178 +0,0 @@
/*
* 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.datasourcesummary.datamodel;
import java.sql.SQLException;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import static org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceInfoUtilities.getBaseQueryResult;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.DataSource;
import org.sleuthkit.datamodel.TskData;
/**
* Provides methods to query for data source overview details.
*/
public class DataSourceDetailsSummary {
private static final Logger logger = Logger.getLogger(DataSourceDetailsSummary.class.getName());
/**
* Gets the size of unallocated files in a particular datasource.
*
* @param currentDataSource The data source.
*
* @return The size or null if the query could not be executed.
*/
public static Long getSizeOfUnallocatedFiles(DataSource currentDataSource) {
if (currentDataSource == null) {
return null;
}
final String valueParam = "value";
final String countParam = "count";
String query = "SELECT SUM(size) AS " + valueParam + ", COUNT(*) AS " + countParam
+ " FROM tsk_files"
+ " WHERE " + DataSourceInfoUtilities.getMetaFlagsContainsStatement(TskData.TSK_FS_META_FLAG_ENUM.UNALLOC)
+ " AND type<>" + TskData.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 name<>''"
+ " AND data_source_obj_id=" + currentDataSource.getId();
DataSourceInfoUtilities.ResultSetHandler<Long> handler = (resultSet) -> {
if (resultSet.next()) {
// ensure that there is an unallocated count result that is attached to this data source
long resultCount = resultSet.getLong(valueParam);
return (resultCount > 0) ? resultSet.getLong(valueParam) : null;
} else {
return null;
}
};
String errorMessage = "Unable to get size of unallocated files; returning null.";
return DataSourceInfoUtilities.getBaseQueryResult(query, handler, errorMessage);
}
/**
* Retrieves the concatenation of operating system attributes for a
* particular data source.
*
* @param dataSource The data source.
*
* @return The concatenated value or null if the query could not be
* executed.
*/
public static String getOperatingSystems(DataSource dataSource) {
if (dataSource == null) {
return null;
}
return getConcattedAttrValue(dataSource.getId(),
BlackboardArtifact.ARTIFACT_TYPE.TSK_OS_INFO.getTypeID(),
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID());
}
/**
* Retrieves the concatenation of data source usage for a particular data
* source.
*
* @param dataSource The data source.
*
* @return The concatenated value or null if the query could not be
* executed.
*/
public static String getDataSourceType(DataSource dataSource) {
if (dataSource == null) {
return null;
}
return getConcattedAttrValue(dataSource.getId(),
BlackboardArtifact.ARTIFACT_TYPE.TSK_DATA_SOURCE_USAGE.getTypeID(),
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION.getTypeID());
}
/**
* Generates a string which is a concatenation of the value received from
* the result set.
*
* @param query The query.
* @param valueParam The parameter for the value in the result set.
* @param separator The string separator used in concatenation.
* @param errorMessage The error message if the result set could not
* be received.
* @param singleErrorMessage The error message if a single result could not
* be obtained.
*
* @return The concatenated string or null if the query could not be
* executed.
*/
private static String getConcattedStringsResult(String query, String valueParam, String separator, String errorMessage, String singleErrorMessage) {
DataSourceInfoUtilities.ResultSetHandler<String> handler = (resultSet) -> {
String toRet = "";
boolean first = true;
while (resultSet.next()) {
try {
if (first) {
first = false;
} else {
toRet += separator;
}
toRet += resultSet.getString(valueParam);
} catch (SQLException ex) {
logger.log(Level.WARNING, singleErrorMessage, ex);
}
}
return toRet;
};
return getBaseQueryResult(query, handler, errorMessage);
}
/**
* Generates a concatenated string value based on the text value of a
* particular attribute in a particular artifact for a specific data source.
*
* @param dataSourceId The data source id.
* @param artifactTypeId The artifact type id.
* @param attributeTypeId The attribute type id.
*
* @return The concatenated value or null if the query could not be
* executed.
*/
private static String getConcattedAttrValue(long dataSourceId, int artifactTypeId, int attributeTypeId) {
final String valueParam = "concatted_attribute_value";
String query = "SELECT attr.value_text AS " + valueParam
+ " FROM blackboard_artifacts bba "
+ " INNER JOIN blackboard_attributes attr ON bba.artifact_id = attr.artifact_id "
+ " WHERE bba.data_source_obj_id = " + dataSourceId
+ " AND bba.artifact_type_id = " + artifactTypeId
+ " AND attr.attribute_type_id = " + attributeTypeId;
String errorMessage = "Unable to execute query to retrieve concatted attribute values.";
String singleErrorMessage = "There was an error retrieving one of the results. That result will be omitted from concatted value.";
String separator = ", ";
return getConcattedStringsResult(query, valueParam, separator, errorMessage, singleErrorMessage);
}
private DataSourceDetailsSummary() {
}
}

View File

@ -1,141 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019 - 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.datasourcesummary.datamodel;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
import org.apache.commons.lang.StringUtils;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.datamodel.TskData;
import org.sleuthkit.datamodel.DataSource;
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
* from the case database.
*/
final class DataSourceInfoUtilities {
private static final Logger logger = Logger.getLogger(DataSourceInfoUtilities.class.getName());
/**
* 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.
* @param onError The message to log on error.
*
* @return The count of files or null on error.
*/
static Long getCountOfTskFiles(DataSource currentDataSource, String additionalWhere, String onError) {
if (currentDataSource != null) {
try {
SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
return skCase.countFilesWhere(
"data_source_obj_id=" + currentDataSource.getId()
+ " AND dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue()
+ " AND name<>''"
+ (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
}
}
return null;
}
/**
* 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.
*/
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);
}
/**
* An interface for handling a result set and returning a value.
*/
interface ResultSetHandler<T> {
T process(ResultSet resultset) throws SQLException;
}
/**
* Retrieves a result based on the provided query.
*
* @param query The query.
* @param processor The result set handler.
* @param errorMessage The error message to display if there is an error
* retrieving the resultset.
*
* @return The ResultSetHandler value or null if no ResultSet could be
* obtained.
*/
static <T> T getBaseQueryResult(String query, ResultSetHandler<T> processor, String errorMessage) {
try (SleuthkitCase.CaseDbQuery dbQuery = Case.getCurrentCaseThrows().getSleuthkitCase().executeQuery(query)) {
ResultSet resultSet = dbQuery.getResultSet();
try {
return processor.process(resultSet);
} catch (SQLException ex) {
logger.log(Level.WARNING, errorMessage, ex);
}
} catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.WARNING, errorMessage, ex);
}
return null;
}
/**
* 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.
*/
static String getMetaFlagsContainsStatement(TSK_FS_META_FLAG_ENUM flag) {
return "meta_flags & " + flag.getValue() + " > 0";
}
/**
* Empty private constructor
*/
private DataSourceInfoUtilities() {
}
}

View File

@ -1,107 +0,0 @@
/*
* 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.datasourcesummary.datamodel;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.sleuthkit.datamodel.DataSource;
/**
* Provides methods to query for datasource files by mime type.
*/
public class DataSourceMimeTypeSummary {
/**
* Get the number of files in the case database for the current data source
* which have the specified mimetypes.
*
* @param currentDataSource the data source which we are finding a file
* count
*
* @param setOfMimeTypes the set of mime types which we are finding the
* number of occurences of
*
* @return a Long value which represents the number of occurrences of the
* specified mime types in the current case for the specified data
* source, null if no count was retrieved
*/
public static Long getCountOfFilesForMimeTypes(DataSource currentDataSource, Set<String> setOfMimeTypes) {
return DataSourceInfoUtilities.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.
*/
public static Long getCountOfFilesNotInMimeTypes(DataSource currentDataSource, Set<String> setOfMimeTypes) {
return DataSourceInfoUtilities.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.
*
*/
public static Long getCountOfFilesWithNoMimeType(DataSource currentDataSource) {
return DataSourceInfoUtilities.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<String> setValues) {
List<String> quotedValues = setValues
.stream()
.map(str -> String.format("'%s'", str.replace("'", "")))
.collect(Collectors.toList());
String commaSeparatedQuoted = String.join(", ", quotedValues);
return String.format("(%s) ", commaSeparatedQuoted);
}
private DataSourceMimeTypeSummary() {
}
}

View File

@ -1,295 +0,0 @@
/*
* 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.datasourcesummary.datamodel;
import java.io.File;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.function.Function;
import java.util.logging.Level;
import java.util.stream.Collectors;
import org.apache.commons.lang.StringUtils;
import org.sleuthkit.autopsy.coreutils.Logger;
import static org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceInfoUtilities.getBaseQueryResult;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.DataSource;
/**
* Provides information to populate Top Programs Summary queries.
*/
public class DataSourceTopProgramsSummary {
private static final Logger logger = Logger.getLogger(DataSourceTopProgramsSummary.class.getName());
/**
* A SQL join type.
*/
private enum JoinType {
LEFT,
RIGHT,
INNER,
OUTER
}
/**
* A blackboard attribute value column.
*/
private enum AttributeColumn {
value_text,
value_int32,
value_int64
}
/**
* The suffix joined to a key name for use as an identifier of a query.
*/
private static final String QUERY_SUFFIX = "_query";
/**
* Creates a sql statement querying the blackboard attributes table for a
* particular attribute type and returning a specified value. That query
* also joins with the blackboard artifact table.
*
* @param joinType The type of join statement to create.
* @param attributeColumn The blackboard attribute column that should be
* returned.
* @param attrType The attribute type to query for.
* @param keyName The aliased name of the attribute to return. This
* is also used to calculate the alias of the query
* same as getFullKey.
* @param bbaName The blackboard artifact table alias.
*
* @return The generated sql statement.
*/
private static String getAttributeJoin(JoinType joinType, AttributeColumn attributeColumn, BlackboardAttribute.ATTRIBUTE_TYPE attrType, String keyName, String bbaName) {
String queryName = keyName + QUERY_SUFFIX;
String innerQueryName = "inner_attribute_" + queryName;
return "\n" + joinType + " JOIN (\n"
+ " SELECT \n"
+ " " + innerQueryName + ".artifact_id,\n"
+ " " + innerQueryName + "." + attributeColumn + " AS " + keyName + "\n"
+ " FROM blackboard_attributes " + innerQueryName + "\n"
+ " WHERE " + innerQueryName + ".attribute_type_id = " + attrType.getTypeID() + " -- " + attrType.name() + "\n"
+ ") " + queryName + " ON " + queryName + ".artifact_id = " + bbaName + ".artifact_id\n";
}
/**
* Given a column key, creates the full name for the column key.
*
* @param key The column key.
*
* @return The full identifier for the column key.
*/
private static String getFullKey(String key) {
return key + QUERY_SUFFIX + "." + key;
}
/**
* Constructs a SQL 'where' statement from a list of clauses and puts
* parenthesis around each clause.
*
* @param clauses The clauses
*
* @return The generated 'where' statement.
*/
private static String getWhereString(List<String> clauses) {
if (clauses.isEmpty()) {
return "";
}
List<String> parenthesized = clauses.stream()
.map(c -> "(" + c + ")")
.collect(Collectors.toList());
return "\nWHERE " + String.join("\n AND ", parenthesized) + "\n";
}
/**
* Generates a [column] LIKE sql clause.
*
* @param column The column identifier.
* @param likeString The string that will be used as column comparison.
* @param isLike if false, the statement becomes NOT LIKE.
*
* @return The generated statement.
*/
private static String getLikeClause(String column, String likeString, boolean isLike) {
return column + (isLike ? "" : " NOT") + " LIKE '" + likeString + "'";
}
/**
* Retrieves a list of the top programs used on the data source. Currently
* determines this based off of which prefetch results return the highest
* count.
*
* @param dataSource The data source.
* @param count The number of programs to return.
*
* @return
*/
public static List<TopProgramsResult> getTopPrograms(DataSource dataSource, int count) {
if (dataSource == null || count <= 0) {
return Collections.emptyList();
}
// ntosboot should be ignored
final String ntosBootIdentifier = "NTOSBOOT";
// programs in windows directory to be ignored
final String windowsDir = "/WINDOWS%";
final String nameParam = "name";
final String pathParam = "path";
final String runCountParam = "run_count";
final String lastRunParam = "last_run";
String bbaQuery = "bba";
final String query = "SELECT\n"
+ " " + getFullKey(nameParam) + " AS " + nameParam + ",\n"
+ " " + getFullKey(pathParam) + " AS " + pathParam + ",\n"
+ " MAX(" + getFullKey(runCountParam) + ") AS " + runCountParam + ",\n"
+ " MAX(" + getFullKey(lastRunParam) + ") AS " + lastRunParam + "\n"
+ "FROM blackboard_artifacts " + bbaQuery + "\n"
+ getAttributeJoin(JoinType.INNER, AttributeColumn.value_text, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME, nameParam, bbaQuery)
+ getAttributeJoin(JoinType.LEFT, AttributeColumn.value_text, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH, pathParam, bbaQuery)
+ getAttributeJoin(JoinType.LEFT, AttributeColumn.value_int32, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COUNT, runCountParam, bbaQuery)
+ getAttributeJoin(JoinType.LEFT, AttributeColumn.value_int64, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, lastRunParam, bbaQuery)
+ getWhereString(Arrays.asList(
bbaQuery + ".artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_PROG_RUN.getTypeID(),
bbaQuery + ".data_source_obj_id = " + dataSource.getId(),
// exclude ntosBootIdentifier from results
getLikeClause(getFullKey(nameParam), ntosBootIdentifier, false),
// exclude windows directory items from results
getFullKey(pathParam) + " IS NULL OR " + getLikeClause(getFullKey(pathParam), windowsDir, false)
))
+ "GROUP BY " + getFullKey(nameParam) + ", " + getFullKey(pathParam) + "\n"
+ "ORDER BY \n"
+ " MAX(" + getFullKey(runCountParam) + ") DESC,\n"
+ " MAX(" + getFullKey(lastRunParam) + ") DESC,\n"
+ " " + getFullKey(nameParam) + " ASC";
final String errorMessage = "Unable to get top program results; returning null.";
DataSourceInfoUtilities.ResultSetHandler<List<TopProgramsResult>> handler = (resultSet) -> {
List<TopProgramsResult> progResults = new ArrayList<>();
boolean quitAtCount = false;
while (resultSet.next() && (!quitAtCount || progResults.size() < count)) {
try {
long lastRunEpoch = resultSet.getLong(lastRunParam);
Date lastRun = (resultSet.wasNull()) ? null : new Date(lastRunEpoch * 1000);
Long runCount = resultSet.getLong(runCountParam);
if (resultSet.wasNull()) {
runCount = null;
}
if (lastRun != null || runCount != null) {
quitAtCount = true;
}
progResults.add(new TopProgramsResult(
resultSet.getString(nameParam),
resultSet.getString(pathParam),
runCount,
lastRun));
} catch (SQLException ex) {
logger.log(Level.WARNING, "Failed to get a top program result from the result set.", ex);
}
}
return progResults;
};
return getBaseQueryResult(query, handler, errorMessage);
}
/**
* Functions that determine the folder name of a list of path elements. If
* not matched, function returns null.
*/
private static final List<Function<List<String>, String>> SHORT_FOLDER_MATCHERS = Arrays.asList(
// handle Program Files and Program Files (x86) - if true, return the next folder
(pathList) -> {
if (pathList.size() < 2) {
return null;
}
String rootParent = pathList.get(0).toUpperCase();
if ("PROGRAM FILES".equals(rootParent) || "PROGRAM FILES (X86)".equals(rootParent)) {
return pathList.get(1);
} else {
return null;
}
},
// if there is a folder named "APPLICATION DATA" or "APPDATA"
(pathList) -> {
for (String pathEl : pathList) {
String uppered = pathEl.toUpperCase();
if ("APPLICATION DATA".equals(uppered) || "APPDATA".equals(uppered)) {
return "AppData";
}
}
return null;
}
);
/**
* Determines a short folder name if any. Otherwise, returns empty string.
*
* @param strPath The string path.
*
* @return The short folder name or empty string if not found.
*/
public static String getShortFolderName(String strPath, String applicationName) {
if (strPath == null) {
return "";
}
List<String> pathEls = new ArrayList<>(Arrays.asList(applicationName));
File file = new File(strPath);
while (file != null && StringUtils.isNotBlank(file.getName())) {
pathEls.add(file.getName());
file = file.getParentFile();
}
Collections.reverse(pathEls);
for (Function<List<String>, String> matchEntry : SHORT_FOLDER_MATCHERS) {
String result = matchEntry.apply(pathEls);
if (StringUtils.isNotBlank(result)) {
return result;
}
}
return "";
}
private DataSourceTopProgramsSummary() {
}
}

View File

@ -1,74 +0,0 @@
/*
* 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.datasourcesummary.datamodel;
import java.util.Date;
/**
* Describes a result of a program run on a datasource.
*/
public class TopProgramsResult {
private final String programName;
private final String programPath;
private final Long runTimes;
private final Date lastRun;
/**
* Main constructor.
*
* @param programName The name of the program.
* @param programPath The path of the program.
* @param runTimes The number of runs.
*/
TopProgramsResult(String programName, String programPath, Long runTimes, Date lastRun) {
this.programName = programName;
this.programPath = programPath;
this.runTimes = runTimes;
this.lastRun = lastRun;
}
/**
* @return The name of the program
*/
public String getProgramName() {
return programName;
}
/**
* @return The path of the program.
*/
public String getProgramPath() {
return programPath;
}
/**
* @return The number of run times or null if not present.
*/
public Long getRunTimes() {
return runTimes;
}
/**
* @return The last time the program was run or null if not present.
*/
public Date getLastRun() {
return lastRun;
}
}

View File

@ -1,222 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.8" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="scrollParent" alignment="0" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="scrollParent" alignment="0" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JScrollPane" name="scrollParent">
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="parentPanel">
<Properties>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[840, 320]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="fileTypePiePanel" min="-2" pref="400" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="fileCountsByCategoryScrollPane" alignment="0" min="-2" pref="140" max="-2" attributes="0"/>
<Component id="byCategoryLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="filesByCatParent" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="resultsByTypeLabel" min="-2" pref="79" max="-2" attributes="0"/>
<Group type="102" attributes="0">
<Component id="artifactCountsScrollPane" min="-2" pref="244" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="resultsByTypeParent" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="fileTypePiePanel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="3" attributes="0">
<Component id="byCategoryLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="resultsByTypeLabel" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace max="32767" attributes="0"/>
<Component id="resultsByTypeParent" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="148" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="artifactCountsScrollPane" pref="0" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<Component id="fileCountsByCategoryScrollPane" min="-2" pref="107" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="31" max="-2" attributes="0"/>
<Component id="filesByCatParent" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</Group>
</Group>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JScrollPane" name="fileCountsByCategoryScrollPane">
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTable" name="fileCountsByCategoryTable">
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JLabel" name="byCategoryLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryCountsPanel.byCategoryLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
</Component>
<Component class="javax.swing.JLabel" name="resultsByTypeLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryCountsPanel.resultsByTypeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
</Component>
<Container class="javax.swing.JScrollPane" name="artifactCountsScrollPane">
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTable" name="artifactCountsTable">
<Properties>
<Property name="autoCreateRowSorter" type="boolean" value="true"/>
</Properties>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="fileTypePiePanel">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[400, 300]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="fileTypePieChart"/>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignFlowLayout"/>
</Container>
<Container class="javax.swing.JPanel" name="filesByCatParent">
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
</Container>
<Container class="javax.swing.JPanel" name="resultsByTypeParent">
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
</Container>
</SubComponents>
</Container>
</SubComponents>
</Container>
</SubComponents>
</Form>

View File

@ -1,190 +0,0 @@
/*
* 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.datasourcesummary.ui;
import java.awt.BorderLayout;
import java.awt.Font;
import javax.swing.JPanel;
import org.sleuthkit.datamodel.DataSource;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.labels.PieSectionLabelGenerator;
import org.jfree.chart.labels.StandardPieSectionLabelGenerator;
import org.jfree.chart.plot.PiePlot;
import org.jfree.data.general.DefaultPieDataset;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;
import javax.swing.JLabel;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.coreutils.FileTypeUtils;
import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceMimeTypeSummary;
import static org.sleuthkit.autopsy.coreutils.FileTypeUtils.FileTypeCategory;
/**
* A Pie Chart that shows file mime types in a data source.
*/
class FileTypePieChart extends JPanel {
private static final long serialVersionUID = 1L;
private static final Font DEFAULT_FONT = new JLabel().getFont();
private static final Font DEFAULT_HEADER_FONT = new Font(DEFAULT_FONT.getName(), DEFAULT_FONT.getStyle(), (int) (DEFAULT_FONT.getSize() * 1.5));
private final DefaultPieDataset dataset = new DefaultPieDataset();
private DataSource dataSource;
// used for determining mime types that fall in the 'other' category
private static final Set<String> ALL_CATEGORY_MIME_TYPES = Arrays.asList(
FileTypeCategory.IMAGE,
FileTypeCategory.VIDEO,
FileTypeCategory.AUDIO,
FileTypeCategory.DOCUMENTS,
FileTypeCategory.EXECUTABLE)
.stream()
.flatMap((cat) -> cat.getMediaTypes().stream())
.collect(Collectors.toSet());
/**
* Default constructor for the pie chart.
*/
@Messages({
"DataSourceSummaryCountsPanel.byMimeTypeLabel.text=Files by MIME Type",
"DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.audio.row=Audio",
"DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.documents.row=Documents",
"DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.executables.row=Executables",
"DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.images.row=Images",
"DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.videos.row=Videos",
"DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_other_label=Other",
"DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_notAnalyzed_label=Not Analyzed"
})
FileTypePieChart() {
// Create chart
JFreeChart chart = ChartFactory.createPieChart(
Bundle.DataSourceSummaryCountsPanel_byMimeTypeLabel_text(),
dataset,
true,
true,
false);
chart.setBackgroundPaint(null);
chart.getLegend().setItemFont(DEFAULT_FONT);
chart.getTitle().setFont(DEFAULT_HEADER_FONT);
PiePlot plot = ((PiePlot) chart.getPlot());
//Format Label
PieSectionLabelGenerator labelGenerator = new StandardPieSectionLabelGenerator(
"{0}: {1} ({2})", new DecimalFormat("0"), new DecimalFormat("0.0%"));
plot.setLabelGenerator(labelGenerator);
plot.setLabelFont(DEFAULT_FONT);
plot.setBackgroundPaint(null);
plot.setOutlinePaint(null);
// Create Panel
ChartPanel panel = new ChartPanel(chart);
this.setLayout(new BorderLayout());
this.add(panel, BorderLayout.CENTER);
}
/**
* The datasource currently used as the model with this pie chart.
*
* @return The datasource currently being used as the model in this pie
* chart.
*/
DataSource getDataSource() {
return dataSource;
}
/**
* Sets datasource to visualize in the pie chart.
*
* @param dataSource The datasource to use in this pie chart.
*/
void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
this.dataset.clear();
if (dataSource != null) {
addIfPresent(Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_images_row(),
this.dataSource, FileTypeCategory.IMAGE);
addIfPresent(Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_videos_row(),
this.dataSource, FileTypeCategory.VIDEO);
addIfPresent(Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_audio_row(),
this.dataSource, FileTypeCategory.AUDIO);
addIfPresent(Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_documents_row(),
this.dataSource, FileTypeCategory.DOCUMENTS);
addIfPresent(Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_executables_row(),
this.dataSource, FileTypeCategory.EXECUTABLE);
addIfPresent(Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_other_label(),
DataSourceMimeTypeSummary.getCountOfFilesNotInMimeTypes(this.dataSource, ALL_CATEGORY_MIME_TYPES));
addIfPresent(Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_notAnalyzed_label(),
DataSourceMimeTypeSummary.getCountOfFilesWithNoMimeType(this.dataSource));
}
}
/**
* Adds count for file type category if there is a value. Uses fields
* 'dataSource' and 'dataset'.
*
* @param label The label for this pie slice.
* @param dataSource The data source.
* @param category The category for the pie slice.
*/
private void addIfPresent(String label, DataSource dataSource, FileTypeUtils.FileTypeCategory category) {
if (dataSource == null) {
return;
}
Long count = getCount(dataSource, category);
addIfPresent(label, count);
}
/**
* Adds count for a a label if the count is non-null and greater than 0.
*
* @param label The label.
* @param count The count.
*/
private void addIfPresent(String label, Long count) {
if (count != null && count > 0) {
this.dataset.setValue(label, count);
}
}
/**
* Retrieves the counts of files of a particular mime type for a particular
* DataSource.
*
* @param dataSource The DataSource.
* @param category The mime type category.
*
* @return The count.
*/
private static Long getCount(DataSource dataSource, FileTypeUtils.FileTypeCategory category) {
return DataSourceMimeTypeSummary.getCountOfFilesForMimeTypes(dataSource, category.getMediaTypes());
}
}

View File

@ -26,7 +26,7 @@ import org.openide.explorer.ExplorerManager;
import org.openide.nodes.Node; import org.openide.nodes.Node;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.openide.util.lookup.ServiceProvider; import org.openide.util.lookup.ServiceProvider;
import org.sleuthkit.autopsy.datasourcesummary.ui.DataSourceSummaryTabbedPane; import org.sleuthkit.autopsy.casemodule.datasourcesummary.DataSourceSummaryTabbedPane;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer; import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer;
import org.sleuthkit.autopsy.corecomponents.AbstractDataResultViewer; import org.sleuthkit.autopsy.corecomponents.AbstractDataResultViewer;
import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.DataSource;