mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-15 09:17:42 +00:00
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:
commit
30edc43c20
@ -51,9 +51,6 @@
|
||||
<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"/>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/jfree/jfreechart -->
|
||||
<dependency org="org.jfree" name="jfreechart" rev="1.0.19"/>
|
||||
|
||||
<!-- map support for geolocation -->
|
||||
<dependency conf="core->default" org="org.jxmapviewer" name="jxmapviewer2" rev="2.4"/>
|
||||
|
||||
|
@ -479,14 +479,6 @@
|
||||
<runtime-relative-path>ext/jxmapviewer2-2.4.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/jxmapviewer2-2.4.jar</binary-origin>
|
||||
</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>
|
||||
<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>
|
||||
|
@ -70,7 +70,7 @@ import org.sleuthkit.autopsy.actions.OpenOutputFolderAction;
|
||||
import org.sleuthkit.autopsy.appservices.AutopsyService;
|
||||
import org.sleuthkit.autopsy.appservices.AutopsyService.CaseContext;
|
||||
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.AddingDataSourceFailedEvent;
|
||||
import org.sleuthkit.autopsy.casemodule.events.BlackBoardArtifactTagAddedEvent;
|
||||
|
@ -33,6 +33,7 @@ DataSourceSummaryDetailsPanel.acquisitionDetailsTextArea.text=
|
||||
DataSourceSummaryDetailsPanel.acquisitionDetailsLabel.text=Acquisition Details:
|
||||
DataSourceSummaryDetailsPanel.unallocatedSizeLabel.text=Unallocated Space:
|
||||
DataSourceSummaryDetailsPanel.unallocatedSizeValue.text=
|
||||
DataSourceSummaryCountsPanel.byMimeTypeLabel.text=Files by MIME Type
|
||||
DataSourceSummaryCountsPanel.byCategoryLabel.text=Files by Category
|
||||
DataSourceSummaryCountsPanel.resultsByTypeLabel.text=Results by Type
|
||||
DataSourceSummaryCountsPanel.jLabel1.text=Results by Type
|
||||
DataSourceSummaryUserActivityPanel.programsRunLabel.text=Top Programs Run
|
@ -1,7 +1,6 @@
|
||||
CTL_DataSourceSummaryAction=Data Source Summary
|
||||
DataSourceSummaryCountsPanel.ArtifactCountsTableModel.count.header=Count
|
||||
DataSourceSummaryCountsPanel.ArtifactCountsTableModel.type.header=Result Type
|
||||
DataSourceSummaryCountsPanel.byMimeTypeLabel.text=Files by MIME Type
|
||||
DataSourceSummaryCountsPanel.FilesByCategoryTableModel.all.row=All
|
||||
DataSourceSummaryCountsPanel.FilesByCategoryTableModel.allocated.row=Allocated
|
||||
DataSourceSummaryCountsPanel.FilesByCategoryTableModel.count.header=Count
|
||||
@ -16,8 +15,6 @@ DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.executables.row=Executabl
|
||||
DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.images.row=Images
|
||||
DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.type.header=File Type
|
||||
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.title=Load Failure
|
||||
DataSourceSummaryDetailsPanel.units.bytes=\ bytes
|
||||
@ -61,8 +58,9 @@ DataSourceSummaryDetailsPanel.acquisitionDetailsTextArea.text=
|
||||
DataSourceSummaryDetailsPanel.acquisitionDetailsLabel.text=Acquisition Details:
|
||||
DataSourceSummaryDetailsPanel.unallocatedSizeLabel.text=Unallocated Space:
|
||||
DataSourceSummaryDetailsPanel.unallocatedSizeValue.text=
|
||||
DataSourceSummaryCountsPanel.byMimeTypeLabel.text=Files by MIME Type
|
||||
DataSourceSummaryCountsPanel.byCategoryLabel.text=Files by Category
|
||||
DataSourceSummaryCountsPanel.resultsByTypeLabel.text=Results by Type
|
||||
DataSourceSummaryCountsPanel.jLabel1.text=Results by Type
|
||||
DataSourceSummaryDialog.window.title=Data Sources Summary
|
||||
DataSourceSummaryNode.column.dataSourceName.header=Data Source Name
|
||||
DataSourceSummaryNode.column.files.header=Files
|
@ -16,7 +16,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datasourcesummary.ui;
|
||||
package org.sleuthkit.autopsy.casemodule.datasourcesummary;
|
||||
|
||||
import java.awt.EventQueue;
|
||||
import java.beans.PropertyVetoException;
|
||||
@ -35,11 +35,10 @@ import javax.swing.event.ListSelectionListener;
|
||||
import org.openide.nodes.Node;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
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 javax.swing.SwingUtilities;
|
||||
import javax.swing.table.TableColumn;
|
||||
import org.sleuthkit.autopsy.datasourcesummary.datamodel.CaseDataSourcesSummary;
|
||||
import org.sleuthkit.datamodel.DataSource;
|
||||
import org.sleuthkit.datamodel.IngestJobInfo;
|
||||
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) {
|
||||
List<DataSourceSummary> summaryList = new ArrayList<>();
|
||||
|
||||
final Map<Long, Long> artifactCountsMap = CaseDataSourcesSummary.getCountsOfArtifacts();
|
||||
final Map<Long, Long> tagCountsMap = CaseDataSourcesSummary.getCountsOfTags();
|
||||
final Map<Long, Long> artifactCountsMap = DataSourceInfoUtilities.getCountsOfArtifacts();
|
||||
final Map<Long, Long> tagCountsMap = DataSourceInfoUtilities.getCountsOfTags();
|
||||
try {
|
||||
SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
|
||||
for (DataSource dataSource : skCase.getDataSources()) {
|
@ -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() {
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datasourcesummary.datamodel;
|
||||
package org.sleuthkit.autopsy.casemodule.datasourcesummary;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
@ -16,7 +16,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datasourcesummary.datamodel;
|
||||
package org.sleuthkit.autopsy.casemodule.datasourcesummary;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
@ -16,7 +16,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datasourcesummary.ui;
|
||||
package org.sleuthkit.autopsy.casemodule.datasourcesummary;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
@ -16,7 +16,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datasourcesummary.ui;
|
||||
package org.sleuthkit.autopsy.casemodule.datasourcesummary;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
@ -28,7 +28,6 @@ import org.openide.util.HelpCtx;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.util.actions.CallableSystemAction;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.datasourcesummary.ui.Bundle;
|
||||
|
||||
@ActionID(category = "Case", id = "org.sleuthkit.autopsy.casemodule.datasourcesummary.DataSourceSummaryAction")
|
||||
@ActionRegistration(displayName = "#CTL_DataSourceSummaryAction", lazy = false)
|
@ -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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</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>
|
@ -16,7 +16,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datasourcesummary.ui;
|
||||
package org.sleuthkit.autopsy.casemodule.datasourcesummary;
|
||||
|
||||
import java.util.Map;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
@ -24,8 +24,7 @@ import javax.swing.JLabel;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceCountsSummary;
|
||||
|
||||
import org.sleuthkit.autopsy.coreutils.FileTypeUtils;
|
||||
import org.sleuthkit.datamodel.DataSource;
|
||||
|
||||
/**
|
||||
@ -41,8 +40,6 @@ import org.sleuthkit.datamodel.DataSource;
|
||||
})
|
||||
class DataSourceSummaryCountsPanel extends javax.swing.JPanel {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
// Result returned for a data model if no data found.
|
||||
private static final Object[][] EMPTY_PAIRS = new Object[][]{};
|
||||
|
||||
@ -64,11 +61,10 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel {
|
||||
Bundle.DataSourceSummaryCountsPanel_ArtifactCountsTableModel_count_header()
|
||||
};
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger logger = Logger.getLogger(DataSourceSummaryCountsPanel.class.getName());
|
||||
private final DefaultTableCellRenderer rightAlignedRenderer = new DefaultTableCellRenderer();
|
||||
|
||||
private final FileTypePieChart fileTypePieChart = new FileTypePieChart();
|
||||
|
||||
private DataSource dataSource;
|
||||
|
||||
/**
|
||||
@ -77,6 +73,7 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel {
|
||||
DataSourceSummaryCountsPanel() {
|
||||
rightAlignedRenderer.setHorizontalAlignment(JLabel.RIGHT);
|
||||
initComponents();
|
||||
fileCountsByMimeTypeTable.getTableHeader().setReorderingAllowed(false);
|
||||
fileCountsByCategoryTable.getTableHeader().setReorderingAllowed(false);
|
||||
artifactCountsTable.getTableHeader().setReorderingAllowed(false);
|
||||
setDataSource(null);
|
||||
@ -99,20 +96,29 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel {
|
||||
public void setDataSource(DataSource dataSource) {
|
||||
this.dataSource = dataSource;
|
||||
if (dataSource == null || !Case.isCaseOpen()) {
|
||||
updateCountsTableData(EMPTY_PAIRS, EMPTY_PAIRS);
|
||||
updateCountsTableData(EMPTY_PAIRS,
|
||||
EMPTY_PAIRS,
|
||||
EMPTY_PAIRS);
|
||||
} 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.
|
||||
*
|
||||
* @param mimeTypeDataModel The mime type data model.
|
||||
* @param fileCategoryDataModel The file category 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.getColumnModel().getColumn(1).setCellRenderer(rightAlignedRenderer);
|
||||
fileCountsByCategoryTable.getColumnModel().getColumn(0).setPreferredWidth(130);
|
||||
@ -124,6 +130,48 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel {
|
||||
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.
|
||||
*
|
||||
@ -139,11 +187,11 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel {
|
||||
"DataSourceSummaryCountsPanel.FilesByCategoryTableModel.directory.row=Directory"
|
||||
})
|
||||
private static Object[][] getFileCategoryModel(DataSource selectedDataSource) {
|
||||
Long fileCount = zeroIfNull(DataSourceCountsSummary.getCountOfFiles(selectedDataSource));
|
||||
Long unallocatedFiles = zeroIfNull(DataSourceCountsSummary.getCountOfUnallocatedFiles(selectedDataSource));
|
||||
Long allocatedFiles = zeroIfNull(DataSourceCountsSummary.getCountOfAllocatedFiles(selectedDataSource));
|
||||
Long slackFiles = zeroIfNull(DataSourceCountsSummary.getCountOfSlackFiles(selectedDataSource));
|
||||
Long directories = zeroIfNull(DataSourceCountsSummary.getCountOfDirectories(selectedDataSource));
|
||||
Long fileCount = zeroIfNull(DataSourceInfoUtilities.getCountOfFiles(selectedDataSource));
|
||||
Long unallocatedFiles = zeroIfNull(DataSourceInfoUtilities.getCountOfUnallocatedFiles(selectedDataSource));
|
||||
Long allocatedFiles = zeroIfNull(getAllocatedCount(fileCount, unallocatedFiles));
|
||||
Long slackFiles = zeroIfNull(DataSourceInfoUtilities.getCountOfSlackFiles(selectedDataSource));
|
||||
Long directories = zeroIfNull(DataSourceInfoUtilities.getCountOfDirectories(selectedDataSource));
|
||||
|
||||
return new Object[][]{
|
||||
new Object[]{Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_all_row(), fileCount},
|
||||
@ -165,6 +213,24 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel {
|
||||
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.
|
||||
*
|
||||
@ -173,7 +239,7 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel {
|
||||
* @return The JTable data model of counts of artifact types.
|
||||
*/
|
||||
private static Object[][] getArtifactCountsModel(DataSource selectedDataSource) {
|
||||
Map<String, Long> artifactMapping = DataSourceCountsSummary.getCountsOfArtifactsByType(selectedDataSource);
|
||||
Map<String, Long> artifactMapping = DataSourceInfoUtilities.getCountsOfArtifactsByType(selectedDataSource);
|
||||
if (artifactMapping == null) {
|
||||
return EMPTY_PAIRS;
|
||||
}
|
||||
@ -194,120 +260,83 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel {
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
|
||||
javax.swing.JScrollPane scrollParent = new javax.swing.JScrollPane();
|
||||
javax.swing.JPanel parentPanel = new javax.swing.JPanel();
|
||||
javax.swing.JScrollPane fileCountsByCategoryScrollPane = new javax.swing.JScrollPane();
|
||||
fileCountsByMimeTypeScrollPane = new javax.swing.JScrollPane();
|
||||
fileCountsByMimeTypeTable = new javax.swing.JTable();
|
||||
byMimeTypeLabel = new javax.swing.JLabel();
|
||||
fileCountsByCategoryScrollPane = new javax.swing.JScrollPane();
|
||||
fileCountsByCategoryTable = new javax.swing.JTable();
|
||||
javax.swing.JLabel byCategoryLabel = new javax.swing.JLabel();
|
||||
javax.swing.JLabel resultsByTypeLabel = new javax.swing.JLabel();
|
||||
javax.swing.JScrollPane artifactCountsScrollPane = new javax.swing.JScrollPane();
|
||||
byCategoryLabel = new javax.swing.JLabel();
|
||||
jLabel1 = new javax.swing.JLabel();
|
||||
artifactCountsScrollPane = new javax.swing.JScrollPane();
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
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.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
|
||||
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JScrollPane artifactCountsScrollPane;
|
||||
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.JScrollPane fileCountsByMimeTypeScrollPane;
|
||||
private javax.swing.JTable fileCountsByMimeTypeTable;
|
||||
private javax.swing.JLabel jLabel1;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
@ -40,7 +40,7 @@
|
||||
<Component class="javax.swing.JLabel" name="operatingSystemLabel">
|
||||
<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="DataSourceSummaryDetailsPanel.operatingSystemLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.operatingSystemLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
@ -52,7 +52,7 @@
|
||||
<Component class="javax.swing.JLabel" name="displayNameLabel">
|
||||
<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="DataSourceSummaryDetailsPanel.displayNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.displayNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
@ -64,7 +64,7 @@
|
||||
<Component class="javax.swing.JLabel" name="originalNameLabel">
|
||||
<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="DataSourceSummaryDetailsPanel.originalNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.originalNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
@ -76,7 +76,7 @@
|
||||
<Component class="javax.swing.JLabel" name="sha1HashValue">
|
||||
<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="DataSourceSummaryDetailsPanel.sha1HashValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.sha1HashValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
@ -88,10 +88,10 @@
|
||||
<Component class="javax.swing.JLabel" name="operatingSystemValue">
|
||||
<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="DataSourceSummaryDetailsPanel.operatingSystemValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.operatingSystemValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<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, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.operatingSystemValue.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
@ -103,7 +103,7 @@
|
||||
<Component class="javax.swing.JLabel" name="displayNameValue">
|
||||
<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="DataSourceSummaryDetailsPanel.displayNameValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.displayNameValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
@ -115,7 +115,7 @@
|
||||
<Component class="javax.swing.JLabel" name="sha256HashValue">
|
||||
<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="DataSourceSummaryDetailsPanel.sha256HashValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.sha256HashValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
@ -127,7 +127,7 @@
|
||||
<Component class="javax.swing.JLabel" name="originalNameValue">
|
||||
<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="DataSourceSummaryDetailsPanel.originalNameValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.originalNameValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
@ -139,10 +139,10 @@
|
||||
<Component class="javax.swing.JLabel" name="deviceIdValue">
|
||||
<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="DataSourceSummaryDetailsPanel.deviceIdValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.deviceIdValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<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, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.deviceIdValue.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
@ -179,7 +179,7 @@
|
||||
<TableColumnModel selectionModel="0">
|
||||
<Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true">
|
||||
<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, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.filePathsTable.columnModel.title0" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Title>
|
||||
<Editor/>
|
||||
<Renderer/>
|
||||
@ -196,7 +196,7 @@
|
||||
<Component class="javax.swing.JLabel" name="dataSourceUsageValue">
|
||||
<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="DataSourceSummaryDetailsPanel.dataSourceUsageValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.dataSourceUsageValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
@ -208,7 +208,7 @@
|
||||
<Component class="javax.swing.JLabel" name="timeZoneValue">
|
||||
<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="DataSourceSummaryDetailsPanel.timeZoneValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.timeZoneValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
@ -220,10 +220,10 @@
|
||||
<Component class="javax.swing.JLabel" name="imageTypeValue">
|
||||
<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="DataSourceSummaryDetailsPanel.imageTypeValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.imageTypeValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<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, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.imageTypeValue.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
@ -235,10 +235,10 @@
|
||||
<Component class="javax.swing.JLabel" name="md5HashValue">
|
||||
<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="DataSourceSummaryDetailsPanel.md5HashValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.md5HashValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<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, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.md5HashValue.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
@ -250,7 +250,7 @@
|
||||
<Component class="javax.swing.JLabel" name="sectorSizeValue">
|
||||
<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="DataSourceSummaryDetailsPanel.sectorSizeValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.sectorSizeValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
@ -262,7 +262,7 @@
|
||||
<Component class="javax.swing.JLabel" name="sizeValue">
|
||||
<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="DataSourceSummaryDetailsPanel.sizeValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.sizeValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
@ -274,7 +274,7 @@
|
||||
<Component class="javax.swing.JLabel" name="filePathsLabel">
|
||||
<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="DataSourceSummaryDetailsPanel.filePathsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.filePathsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
@ -286,7 +286,7 @@
|
||||
<Component class="javax.swing.JLabel" name="sha256HashLabel">
|
||||
<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="DataSourceSummaryDetailsPanel.sha256HashLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.sha256HashLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
@ -298,7 +298,7 @@
|
||||
<Component class="javax.swing.JLabel" name="sha1HashLabel">
|
||||
<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="DataSourceSummaryDetailsPanel.sha1HashLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.sha1HashLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
@ -310,7 +310,7 @@
|
||||
<Component class="javax.swing.JLabel" name="md5HashLabel">
|
||||
<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="DataSourceSummaryDetailsPanel.md5HashLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.md5HashLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
@ -322,7 +322,7 @@
|
||||
<Component class="javax.swing.JLabel" name="sectorSizeLabel">
|
||||
<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="DataSourceSummaryDetailsPanel.sectorSizeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.sectorSizeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
@ -334,7 +334,7 @@
|
||||
<Component class="javax.swing.JLabel" name="sizeLabel">
|
||||
<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="DataSourceSummaryDetailsPanel.sizeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.sizeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
@ -346,7 +346,7 @@
|
||||
<Component class="javax.swing.JLabel" name="imageTypeLabel">
|
||||
<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="DataSourceSummaryDetailsPanel.imageTypeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.imageTypeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
@ -358,7 +358,7 @@
|
||||
<Component class="javax.swing.JLabel" name="acquisitionDetailsLabel">
|
||||
<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="DataSourceSummaryDetailsPanel.acquisitionDetailsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.acquisitionDetailsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
@ -370,7 +370,7 @@
|
||||
<Component class="javax.swing.JLabel" name="timeZoneLabel">
|
||||
<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="DataSourceSummaryDetailsPanel.timeZoneLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.timeZoneLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
@ -382,7 +382,7 @@
|
||||
<Component class="javax.swing.JLabel" name="dataSourceUsageLabel">
|
||||
<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="DataSourceSummaryDetailsPanel.dataSourceUsageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.dataSourceUsageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
@ -394,7 +394,7 @@
|
||||
<Component class="javax.swing.JLabel" name="deviceIdLabel">
|
||||
<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="DataSourceSummaryDetailsPanel.deviceIdLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.deviceIdLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
@ -424,7 +424,7 @@
|
||||
<Property name="columns" type="int" value="20"/>
|
||||
<Property name="rows" type="int" value="4"/>
|
||||
<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, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.acquisitionDetailsTextArea.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="null"/>
|
||||
@ -466,7 +466,7 @@
|
||||
<Component class="javax.swing.JLabel" name="unallocatedSizeLabel">
|
||||
<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="DataSourceSummaryDetailsPanel.unallocatedSizeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.unallocatedSizeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
@ -478,7 +478,7 @@
|
||||
<Component class="javax.swing.JLabel" name="unallocatedSizeValue">
|
||||
<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="DataSourceSummaryDetailsPanel.unallocatedSizeValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.unallocatedSizeValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
@ -16,7 +16,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datasourcesummary.ui;
|
||||
package org.sleuthkit.autopsy.casemodule.datasourcesummary;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.logging.Level;
|
||||
@ -25,7 +25,6 @@ import javax.swing.table.DefaultTableModel;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceDetailsSummary;
|
||||
import org.sleuthkit.datamodel.DataSource;
|
||||
import org.sleuthkit.datamodel.Image;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
@ -74,9 +73,9 @@ class DataSourceSummaryDetailsPanel extends javax.swing.JPanel {
|
||||
updateDetailsPanelData(null, null, null, null);
|
||||
} else {
|
||||
updateDetailsPanelData(dataSource,
|
||||
DataSourceDetailsSummary.getSizeOfUnallocatedFiles(dataSource),
|
||||
DataSourceDetailsSummary.getOperatingSystems(dataSource),
|
||||
DataSourceDetailsSummary.getDataSourceType(dataSource));
|
||||
DataSourceInfoUtilities.getSizeOfUnallocatedFiles(dataSource),
|
||||
DataSourceInfoUtilities.getOperatingSystems(dataSource),
|
||||
DataSourceInfoUtilities.getDataSourceType(dataSource));
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace max="-2" 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">
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
<Component id="closeButton" min="-2" max="-2" attributes="0"/>
|
||||
@ -36,7 +36,7 @@
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" 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"/>
|
||||
<Component id="closeButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
@ -48,7 +48,7 @@
|
||||
<Component class="javax.swing.JButton" name="closeButton">
|
||||
<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="DataSourceSummaryDialog.closeButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDialog.closeButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
@ -16,7 +16,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datasourcesummary.ui;
|
||||
package org.sleuthkit.autopsy.casemodule.datasourcesummary;
|
||||
|
||||
import java.awt.Frame;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
@ -27,7 +27,6 @@ import java.util.Observer;
|
||||
import java.util.Set;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.autopsy.datasourcesummary.datamodel.CaseDataSourcesSummary;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
import org.sleuthkit.autopsy.ingest.events.DataSourceAnalysisCompletedEvent;
|
||||
import org.sleuthkit.autopsy.ingest.events.DataSourceAnalysisCompletedEvent.Reason;
|
||||
@ -54,8 +53,8 @@ final class DataSourceSummaryDialog extends javax.swing.JDialog implements Obser
|
||||
})
|
||||
DataSourceSummaryDialog(Frame owner) {
|
||||
super(owner, Bundle.DataSourceSummaryDialog_window_title(), true);
|
||||
Map<Long, String> usageMap = CaseDataSourcesSummary.getDataSourceTypes();
|
||||
Map<Long, Long> fileCountsMap = CaseDataSourcesSummary.getCountsOfFiles();
|
||||
Map<Long, String> usageMap = DataSourceInfoUtilities.getDataSourceTypes();
|
||||
Map<Long, Long> fileCountsMap = DataSourceInfoUtilities.getCountsOfFiles();
|
||||
dataSourcesPanel = new DataSourceBrowser(usageMap, fileCountsMap);
|
||||
dataSourceSummaryTabbedPane = new DataSourceSummaryTabbedPane();
|
||||
initComponents();
|
||||
@ -126,7 +125,7 @@ final class DataSourceSummaryDialog extends javax.swing.JDialog implements Obser
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.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()
|
||||
.addGap(0, 0, Short.MAX_VALUE)
|
||||
.addComponent(closeButton)))
|
||||
@ -136,7 +135,7 @@ final class DataSourceSummaryDialog extends javax.swing.JDialog implements Obser
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.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)
|
||||
.addComponent(closeButton)
|
||||
.addContainerGap())
|
@ -16,7 +16,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datasourcesummary.ui;
|
||||
package org.sleuthkit.autopsy.casemodule.datasourcesummary;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.util.ArrayList;
|
||||
@ -30,7 +30,6 @@ import org.openide.nodes.Children;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.nodes.Sheet;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.autopsy.datasourcesummary.ui.Bundle;
|
||||
import org.sleuthkit.autopsy.datamodel.NodeProperty;
|
||||
import org.sleuthkit.autopsy.directorytree.ViewContextAction;
|
||||
import org.sleuthkit.datamodel.DataSource;
|
@ -16,12 +16,11 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datasourcesummary.ui;
|
||||
package org.sleuthkit.autopsy.casemodule.datasourcesummary;
|
||||
|
||||
import javax.swing.JTabbedPane;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.autopsy.casemodule.IngestJobInfoPanel;
|
||||
import org.sleuthkit.autopsy.datasourcesummary.ui.Bundle;
|
||||
import org.sleuthkit.datamodel.DataSource;
|
||||
|
||||
/**
|
@ -42,7 +42,7 @@
|
||||
<Component class="javax.swing.JLabel" name="programsRunLabel">
|
||||
<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="DataSourceSummaryUserActivityPanel.programsRunLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryUserActivityPanel.programsRunLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
@ -16,7 +16,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datasourcesummary.ui;
|
||||
package org.sleuthkit.autopsy.casemodule.datasourcesummary;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.text.DateFormat;
|
||||
@ -32,8 +32,6 @@ import javax.swing.table.DefaultTableCellRenderer;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
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;
|
||||
|
||||
/**
|
||||
@ -116,8 +114,8 @@ public class DataSourceSummaryUserActivityPanel extends javax.swing.JPanel {
|
||||
* @return The JTable data model of counts of program runs.
|
||||
*/
|
||||
private static TopProgramsModel getTopProgramsModel(DataSource selectedDataSource) {
|
||||
List<TopProgramsResult> topProgramList
|
||||
= DataSourceTopProgramsSummary.getTopPrograms(selectedDataSource, TOP_PROGS_COUNT);
|
||||
List<DataSourceInfoUtilities.TopProgramsResult> topProgramList
|
||||
= DataSourceInfoUtilities.getTopPrograms(selectedDataSource, TOP_PROGS_COUNT);
|
||||
|
||||
if (topProgramList == null) {
|
||||
return new TopProgramsModel(null);
|
||||
@ -196,14 +194,14 @@ public class DataSourceSummaryUserActivityPanel extends javax.swing.JPanel {
|
||||
Bundle.DataSourceSummaryUserActivityPanel_TopProgramsTableModel_lastrun_header()
|
||||
};
|
||||
|
||||
private final List<TopProgramsResult> programResults;
|
||||
private final List<DataSourceInfoUtilities.TopProgramsResult> programResults;
|
||||
|
||||
/**
|
||||
* Main constructor.
|
||||
*
|
||||
* @param programResults The results to display.
|
||||
*/
|
||||
TopProgramsModel(List<TopProgramsResult> programResults) {
|
||||
TopProgramsModel(List<DataSourceInfoUtilities.TopProgramsResult> programResults) {
|
||||
this.programResults = programResults == null ? new ArrayList<>() : Collections.unmodifiableList(programResults);
|
||||
}
|
||||
|
||||
@ -228,12 +226,12 @@ public class DataSourceSummaryUserActivityPanel extends javax.swing.JPanel {
|
||||
return null;
|
||||
}
|
||||
|
||||
TopProgramsResult result = programResults.get(rowIndex);
|
||||
DataSourceInfoUtilities.TopProgramsResult result = programResults.get(rowIndex);
|
||||
switch (columnIndex) {
|
||||
case 0:
|
||||
return new ProgramNameCellValue(result.getProgramName(), result.getProgramPath());
|
||||
case 1:
|
||||
return DataSourceTopProgramsSummary.getShortFolderName(result.getProgramPath(), result.getProgramName());
|
||||
return DataSourceInfoUtilities.getShortFolderName(result.getProgramPath(), result.getProgramName());
|
||||
case 2:
|
||||
return result.getRunTimes();
|
||||
case 3:
|
@ -16,7 +16,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datasourcesummary.ui;
|
||||
package org.sleuthkit.autopsy.casemodule.datasourcesummary;
|
||||
|
||||
import javax.swing.table.DefaultTableModel;
|
||||
|
@ -16,7 +16,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datasourcesummary.ui;
|
||||
package org.sleuthkit.autopsy.casemodule.datasourcesummary;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.lang.reflect.InvocationTargetException;
|
@ -16,7 +16,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datasourcesummary.ui;
|
||||
package org.sleuthkit.autopsy.casemodule.datasourcesummary;
|
||||
|
||||
import java.awt.Frame;
|
||||
import java.awt.event.ActionEvent;
|
||||
@ -24,7 +24,6 @@ import javax.swing.AbstractAction;
|
||||
import javax.swing.SwingUtilities;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.windows.WindowManager;
|
||||
import org.sleuthkit.autopsy.datasourcesummary.ui.Bundle;
|
||||
|
||||
/**
|
||||
* ViewSummaryInformationAction action for opening a Data Sources Summary Dialog
|
@ -36,7 +36,7 @@ import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.DeleteDataSourceAction;
|
||||
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.corecomponents.DataResultViewerTable;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
@ -24,7 +24,7 @@ import java.util.List;
|
||||
import javax.swing.Action;
|
||||
import org.openide.util.NbBundle;
|
||||
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.directorytree.ExportCSVAction;
|
||||
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
||||
|
@ -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() {
|
||||
}
|
||||
}
|
@ -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() {
|
||||
}
|
||||
}
|
@ -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() {
|
||||
}
|
||||
}
|
@ -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() {
|
||||
}
|
||||
}
|
@ -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() {
|
||||
}
|
||||
}
|
@ -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() {
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</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>
|
@ -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());
|
||||
}
|
||||
}
|
@ -26,7 +26,7 @@ import org.openide.explorer.ExplorerManager;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
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.corecomponents.AbstractDataResultViewer;
|
||||
import org.sleuthkit.datamodel.DataSource;
|
||||
|
Loading…
x
Reference in New Issue
Block a user