mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-14 17:06:16 +00:00
Moved file type export functionality
This commit is contained in:
parent
0aa708388c
commit
e948b14c86
@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.contentutils;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
@ -45,10 +46,12 @@ import org.sleuthkit.datamodel.TskData.TSK_FS_META_TYPE_ENUM;
|
||||
*/
|
||||
public final class DataSourceInfoUtilities {
|
||||
|
||||
public static final String COMMA_FORMAT_STR = "#,###";
|
||||
public static final DecimalFormat COMMA_FORMATTER = new DecimalFormat(COMMA_FORMAT_STR);
|
||||
|
||||
/**
|
||||
* Gets a count of tsk_files for a particular datasource.
|
||||
*
|
||||
* @param skCase The current SleuthkitCase.
|
||||
* @param currentDataSource The datasource.
|
||||
* @param additionalWhere Additional sql where clauses.
|
||||
*
|
||||
@ -56,11 +59,12 @@ public final class DataSourceInfoUtilities {
|
||||
*
|
||||
* @throws TskCoreException
|
||||
* @throws SQLException
|
||||
* @throws NoCurrentCaseException
|
||||
*/
|
||||
public static Long getCountOfTskFiles(SleuthkitCase skCase, DataSource currentDataSource, String additionalWhere)
|
||||
throws TskCoreException, SQLException {
|
||||
public static Long getCountOfTskFiles(DataSource currentDataSource, String additionalWhere)
|
||||
throws TskCoreException, SQLException, NoCurrentCaseException {
|
||||
if (currentDataSource != null) {
|
||||
return skCase.countFilesWhere(
|
||||
return Case.getCurrentCaseThrows().getSleuthkitCase().countFilesWhere(
|
||||
"data_source_obj_id=" + currentDataSource.getId()
|
||||
+ (StringUtils.isBlank(additionalWhere) ? "" : (" AND " + additionalWhere)));
|
||||
}
|
||||
@ -70,7 +74,6 @@ public final class DataSourceInfoUtilities {
|
||||
/**
|
||||
* Gets a count of regular files for a particular datasource.
|
||||
*
|
||||
* @param skCase The current SleuthkitCase.
|
||||
* @param currentDataSource The datasource.
|
||||
* @param additionalWhere Additional sql where clauses.
|
||||
*
|
||||
@ -78,22 +81,22 @@ public final class DataSourceInfoUtilities {
|
||||
*
|
||||
* @throws TskCoreException
|
||||
* @throws SQLException
|
||||
* @throws NoCurrentCaseException
|
||||
*/
|
||||
public static Long getCountOfRegularFiles(SleuthkitCase skCase, DataSource currentDataSource, String additionalWhere)
|
||||
throws TskCoreException, SQLException {
|
||||
public static Long getCountOfRegularFiles(DataSource currentDataSource, String additionalWhere)
|
||||
throws TskCoreException, SQLException, NoCurrentCaseException {
|
||||
String whereClause = "meta_type=" + TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG.getValue();
|
||||
|
||||
if (StringUtils.isNotBlank(additionalWhere)) {
|
||||
whereClause += " AND " + additionalWhere;
|
||||
}
|
||||
|
||||
return getCountOfTskFiles(skCase, currentDataSource, whereClause);
|
||||
return getCountOfTskFiles(currentDataSource, whereClause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a count of regular non-slack files for a particular datasource.
|
||||
*
|
||||
* @param skCase The current SleuthkitCase.
|
||||
* @param currentDataSource The datasource.
|
||||
* @param additionalWhere Additional sql where clauses.
|
||||
*
|
||||
@ -101,9 +104,10 @@ public final class DataSourceInfoUtilities {
|
||||
*
|
||||
* @throws TskCoreException
|
||||
* @throws SQLException
|
||||
* @throws NoCurrentCaseException
|
||||
*/
|
||||
public static Long getCountOfRegNonSlackFiles(SleuthkitCase skCase, DataSource currentDataSource, String additionalWhere)
|
||||
throws TskCoreException, SQLException {
|
||||
public static Long getCountOfRegNonSlackFiles(DataSource currentDataSource, String additionalWhere)
|
||||
throws TskCoreException, SQLException, NoCurrentCaseException {
|
||||
String whereClause = "meta_type=" + TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG.getValue()
|
||||
+ " AND type<>" + TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType();
|
||||
|
||||
@ -111,7 +115,7 @@ public final class DataSourceInfoUtilities {
|
||||
whereClause += " AND " + additionalWhere;
|
||||
}
|
||||
|
||||
return getCountOfTskFiles(skCase, currentDataSource, whereClause);
|
||||
return getCountOfTskFiles(currentDataSource, whereClause);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -429,4 +433,27 @@ public final class DataSourceInfoUtilities {
|
||||
Long longVal = getLongOrNull(artifact, attributeType);
|
||||
return (longVal == null || longVal == 0) ? null : new Date(longVal * 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the long value or zero if longVal is null.
|
||||
*
|
||||
* @param longVal The long value.
|
||||
*
|
||||
* @return The long value or 0 if provided value is null.
|
||||
*/
|
||||
public static long getLongOrZero(Long longVal) {
|
||||
return longVal == null ? 0 : longVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns string value of long with comma separators. If null returns a
|
||||
* string of '0'.
|
||||
*
|
||||
* @param longVal The long value.
|
||||
*
|
||||
* @return The string value of the long.
|
||||
*/
|
||||
public static String getStringOrZero(Long longVal) {
|
||||
return longVal == null ? "0" : COMMA_FORMATTER.format(longVal);
|
||||
}
|
||||
}
|
||||
|
@ -22,14 +22,11 @@ import java.nio.file.Paths;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
|
182
Core/src/org/sleuthkit/autopsy/contentutils/TypesSummary.java
Executable file
182
Core/src/org/sleuthkit/autopsy/contentutils/TypesSummary.java
Executable file
@ -0,0 +1,182 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2019 - 2021 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.contentutils;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Set;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.coreutils.FileTypeUtils;
|
||||
import org.sleuthkit.datamodel.DataSource;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
|
||||
/**
|
||||
* Helper class for getting summary information on the known files present in the
|
||||
* specified DataSource..
|
||||
*/
|
||||
public class TypesSummary {
|
||||
|
||||
private TypesSummary() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get count of regular files (not directories) in a data source.
|
||||
*
|
||||
* @param currentDataSource The data source.
|
||||
*
|
||||
* @return The count.
|
||||
*
|
||||
* @throws TskCoreException
|
||||
* @throws SQLException
|
||||
* @throws NoCurrentCaseException
|
||||
*/
|
||||
public static Long getCountOfFiles(DataSource currentDataSource)
|
||||
throws TskCoreException, SQLException, NoCurrentCaseException {
|
||||
return DataSourceInfoUtilities.getCountOfRegularFiles(currentDataSource, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get count of allocated files in a data source.
|
||||
*
|
||||
* @param currentDataSource The data source.
|
||||
*
|
||||
* @return The count.
|
||||
*
|
||||
* @throws TskCoreException
|
||||
* @throws SQLException
|
||||
* @throws NoCurrentCaseException
|
||||
*/
|
||||
public static Long getCountOfAllocatedFiles(DataSource currentDataSource)
|
||||
throws TskCoreException, SQLException, NoCurrentCaseException {
|
||||
|
||||
return DataSourceInfoUtilities.getCountOfRegNonSlackFiles(currentDataSource,
|
||||
DataSourceInfoUtilities.getMetaFlagsContainsStatement(TskData.TSK_FS_META_FLAG_ENUM.ALLOC));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get count of unallocated files in a data source.
|
||||
*
|
||||
* @param currentDataSource The data source.
|
||||
*
|
||||
* @return The count.
|
||||
*
|
||||
* @throws TskCoreException
|
||||
* @throws SQLException
|
||||
* @throws NoCurrentCaseException
|
||||
*/
|
||||
public static Long getCountOfUnallocatedFiles(DataSource currentDataSource)
|
||||
throws NoCurrentCaseException, TskCoreException, SQLException {
|
||||
|
||||
return DataSourceInfoUtilities.getCountOfRegNonSlackFiles(currentDataSource,
|
||||
DataSourceInfoUtilities.getMetaFlagsContainsStatement(TskData.TSK_FS_META_FLAG_ENUM.UNALLOC));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get count of directories in a data source.
|
||||
*
|
||||
* @param currentDataSource The data source.
|
||||
*
|
||||
* @return The count.
|
||||
*
|
||||
* @throws TskCoreException
|
||||
* @throws SQLException
|
||||
* @throws NoCurrentCaseException
|
||||
*/
|
||||
public static Long getCountOfDirectories(DataSource currentDataSource)
|
||||
throws NoCurrentCaseException, TskCoreException, SQLException {
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get count of slack files in a data source.
|
||||
*
|
||||
* @param currentDataSource The data source.
|
||||
*
|
||||
* @return The count.
|
||||
*
|
||||
* @throws TskCoreException
|
||||
* @throws SQLException
|
||||
* @throws NoCurrentCaseException
|
||||
*/
|
||||
public static Long getCountOfSlackFiles(DataSource currentDataSource)
|
||||
throws NoCurrentCaseException, TskCoreException, SQLException {
|
||||
|
||||
return DataSourceInfoUtilities.getCountOfRegularFiles(currentDataSource,
|
||||
"type=" + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Information concerning a particular file type category.
|
||||
*/
|
||||
public static class FileTypeCategoryData {
|
||||
|
||||
private final String label;
|
||||
private final Set<String> mimeTypes;
|
||||
private final Color color;
|
||||
|
||||
/**
|
||||
* Main constructor.
|
||||
*
|
||||
* @param label The label for this slice.
|
||||
* @param mimeTypes The mime types associated with this slice.
|
||||
* @param color The color associated with this slice.
|
||||
*/
|
||||
public FileTypeCategoryData(String label, Set<String> mimeTypes, Color color) {
|
||||
this.label = label;
|
||||
this.mimeTypes = mimeTypes;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor that accepts FileTypeCategory.
|
||||
*
|
||||
* @param label The label for this slice.
|
||||
* @param mimeTypes The mime types associated with this slice.
|
||||
* @param color The color associated with this slice.
|
||||
*/
|
||||
public FileTypeCategoryData(String label, FileTypeUtils.FileTypeCategory fileCategory, Color color) {
|
||||
this(label, fileCategory.getMediaTypes(), color);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The label for this category.
|
||||
*/
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The mime types associated with this category.
|
||||
*/
|
||||
public Set<String> getMimeTypes() {
|
||||
return mimeTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The color associated with this category.
|
||||
*/
|
||||
public Color getColor() {
|
||||
return color;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2020 Basis Technology Corp.
|
||||
* Copyright 2020-2021 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -21,10 +21,12 @@ package org.sleuthkit.autopsy.datasourcesummary.datamodel;
|
||||
import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultUpdateGovernor;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException;
|
||||
import org.sleuthkit.autopsy.contentutils.DataSourceInfoUtilities;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
@ -34,11 +36,10 @@ import org.sleuthkit.datamodel.DataSource;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* Provides methods to query for datasource files by mime type.
|
||||
* Wrapper class for converting org.sleuthkit.autopsy.contentutils.TypesSummary
|
||||
* functionality into a DefaultArtifactUpdateGovernor used by TypesPanel tab.
|
||||
*/
|
||||
public class MimeTypeSummary implements DefaultUpdateGovernor {
|
||||
|
||||
private final SleuthkitCaseProvider provider;
|
||||
public class MimeTypeSummaryGetter implements DefaultUpdateGovernor {
|
||||
|
||||
private static final Set<IngestManager.IngestJobEvent> INGEST_JOB_EVENTS = new HashSet<>(
|
||||
Arrays.asList(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED));
|
||||
@ -46,17 +47,7 @@ public class MimeTypeSummary implements DefaultUpdateGovernor {
|
||||
/**
|
||||
* Main constructor.
|
||||
*/
|
||||
public MimeTypeSummary() {
|
||||
this(SleuthkitCaseProvider.DEFAULT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Main constructor.
|
||||
*
|
||||
* @param provider The means of obtaining a sleuthkit case.
|
||||
*/
|
||||
public MimeTypeSummary(SleuthkitCaseProvider provider) {
|
||||
this.provider = provider;
|
||||
public MimeTypeSummaryGetter() {
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -76,7 +67,7 @@ public class MimeTypeSummary implements DefaultUpdateGovernor {
|
||||
|
||||
@Override
|
||||
public Set<IngestManager.IngestJobEvent> getIngestJobEventUpdates() {
|
||||
return INGEST_JOB_EVENTS;
|
||||
return Collections.unmodifiableSet(INGEST_JOB_EVENTS);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -99,12 +90,11 @@ public class MimeTypeSummary implements DefaultUpdateGovernor {
|
||||
*/
|
||||
public Long getCountOfFilesForMimeTypes(DataSource currentDataSource, Set<String> setOfMimeTypes)
|
||||
throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException {
|
||||
|
||||
return DataSourceInfoUtilities.getCountOfRegNonSlackFiles(
|
||||
provider.get(),
|
||||
currentDataSource,
|
||||
"mime_type IN " + getSqlSet(setOfMimeTypes)
|
||||
);
|
||||
try {
|
||||
return DataSourceInfoUtilities.getCountOfRegNonSlackFiles(currentDataSource, "mime_type IN " + getSqlSet(setOfMimeTypes));
|
||||
} catch (NoCurrentCaseException ex) {
|
||||
throw new SleuthkitCaseProviderException("No currently open case.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -125,13 +115,13 @@ public class MimeTypeSummary implements DefaultUpdateGovernor {
|
||||
*/
|
||||
public Long getCountOfFilesNotInMimeTypes(DataSource currentDataSource, Set<String> setOfMimeTypes)
|
||||
throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException {
|
||||
|
||||
return DataSourceInfoUtilities.getCountOfRegNonSlackFiles(
|
||||
provider.get(),
|
||||
currentDataSource,
|
||||
"mime_type NOT IN " + getSqlSet(setOfMimeTypes)
|
||||
+ " AND mime_type IS NOT NULL AND mime_type <> '' "
|
||||
);
|
||||
try {
|
||||
return DataSourceInfoUtilities.getCountOfRegNonSlackFiles(currentDataSource,
|
||||
"mime_type NOT IN " + getSqlSet(setOfMimeTypes)
|
||||
+ " AND mime_type IS NOT NULL AND mime_type <> '' ");
|
||||
} catch (NoCurrentCaseException ex) {
|
||||
throw new SleuthkitCaseProviderException("No currently open case.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -147,8 +137,11 @@ public class MimeTypeSummary implements DefaultUpdateGovernor {
|
||||
*/
|
||||
public Long getCountOfAllRegularFiles(DataSource dataSource)
|
||||
throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException {
|
||||
|
||||
return DataSourceInfoUtilities.getCountOfRegNonSlackFiles(provider.get(), dataSource, null);
|
||||
try {
|
||||
return DataSourceInfoUtilities.getCountOfRegNonSlackFiles(dataSource, null);
|
||||
} catch (NoCurrentCaseException ex) {
|
||||
throw new SleuthkitCaseProviderException("No currently open case.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -165,12 +158,11 @@ public class MimeTypeSummary implements DefaultUpdateGovernor {
|
||||
*/
|
||||
public Long getCountOfFilesWithNoMimeType(DataSource currentDataSource)
|
||||
throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException {
|
||||
|
||||
return DataSourceInfoUtilities.getCountOfRegNonSlackFiles(
|
||||
provider.get(),
|
||||
currentDataSource,
|
||||
"(mime_type IS NULL OR mime_type = '') "
|
||||
);
|
||||
try {
|
||||
return DataSourceInfoUtilities.getCountOfRegNonSlackFiles(currentDataSource, "(mime_type IS NULL OR mime_type = '') ");
|
||||
} catch (NoCurrentCaseException ex) {
|
||||
throw new SleuthkitCaseProviderException("No currently open case.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
@ -21,41 +21,31 @@ package org.sleuthkit.autopsy.datasourcesummary.datamodel;
|
||||
import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultUpdateGovernor;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import org.sleuthkit.autopsy.contentutils.DataSourceInfoUtilities;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.contentutils.TypesSummary;
|
||||
import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
import org.sleuthkit.autopsy.ingest.ModuleContentEvent;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.DataSource;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
|
||||
/**
|
||||
* Provides information for the DataSourceSummaryCountsPanel.
|
||||
* Wrapper class for converting org.sleuthkit.autopsy.contentutils.TypesSummary functionality into a
|
||||
* DefaultArtifactUpdateGovernor used by DataSourceSummaryCountsPanel.
|
||||
*/
|
||||
public class TypesSummary implements DefaultUpdateGovernor {
|
||||
public class TypesSummaryGetter implements DefaultUpdateGovernor {
|
||||
|
||||
private static final Set<IngestManager.IngestJobEvent> INGEST_JOB_EVENTS = new HashSet<>(
|
||||
Arrays.asList(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED));
|
||||
|
||||
private final SleuthkitCaseProvider provider;
|
||||
|
||||
/**
|
||||
* Main constructor.
|
||||
*/
|
||||
public TypesSummary() {
|
||||
this(SleuthkitCaseProvider.DEFAULT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Main constructor.
|
||||
*
|
||||
* @param provider The means of obtaining a sleuthkit case.
|
||||
*/
|
||||
public TypesSummary(SleuthkitCaseProvider provider) {
|
||||
this.provider = provider;
|
||||
public TypesSummaryGetter() {
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -75,7 +65,7 @@ public class TypesSummary implements DefaultUpdateGovernor {
|
||||
|
||||
@Override
|
||||
public Set<IngestManager.IngestJobEvent> getIngestJobEventUpdates() {
|
||||
return INGEST_JOB_EVENTS;
|
||||
return Collections.unmodifiableSet(INGEST_JOB_EVENTS);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -91,11 +81,11 @@ public class TypesSummary implements DefaultUpdateGovernor {
|
||||
*/
|
||||
public Long getCountOfFiles(DataSource currentDataSource)
|
||||
throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException {
|
||||
return DataSourceInfoUtilities.getCountOfRegularFiles(
|
||||
provider.get(),
|
||||
currentDataSource,
|
||||
null
|
||||
);
|
||||
try {
|
||||
return TypesSummary.getCountOfFiles(currentDataSource);
|
||||
} catch (NoCurrentCaseException ex) {
|
||||
throw new SleuthkitCaseProviderException("No currently open case.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -111,9 +101,11 @@ public class TypesSummary implements DefaultUpdateGovernor {
|
||||
*/
|
||||
public Long getCountOfAllocatedFiles(DataSource currentDataSource)
|
||||
throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException {
|
||||
|
||||
return DataSourceInfoUtilities.getCountOfRegNonSlackFiles(provider.get(), currentDataSource,
|
||||
DataSourceInfoUtilities.getMetaFlagsContainsStatement(TskData.TSK_FS_META_FLAG_ENUM.ALLOC));
|
||||
try {
|
||||
return TypesSummary.getCountOfAllocatedFiles(currentDataSource);
|
||||
} catch (NoCurrentCaseException ex) {
|
||||
throw new SleuthkitCaseProviderException("No currently open case.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -129,9 +121,11 @@ public class TypesSummary implements DefaultUpdateGovernor {
|
||||
*/
|
||||
public Long getCountOfUnallocatedFiles(DataSource currentDataSource)
|
||||
throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException {
|
||||
|
||||
return DataSourceInfoUtilities.getCountOfRegNonSlackFiles(provider.get(), currentDataSource,
|
||||
DataSourceInfoUtilities.getMetaFlagsContainsStatement(TskData.TSK_FS_META_FLAG_ENUM.UNALLOC));
|
||||
try {
|
||||
return TypesSummary.getCountOfUnallocatedFiles(currentDataSource);
|
||||
} catch (NoCurrentCaseException ex) {
|
||||
throw new SleuthkitCaseProviderException("No currently open case.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -147,10 +141,11 @@ public class TypesSummary implements DefaultUpdateGovernor {
|
||||
*/
|
||||
public Long getCountOfDirectories(DataSource currentDataSource)
|
||||
throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException {
|
||||
|
||||
return DataSourceInfoUtilities.getCountOfTskFiles(provider.get(), 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());
|
||||
try {
|
||||
return TypesSummary.getCountOfDirectories(currentDataSource);
|
||||
} catch (NoCurrentCaseException ex) {
|
||||
throw new SleuthkitCaseProviderException("No currently open case.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -166,8 +161,10 @@ public class TypesSummary implements DefaultUpdateGovernor {
|
||||
*/
|
||||
public Long getCountOfSlackFiles(DataSource currentDataSource)
|
||||
throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException {
|
||||
|
||||
return DataSourceInfoUtilities.getCountOfRegularFiles(provider.get(), currentDataSource,
|
||||
"type=" + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType());
|
||||
try {
|
||||
return TypesSummary.getCountOfSlackFiles(currentDataSource);
|
||||
} catch (NoCurrentCaseException ex) {
|
||||
throw new SleuthkitCaseProviderException("No currently open case.", ex);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2019 Basis Technology Corp.
|
||||
* Copyright 2019-2021 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -23,17 +23,17 @@ import java.sql.SQLException;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.autopsy.coreutils.FileTypeUtils.FileTypeCategory;
|
||||
import org.sleuthkit.autopsy.datasourcesummary.datamodel.TypesSummary;
|
||||
import org.sleuthkit.autopsy.contentutils.DataSourceInfoUtilities;
|
||||
import org.sleuthkit.autopsy.contentutils.TypesSummary.FileTypeCategoryData;
|
||||
import org.sleuthkit.autopsy.datasourcesummary.datamodel.TypesSummaryGetter;
|
||||
import org.sleuthkit.autopsy.datasourcesummary.datamodel.ContainerSummaryGetter;
|
||||
import org.sleuthkit.autopsy.datasourcesummary.datamodel.MimeTypeSummary;
|
||||
import org.sleuthkit.autopsy.datasourcesummary.datamodel.MimeTypeSummaryGetter;
|
||||
import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException;
|
||||
import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult;
|
||||
import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult.ResultType;
|
||||
@ -90,7 +90,7 @@ class TypesPanel extends BaseDataSourceSummaryPanel {
|
||||
* @param usefulContent True if this is useful content; false if there
|
||||
* is 0 mime type information.
|
||||
*/
|
||||
public TypesPieChartData(List<PieChartItem> pieSlices, boolean usefulContent) {
|
||||
TypesPieChartData(List<PieChartItem> pieSlices, boolean usefulContent) {
|
||||
this.pieSlices = pieSlices;
|
||||
this.usefulContent = usefulContent;
|
||||
}
|
||||
@ -98,78 +98,20 @@ class TypesPanel extends BaseDataSourceSummaryPanel {
|
||||
/**
|
||||
* @return The pie chart data.
|
||||
*/
|
||||
public List<PieChartItem> getPieSlices() {
|
||||
List<PieChartItem> getPieSlices() {
|
||||
return pieSlices;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether or not the data is usefulContent.
|
||||
*/
|
||||
public boolean isUsefulContent() {
|
||||
boolean isUsefulContent() {
|
||||
return usefulContent;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Information concerning a particular category in the file types pie chart.
|
||||
*/
|
||||
private static class TypesPieCategory {
|
||||
|
||||
private final String label;
|
||||
private final Set<String> mimeTypes;
|
||||
private final Color color;
|
||||
|
||||
/**
|
||||
* Main constructor.
|
||||
*
|
||||
* @param label The label for this slice.
|
||||
* @param mimeTypes The mime types associated with this slice.
|
||||
* @param color The color associated with this slice.
|
||||
*/
|
||||
TypesPieCategory(String label, Set<String> mimeTypes, Color color) {
|
||||
this.label = label;
|
||||
this.mimeTypes = mimeTypes;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor that accepts FileTypeCategory.
|
||||
*
|
||||
* @param label The label for this slice.
|
||||
* @param mimeTypes The mime types associated with this slice.
|
||||
* @param color The color associated with this slice.
|
||||
*/
|
||||
TypesPieCategory(String label, FileTypeCategory fileCategory, Color color) {
|
||||
this(label, fileCategory.getMediaTypes(), color);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The label for this category.
|
||||
*/
|
||||
String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The mime types associated with this category.
|
||||
*/
|
||||
Set<String> getMimeTypes() {
|
||||
return mimeTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The color associated with this category.
|
||||
*/
|
||||
Color getColor() {
|
||||
return color;
|
||||
}
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final DecimalFormat INTEGER_SIZE_FORMAT = new DecimalFormat("#");
|
||||
private static final String COMMA_FORMAT_STR = "#,###";
|
||||
|
||||
private static final DecimalFormat COMMA_FORMATTER = new DecimalFormat(COMMA_FORMAT_STR);
|
||||
|
||||
private static final Color IMAGES_COLOR = new Color(156, 39, 176);
|
||||
private static final Color VIDEOS_COLOR = Color.YELLOW;
|
||||
@ -181,13 +123,13 @@ class TypesPanel extends BaseDataSourceSummaryPanel {
|
||||
private static final Color NOT_ANALYZED_COLOR = Color.WHITE;
|
||||
|
||||
// All file type categories.
|
||||
private static final List<TypesPieCategory> FILE_MIME_TYPE_CATEGORIES = Arrays.asList(
|
||||
new TypesPieCategory(Bundle.TypesPanel_fileMimeTypesChart_images_title(), FileTypeCategory.IMAGE.getMediaTypes(), IMAGES_COLOR),
|
||||
new TypesPieCategory(Bundle.TypesPanel_fileMimeTypesChart_videos_title(), FileTypeCategory.VIDEO.getMediaTypes(), VIDEOS_COLOR),
|
||||
new TypesPieCategory(Bundle.TypesPanel_fileMimeTypesChart_audio_title(), FileTypeCategory.AUDIO.getMediaTypes(), AUDIO_COLOR),
|
||||
new TypesPieCategory(Bundle.TypesPanel_fileMimeTypesChart_documents_title(), FileTypeCategory.DOCUMENTS.getMediaTypes(), DOCUMENTS_COLOR),
|
||||
new TypesPieCategory(Bundle.TypesPanel_fileMimeTypesChart_executables_title(), FileTypeCategory.EXECUTABLE.getMediaTypes(), EXECUTABLES_COLOR),
|
||||
new TypesPieCategory(Bundle.TypesPanel_fileMimeTypesChart_unknown_title(), new HashSet<>(Arrays.asList("application/octet-stream")), UNKNOWN_COLOR)
|
||||
private static final List<FileTypeCategoryData> FILE_MIME_TYPE_CATEGORIES = Arrays.asList(
|
||||
new FileTypeCategoryData(Bundle.TypesPanel_fileMimeTypesChart_images_title(), FileTypeCategory.IMAGE.getMediaTypes(), IMAGES_COLOR),
|
||||
new FileTypeCategoryData(Bundle.TypesPanel_fileMimeTypesChart_videos_title(), FileTypeCategory.VIDEO.getMediaTypes(), VIDEOS_COLOR),
|
||||
new FileTypeCategoryData(Bundle.TypesPanel_fileMimeTypesChart_audio_title(), FileTypeCategory.AUDIO.getMediaTypes(), AUDIO_COLOR),
|
||||
new FileTypeCategoryData(Bundle.TypesPanel_fileMimeTypesChart_documents_title(), FileTypeCategory.DOCUMENTS.getMediaTypes(), DOCUMENTS_COLOR),
|
||||
new FileTypeCategoryData(Bundle.TypesPanel_fileMimeTypesChart_executables_title(), FileTypeCategory.EXECUTABLE.getMediaTypes(), EXECUTABLES_COLOR),
|
||||
new FileTypeCategoryData(Bundle.TypesPanel_fileMimeTypesChart_unknown_title(), new HashSet<>(Arrays.asList("application/octet-stream")), UNKNOWN_COLOR)
|
||||
);
|
||||
|
||||
private final DataFetcher<DataSource, String> usageFetcher;
|
||||
@ -233,7 +175,7 @@ class TypesPanel extends BaseDataSourceSummaryPanel {
|
||||
* Creates a new TypesPanel.
|
||||
*/
|
||||
public TypesPanel() {
|
||||
this(new MimeTypeSummary(), new TypesSummary(), new ContainerSummaryGetter());
|
||||
this(new MimeTypeSummaryGetter(), new TypesSummaryGetter(), new ContainerSummaryGetter());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -250,8 +192,8 @@ class TypesPanel extends BaseDataSourceSummaryPanel {
|
||||
* @param containerData The service for container information.
|
||||
*/
|
||||
public TypesPanel(
|
||||
MimeTypeSummary mimeTypeData,
|
||||
TypesSummary typeData,
|
||||
MimeTypeSummaryGetter mimeTypeData,
|
||||
TypesSummaryGetter typeData,
|
||||
ContainerSummaryGetter containerData) {
|
||||
|
||||
super(mimeTypeData, typeData, containerData);
|
||||
@ -277,13 +219,13 @@ class TypesPanel extends BaseDataSourceSummaryPanel {
|
||||
size -> SizeRepresentationUtil.getSizeString(size, INTEGER_SIZE_FORMAT, false)))),
|
||||
new DataFetchWorker.DataFetchComponents<>(typesFetcher, this::showMimeTypeCategories),
|
||||
new DataFetchWorker.DataFetchComponents<>(allocatedFetcher,
|
||||
countRes -> allocatedLabel.showDataFetchResult(DataFetchResult.getSubResult(countRes, (count) -> getStringOrZero(count)))),
|
||||
countRes -> allocatedLabel.showDataFetchResult(DataFetchResult.getSubResult(countRes, (count) -> DataSourceInfoUtilities.getStringOrZero(count)))),
|
||||
new DataFetchWorker.DataFetchComponents<>(unallocatedFetcher,
|
||||
countRes -> unallocatedLabel.showDataFetchResult(DataFetchResult.getSubResult(countRes, (count) -> getStringOrZero(count)))),
|
||||
countRes -> unallocatedLabel.showDataFetchResult(DataFetchResult.getSubResult(countRes, (count) -> DataSourceInfoUtilities.getStringOrZero(count)))),
|
||||
new DataFetchWorker.DataFetchComponents<>(slackFetcher,
|
||||
countRes -> slackLabel.showDataFetchResult(DataFetchResult.getSubResult(countRes, (count) -> getStringOrZero(count)))),
|
||||
countRes -> slackLabel.showDataFetchResult(DataFetchResult.getSubResult(countRes, (count) -> DataSourceInfoUtilities.getStringOrZero(count)))),
|
||||
new DataFetchWorker.DataFetchComponents<>(directoriesFetcher,
|
||||
countRes -> directoriesLabel.showDataFetchResult(DataFetchResult.getSubResult(countRes, (count) -> getStringOrZero(count))))
|
||||
countRes -> directoriesLabel.showDataFetchResult(DataFetchResult.getSubResult(countRes, (count) -> DataSourceInfoUtilities.getStringOrZero(count))))
|
||||
);
|
||||
|
||||
initComponents();
|
||||
@ -307,7 +249,7 @@ class TypesPanel extends BaseDataSourceSummaryPanel {
|
||||
*
|
||||
* @return The pie chart items.
|
||||
*/
|
||||
private TypesPieChartData getMimeTypeCategoriesModel(MimeTypeSummary mimeTypeData, DataSource dataSource)
|
||||
private TypesPieChartData getMimeTypeCategoriesModel(MimeTypeSummaryGetter mimeTypeData, DataSource dataSource)
|
||||
throws SQLException, SleuthkitCaseProviderException, TskCoreException {
|
||||
|
||||
if (dataSource == null) {
|
||||
@ -318,8 +260,8 @@ class TypesPanel extends BaseDataSourceSummaryPanel {
|
||||
List<PieChartItem> fileCategoryItems = new ArrayList<>();
|
||||
long categoryTotalCount = 0;
|
||||
|
||||
for (TypesPieCategory cat : FILE_MIME_TYPE_CATEGORIES) {
|
||||
long thisValue = getLongOrZero(mimeTypeData.getCountOfFilesForMimeTypes(dataSource, cat.getMimeTypes()));
|
||||
for (FileTypeCategoryData cat : FILE_MIME_TYPE_CATEGORIES) {
|
||||
long thisValue = DataSourceInfoUtilities.getLongOrZero(mimeTypeData.getCountOfFilesForMimeTypes(dataSource, cat.getMimeTypes()));
|
||||
categoryTotalCount += thisValue;
|
||||
|
||||
fileCategoryItems.add(new PieChartItem(
|
||||
@ -329,10 +271,10 @@ class TypesPanel extends BaseDataSourceSummaryPanel {
|
||||
}
|
||||
|
||||
// get a count of all files with no mime type
|
||||
long noMimeTypeCount = getLongOrZero(mimeTypeData.getCountOfFilesWithNoMimeType(dataSource));
|
||||
long noMimeTypeCount = DataSourceInfoUtilities.getLongOrZero(mimeTypeData.getCountOfFilesWithNoMimeType(dataSource));
|
||||
|
||||
// get a count of all regular files
|
||||
long allRegularFiles = getLongOrZero(mimeTypeData.getCountOfAllRegularFiles(dataSource));
|
||||
long allRegularFiles = DataSourceInfoUtilities.getLongOrZero(mimeTypeData.getCountOfAllRegularFiles(dataSource));
|
||||
|
||||
// create entry for mime types in other category
|
||||
long otherCount = allRegularFiles - (categoryTotalCount + noMimeTypeCount);
|
||||
@ -385,29 +327,6 @@ class TypesPanel extends BaseDataSourceSummaryPanel {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the long value or zero if longVal is null.
|
||||
*
|
||||
* @param longVal The long value.
|
||||
*
|
||||
* @return The long value or 0 if provided value is null.
|
||||
*/
|
||||
private static long getLongOrZero(Long longVal) {
|
||||
return longVal == null ? 0 : longVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns string value of long with comma separators. If null returns a
|
||||
* string of '0'.
|
||||
*
|
||||
* @param longVal The long value.
|
||||
*
|
||||
* @return The string value of the long.
|
||||
*/
|
||||
private static String getStringOrZero(Long longVal) {
|
||||
return longVal == null ? "0" : COMMA_FORMATTER.format(longVal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a key value pair to be exported in a sheet.
|
||||
*
|
||||
|
@ -5,6 +5,7 @@ DataSourceSummaryReport.endReport.srcModuleName.text=Excel Report
|
||||
ExcelExport_writeExcel_noSheetName=Sheet {0}
|
||||
ExcelExportAction_exportToXLSX_beginExport=Beginning Export...
|
||||
ExcelExportAction_exportToXLSX_gatheringContainerData=Fetching Container & Image Data
|
||||
ExcelExportAction_exportToXLSX_gatheringFileData=Fetching File and MIME Type Data
|
||||
ExcelExportAction_exportToXLSX_gatheringRecentActivityData=Fetching Recent Activity Data
|
||||
ExcelExportAction_exportToXLSX_gatheringTimelineData=Fetching Timeline Data
|
||||
ExcelExportAction_exportToXLSX_writingToFile=Writing to File...
|
||||
@ -32,6 +33,25 @@ ExportRecentFiles_col_header_path=Path
|
||||
ExportRecentFiles_col_header_sender=Sender
|
||||
ExportRecentFiles_docsTable_tabName=Recently Opened Documents
|
||||
ExportRecentFiles_downloadsTable_tabName=Recently Downloads
|
||||
ExportTypes_artifactsTypesPieChart_title=Artifact Types
|
||||
ExportTypes_excelTabName=Types
|
||||
ExportTypes_fileMimeTypesChart_audio_title=Audio
|
||||
ExportTypes_fileMimeTypesChart_documents_title=Documents
|
||||
ExportTypes_fileMimeTypesChart_executables_title=Executables
|
||||
ExportTypes_fileMimeTypesChart_images_title=Images
|
||||
ExportTypes_fileMimeTypesChart_notAnalyzed_title=Not Analyzed
|
||||
ExportTypes_fileMimeTypesChart_other_title=Other
|
||||
ExportTypes_fileMimeTypesChart_title=File Types
|
||||
ExportTypes_fileMimeTypesChart_unknown_title=Unknown
|
||||
ExportTypes_fileMimeTypesChart_valueLabel=Count
|
||||
ExportTypes_fileMimeTypesChart_videos_title=Videos
|
||||
ExportTypes_filesByCategoryTable_allocatedRow_title=Allocated Files
|
||||
ExportTypes_filesByCategoryTable_directoryRow_title=Directories
|
||||
ExportTypes_filesByCategoryTable_slackRow_title=Slack Files
|
||||
ExportTypes_filesByCategoryTable_unallocatedRow_title=Unallocated Files
|
||||
ExportTypes_osLabel_title=OS
|
||||
ExportTypes_sizeLabel_title=Size
|
||||
ExportTypes_usageLabel_title=Usage
|
||||
SizeRepresentationUtil_units_bytes=bytes
|
||||
SizeRepresentationUtil_units_gigabytes=GB
|
||||
SizeRepresentationUtil_units_kilobytes=KB
|
||||
|
@ -93,6 +93,7 @@ class ExcelExportAction {
|
||||
"ExcelExportAction_exportToXLSX_gatheringRecentActivityData=Fetching Recent Activity Data",
|
||||
"ExcelExportAction_exportToXLSX_gatheringContainerData=Fetching Container & Image Data",
|
||||
"ExcelExportAction_exportToXLSX_gatheringTimelineData=Fetching Timeline Data",
|
||||
"ExcelExportAction_exportToXLSX_gatheringFileData=Fetching File and MIME Type Data",
|
||||
"ExcelExportAction_exportToXLSX_writingToFile=Writing to File...",})
|
||||
|
||||
void exportToXLSX(ReportProgressPanel progressPanel, DataSource dataSource, String baseReportDir)
|
||||
@ -127,7 +128,15 @@ class ExcelExportAction {
|
||||
exports = ExportTimeline.getExports(dataSource);
|
||||
if (exports != null) {
|
||||
sheetExports.addAll(exports);
|
||||
}
|
||||
}
|
||||
|
||||
// Export file and MIME type data
|
||||
progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_gatheringFileData());
|
||||
progressPanel.setProgress(4);
|
||||
exports = ExportTypes.getExports(dataSource);
|
||||
if (exports != null) {
|
||||
sheetExports.addAll(exports);
|
||||
}
|
||||
|
||||
progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_writingToFile());
|
||||
progressPanel.setProgress(9);
|
||||
|
@ -0,0 +1,312 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2019-2021 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.report.modules.datasourcesummaryexport;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.contentutils.ContainerSummary;
|
||||
import org.sleuthkit.autopsy.coreutils.FileTypeUtils.FileTypeCategory;
|
||||
import org.sleuthkit.autopsy.contentutils.DataSourceInfoUtilities;
|
||||
import org.sleuthkit.autopsy.contentutils.TypesSummary;
|
||||
import org.sleuthkit.autopsy.contentutils.TypesSummary.FileTypeCategoryData;
|
||||
import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelSpecialFormatExport.KeyValueItemExportable;
|
||||
import org.sleuthkit.datamodel.DataSource;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* Panel for displaying summary information on the known files present in the
|
||||
* specified DataSource.
|
||||
*/
|
||||
@Messages({
|
||||
"ExportTypes_artifactsTypesPieChart_title=Artifact Types",
|
||||
"ExportTypes_filesByCategoryTable_allocatedRow_title=Allocated Files",
|
||||
"ExportTypes_filesByCategoryTable_unallocatedRow_title=Unallocated Files",
|
||||
"ExportTypes_filesByCategoryTable_slackRow_title=Slack Files",
|
||||
"ExportTypes_filesByCategoryTable_directoryRow_title=Directories",
|
||||
"ExportTypes_fileMimeTypesChart_title=File Types",
|
||||
"ExportTypes_fileMimeTypesChart_valueLabel=Count",
|
||||
"ExportTypes_fileMimeTypesChart_audio_title=Audio",
|
||||
"ExportTypes_fileMimeTypesChart_documents_title=Documents",
|
||||
"ExportTypes_fileMimeTypesChart_executables_title=Executables",
|
||||
"ExportTypes_fileMimeTypesChart_images_title=Images",
|
||||
"ExportTypes_fileMimeTypesChart_videos_title=Videos",
|
||||
"ExportTypes_fileMimeTypesChart_other_title=Other",
|
||||
"ExportTypes_fileMimeTypesChart_unknown_title=Unknown",
|
||||
"ExportTypes_fileMimeTypesChart_notAnalyzed_title=Not Analyzed",
|
||||
"ExportTypes_usageLabel_title=Usage",
|
||||
"ExportTypes_osLabel_title=OS",
|
||||
"ExportTypes_sizeLabel_title=Size",
|
||||
"ExportTypes_excelTabName=Types"})
|
||||
class ExportTypes {
|
||||
|
||||
/**
|
||||
* Data for types pie chart.
|
||||
*/
|
||||
private static class TypesPieChartData {
|
||||
|
||||
private final List<PieChartItem> pieSlices;
|
||||
private final boolean usefulContent;
|
||||
|
||||
/**
|
||||
* Main constructor.
|
||||
*
|
||||
* @param pieSlices The pie slices.
|
||||
* @param usefulContent True if this is useful content; false if there
|
||||
* is 0 mime type information.
|
||||
*/
|
||||
TypesPieChartData(List<PieChartItem> pieSlices, boolean usefulContent) {
|
||||
this.pieSlices = pieSlices;
|
||||
this.usefulContent = usefulContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The pie chart data.
|
||||
*/
|
||||
List<PieChartItem> getPieSlices() {
|
||||
return pieSlices;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether or not the data is usefulContent.
|
||||
*/
|
||||
boolean isUsefulContent() {
|
||||
return usefulContent;
|
||||
}
|
||||
}
|
||||
|
||||
private static final Color IMAGES_COLOR = new Color(156, 39, 176);
|
||||
private static final Color VIDEOS_COLOR = Color.YELLOW;
|
||||
private static final Color AUDIO_COLOR = Color.BLUE;
|
||||
private static final Color DOCUMENTS_COLOR = Color.GREEN;
|
||||
private static final Color EXECUTABLES_COLOR = new Color(0, 188, 212);
|
||||
private static final Color UNKNOWN_COLOR = Color.ORANGE;
|
||||
private static final Color OTHER_COLOR = new Color(78, 52, 46);
|
||||
private static final Color NOT_ANALYZED_COLOR = Color.WHITE;
|
||||
|
||||
// All file type categories.
|
||||
private static final List<FileTypeCategoryData> FILE_MIME_TYPE_CATEGORIES = Arrays.asList(
|
||||
new FileTypeCategoryData(Bundle.ExportTypes_fileMimeTypesChart_images_title(), FileTypeCategory.IMAGE.getMediaTypes(), IMAGES_COLOR),
|
||||
new FileTypeCategoryData(Bundle.ExportTypes_fileMimeTypesChart_videos_title(), FileTypeCategory.VIDEO.getMediaTypes(), VIDEOS_COLOR),
|
||||
new FileTypeCategoryData(Bundle.ExportTypes_fileMimeTypesChart_audio_title(), FileTypeCategory.AUDIO.getMediaTypes(), AUDIO_COLOR),
|
||||
new FileTypeCategoryData(Bundle.ExportTypes_fileMimeTypesChart_documents_title(), FileTypeCategory.DOCUMENTS.getMediaTypes(), DOCUMENTS_COLOR),
|
||||
new FileTypeCategoryData(Bundle.ExportTypes_fileMimeTypesChart_executables_title(), FileTypeCategory.EXECUTABLE.getMediaTypes(), EXECUTABLES_COLOR),
|
||||
new FileTypeCategoryData(Bundle.ExportTypes_fileMimeTypesChart_unknown_title(), new HashSet<>(Arrays.asList("application/octet-stream")), UNKNOWN_COLOR)
|
||||
);
|
||||
|
||||
private ExportTypes() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* @throws NoCurrentCaseException
|
||||
* @throws TskCoreException
|
||||
* @throws SQLException
|
||||
*/
|
||||
private static Long getCountOfFilesForMimeTypes(DataSource currentDataSource, Set<String> setOfMimeTypes) throws TskCoreException, SQLException, NoCurrentCaseException {
|
||||
return DataSourceInfoUtilities.getCountOfRegNonSlackFiles(currentDataSource, "mime_type IN " + getSqlSet(setOfMimeTypes));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @throws NoCurrentCaseException
|
||||
* @throws TskCoreException
|
||||
* @throws SQLException
|
||||
*/
|
||||
private static Long getCountOfFilesWithNoMimeType(DataSource currentDataSource) throws TskCoreException, SQLException, NoCurrentCaseException {
|
||||
return DataSourceInfoUtilities.getCountOfRegNonSlackFiles(currentDataSource, "(mime_type IS NULL OR mime_type = '') ");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all the data for the file type pie chart.
|
||||
*
|
||||
* @param mimeTypeData The means of acquiring data.
|
||||
* @param dataSource The datasource.
|
||||
*
|
||||
* @return The pie chart items.
|
||||
*/
|
||||
private static TypesPieChartData getMimeTypeCategoriesModel(DataSource dataSource)
|
||||
throws SQLException, TskCoreException, NoCurrentCaseException {
|
||||
|
||||
if (dataSource == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// for each category of file types, get the counts of files
|
||||
List<PieChartItem> fileCategoryItems = new ArrayList<>();
|
||||
long categoryTotalCount = 0;
|
||||
|
||||
for (FileTypeCategoryData cat : FILE_MIME_TYPE_CATEGORIES) {
|
||||
long thisValue = DataSourceInfoUtilities.getLongOrZero(getCountOfFilesForMimeTypes(dataSource, cat.getMimeTypes()));
|
||||
categoryTotalCount += thisValue;
|
||||
|
||||
fileCategoryItems.add(new PieChartItem(
|
||||
cat.getLabel(),
|
||||
thisValue,
|
||||
cat.getColor()));
|
||||
}
|
||||
|
||||
// get a count of all files with no mime type
|
||||
long noMimeTypeCount = DataSourceInfoUtilities.getLongOrZero(getCountOfFilesWithNoMimeType(dataSource));
|
||||
|
||||
// get a count of all regular files
|
||||
long allRegularFiles = DataSourceInfoUtilities.getLongOrZero(DataSourceInfoUtilities.getCountOfRegNonSlackFiles(dataSource, null));
|
||||
|
||||
// create entry for mime types in other category
|
||||
long otherCount = allRegularFiles - (categoryTotalCount + noMimeTypeCount);
|
||||
PieChartItem otherPieItem = new PieChartItem(Bundle.ExportTypes_fileMimeTypesChart_other_title(),
|
||||
otherCount, OTHER_COLOR);
|
||||
|
||||
// check at this point to see if these are all 0; if so, we don't have useful content.
|
||||
boolean usefulContent = categoryTotalCount > 0 || otherCount > 0;
|
||||
|
||||
// create entry for not analyzed mime types category
|
||||
PieChartItem notAnalyzedItem = new PieChartItem(Bundle.ExportTypes_fileMimeTypesChart_notAnalyzed_title(),
|
||||
noMimeTypeCount, NOT_ANALYZED_COLOR);
|
||||
|
||||
// combine categories with 'other' and 'not analyzed'
|
||||
List<PieChartItem> items = Stream.concat(
|
||||
fileCategoryItems.stream(),
|
||||
Stream.of(otherPieItem, notAnalyzedItem))
|
||||
// remove items that have no value
|
||||
.filter(slice -> slice.getValue() > 0)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return new TypesPieChartData(items, usefulContent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a key value pair to be exported in a sheet.
|
||||
*
|
||||
* @param fetcher The means of fetching the data.
|
||||
* @param key The key to use.
|
||||
* @param dataSource The data source containing the data.
|
||||
*
|
||||
* @return The key value pair to be exported.
|
||||
*/
|
||||
private static KeyValueItemExportable getStrExportable(DataFetcher<DataSource, String> fetcher, String key, DataSource dataSource) {
|
||||
String result = ExcelExportAction.getFetchResult(fetcher, "Types", dataSource);
|
||||
return (result == null) ? null : new KeyValueItemExportable(key, new DefaultCellModel<>(result));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a key value pair to be exported in a sheet formatting the long
|
||||
* with commas separated by orders of 1000.
|
||||
*
|
||||
* @param fetcher The means of fetching the data.
|
||||
* @param key The string key for this key value pair.
|
||||
* @param dataSource The data source.
|
||||
*
|
||||
* @return The key value pair.
|
||||
*/
|
||||
private static KeyValueItemExportable getCountExportable(DataFetcher<DataSource, Long> fetcher, String key, DataSource dataSource) {
|
||||
Long count = ExcelExportAction.getFetchResult(fetcher, "Types", dataSource);
|
||||
return (count == null) ? null : new KeyValueItemExportable(key,
|
||||
new DefaultCellModel<Long>(count, DataSourceInfoUtilities.COMMA_FORMATTER::format, DataSourceInfoUtilities.COMMA_FORMAT_STR));
|
||||
}
|
||||
|
||||
static List<ExcelExport.ExcelSheetExport> getExports(DataSource dataSource) {
|
||||
if (dataSource == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
DataFetcher<DataSource, String> usageFetcher = (ds) -> ContainerSummary.getDataSourceType(ds);
|
||||
DataFetcher<DataSource, String> osFetcher = (ds) -> ContainerSummary.getOperatingSystems(ds);
|
||||
DataFetcher<DataSource, Long> sizeFetcher = (ds) -> ds == null ? null : ds.getSize();
|
||||
|
||||
DataFetcher<DataSource, TypesPieChartData> typesFetcher = (ds) -> getMimeTypeCategoriesModel(ds);
|
||||
|
||||
DataFetcher<DataSource, Long> allocatedFetcher = (ds) -> TypesSummary.getCountOfAllocatedFiles(ds);
|
||||
DataFetcher<DataSource, Long> unallocatedFetcher = (ds) -> TypesSummary.getCountOfUnallocatedFiles(ds);
|
||||
DataFetcher<DataSource, Long> slackFetcher = (ds) -> TypesSummary.getCountOfSlackFiles(ds);
|
||||
DataFetcher<DataSource, Long> directoriesFetcher = (ds) -> TypesSummary.getCountOfDirectories(ds);
|
||||
|
||||
// Retrieve data to create the types pie chart
|
||||
TypesPieChartData typesData = ExcelExportAction.getFetchResult(typesFetcher, "Types", dataSource);
|
||||
PieChartExport typesChart = (typesData == null || !typesData.isUsefulContent()) ? null
|
||||
: new PieChartExport(
|
||||
Bundle.ExportTypes_fileMimeTypesChart_title(),
|
||||
Bundle.ExportTypes_fileMimeTypesChart_valueLabel(),
|
||||
"#,###",
|
||||
Bundle.ExportTypes_fileMimeTypesChart_title(),
|
||||
typesData.getPieSlices());
|
||||
|
||||
return Arrays.asList(new ExcelSpecialFormatExport(Bundle.ExportTypes_excelTabName(),
|
||||
Stream.of(
|
||||
getStrExportable(usageFetcher, Bundle.ExportTypes_usageLabel_title(), dataSource),
|
||||
getStrExportable(osFetcher, Bundle.ExportTypes_osLabel_title(), dataSource),
|
||||
new KeyValueItemExportable(Bundle.ExportTypes_sizeLabel_title(),
|
||||
SizeRepresentationUtil.getBytesCell(ExcelExportAction.getFetchResult(sizeFetcher, "Types", dataSource))),
|
||||
typesChart,
|
||||
getCountExportable(allocatedFetcher, Bundle.ExportTypes_filesByCategoryTable_allocatedRow_title(), dataSource),
|
||||
getCountExportable(unallocatedFetcher, Bundle.ExportTypes_filesByCategoryTable_unallocatedRow_title(), dataSource),
|
||||
getCountExportable(slackFetcher, Bundle.ExportTypes_filesByCategoryTable_slackRow_title(), dataSource),
|
||||
getCountExportable(directoriesFetcher, Bundle.ExportTypes_filesByCategoryTable_directoryRow_title(), dataSource))
|
||||
.filter(sheet -> sheet != null)
|
||||
.collect(Collectors.toList())
|
||||
));
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user