Merge pull request #6190 from gdicristofaro/data_source_summary_result_viewer

Merge data_source_summary_result_viewer into data-src-summaries
This commit is contained in:
Richard Cordovano 2020-08-19 15:11:03 -04:00 committed by GitHub
commit 529417b656
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 626 additions and 260 deletions

View File

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

View File

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

View File

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

View File

@ -1,6 +1,7 @@
CTL_DataSourceSummaryAction=Data Source Summary CTL_DataSourceSummaryAction=Data Source Summary
DataSourceSummaryCountsPanel.ArtifactCountsTableModel.count.header=Count DataSourceSummaryCountsPanel.ArtifactCountsTableModel.count.header=Count
DataSourceSummaryCountsPanel.ArtifactCountsTableModel.type.header=Result Type DataSourceSummaryCountsPanel.ArtifactCountsTableModel.type.header=Result Type
DataSourceSummaryCountsPanel.byMimeTypeLabel.text=Files by MIME Type
DataSourceSummaryCountsPanel.FilesByCategoryTableModel.all.row=All DataSourceSummaryCountsPanel.FilesByCategoryTableModel.all.row=All
DataSourceSummaryCountsPanel.FilesByCategoryTableModel.allocated.row=Allocated DataSourceSummaryCountsPanel.FilesByCategoryTableModel.allocated.row=Allocated
DataSourceSummaryCountsPanel.FilesByCategoryTableModel.count.header=Count DataSourceSummaryCountsPanel.FilesByCategoryTableModel.count.header=Count
@ -58,9 +59,11 @@ DataSourceSummaryDetailsPanel.acquisitionDetailsTextArea.text=
DataSourceSummaryDetailsPanel.acquisitionDetailsLabel.text=Acquisition Details: DataSourceSummaryDetailsPanel.acquisitionDetailsLabel.text=Acquisition Details:
DataSourceSummaryDetailsPanel.unallocatedSizeLabel.text=Unallocated Space: DataSourceSummaryDetailsPanel.unallocatedSizeLabel.text=Unallocated Space:
DataSourceSummaryDetailsPanel.unallocatedSizeValue.text= DataSourceSummaryDetailsPanel.unallocatedSizeValue.text=
DataSourceSummaryCountsPanel.byMimeTypeLabel.text=Files by MIME Type
DataSourceSummaryCountsPanel.byCategoryLabel.text=Files by Category DataSourceSummaryCountsPanel.byCategoryLabel.text=Files by Category
DataSourceSummaryCountsPanel.jLabel1.text=Results by Type DataSourceSummaryCountsPanel.resultsByTypeLabel.text=Results by Type
DataSourceSummaryDialog.countsTab.title=Counts
DataSourceSummaryDialog.detailsTab.title=Details
DataSourceSummaryDialog.ingestHistoryTab.title=Ingest History
DataSourceSummaryDialog.window.title=Data Sources Summary DataSourceSummaryDialog.window.title=Data Sources Summary
DataSourceSummaryNode.column.dataSourceName.header=Data Source Name DataSourceSummaryNode.column.dataSourceName.header=Data Source Name
DataSourceSummaryNode.column.files.header=Files DataSourceSummaryNode.column.files.header=Files

View File

@ -45,6 +45,9 @@ import org.sleuthkit.datamodel.TskData;
import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.DataSource;
import org.sleuthkit.datamodel.TskData.TSK_DB_FILES_TYPE_ENUM;
import org.sleuthkit.datamodel.TskData.TSK_FS_META_FLAG_ENUM;
import org.sleuthkit.datamodel.TskData.TSK_FS_META_TYPE_ENUM;
/** /**
* Utilities for getting information about a data source or all data sources * Utilities for getting information about a data source or all data sources
@ -55,8 +58,8 @@ final class DataSourceInfoUtilities {
private static final Logger logger = Logger.getLogger(DataSourceInfoUtilities.class.getName()); private static final Logger logger = Logger.getLogger(DataSourceInfoUtilities.class.getName());
/** /**
* Gets a count of files for a particular datasource where it is not a * Gets a count of tsk_files for a particular datasource where dir_type is
* virtual directory and has a name. * not a virtual directory and has a name.
* *
* @param currentDataSource The datasource. * @param currentDataSource The datasource.
* @param additionalWhere Additional sql where clauses. * @param additionalWhere Additional sql where clauses.
@ -64,15 +67,15 @@ final class DataSourceInfoUtilities {
* *
* @return The count of files or null on error. * @return The count of files or null on error.
*/ */
private static Long getCountOfFiles(DataSource currentDataSource, String additionalWhere, String onError) { private static Long getCountOfTskFiles(DataSource currentDataSource, String additionalWhere, String onError) {
if (currentDataSource != null) { if (currentDataSource != null) {
try { try {
SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase(); SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
return skCase.countFilesWhere( return skCase.countFilesWhere(
"dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue() "data_source_obj_id=" + currentDataSource.getId()
+ " AND dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue()
+ " AND name<>''" + " AND name<>''"
+ " AND data_source_obj_id=" + currentDataSource.getId() + (StringUtils.isBlank(additionalWhere) ? "" : (" AND " + additionalWhere)));
+ " AND " + additionalWhere);
} catch (TskCoreException | NoCurrentCaseException ex) { } catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.WARNING, onError, ex); logger.log(Level.WARNING, onError, ex);
//unable to get count of files for the specified types cell will be displayed as empty //unable to get count of files for the specified types cell will be displayed as empty
@ -82,18 +85,51 @@ final class DataSourceInfoUtilities {
} }
/** /**
* Get count of files in a data source. * Gets a count of regular files for a particular datasource where the
* dir_type and type are not a virtual directory and has a name.
*
* @param currentDataSource The datasource.
* @param additionalWhere Additional sql where clauses.
* @param onError The message to log on error.
*
* @return The count of files or null on error.
*/
private static Long getCountOfRegularFiles(DataSource currentDataSource, String additionalWhere, String onError) {
String whereClause = "meta_type=" + TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG.getValue()
+ " AND type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType();
if (StringUtils.isNotBlank(additionalWhere)) {
whereClause += " AND " + additionalWhere;
}
return getCountOfTskFiles(currentDataSource, whereClause, onError);
}
/**
* Get count of regular files (not directories) in a data source.
* *
* @param currentDataSource The data source. * @param currentDataSource The data source.
* *
* @return The count. * @return The count.
*/ */
static Long getCountOfFiles(DataSource currentDataSource) { static Long getCountOfFiles(DataSource currentDataSource) {
return getCountOfFiles(currentDataSource, return getCountOfRegularFiles(currentDataSource, null,
"type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType(),
"Unable to get count of files, providing empty results"); "Unable to get count of files, providing empty results");
} }
/**
* Get count of allocated files in a data source.
*
* @param currentDataSource The data source.
*
* @return The count.
*/
static Long getCountOfAllocatedFiles(DataSource currentDataSource) {
return getCountOfRegularFiles(currentDataSource,
getMetaFlagsContainsStatement(TSK_FS_META_FLAG_ENUM.ALLOC),
"Unable to get counts of unallocated files for datasource, providing empty results");
}
/** /**
* Get count of unallocated files in a data source. * Get count of unallocated files in a data source.
* *
@ -102,9 +138,9 @@ final class DataSourceInfoUtilities {
* @return The count. * @return The count.
*/ */
static Long getCountOfUnallocatedFiles(DataSource currentDataSource) { static Long getCountOfUnallocatedFiles(DataSource currentDataSource) {
return getCountOfFiles(currentDataSource, return getCountOfRegularFiles(currentDataSource,
"type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType() getMetaFlagsContainsStatement(TSK_FS_META_FLAG_ENUM.UNALLOC)
+ " AND dir_flags=" + TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC.getValue(), + " AND type<>" + TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType(),
"Unable to get counts of unallocated files for datasource, providing empty results"); "Unable to get counts of unallocated files for datasource, providing empty results");
} }
@ -116,9 +152,9 @@ final class DataSourceInfoUtilities {
* @return The count. * @return The count.
*/ */
static Long getCountOfDirectories(DataSource currentDataSource) { static Long getCountOfDirectories(DataSource currentDataSource) {
return getCountOfFiles(currentDataSource, return getCountOfTskFiles(currentDataSource,
"type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType() "meta_type=" + TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR.getValue()
+ " AND 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"); "Unable to get count of directories for datasource, providing empty results");
} }
@ -130,8 +166,9 @@ final class DataSourceInfoUtilities {
* @return The count. * @return The count.
*/ */
static Long getCountOfSlackFiles(DataSource currentDataSource) { static Long getCountOfSlackFiles(DataSource currentDataSource) {
return getCountOfFiles(currentDataSource, return getCountOfRegularFiles(currentDataSource,
"type=" + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType(), getMetaFlagsContainsStatement(TSK_FS_META_FLAG_ENUM.UNALLOC)
+ " AND type=" + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType(),
"Unable to get count of slack files for datasources, providing empty results"); "Unable to get count of slack files for datasources, providing empty results");
} }
@ -183,9 +220,11 @@ final class DataSourceInfoUtilities {
final String valueParam = "value"; final String valueParam = "value";
final String countParam = "count"; final String countParam = "count";
String query = "SELECT SUM(size) AS " + valueParam + ", COUNT(*) AS " + countParam String query = "SELECT SUM(size) AS " + valueParam + ", COUNT(*) AS " + countParam
+ " FROM tsk_files WHERE type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType() + " FROM tsk_files"
+ " WHERE " + getMetaFlagsContainsStatement(TSK_FS_META_FLAG_ENUM.UNALLOC)
+ " AND type<>" + TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType()
+ " AND type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType()
+ " AND dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue() + " AND dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue()
+ " AND dir_flags=" + TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC.getValue()
+ " AND name<>''" + " AND name<>''"
+ " AND data_source_obj_id=" + currentDataSource.getId(); + " AND data_source_obj_id=" + currentDataSource.getId();
@ -700,10 +739,12 @@ final class DataSourceInfoUtilities {
*/ */
static Map<Long, Long> getCountsOfFiles() { static Map<Long, Long> getCountsOfFiles() {
try { try {
final String countFilesQuery = "data_source_obj_id, COUNT(*) AS value" final String countFilesQuery = "data_source_obj_id, COUNT(*) AS value FROM tsk_files"
+ " FROM tsk_files WHERE type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType() + " WHERE meta_type=" + TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG.getValue()
+ " AND type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType()
+ " AND dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue() + " AND dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue()
+ " AND name<>'' GROUP BY data_source_obj_id"; //NON-NLS + " AND name<>''"
+ " GROUP BY data_source_obj_id"; //NON-NLS
return getValuesMap(countFilesQuery); return getValuesMap(countFilesQuery);
} catch (TskCoreException | NoCurrentCaseException ex) { } catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.WARNING, "Unable to get counts of files for all datasources, providing empty results", ex); logger.log(Level.WARNING, "Unable to get counts of files for all datasources, providing empty results", ex);
@ -776,21 +817,75 @@ final class DataSourceInfoUtilities {
* source, null if no count was retrieved * source, null if no count was retrieved
*/ */
static Long getCountOfFilesForMimeTypes(DataSource currentDataSource, Set<String> setOfMimeTypes) { static Long getCountOfFilesForMimeTypes(DataSource currentDataSource, Set<String> setOfMimeTypes) {
if (currentDataSource != null) { return getCountOfRegularFiles(currentDataSource,
try { "mime_type IN " + getSqlSet(setOfMimeTypes),
String inClause = String.join("', '", setOfMimeTypes); "Unable to get count of files for specified mime types");
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() * Get the number of files in the case database for the current data source
+ " AND mime_type IN ('" + inClause + "')" * which do not have the specified mimetypes.
+ " AND name<>''"); *
} catch (TskCoreException | NoCurrentCaseException ex) { * @param currentDataSource the data source which we are finding a file
logger.log(Level.WARNING, "Unable to get count of files for specified mime types", ex); * count
//unable to get count of files for the specified mimetypes cell will be displayed as empty *
} * @param setOfMimeTypes the set of mime types that should be excluded.
} *
return null; * @return a Long value which represents the number of files that do not
* have the specific mime type, but do have a mime type.
*/
static Long getCountOfFilesNotInMimeTypes(DataSource currentDataSource, Set<String> setOfMimeTypes) {
return getCountOfRegularFiles(currentDataSource,
"mime_type NOT IN " + getSqlSet(setOfMimeTypes)
+ " AND mime_type IS NOT NULL AND mime_type <> '' ",
"Unable to get count of files without specified mime types");
}
/**
* Gets the number of files in the data source with no assigned mime type.
*
* @param currentDataSource The data source.
*
* @return The number of files with no mime type or null if there is an
* issue searching the data source.
*
*/
static Long getCountOfFilesWithNoMimeType(DataSource currentDataSource) {
return getCountOfRegularFiles(currentDataSource,
"(mime_type IS NULL OR mime_type = '') ",
"Unable to get count of files without a mime type");
}
/**
* Derives a sql set string (i.e. "('val1', 'val2', 'val3')"). A naive
* attempt is made to sanitize the strings by removing single quotes from
* values.
*
* @param setValues The values that should be present in the set. Single
* quotes are removed.
*
* @return The sql set string.
*/
private static String getSqlSet(Set<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);
}
/**
* Creates sql where clause that does a bitwise check to see if flag is
* present.
*
* @param flag The flag for which to check.
*
* @return The clause.
*/
private static String getMetaFlagsContainsStatement(TSK_FS_META_FLAG_ENUM flag) {
return "meta_flags & " + flag.getValue() + " > 0";
} }
/** /**

View File

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

View File

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

View File

@ -22,7 +22,7 @@
<Group type="102" alignment="1" attributes="0"> <Group type="102" alignment="1" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0"> <Group type="103" groupAlignment="1" attributes="0">
<Component id="dataSourceSummarySplitPane" pref="668" max="32767" attributes="0"/> <Component id="dataSourceSummarySplitPane" pref="860" max="32767" attributes="0"/>
<Group type="102" attributes="0"> <Group type="102" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/> <EmptySpace min="0" pref="0" max="32767" attributes="0"/>
<Component id="closeButton" min="-2" max="-2" attributes="0"/> <Component id="closeButton" min="-2" max="-2" attributes="0"/>
@ -36,7 +36,7 @@
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="dataSourceSummarySplitPane" pref="362" max="32767" attributes="0"/> <Component id="dataSourceSummarySplitPane" pref="540" max="32767" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="closeButton" min="-2" max="-2" attributes="0"/> <Component id="closeButton" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>

View File

@ -125,7 +125,7 @@ final class DataSourceSummaryDialog extends javax.swing.JDialog implements Obser
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(dataSourceSummarySplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 668, Short.MAX_VALUE) .addComponent(dataSourceSummarySplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 860, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE) .addGap(0, 0, Short.MAX_VALUE)
.addComponent(closeButton))) .addComponent(closeButton)))
@ -135,7 +135,7 @@ final class DataSourceSummaryDialog extends javax.swing.JDialog implements Obser
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addComponent(dataSourceSummarySplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 362, Short.MAX_VALUE) .addComponent(dataSourceSummarySplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 540, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(closeButton) .addComponent(closeButton)
.addContainerGap()) .addContainerGap())

View File

@ -0,0 +1,188 @@
/*
* 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.casemodule.datasourcesummary;
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 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(),
DataSourceInfoUtilities.getCountOfFilesNotInMimeTypes(this.dataSource, ALL_CATEGORY_MIME_TYPES));
addIfPresent(Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_notAnalyzed_label(),
DataSourceInfoUtilities.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 DataSourceInfoUtilities.getCountOfFilesForMimeTypes(dataSource, category.getMediaTypes());
}
}