From 22041a8ca6a79c48fb4ee626def3182e989d4bf8 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Wed, 4 Aug 2021 15:43:49 -0400 Subject: [PATCH 01/33] Moved RecentFilesSummary into contentutils package --- .../DataSourceInfoUtilities.java | 32 ++--- .../RecentFilesSummary.java | 63 ++++------ .../datamodel/AnalysisSummary.java | 1 + .../datamodel/ContainerSummary.java | 1 + .../datamodel/MimeTypeSummary.java | 1 + .../datamodel/PastCasesSummary.java | 1 + .../datamodel/RecentFilesGetter.java | 113 ++++++++++++++++++ .../datamodel/TypesSummary.java | 1 + .../datamodel/UserActivitySummary.java | 3 +- .../ui/RecentFilesPanel.java | 14 +-- .../DataSourceInfoUtilitiesTest.java | 3 +- .../datamodel/RecentFilesSummaryTest.java | 40 +++---- 12 files changed, 188 insertions(+), 85 deletions(-) rename Core/src/org/sleuthkit/autopsy/{datasourcesummary/datamodel => contentutils}/DataSourceInfoUtilities.java (90%) rename Core/src/org/sleuthkit/autopsy/{datasourcesummary/datamodel => contentutils}/RecentFilesSummary.java (85%) create mode 100755 Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesGetter.java diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceInfoUtilities.java b/Core/src/org/sleuthkit/autopsy/contentutils/DataSourceInfoUtilities.java similarity index 90% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceInfoUtilities.java rename to Core/src/org/sleuthkit/autopsy/contentutils/DataSourceInfoUtilities.java index c711f3c9a0..8fef1c54f0 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceInfoUtilities.java +++ b/Core/src/org/sleuthkit/autopsy/contentutils/DataSourceInfoUtilities.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019 - 2020 Basis Technology Corp. + * Copyright 2019 - 2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datasourcesummary.datamodel; +package org.sleuthkit.autopsy.contentutils; import java.sql.ResultSet; import java.sql.SQLException; @@ -41,7 +41,7 @@ import org.sleuthkit.datamodel.TskData.TSK_FS_META_TYPE_ENUM; * Utilities for getting information about a data source or all data sources * from the case database. */ -final class DataSourceInfoUtilities { +public final class DataSourceInfoUtilities { /** * Gets a count of tsk_files for a particular datasource. @@ -55,7 +55,7 @@ final class DataSourceInfoUtilities { * @throws TskCoreException * @throws SQLException */ - static Long getCountOfTskFiles(SleuthkitCase skCase, DataSource currentDataSource, String additionalWhere) + public static Long getCountOfTskFiles(SleuthkitCase skCase, DataSource currentDataSource, String additionalWhere) throws TskCoreException, SQLException { if (currentDataSource != null) { return skCase.countFilesWhere( @@ -77,7 +77,7 @@ final class DataSourceInfoUtilities { * @throws TskCoreException * @throws SQLException */ - static Long getCountOfRegularFiles(SleuthkitCase skCase, DataSource currentDataSource, String additionalWhere) + public static Long getCountOfRegularFiles(SleuthkitCase skCase, DataSource currentDataSource, String additionalWhere) throws TskCoreException, SQLException { String whereClause = "meta_type=" + TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG.getValue(); @@ -100,7 +100,7 @@ final class DataSourceInfoUtilities { * @throws TskCoreException * @throws SQLException */ - static Long getCountOfRegNonSlackFiles(SleuthkitCase skCase, DataSource currentDataSource, String additionalWhere) + public static Long getCountOfRegNonSlackFiles(SleuthkitCase skCase, DataSource currentDataSource, String additionalWhere) throws TskCoreException, SQLException { String whereClause = "meta_type=" + TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG.getValue() + " AND type<>" + TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType(); @@ -115,7 +115,7 @@ final class DataSourceInfoUtilities { /** * An interface for handling a result set and returning a value. */ - interface ResultSetHandler { + public interface ResultSetHandler { T process(ResultSet resultset) throws SQLException; } @@ -133,7 +133,7 @@ final class DataSourceInfoUtilities { * @throws TskCoreException * @throws SQLException */ - static T getBaseQueryResult(SleuthkitCase skCase, String query, ResultSetHandler processor) + public static T getBaseQueryResult(SleuthkitCase skCase, String query, ResultSetHandler processor) throws TskCoreException, SQLException { try (SleuthkitCase.CaseDbQuery dbQuery = skCase.executeQuery(query)) { ResultSet resultSet = dbQuery.getResultSet(); @@ -149,14 +149,14 @@ final class DataSourceInfoUtilities { * * @return The clause. */ - static String getMetaFlagsContainsStatement(TSK_FS_META_FLAG_ENUM flag) { + public static String getMetaFlagsContainsStatement(TSK_FS_META_FLAG_ENUM flag) { return "meta_flags & " + flag.getValue() + " > 0"; } /** * Enum for specifying the sort order for getAttributes. */ - enum SortOrder { + public enum SortOrder { DESCENDING, ASCENDING } @@ -181,7 +181,7 @@ final class DataSourceInfoUtilities { * * @throws TskCoreException */ - static List getArtifacts(SleuthkitCase skCase, BlackboardArtifact.Type artifactType, DataSource dataSource, BlackboardAttribute.Type attributeType, SortOrder sortOrder) throws TskCoreException { + public static List getArtifacts(SleuthkitCase skCase, BlackboardArtifact.Type artifactType, DataSource dataSource, BlackboardAttribute.Type attributeType, SortOrder sortOrder) throws TskCoreException { return getArtifacts(skCase, artifactType, dataSource, attributeType, sortOrder, 0); } @@ -207,7 +207,7 @@ final class DataSourceInfoUtilities { * * @throws TskCoreException */ - static List getArtifacts(SleuthkitCase skCase, BlackboardArtifact.Type artifactType, DataSource dataSource, BlackboardAttribute.Type attributeType, SortOrder sortOrder, int maxCount) throws TskCoreException { + public static List getArtifacts(SleuthkitCase skCase, BlackboardArtifact.Type artifactType, DataSource dataSource, BlackboardAttribute.Type attributeType, SortOrder sortOrder, int maxCount) throws TskCoreException { if (maxCount < 0) { throw new IllegalArgumentException("Invalid maxCount passed to getArtifacts, value must be equal to or greater than 0"); } @@ -380,7 +380,7 @@ final class DataSourceInfoUtilities { * @return The 'getValueString()' value or null if the attribute or String * could not be retrieved. */ - static String getStringOrNull(BlackboardArtifact artifact, Type attributeType) { + public static String getStringOrNull(BlackboardArtifact artifact, Type attributeType) { BlackboardAttribute attr = getAttributeOrNull(artifact, attributeType); return (attr == null) ? null : attr.getValueString(); } @@ -394,7 +394,7 @@ final class DataSourceInfoUtilities { * @return The 'getValueLong()' value or null if the attribute could not be * retrieved. */ - static Long getLongOrNull(BlackboardArtifact artifact, Type attributeType) { + public static Long getLongOrNull(BlackboardArtifact artifact, Type attributeType) { BlackboardAttribute attr = getAttributeOrNull(artifact, attributeType); return (attr == null) ? null : attr.getValueLong(); } @@ -408,7 +408,7 @@ final class DataSourceInfoUtilities { * @return The 'getValueInt()' value or null if the attribute could not be * retrieved. */ - static Integer getIntOrNull(BlackboardArtifact artifact, Type attributeType) { + public static Integer getIntOrNull(BlackboardArtifact artifact, Type attributeType) { BlackboardAttribute attr = getAttributeOrNull(artifact, attributeType); return (attr == null) ? null : attr.getValueInt(); } @@ -423,7 +423,7 @@ final class DataSourceInfoUtilities { * @return The date determined from the 'getValueLong()' as seconds from * epoch or null if the attribute could not be retrieved or is 0. */ - static Date getDateOrNull(BlackboardArtifact artifact, Type attributeType) { + public static Date getDateOrNull(BlackboardArtifact artifact, Type attributeType) { Long longVal = getLongOrNull(artifact, attributeType); return (longVal == null || longVal == 0) ? null : new Date(longVal * 1000); } diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesSummary.java b/Core/src/org/sleuthkit/autopsy/contentutils/RecentFilesSummary.java similarity index 85% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesSummary.java rename to Core/src/org/sleuthkit/autopsy/contentutils/RecentFilesSummary.java index 4f1a34fa73..62b80516cd 100755 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesSummary.java +++ b/Core/src/org/sleuthkit/autopsy/contentutils/RecentFilesSummary.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2020 Basis Technology Corp. + * Copyright 2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,9 +16,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datasourcesummary.datamodel; +package org.sleuthkit.autopsy.contentutils; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultArtifactUpdateGovernor; import java.nio.file.Paths; import java.text.DateFormat; import java.text.SimpleDateFormat; @@ -33,6 +32,8 @@ 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; +import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; @@ -40,13 +41,12 @@ import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; /** - * Helper class for getting data for the Recent Files Data Summary tab. + * Helper class for getting Recent Activity data. */ -public class RecentFilesSummary implements DefaultArtifactUpdateGovernor { +public class RecentFilesSummary { private final static BlackboardAttribute.Type DATETIME_ACCESSED_ATT = new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED); private final static BlackboardAttribute.Type DOMAIN_ATT = new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN); @@ -66,30 +66,13 @@ public class RecentFilesSummary implements DefaultArtifactUpdateGovernor { ARTIFACT_TYPE.TSK_MESSAGE.getTypeID() )); - private final SleuthkitCaseProvider provider; - /** * Default constructor. */ - public RecentFilesSummary() { - this(SleuthkitCaseProvider.DEFAULT); + private RecentFilesSummary() { } - /** - * Construct object with given SleuthkitCaseProvider - * - * @param provider SleuthkitCaseProvider provider, cannot be null. - */ - public RecentFilesSummary(SleuthkitCaseProvider provider) { - if (provider == null) { - throw new IllegalArgumentException("Unable to construct RecentFileSummary object. SleuthkitCaseProvider cannot be null"); - } - - this.provider = provider; - } - - @Override - public Set getArtifactTypeIdsForRefresh() { + public static Set getArtifactTypeIdsForRefresh() { return ARTIFACT_UPDATE_TYPE_IDS; } @@ -101,7 +84,7 @@ public class RecentFilesSummary implements DefaultArtifactUpdateGovernor { * @param limit The maximum number of entries to return. * @return The sorted limited list with unique paths. */ - private List getSortedLimited(List fileDetails, int limit) { + private static List getSortedLimited(List fileDetails, int limit) { Map fileDetailsMap = fileDetails.stream() .filter(details -> details != null) .collect(Collectors.toMap( @@ -122,7 +105,7 @@ public class RecentFilesSummary implements DefaultArtifactUpdateGovernor { * @param artifact The artifact. * @return The derived object or null if artifact is invalid. */ - private RecentFileDetails getRecentlyOpenedDocument(BlackboardArtifact artifact) { + private static RecentFileDetails getRecentlyOpenedDocument(BlackboardArtifact artifact) { String path = DataSourceInfoUtilities.getStringOrNull(artifact, PATH_ATT); Long lastOpened = DataSourceInfoUtilities.getLongOrNull(artifact, DATETIME_ACCESSED_ATT); @@ -144,17 +127,17 @@ public class RecentFilesSummary implements DefaultArtifactUpdateGovernor { * @return A list RecentFileDetails representing the most recently opened * documents or an empty list if none were found. * - * @throws SleuthkitCaseProviderException + * @throws NoCurrentCaseException * @throws TskCoreException */ - public List getRecentlyOpenedDocuments(DataSource dataSource, int maxCount) throws SleuthkitCaseProviderException, TskCoreException { + public static List getRecentlyOpenedDocuments(DataSource dataSource, int maxCount) throws TskCoreException, NoCurrentCaseException { if (dataSource == null) { return Collections.emptyList(); } throwOnNonPositiveCount(maxCount); - List details = provider.get().getBlackboard() + List details = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboard() .getArtifacts(ARTIFACT_TYPE.TSK_RECENT_OBJECT.getTypeID(), dataSource.getId()).stream() .map(art -> getRecentlyOpenedDocument(art)) .filter(d -> d != null) @@ -170,7 +153,7 @@ public class RecentFilesSummary implements DefaultArtifactUpdateGovernor { * @param artifact The artifact. * @return The derived object or null if artifact is invalid. */ - private RecentDownloadDetails getRecentDownload(BlackboardArtifact artifact) { + private static RecentDownloadDetails getRecentDownload(BlackboardArtifact artifact) { Long accessedTime = DataSourceInfoUtilities.getLongOrNull(artifact, DATETIME_ACCESSED_ATT); String domain = DataSourceInfoUtilities.getStringOrNull(artifact, DOMAIN_ATT); String path = DataSourceInfoUtilities.getStringOrNull(artifact, PATH_ATT); @@ -187,7 +170,7 @@ public class RecentFilesSummary implements DefaultArtifactUpdateGovernor { * * @param count The count. */ - private void throwOnNonPositiveCount(int count) { + private static void throwOnNonPositiveCount(int count) { if (count < 1) { throw new IllegalArgumentException("Invalid count: value must be greater than 0."); } @@ -205,16 +188,16 @@ public class RecentFilesSummary implements DefaultArtifactUpdateGovernor { * found. * * @throws TskCoreException - * @throws SleuthkitCaseProviderException + * @throws NoCurrentCaseException */ - public List getRecentDownloads(DataSource dataSource, int maxCount) throws TskCoreException, SleuthkitCaseProviderException { + public static List getRecentDownloads(DataSource dataSource, int maxCount) throws TskCoreException, NoCurrentCaseException { if (dataSource == null) { return Collections.emptyList(); } throwOnNonPositiveCount(maxCount); - List details = provider.get().getBlackboard() + List details = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboard() .getArtifacts(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID(), dataSource.getId()).stream() .map(art -> getRecentDownload(art)) .filter(d -> d != null) @@ -232,17 +215,17 @@ public class RecentFilesSummary implements DefaultArtifactUpdateGovernor { * * @return A list of RecentFileDetails of the most recent attachments. * - * @throws SleuthkitCaseProviderException + * @throws NoCurrentCaseException * @throws TskCoreException */ - public List getRecentAttachments(DataSource dataSource, int maxCount) throws SleuthkitCaseProviderException, TskCoreException { + public static List getRecentAttachments(DataSource dataSource, int maxCount) throws NoCurrentCaseException, TskCoreException { if (dataSource == null) { return Collections.emptyList(); } throwOnNonPositiveCount(maxCount); - SleuthkitCase skCase = provider.get(); + SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase(); List associatedArtifacts = skCase.getBlackboard() .getArtifacts(ASSOCATED_OBJ_ART.getTypeID(), dataSource.getId()); @@ -268,7 +251,7 @@ public class RecentFilesSummary implements DefaultArtifactUpdateGovernor { * @return The derived object or null. * @throws TskCoreException */ - private RecentAttachmentDetails getRecentAttachment(BlackboardArtifact artifact, SleuthkitCase skCase) throws TskCoreException { + private static RecentAttachmentDetails getRecentAttachment(BlackboardArtifact artifact, SleuthkitCase skCase) throws TskCoreException { // get associated artifact or return no result BlackboardAttribute attribute = artifact.getAttribute(ASSOCATED_ATT); if (attribute == null) { @@ -309,7 +292,7 @@ public class RecentFilesSummary implements DefaultArtifactUpdateGovernor { * * @return True if the given artifact is a message artifact */ - private boolean isMessageArtifact(BlackboardArtifact nodeArtifact) { + private static boolean isMessageArtifact(BlackboardArtifact nodeArtifact) { final int artifactTypeID = nodeArtifact.getArtifactTypeID(); return artifactTypeID == ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID() || artifactTypeID == ARTIFACT_TYPE.TSK_MESSAGE.getTypeID(); diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/AnalysisSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/AnalysisSummary.java index 5fff3eac6c..db9bc067c2 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/AnalysisSummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/AnalysisSummary.java @@ -30,6 +30,7 @@ import java.util.function.Function; import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; +import org.sleuthkit.autopsy.contentutils.DataSourceInfoUtilities; import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummary.java index 8129911500..eb11b99b2a 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummary.java @@ -24,6 +24,7 @@ import java.util.Arrays; import java.util.HashSet; import java.util.Set; import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.autopsy.contentutils.DataSourceInfoUtilities; import org.sleuthkit.autopsy.ingest.ModuleContentEvent; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/MimeTypeSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/MimeTypeSummary.java index e753a44a76..1b8ac3fc1c 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/MimeTypeSummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/MimeTypeSummary.java @@ -26,6 +26,7 @@ import java.util.List; import java.util.Set; import java.util.stream.Collectors; import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.autopsy.contentutils.DataSourceInfoUtilities; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.ModuleContentEvent; import org.sleuthkit.datamodel.AbstractFile; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/PastCasesSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/PastCasesSummary.java index ea6c089fca..e7776fbf62 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/PastCasesSummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/PastCasesSummary.java @@ -32,6 +32,7 @@ import org.apache.commons.lang3.tuple.Pair; import org.sleuthkit.autopsy.centralrepository.ingestmodule.CentralRepoIngestModuleFactory; import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultArtifactUpdateGovernor; +import org.sleuthkit.autopsy.contentutils.DataSourceInfoUtilities; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import org.sleuthkit.datamodel.BlackboardAttribute; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesGetter.java new file mode 100755 index 0000000000..446659ebef --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesGetter.java @@ -0,0 +1,113 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2020-2021 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.datasourcesummary.datamodel; + +import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultArtifactUpdateGovernor; +import java.util.List; +import java.util.Set; +import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.autopsy.contentutils.RecentFilesSummary; +import org.sleuthkit.autopsy.contentutils.RecentFilesSummary.RecentAttachmentDetails; +import org.sleuthkit.autopsy.contentutils.RecentFilesSummary.RecentDownloadDetails; +import org.sleuthkit.autopsy.contentutils.RecentFilesSummary.RecentFileDetails; +import org.sleuthkit.datamodel.DataSource; +import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; + +/** + * Wrapper class for converting org.sleuthkit.autopsy.contentutils.RecentFilesSummary functionality into + * a DefaultArtifactUpdateGovernor used by Recent Files Data Summary tab. + */ +public class RecentFilesGetter implements DefaultArtifactUpdateGovernor { + + /** + * Default constructor. + */ + public RecentFilesGetter() { + } + + @Override + public Set getArtifactTypeIdsForRefresh() { + return RecentFilesSummary.getArtifactTypeIdsForRefresh(); + } + + /** + * Return a list of the most recently opened documents based on the + * TSK_RECENT_OBJECT artifact. + * + * @param dataSource The data source to query. + * @param maxCount The maximum number of results to return, pass 0 to get a + * list of all results. + * + * @return A list RecentFileDetails representing the most recently opened + * documents or an empty list if none were found. + * + * @throws SleuthkitCaseProviderException + * @throws TskCoreException + */ + public List getRecentlyOpenedDocuments(DataSource dataSource, int maxCount) throws SleuthkitCaseProviderException, TskCoreException { + try { + return RecentFilesSummary.getRecentlyOpenedDocuments(dataSource, maxCount); + } catch (NoCurrentCaseException ex) { + throw new SleuthkitCaseProviderException("No currently open case.", ex); + } + } + + /** + * Return a list of the most recent downloads based on the value of the the + * artifact TSK_DATETIME_ACCESSED attribute. + * + * @param dataSource Data source to query. + * @param maxCount Maximum number of results to return, passing 0 will + * return all results. + * + * @return A list of RecentFileDetails objects or empty list if none were + * found. + * + * @throws TskCoreException + * @throws SleuthkitCaseProviderException + */ + public List getRecentDownloads(DataSource dataSource, int maxCount) throws TskCoreException, SleuthkitCaseProviderException { + try { + return RecentFilesSummary.getRecentDownloads(dataSource, maxCount); + } catch (NoCurrentCaseException ex) { + throw new SleuthkitCaseProviderException("No currently open case.", ex); + } + } + + /** + * Returns a list of the most recent message attachments. + * + * @param dataSource Data source to query. + * @param maxCount Maximum number of results to return, passing 0 will + * return all results. + * + * @return A list of RecentFileDetails of the most recent attachments. + * + * @throws SleuthkitCaseProviderException + * @throws TskCoreException + */ + public List getRecentAttachments(DataSource dataSource, int maxCount) throws SleuthkitCaseProviderException, TskCoreException { + try { + return RecentFilesSummary.getRecentAttachments(dataSource, maxCount); + } catch (NoCurrentCaseException ex) { + throw new SleuthkitCaseProviderException("No currently open case.", ex); + } + } +} diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TypesSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TypesSummary.java index ff4bcae0a0..3b21654c14 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TypesSummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TypesSummary.java @@ -23,6 +23,7 @@ import java.sql.SQLException; import java.util.Arrays; import java.util.HashSet; import java.util.Set; +import org.sleuthkit.autopsy.contentutils.DataSourceInfoUtilities; import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.ModuleContentEvent; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummary.java index 10f700d51f..5151617775 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummary.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2020 Basis Technology Corp. + * Copyright 2020-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -39,6 +39,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.autopsy.contentutils.DataSourceInfoUtilities; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.DataSource; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesPanel.java index f89651072c..44d916992f 100755 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2020 Basis Technology Corp. + * Copyright 2020-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -30,10 +30,10 @@ import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.RecentFilesSummary; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.RecentFilesSummary.RecentAttachmentDetails; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.RecentFilesSummary.RecentDownloadDetails; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.RecentFilesSummary.RecentFileDetails; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.RecentFilesGetter; +import org.sleuthkit.autopsy.contentutils.RecentFilesSummary.RecentAttachmentDetails; +import org.sleuthkit.autopsy.contentutils.RecentFilesSummary.RecentDownloadDetails; +import org.sleuthkit.autopsy.contentutils.RecentFilesSummary.RecentFileDetails; import static org.sleuthkit.autopsy.datasourcesummary.ui.BaseDataSourceSummaryPanel.getTableExport; import org.sleuthkit.autopsy.datasourcesummary.uiutils.CellModelTableCellRenderer; import org.sleuthkit.autopsy.datasourcesummary.uiutils.ColumnModel; @@ -120,13 +120,13 @@ public final class RecentFilesPanel extends BaseDataSourceSummaryPanel { "RecentFilePanel_emailParserModuleName=Email Parser" }) public RecentFilesPanel() { - this(new RecentFilesSummary()); + this(new RecentFilesGetter()); } /** * Creates new form RecentFilesPanel */ - public RecentFilesPanel(RecentFilesSummary dataHandler) { + public RecentFilesPanel(RecentFilesGetter dataHandler) { super(dataHandler); docsFetcher = (dataSource) -> dataHandler.getRecentlyOpenedDocuments(dataSource, 10); downloadsFetcher = (dataSource) -> dataHandler.getRecentDownloads(dataSource, 10); diff --git a/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceInfoUtilitiesTest.java b/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceInfoUtilitiesTest.java index 1b5d809b1f..5179b4a509 100644 --- a/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceInfoUtilitiesTest.java +++ b/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceInfoUtilitiesTest.java @@ -27,7 +27,7 @@ import org.junit.Assert; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceInfoUtilities.SortOrder; +import org.sleuthkit.autopsy.contentutils.DataSourceInfoUtilities.SortOrder; import org.sleuthkit.datamodel.Blackboard; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; @@ -36,6 +36,7 @@ import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.autopsy.testutils.TskMockUtils; import static org.mockito.Mockito.*; +import org.sleuthkit.autopsy.contentutils.DataSourceInfoUtilities; import org.sleuthkit.autopsy.testutils.RandomizationUtils; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; diff --git a/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesSummaryTest.java b/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesSummaryTest.java index 0acda3954a..302223a234 100644 --- a/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesSummaryTest.java +++ b/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesSummaryTest.java @@ -40,9 +40,9 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.RecentFilesSummary.RecentAttachmentDetails; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.RecentFilesSummary.RecentDownloadDetails; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.RecentFilesSummary.RecentFileDetails; +import org.sleuthkit.autopsy.contentutils.RecentFilesSummary.RecentAttachmentDetails; +import org.sleuthkit.autopsy.contentutils.RecentFilesSummary.RecentDownloadDetails; +import org.sleuthkit.autopsy.contentutils.RecentFilesSummary.RecentFileDetails; import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.autopsy.testutils.RandomizationUtils; import org.sleuthkit.autopsy.testutils.TskMockUtils; @@ -62,15 +62,15 @@ import org.sleuthkit.datamodel.TskCoreException; public class RecentFilesSummaryTest { /** - * An interface for calling methods in RecentFilesSummary in a uniform - * manner. + * An interface for calling methods in RecentFilesGetter in a uniform + manner. */ private interface RecentFilesMethod { /** - * Means of acquiring data from a method in RecentFilesSummary. + * Means of acquiring data from a method in RecentFilesGetter. * - * @param recentFilesSummary The RecentFilesSummary object. + * @param recentFilesSummary The RecentFilesGetter object. * @param dataSource The datasource. * @param count The number of items to retrieve. * @@ -79,7 +79,7 @@ public class RecentFilesSummaryTest { * @throws SleuthkitCaseProviderException * @throws TskCoreException */ - List fetch(RecentFilesSummary recentFilesSummary, DataSource dataSource, int count) + List fetch(RecentFilesGetter recentFilesSummary, DataSource dataSource, int count) throws SleuthkitCaseProviderException, TskCoreException; } @@ -105,7 +105,7 @@ public class RecentFilesSummaryTest { throws TskCoreException, SleuthkitCaseProviderException { Pair casePair = DataSourceSummaryMockUtils.getArtifactsTSKMock(null); DataSource dataSource = TskMockUtils.getDataSource(1); - RecentFilesSummary summary = new RecentFilesSummary(() -> casePair.getLeft()); + RecentFilesGetter summary = new RecentFilesGetter(); try { method.fetch(summary, dataSource, -1); @@ -146,7 +146,7 @@ public class RecentFilesSummaryTest { throws SleuthkitCaseProviderException, TskCoreException { Pair casePair = DataSourceSummaryMockUtils.getArtifactsTSKMock(null); - RecentFilesSummary summary = new RecentFilesSummary(() -> casePair.getLeft()); + RecentFilesGetter summary = new RecentFilesGetter(); List items = recentFilesMethod.fetch(summary, null, 10); Assert.assertNotNull("Expected method " + methodName + " to return an empty list.", items); @@ -184,7 +184,7 @@ public class RecentFilesSummaryTest { throws SleuthkitCaseProviderException, TskCoreException { Pair casePair = DataSourceSummaryMockUtils.getArtifactsTSKMock(Collections.emptyList()); - RecentFilesSummary summary = new RecentFilesSummary(() -> casePair.getLeft()); + RecentFilesGetter summary = new RecentFilesGetter(); DataSource dataSource = TskMockUtils.getDataSource(1); List items = recentFilesMethod.fetch(summary, dataSource, 10); Assert.assertNotNull("Expected method " + methodName + " to return an empty list.", items); @@ -278,7 +278,7 @@ public class RecentFilesSummaryTest { // run through method Pair casePair = DataSourceSummaryMockUtils.getArtifactsTSKMock(RandomizationUtils.getMixedUp(artifacts)); - RecentFilesSummary summary = new RecentFilesSummary(() -> casePair.getLeft()); + RecentFilesGetter summary = new RecentFilesGetter(); List results = summary.getRecentlyOpenedDocuments(dataSource, countRequest); // verify results @@ -302,7 +302,7 @@ public class RecentFilesSummaryTest { List artifacts = Arrays.asList(item2, item3, item1); Pair casePair = DataSourceSummaryMockUtils.getArtifactsTSKMock(RandomizationUtils.getMixedUp(artifacts)); - RecentFilesSummary summary = new RecentFilesSummary(() -> casePair.getLeft()); + RecentFilesGetter summary = new RecentFilesGetter(); List results = summary.getRecentlyOpenedDocuments(dataSource, 10); // verify results (only successItem) @@ -322,7 +322,7 @@ public class RecentFilesSummaryTest { List artifacts = Arrays.asList(nullTime, zeroTime, successItem); Pair casePair = DataSourceSummaryMockUtils.getArtifactsTSKMock(RandomizationUtils.getMixedUp(artifacts)); - RecentFilesSummary summary = new RecentFilesSummary(() -> casePair.getLeft()); + RecentFilesGetter summary = new RecentFilesGetter(); List results = summary.getRecentlyOpenedDocuments(dataSource, 10); // verify results (only successItem) @@ -373,7 +373,7 @@ public class RecentFilesSummaryTest { // call method Pair casePair = DataSourceSummaryMockUtils.getArtifactsTSKMock(RandomizationUtils.getMixedUp(artifacts)); - RecentFilesSummary summary = new RecentFilesSummary(() -> casePair.getLeft()); + RecentFilesGetter summary = new RecentFilesGetter(); List results = summary.getRecentDownloads(dataSource, countRequest); // verify results @@ -399,7 +399,7 @@ public class RecentFilesSummaryTest { List artifacts = Arrays.asList(item2, item3, item1); Pair casePair = DataSourceSummaryMockUtils.getArtifactsTSKMock(RandomizationUtils.getMixedUp(artifacts)); - RecentFilesSummary summary = new RecentFilesSummary(() -> casePair.getLeft()); + RecentFilesGetter summary = new RecentFilesGetter(); // call method List results = summary.getRecentDownloads(dataSource, 10); @@ -422,7 +422,7 @@ public class RecentFilesSummaryTest { List artifacts = Arrays.asList(nullTime, zeroTime, successItem); Pair casePair = DataSourceSummaryMockUtils.getArtifactsTSKMock(RandomizationUtils.getMixedUp(artifacts)); - RecentFilesSummary summary = new RecentFilesSummary(() -> casePair.getLeft()); + RecentFilesGetter summary = new RecentFilesGetter(); // call method List results = summary.getRecentDownloads(dataSource, 10); @@ -651,7 +651,7 @@ public class RecentFilesSummaryTest { List mixedUpItems = RandomizationUtils.getMixedUp(items); Pair casePair = getRecentAttachmentArtifactCase(mixedUpItems); - RecentFilesSummary summary = new RecentFilesSummary(() -> casePair.getLeft()); + RecentFilesGetter summary = new RecentFilesGetter(); // retrieve results List results = summary.getRecentAttachments(dataSource, countRequest); @@ -698,7 +698,7 @@ public class RecentFilesSummaryTest { noParentFile, noAssocAttr, missingAssocArt); Pair casePair = getRecentAttachmentArtifactCase(items); - RecentFilesSummary summary = new RecentFilesSummary(() -> casePair.getLeft()); + RecentFilesGetter summary = new RecentFilesGetter(); // get data List results = summary.getRecentAttachments(dataSource, 10); @@ -735,7 +735,7 @@ public class RecentFilesSummaryTest { List items = Arrays.asList(item1, item2, item3); Pair casePair = getRecentAttachmentArtifactCase(items); - RecentFilesSummary summary = new RecentFilesSummary(() -> casePair.getLeft()); + RecentFilesGetter summary = new RecentFilesGetter(); // get data List results = summary.getRecentAttachments(dataSource, 10); From d1605852d94d53e7fc3779790169a8a02a7f3fb2 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Wed, 4 Aug 2021 19:00:54 -0400 Subject: [PATCH 02/33] Moved Excel export functionality and classes into report module --- .../datasourcesummary/ui/AnalysisPanel.java | 6 +- .../ui/BaseDataSourceSummaryPanel.java | 30 ++-- .../ui/Bundle.properties-MERGED | 33 ---- .../datasourcesummary/ui/ContainerPanel.java | 15 +- .../ui/DataSourceSummaryTabbedPane.java | 40 +---- .../ui/GeolocationPanel.java | 4 +- .../ui/IngestJobExcelExport.java | 5 +- .../datasourcesummary/ui/PastCasesPanel.java | 7 +- .../ui/RecentFilesPanel.java | 7 +- .../datasourcesummary/ui/TimelinePanel.java | 8 +- .../datasourcesummary/ui/TypesPanel.java | 12 +- .../ui/UserActivityPanel.java | 7 +- .../uiutils/Bundle.properties-MERGED | 2 - .../uiutils/DefaultCellModel.java | 7 +- .../uiutils/ExcelCellModel.java | 32 ---- .../BarChartExport.java | 14 +- .../BarChartSeries.java | 101 ++++++++++++ .../datasourcesummaryexport/Bundle.properties | 3 + .../Bundle.properties-MERGED | 18 +++ .../datasourcesummaryexport/ColumnModel.java | 80 ++++++++++ .../DataSourceSummaryReport.java | 117 ++++++++++++++ .../DefaultCellModel.java | 149 ++++++++++++++++++ .../datasourcesummaryexport}/ExcelExport.java | 6 +- .../ExcelExportAction.java | 7 +- .../ExcelExportDialog.form | 3 - .../ExcelExportDialog.java | 2 +- .../ExcelSpecialFormatExport.java | 16 +- .../ExcelTableExport.java | 18 +-- .../datasourcesummaryexport}/ExportPanel.form | 0 .../datasourcesummaryexport}/ExportPanel.java | 2 +- .../PieChartExport.java | 12 +- .../datasourcesummaryexport/PieChartItem.java | 67 ++++++++ 32 files changed, 612 insertions(+), 218 deletions(-) delete mode 100644 Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/ExcelCellModel.java rename Core/src/org/sleuthkit/autopsy/{datasourcesummary/uiutils => report/modules/datasourcesummaryexport}/BarChartExport.java (95%) create mode 100755 Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/BarChartSeries.java create mode 100755 Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties create mode 100755 Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED create mode 100755 Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ColumnModel.java create mode 100755 Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DataSourceSummaryReport.java create mode 100755 Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DefaultCellModel.java rename Core/src/org/sleuthkit/autopsy/{datasourcesummary/uiutils => report/modules/datasourcesummaryexport}/ExcelExport.java (98%) rename Core/src/org/sleuthkit/autopsy/{datasourcesummary/ui => report/modules/datasourcesummaryexport}/ExcelExportAction.java (97%) rename Core/src/org/sleuthkit/autopsy/{datasourcesummary/ui => report/modules/datasourcesummaryexport}/ExcelExportDialog.form (97%) rename Core/src/org/sleuthkit/autopsy/{datasourcesummary/ui => report/modules/datasourcesummaryexport}/ExcelExportDialog.java (98%) rename Core/src/org/sleuthkit/autopsy/{datasourcesummary/uiutils => report/modules/datasourcesummaryexport}/ExcelSpecialFormatExport.java (93%) rename Core/src/org/sleuthkit/autopsy/{datasourcesummary/uiutils => report/modules/datasourcesummaryexport}/ExcelTableExport.java (84%) rename Core/src/org/sleuthkit/autopsy/{datasourcesummary/ui => report/modules/datasourcesummaryexport}/ExportPanel.form (100%) rename Core/src/org/sleuthkit/autopsy/{datasourcesummary/ui => report/modules/datasourcesummaryexport}/ExportPanel.java (98%) rename Core/src/org/sleuthkit/autopsy/{datasourcesummary/uiutils => report/modules/datasourcesummaryexport}/PieChartExport.java (93%) create mode 100755 Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/PieChartItem.java diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/AnalysisPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/AnalysisPanel.java index 736dce7f3c..99da8fbd5a 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/AnalysisPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/AnalysisPanel.java @@ -21,8 +21,6 @@ package org.sleuthkit.autopsy.datasourcesummary.ui; import java.util.Arrays; import java.util.List; import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; import org.apache.commons.lang3.tuple.Pair; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.datasourcesummary.datamodel.AnalysisSummary; @@ -30,7 +28,6 @@ import org.sleuthkit.autopsy.datasourcesummary.uiutils.ColumnModel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetcher; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultCellModel; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelExport.ExcelSheetExport; import org.sleuthkit.autopsy.datasourcesummary.uiutils.IngestRunningLabel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.JTablePanel; import org.sleuthkit.datamodel.DataSource; @@ -229,6 +226,7 @@ public class AnalysisPanel extends BaseDataSourceSummaryPanel { ); }// //GEN-END:initComponents + /* ELODO @Override List getExports(DataSource dataSource) { return Stream.of( @@ -237,7 +235,7 @@ public class AnalysisPanel extends BaseDataSourceSummaryPanel { getTableExport(interestingItemsFetcher, DEFAULT_COLUMNS, Bundle.AnalysisPanel_interestingItemHits_tabName(), dataSource)) .filter(sheet -> sheet != null) .collect(Collectors.toList()); - } + }*/ // Variables declaration - do not modify//GEN-BEGIN:variables diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/BaseDataSourceSummaryPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/BaseDataSourceSummaryPanel.java index 01773e5626..97965ec9e8 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/BaseDataSourceSummaryPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/BaseDataSourceSummaryPanel.java @@ -44,10 +44,6 @@ import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetcher; import org.sleuthkit.autopsy.datasourcesummary.uiutils.EventUpdateHandler; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelExport.ExcelExportException; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelExport.ExcelSheetExport; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelTableExport; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelCellModel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.GuiCellModel.DefaultMenuItem; import org.sleuthkit.autopsy.datasourcesummary.uiutils.GuiCellModel.MenuItem; import org.sleuthkit.autopsy.datasourcesummary.uiutils.LoadableComponent; @@ -453,14 +449,6 @@ abstract class BaseDataSourceSummaryPanel extends JPanel { */ protected abstract void onNewDataSource(DataSource dataSource); - /** - * Returns all the excel exportable items associated with the tab. - * - * @param dataSource The data source that results should be filtered. - * @return The excel exportable objects. - */ - abstract List getExports(DataSource dataSource); - /** * Runs a data fetcher and returns the result handling any possible errors * with a log message. @@ -488,7 +476,7 @@ abstract class BaseDataSourceSummaryPanel extends JPanel { /** * Function that converts data into a excel sheet data. */ - protected interface ExcelExportFunction { + // ELTODO protected interface ExcelExportFunction { /** * Function that converts data into an excel sheet. @@ -497,8 +485,8 @@ abstract class BaseDataSourceSummaryPanel extends JPanel { * @return The excel sheet export. * @throws ExcelExportException */ - ExcelSheetExport convert(T data) throws ExcelExportException; - } + // ExcelSheetExport convert(T data) throws ExcelExportException; + //} /** * Helper method that converts data into an excel sheet export handling @@ -510,6 +498,7 @@ abstract class BaseDataSourceSummaryPanel extends JPanel { * message). * @return The excel sheet export. */ + /* ELTODO protected static ExcelSheetExport convertToExcel(ExcelExportFunction excelConverter, T data, String sheetName) { if (data == null) { return null; @@ -523,7 +512,7 @@ abstract class BaseDataSourceSummaryPanel extends JPanel { sheetName == null ? "" : sheetName), ex); return null; } - } + }*/ /** * Returns an excel sheet export given the fetching of data or null if no @@ -535,13 +524,14 @@ abstract class BaseDataSourceSummaryPanel extends JPanel { * @param ds The data source to use for fetching data. * @return The excel sheet export or null if no export could be generated. */ + /* ELTODO protected static ExcelSheetExport getExport( DataFetcher dataFetcher, ExcelExportFunction excelConverter, String sheetName, DataSource ds) { T data = getFetchResult(dataFetcher, sheetName, ds); return convertToExcel(excelConverter, data, sheetName); - } + }*/ /** * Returns an excel table export of the data or null if no export created. @@ -551,13 +541,14 @@ abstract class BaseDataSourceSummaryPanel extends JPanel { * @param data The data to be exported. * @return The excel table export or null if no export could be generated. */ + /* ELTODO protected static ExcelSheetExport getTableExport(List> columnsModel, String sheetName, List data) { return convertToExcel((dataList) -> new ExcelTableExport(sheetName, columnsModel, dataList), data, sheetName); - } + }*/ /** * Returns an excel table export of the data or null if no export created. @@ -569,6 +560,7 @@ abstract class BaseDataSourceSummaryPanel extends JPanel { * @param ds The data source. * @return The excel export or null if no export created. */ + /* ELTODO protected static ExcelSheetExport getTableExport( DataFetcher> dataFetcher, List> columnsModel, String sheetName, DataSource ds) { @@ -577,7 +569,7 @@ abstract class BaseDataSourceSummaryPanel extends JPanel { (dataList) -> new ExcelTableExport(sheetName, columnsModel, dataList), sheetName, ds); - } + }*/ /** * Utility method that shows a loading screen with loadable components, diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties-MERGED index a7b3c8870c..2f5056ae25 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties-MERGED @@ -6,19 +6,6 @@ AnalysisPanel_keywordHits_tabName=Keyword Hits AnalysisPanel_keywordSearchModuleName=Keyword Search BaseDataSourceSummaryPanel_goToArtifact=View Source Result BaseDataSourceSummaryPanel_goToFile=View Source File in Directory -ContainerPanel_export_acquisitionDetails=Acquisition Details: -ContainerPanel_export_deviceId=Device ID: -ContainerPanel_export_displayName=Display Name: -ContainerPanel_export_filePaths=File Paths: -ContainerPanel_export_imageType=Image Type: -ContainerPanel_export_md5=MD5: -ContainerPanel_export_originalName=Name: -ContainerPanel_export_sectorSize=Sector Size: -ContainerPanel_export_sha1=SHA1: -ContainerPanel_export_sha256=SHA256: -ContainerPanel_export_size=Size: -ContainerPanel_export_timeZone=Time Zone: -ContainerPanel_export_unallocatedSize=Unallocated Space: ContainerPanel_setFieldsForNonImageDataSource_na=N/A ContainerPanel_tabName=Container CTL_DataSourceSummaryAction=Data Source Summary @@ -62,7 +49,6 @@ DataSourceSummaryNode.column.type.header=Type DataSourceSummaryNode.viewDataSourceAction.text=Go to Data Source DataSourceSummaryTabbedPane_analysisTab_title=Analysis DataSourceSummaryTabbedPane_detailsTab_title=Container -DataSourceSummaryTabbedPane_exportTab_title=Export DataSourceSummaryTabbedPane_geolocationTab_title=Geolocation DataSourceSummaryTabbedPane_ingestHistoryTab_title=Ingest History DataSourceSummaryTabbedPane_pastCasesTab_title=Past Cases @@ -70,19 +56,6 @@ DataSourceSummaryTabbedPane_recentFileTab_title=Recent Files DataSourceSummaryTabbedPane_timelineTab_title=Timeline DataSourceSummaryTabbedPane_typesTab_title=Types DataSourceSummaryTabbedPane_userActivityTab_title=User Activity -ExcelExportAction_exportToXLSX_beginExport=Beginning Export... -# {0} - tabName -ExcelExportAction_exportToXLSX_gatheringTabData=Fetching Data for {0} Tab... -ExcelExportAction_exportToXLSX_writingToFile=Writing to File... -ExcelExportAction_getXLSXPath_directory=DataSourceSummary -ExcelExportAction_moduleName=Data Source Summary -ExcelExportAction_runXLSXExport_errorMessage=There was an error while exporting. -ExcelExportAction_runXLSXExport_errorTitle=Error While Exporting -ExcelExportAction_runXLSXExport_progressCancelActionTitle=Cancelling... -ExcelExportAction_runXLSXExport_progressCancelTitle=Cancel -# {0} - dataSource -ExcelExportAction_runXLSXExport_progressTitle=Exporting {0} to XLSX -ExcelExportDialog_title=Data Source Summary Exported GeolocationPanel_cityColumn_title=Closest City GeolocationPanel_countColumn_title=Count GeolocationPanel_mostCommon_tabName=Most Common Cities @@ -116,12 +89,6 @@ SizeRepresentationUtil_units_megabytes=MB SizeRepresentationUtil_units_petabytes=PB SizeRepresentationUtil_units_terabytes=TB TimelinePanel_earliestLabel_title=Earliest -TimelinePanel_getExports_activityRange=Activity Range -TimelinePanel_getExports_chartName=Last 30 Days -TimelinePanel_getExports_dateColumnHeader=Date -TimelinePanel_getExports_earliest=Earliest: -TimelinePanel_getExports_latest=Latest: -TimelinePanel_getExports_sheetName=Timeline TimelinePanel_latestLabel_title=Latest TimlinePanel_last30DaysChart_artifactEvts_title=Result Events TimlinePanel_last30DaysChart_fileEvts_title=File Events diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java index a8e5fef64e..0fc66a4c72 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java @@ -36,18 +36,10 @@ import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.datasourcesummary.datamodel.ContainerSummary; import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; -import static org.sleuthkit.autopsy.datasourcesummary.ui.BaseDataSourceSummaryPanel.getFetchResult; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult.ResultType; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetcher; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultCellModel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultUpdateGovernor; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelExport.ExcelSheetExport; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelSpecialFormatExport; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelSpecialFormatExport.ExcelItemExportable; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelSpecialFormatExport.KeyValueItemExportable; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelSpecialFormatExport.SingleCellExportable; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelSpecialFormatExport.TitledExportable; import org.sleuthkit.autopsy.datasourcesummary.uiutils.UpdateGovernor; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.Image; @@ -488,6 +480,7 @@ class ContainerPanel extends BaseDataSourceSummaryPanel { * @return The list of key value pairs that can be incorporated into the * excel export. */ + /* ELODO private static List getAcquisitionDetails(String acquisitionDetails) { if (StringUtils.isBlank(acquisitionDetails)) { return Collections.emptyList(); @@ -497,9 +490,9 @@ class ContainerPanel extends BaseDataSourceSummaryPanel { .filter(item -> item != null) .collect(Collectors.toList()); } - } + }*/ - @Override + /* ELODO @Messages({ "ContainerPanel_export_displayName=Display Name:", "ContainerPanel_export_originalName=Name:", @@ -556,7 +549,7 @@ class ContainerPanel extends BaseDataSourceSummaryPanel { new TitledExportable(Bundle.ContainerPanel_export_filePaths(), cellPaths) ))); - } + }*/ /** * This method is called from within the constructor to initialize the form. diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryTabbedPane.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryTabbedPane.java index 146863b58e..af53ab9260 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryTabbedPane.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryTabbedPane.java @@ -25,12 +25,9 @@ import java.util.Arrays; import java.util.EnumSet; import java.util.List; import java.util.function.Consumer; -import java.util.function.Function; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.IngestJobInfoPanel; -import org.sleuthkit.autopsy.datasourcesummary.ui.ExcelExportAction.ExportableTab; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelExport.ExcelSheetExport; import org.sleuthkit.datamodel.DataSource; /** @@ -46,8 +43,7 @@ import org.sleuthkit.datamodel.DataSource; "DataSourceSummaryTabbedPane_pastCasesTab_title=Past Cases", "DataSourceSummaryTabbedPane_analysisTab_title=Analysis", "DataSourceSummaryTabbedPane_geolocationTab_title=Geolocation", - "DataSourceSummaryTabbedPane_timelineTab_title=Timeline", - "DataSourceSummaryTabbedPane_exportTab_title=Export" + "DataSourceSummaryTabbedPane_timelineTab_title=Timeline" }) public class DataSourceSummaryTabbedPane extends javax.swing.JPanel { @@ -55,12 +51,11 @@ public class DataSourceSummaryTabbedPane extends javax.swing.JPanel { * Records of tab information (i.e. title, component, function to call on * new data source). */ - private class DataSourceTab implements ExportableTab { + private class DataSourceTab { private final String tabTitle; private final Component component; private final Consumer onDataSource; - private final Function> excelExporter; private final Runnable onClose; private final Runnable onInit; @@ -71,7 +66,7 @@ public class DataSourceSummaryTabbedPane extends javax.swing.JPanel { * @param panel The component to be displayed in the tab. */ DataSourceTab(String tabTitle, BaseDataSourceSummaryPanel panel) { - this(tabTitle, panel, panel::setDataSource, panel::getExports, panel::close, panel::init); + this(tabTitle, panel, panel::setDataSource, panel::close, panel::init); panel.setParentCloseListener(() -> notifyParentClose()); } @@ -90,12 +85,10 @@ public class DataSourceSummaryTabbedPane extends javax.swing.JPanel { * added to the tabbed pane. */ DataSourceTab(String tabTitle, Component component, Consumer onDataSource, - Function> excelExporter, Runnable onClose, - Runnable onInit) { + Runnable onClose, Runnable onInit) { this.tabTitle = tabTitle; this.component = component; this.onDataSource = onDataSource; - this.excelExporter = excelExporter; this.onClose = onClose; this.onInit = onInit; } @@ -103,7 +96,6 @@ public class DataSourceSummaryTabbedPane extends javax.swing.JPanel { /** * @return The title for the tab. */ - @Override public String getTabTitle() { return tabTitle; } @@ -122,11 +114,6 @@ public class DataSourceSummaryTabbedPane extends javax.swing.JPanel { return onDataSource; } - @Override - public List getExcelExports(DataSource dataSource) { - return excelExporter == null ? null : excelExporter.apply(dataSource); - } - /** * @return The action for closing resources in the tab. */ @@ -152,9 +139,6 @@ public class DataSourceSummaryTabbedPane extends javax.swing.JPanel { private Runnable notifyParentClose = null; private final IngestJobInfoPanel ingestHistoryPanel = new IngestJobInfoPanel(); - // create an export panel whose button triggers the export to XLSX action - private final ExportPanel exportPanel = new ExportPanel(); - private final List tabs = Arrays.asList( new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_typesTab_title(), new TypesPanel()), new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_userActivityTab_title(), new UserActivityPanel()), @@ -168,22 +152,11 @@ public class DataSourceSummaryTabbedPane extends javax.swing.JPanel { Bundle.DataSourceSummaryTabbedPane_ingestHistoryTab_title(), ingestHistoryPanel, ingestHistoryPanel::setDataSource, - IngestJobExcelExport::getExports, null, null), - new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_detailsTab_title(), new ContainerPanel()), - new DataSourceTab( - Bundle.DataSourceSummaryTabbedPane_exportTab_title(), - exportPanel, - null, - null, - null, - null) + new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_detailsTab_title(), new ContainerPanel()) ); - // the action that does the export - private final ExcelExportAction exportAction = new ExcelExportAction(tabs); - private DataSource dataSource = null; private CardLayout cardLayout; @@ -243,9 +216,6 @@ public class DataSourceSummaryTabbedPane extends javax.swing.JPanel { // set this to no datasource initially cardLayout.show(this, NO_DATASOURCE_PANE); - - // set action for when user requests xlsx export - exportPanel.setXlsxExportAction(() -> exportAction.accept(getDataSource())); } /** diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/GeolocationPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/GeolocationPanel.java index be7279afca..fd3ad98dcc 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/GeolocationPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/GeolocationPanel.java @@ -45,7 +45,6 @@ import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetcher; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultCellModel; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelExport; import org.sleuthkit.autopsy.datasourcesummary.uiutils.IngestRunningLabel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.JTablePanel; import org.sleuthkit.autopsy.geolocation.GeoFilter; @@ -349,6 +348,7 @@ public class GeolocationPanel extends BaseDataSourceSummaryPanel { onNewDataSource(dataFetchComponents, tables, dataSource); } + /* ELODO @Override List getExports(DataSource dataSource) { GeolocationViewModel model = getFetchResult(geolocationFetcher, "Geolocation sheets", dataSource); @@ -360,7 +360,7 @@ public class GeolocationPanel extends BaseDataSourceSummaryPanel { getTableExport(DEFAULT_TEMPLATE, Bundle.GeolocationPanel_mostRecent_tabName(), model.getMostRecentData()), getTableExport(DEFAULT_TEMPLATE, Bundle.GeolocationPanel_mostCommon_tabName(), model.getMostCommonData()) ); - } + }*/ @Override public void close() { diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/IngestJobExcelExport.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/IngestJobExcelExport.java index 3ad757e7be..07d789c0fa 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/IngestJobExcelExport.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/IngestJobExcelExport.java @@ -36,8 +36,6 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.datasourcesummary.uiutils.ColumnModel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultCellModel; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelExport.ExcelSheetExport; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelTableExport; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.IngestJobInfo; import org.sleuthkit.datamodel.IngestModuleInfo; @@ -211,6 +209,7 @@ class IngestJobExcelExport { * @param dataSource The data source. * @return The list of sheets to be included in an export. */ + /* ELODO static List getExports(DataSource dataSource) { if (dataSource == null) { return Collections.emptyList(); @@ -246,7 +245,7 @@ class IngestJobExcelExport { .collect(Collectors.toList()); return Arrays.asList(new ExcelTableExport<>(Bundle.IngestJobExcelExport_sheetName(), COLUMNS, toDisplay)); - } + }*/ private IngestJobExcelExport() { } diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesPanel.java index a3169db375..d49bcfdff0 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesPanel.java @@ -19,21 +19,17 @@ package org.sleuthkit.autopsy.datasourcesummary.ui; import java.util.Arrays; -import java.util.Collections; import java.util.List; import org.apache.commons.lang3.tuple.Pair; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.datasourcesummary.datamodel.PastCasesSummary; import org.sleuthkit.autopsy.datasourcesummary.datamodel.PastCasesSummary.PastCasesResult; -import static org.sleuthkit.autopsy.datasourcesummary.ui.BaseDataSourceSummaryPanel.getFetchResult; -import static org.sleuthkit.autopsy.datasourcesummary.ui.BaseDataSourceSummaryPanel.getTableExport; import org.sleuthkit.autopsy.datasourcesummary.uiutils.ColumnModel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetcher; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultCellModel; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelExport; import org.sleuthkit.autopsy.datasourcesummary.uiutils.IngestRunningLabel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.JTablePanel; import org.sleuthkit.datamodel.DataSource; @@ -128,6 +124,7 @@ public class PastCasesPanel extends BaseDataSourceSummaryPanel { onNewDataSource(dataFetchComponents, tables, dataSource); } + /* ELODO @Override List getExports(DataSource dataSource) { PastCasesResult result = getFetchResult(pastCasesFetcher, "Past cases sheets", dataSource); @@ -139,7 +136,7 @@ public class PastCasesPanel extends BaseDataSourceSummaryPanel { getTableExport(DEFAULT_TEMPLATE, Bundle.PastCasesPanel_notableFileTable_tabName(), result.getTaggedNotable()), getTableExport(DEFAULT_TEMPLATE, Bundle.PastCasesPanel_sameIdsTable_tabName(), result.getSameIdsResults()) ); - } + }*/ @Override public void close() { diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesPanel.java index 44d916992f..6bb0ba78af 100755 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesPanel.java @@ -27,20 +27,16 @@ import java.util.List; import java.util.Locale; import java.util.function.Function; import java.util.function.Supplier; -import java.util.stream.Collectors; -import java.util.stream.Stream; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.datasourcesummary.datamodel.RecentFilesGetter; import org.sleuthkit.autopsy.contentutils.RecentFilesSummary.RecentAttachmentDetails; import org.sleuthkit.autopsy.contentutils.RecentFilesSummary.RecentDownloadDetails; import org.sleuthkit.autopsy.contentutils.RecentFilesSummary.RecentFileDetails; -import static org.sleuthkit.autopsy.datasourcesummary.ui.BaseDataSourceSummaryPanel.getTableExport; import org.sleuthkit.autopsy.datasourcesummary.uiutils.CellModelTableCellRenderer; import org.sleuthkit.autopsy.datasourcesummary.uiutils.ColumnModel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetcher; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultCellModel; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelExport; import org.sleuthkit.autopsy.datasourcesummary.uiutils.GuiCellModel.MenuItem; import org.sleuthkit.autopsy.datasourcesummary.uiutils.IngestRunningLabel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.JTablePanel; @@ -190,6 +186,7 @@ public final class RecentFilesPanel extends BaseDataSourceSummaryPanel { onNewDataSource(dataFetchComponents, tablePanelList, dataSource); } + /* ELODO @Override List getExports(DataSource dataSource) { return Stream.of( @@ -198,7 +195,7 @@ public final class RecentFilesPanel extends BaseDataSourceSummaryPanel { getTableExport(attachmentsFetcher, attachmentsTemplate, Bundle.RecentFilesPanel_attachmentsTable_tabName(), dataSource)) .filter(sheet -> sheet != null) .collect(Collectors.toList()); - } + }*/ @Override public void close() { diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java index 94af4b7545..d2dfb8d261 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java @@ -39,7 +39,6 @@ import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineDataSourceUtils import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary; import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary.DailyActivityAmount; import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary.TimelineSummaryData; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartExport; import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartPanel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartSeries; import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartPanel.OrderedKey; @@ -49,10 +48,6 @@ import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetcher; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultCellModel; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelExport; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelSpecialFormatExport; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelSpecialFormatExport.KeyValueItemExportable; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelSpecialFormatExport.TitledExportable; import org.sleuthkit.autopsy.datasourcesummary.uiutils.IngestRunningLabel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.LoadableComponent; import org.sleuthkit.autopsy.datasourcesummary.uiutils.LoadableLabel; @@ -304,6 +299,7 @@ public class TimelinePanel extends BaseDataSourceSummaryPanel { return new DefaultCellModel<>(date, (dt) -> dt == null ? "" : EARLIEST_LATEST_FORMAT.format(dt), EARLIEST_LATEST_FORMAT_STR); } + /* ELODO @Messages({ "TimelinePanel_getExports_sheetName=Timeline", "TimelinePanel_getExports_activityRange=Activity Range", @@ -328,7 +324,7 @@ public class TimelinePanel extends BaseDataSourceSummaryPanel { "#,###", Bundle.TimelinePanel_getExports_chartName(), parseChartData(summaryData.getMostRecentDaysActivity(), true))))); - } + }*/ /** * This method is called from within the constructor to initialize the form. diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java index e11e638459..3f1b19e1a4 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java @@ -40,14 +40,9 @@ import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult.ResultTyp import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetcher; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultCellModel; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelExport; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelSpecialFormatExport; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelSpecialFormatExport.KeyValueItemExportable; import org.sleuthkit.autopsy.datasourcesummary.uiutils.IngestRunningLabel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.LoadableComponent; import org.sleuthkit.autopsy.datasourcesummary.uiutils.LoadableLabel; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.PieChartExport; import org.sleuthkit.autopsy.datasourcesummary.uiutils.PieChartPanel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.PieChartItem; @@ -421,7 +416,7 @@ class TypesPanel extends BaseDataSourceSummaryPanel { * @param dataSource The data source containing the data. * @return The key value pair to be exported. */ - private static KeyValueItemExportable getStrExportable(DataFetcher fetcher, String key, DataSource dataSource) { + /* ELODO private static KeyValueItemExportable getStrExportable(DataFetcher fetcher, String key, DataSource dataSource) { String result = getFetchResult(fetcher, "Types", dataSource); return (result == null) ? null : new KeyValueItemExportable(key, new DefaultCellModel<>(result)); } @@ -435,12 +430,13 @@ class TypesPanel extends BaseDataSourceSummaryPanel { * @param dataSource The data source. * @return The key value pair. */ - private static KeyValueItemExportable getCountExportable(DataFetcher fetcher, String key, DataSource dataSource) { + /* ELODOprivate static KeyValueItemExportable getCountExportable(DataFetcher fetcher, String key, DataSource dataSource) { Long count = getFetchResult(fetcher, "Types", dataSource); return (count == null) ? null : new KeyValueItemExportable(key, new DefaultCellModel(count, COMMA_FORMATTER::format, COMMA_FORMAT_STR)); } + /* ELODO @Override List getExports(DataSource dataSource) { if (dataSource == null) { @@ -471,7 +467,7 @@ class TypesPanel extends BaseDataSourceSummaryPanel { .filter(sheet -> sheet != null) .collect(Collectors.toList()) )); - } + }*/ /** * This method is called from within the constructor to initialize the form. diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivityPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivityPanel.java index 2cde769403..72f19ada78 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivityPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivityPanel.java @@ -26,8 +26,6 @@ import java.util.Date; import java.util.List; import java.util.Locale; import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; import org.apache.commons.lang.StringUtils; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary; @@ -37,12 +35,10 @@ import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.Top import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopWebSearchResult; import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopDomainsResult; import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopProgramsResult; -import static org.sleuthkit.autopsy.datasourcesummary.ui.BaseDataSourceSummaryPanel.getTableExport; import org.sleuthkit.autopsy.datasourcesummary.uiutils.ColumnModel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetcher; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultCellModel; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelExport; import org.sleuthkit.autopsy.datasourcesummary.uiutils.GuiCellModel.MenuItem; import org.sleuthkit.autopsy.datasourcesummary.uiutils.IngestRunningLabel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.JTablePanel; @@ -366,6 +362,7 @@ public class UserActivityPanel extends BaseDataSourceSummaryPanel { super.close(); } + /* ELODO @Override List getExports(DataSource dataSource) { return Stream.of( @@ -376,7 +373,7 @@ public class UserActivityPanel extends BaseDataSourceSummaryPanel { getTableExport(topAccountsFetcher, topAccountsTemplate, Bundle.UserActivityPanel_TopAccountTableModel_tabName(), dataSource)) .filter(sheet -> sheet != null) .collect(Collectors.toList()); - } + }*/ /** * This method is called from within the constructor to initialize the form. diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/Bundle.properties-MERGED index ad10f70c22..c06bc6850a 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/Bundle.properties-MERGED @@ -1,7 +1,5 @@ AbstractLoadableComponent_errorMessage_defaultText=There was an error loading results. AbstractLoadableComponent_loadingMessage_defaultText=Loading results... AbstractLoadableComponent_noDataExists_defaultText=No data exists. -# {0} - sheetNumber -ExcelExport_writeExcel_noSheetName=Sheet {0} IngestRunningLabel_defaultMessage=Ingest is currently running. PieChartPanel_noDataLabel=No Data diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DefaultCellModel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DefaultCellModel.java index 215f71469e..de0319ebf8 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DefaultCellModel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DefaultCellModel.java @@ -27,7 +27,7 @@ import java.util.function.Supplier; /** * The default cell model. */ -public class DefaultCellModel implements GuiCellModel, ExcelCellModel { +public class DefaultCellModel implements GuiCellModel { private final T data; private final String text; @@ -86,11 +86,6 @@ public class DefaultCellModel implements GuiCellModel, ExcelCellModel { return this.data; } - @Override - public String getExcelFormatString() { - return this.excelFormatString; - } - @Override public String getText() { return text; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/ExcelCellModel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/ExcelCellModel.java deleted file mode 100644 index 0ca52f12e4..0000000000 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/ExcelCellModel.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2021 Basis Technology Corp. - * Contact: carrier sleuthkit org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sleuthkit.autopsy.datasourcesummary.uiutils; - -/** - * Basic interface for a cell model. - */ -public interface ExcelCellModel extends CellModel { - - /** - * @return The format string to be used with Apache POI during excel - * export or null if none necessary. - */ - String getExcelFormatString(); - -} diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/BarChartExport.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/BarChartExport.java similarity index 95% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/BarChartExport.java rename to Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/BarChartExport.java index 15a93092cc..edb71c21a9 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/BarChartExport.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/BarChartExport.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datasourcesummary.uiutils; +package org.sleuthkit.autopsy.report.modules.datasourcesummaryexport; import java.awt.Color; import java.nio.ByteBuffer; @@ -49,10 +49,10 @@ import org.apache.poi.xssf.usermodel.XSSFChart; import org.apache.poi.xssf.usermodel.XSSFClientAnchor; import org.apache.poi.xssf.usermodel.XSSFDrawing; import org.apache.poi.xssf.usermodel.XSSFSheet; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelExport.ExcelExportException; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelExport.ExcelSheetExport; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelSpecialFormatExport.ExcelItemExportable; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelSpecialFormatExport.ItemDimensions; +import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExport.ExcelExportException; +import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExport.ExcelSheetExport; +import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelSpecialFormatExport.ExcelItemExportable; +import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelSpecialFormatExport.ItemDimensions; /** * Class that creates an excel stacked bar chart along with data table. @@ -70,7 +70,7 @@ public class BarChartExport implements ExcelItemExportable, ExcelSheetExport { * @return An excel table export to be used as the data source for the chart * in the excel document. */ - private static ExcelTableExport>, ? extends ExcelCellModel> getTableModel( + private static ExcelTableExport>, ? extends DefaultCellModel> getTableModel( List categories, String keyColumnHeader, String chartTitle) { // get the row keys by finding the series with the largest set of bar items @@ -134,7 +134,7 @@ public class BarChartExport implements ExcelItemExportable, ExcelSheetExport { private static final int DEFAULT_ROW_PADDING = 1; private static final int DEFAULT_COL_OFFSET = 1; - private final ExcelTableExport>, ? extends ExcelCellModel> tableExport; + private final ExcelTableExport>, ? extends DefaultCellModel> tableExport; private final int colOffset; private final int rowPadding; private final int colSize; diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/BarChartSeries.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/BarChartSeries.java new file mode 100755 index 0000000000..f7c48a2f30 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/BarChartSeries.java @@ -0,0 +1,101 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit 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.util.Collections; +import java.util.List; + +/** + * Represents a series in a bar chart where all items pertain to one category. + */ +public class BarChartSeries { + + /** + * An individual bar to be displayed in the bar chart. + */ + public static class BarChartItem { + + private final Comparable key; + private final double value; + + /** + * Main constructor. + * + * @param key The key. + * @param value The value for this item. + */ + public BarChartItem(Comparable key, double value) { + this.key = key; + this.value = value; + } + + /** + * @return The key for this item. + */ + public Comparable getKey() { + return key; + } + + /** + * @return The value for this item. + */ + public double getValue() { + return value; + } + } + private final Comparable key; + private final Color color; + private final List items; + + /** + * Main constructor. + * + * @param key The key. + * @param color The color for this series. + * @param items The bars to be displayed for this series. + */ + public BarChartSeries(Comparable key, Color color, List items) { + this.key = key; + this.color = color; + this.items = (items == null) ? Collections.emptyList() : Collections.unmodifiableList(items); + } + + /** + * @return The color for this series. + */ + public Color getColor() { + return color; + } + + /** + * @return The bars to be displayed for this series. + */ + public List getItems() { + return items; + } + + /** + * @return The key for this item. + */ + public Comparable getKey() { + return key; + } + +} diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties new file mode 100755 index 0000000000..6c86626cdb --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties @@ -0,0 +1,3 @@ +DataSourceSummaryReport.getName.text=Data Source Summary Report +DataSourceSummaryReport.getDesc.text=Data source summary report in Excel (XLS) format. +DataSourceSummaryReport.endReport.srcModuleName.text=Excel Report \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED new file mode 100755 index 0000000000..bb28c7960e --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED @@ -0,0 +1,18 @@ +DataSourceSummaryReport.getName.text=Data Source Summary Report +DataSourceSummaryReport.getDesc.text=Data source summary report in Excel (XLS) format. +DataSourceSummaryReport.endReport.srcModuleName.text=Excel Report +# {0} - sheetNumber +ExcelExport_writeExcel_noSheetName=Sheet {0} +ExcelExportAction_exportToXLSX_beginExport=Beginning Export... +# {0} - tabName +ExcelExportAction_exportToXLSX_gatheringTabData=Fetching Data for {0} Tab... +ExcelExportAction_exportToXLSX_writingToFile=Writing to File... +ExcelExportAction_getXLSXPath_directory=DataSourceSummary +ExcelExportAction_moduleName=Data Source Summary +ExcelExportAction_runXLSXExport_errorMessage=There was an error while exporting. +ExcelExportAction_runXLSXExport_errorTitle=Error While Exporting +ExcelExportAction_runXLSXExport_progressCancelActionTitle=Cancelling... +ExcelExportAction_runXLSXExport_progressCancelTitle=Cancel +# {0} - dataSource +ExcelExportAction_runXLSXExport_progressTitle=Exporting {0} to XLSX +ExcelExportDialog_title=Data Source Summary Exported diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ColumnModel.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ColumnModel.java new file mode 100755 index 0000000000..134f86f174 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ColumnModel.java @@ -0,0 +1,80 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit 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.util.function.Function; + +/** + * Describes aspects of a column which can be used with getTableModel or + * getJTablePanel. 'T' represents the object that will represent rows in the + * table. + */ +public class ColumnModel { + + private final String headerTitle; + private final Function cellRenderer; + private final Integer width; + + /** + * Constructor for a DataResultColumnModel. + * + * @param headerTitle The title for the column. + * @param cellRenderer The method that generates a CellModel for the column + * based on the data. + */ + public ColumnModel(String headerTitle, Function cellRenderer) { + this(headerTitle, cellRenderer, null); + } + + /** + * Constructor for a DataResultColumnModel. + * + * @param headerTitle The title for the column. + * @param cellRenderer The method that generates a CellModel for the column + * based on the data. + * @param width The preferred width of the column. + */ + public ColumnModel(String headerTitle, Function cellRenderer, Integer width) { + this.headerTitle = headerTitle; + this.cellRenderer = cellRenderer; + this.width = width; + } + + /** + * @return The title for the column. + */ + public String getHeaderTitle() { + return headerTitle; + } + + /** + * @return The method that generates a CellModel for the column based on the + * data. + */ + public Function getCellRenderer() { + return cellRenderer; + } + + /** + * @return The preferred width of the column (can be null). + */ + public Integer getWidth() { + return width; + } +} diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DataSourceSummaryReport.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DataSourceSummaryReport.java new file mode 100755 index 0000000000..e4b4483675 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DataSourceSummaryReport.java @@ -0,0 +1,117 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit 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.util.List; +import java.util.logging.Level; +import java.util.stream.Collectors; +import javax.swing.JPanel; +import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.report.GeneralReportModule; +import org.sleuthkit.autopsy.report.GeneralReportSettings; +import org.sleuthkit.autopsy.report.ReportProgressPanel; +import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.TskCoreException; + +class DataSourceSummaryReport implements GeneralReportModule { + + private static final Logger logger = Logger.getLogger(DataSourceSummaryReport.class.getName()); + private static DataSourceSummaryReport instance; + + // Get the default instance of this report + public static synchronized DataSourceSummaryReport getDefault() { + if (instance == null) { + instance = new DataSourceSummaryReport(); + } + return instance; + } + + // Hidden constructor + private DataSourceSummaryReport() { + } + + + @Override + public String getName() { + String name = NbBundle.getMessage(this.getClass(), "DataSourceSummaryReport.getName.text"); + return name; + } + + @Override + public String getRelativeFilePath() { + return "DataSourceSummaryReport.xlsx"; //NON-NLS + } + + @Override + public String getDescription() { + String desc = NbBundle.getMessage(this.getClass(), "DataSourceSummaryReport.getDesc.text"); + return desc; + } + + @Override + public JPanel getConfigurationPanel() { + return null; // No configuration panel + } + + @Override + public boolean supportsDataSourceSelection() { + return true; + } + + @Override + public void generateReport(GeneralReportSettings settings, ReportProgressPanel progressPanel) { + Case currentCase = null; + try { + currentCase = Case.getCurrentCaseThrows(); + } catch (NoCurrentCaseException ex) { + logger.log(Level.SEVERE, "Exception while getting open case.", ex); //NON-NLS + return; + } + + if(settings.getSelectedDataSources() == null) { + // Process all data sources if the list is null. + try { + List selectedDataSources = currentCase.getDataSources() + .stream() + .map(Content::getId) + .collect(Collectors.toList()); + settings.setSelectedDataSources(selectedDataSources); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Could not get the datasources from the case", ex); + return; + } + } + + String baseReportDir = settings.getReportDirectoryPath(); + // Start the progress bar and setup the report + progressPanel.setIndeterminate(true); + progressPanel.start(); + //progressPanel.updateStatusLabel(NbBundle.getMessage(this.getClass(), "ReportKML.progress.querying")); + String reportFullPath = baseReportDir + getRelativeFilePath(); //NON-NLS + String errorMessage = ""; + + //progressPanel.updateStatusLabel(NbBundle.getMessage(this.getClass(), "ReportKML.progress.loading")); + + ReportProgressPanel.ReportStatus result = ReportProgressPanel.ReportStatus.COMPLETE; + } + +} diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DefaultCellModel.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DefaultCellModel.java new file mode 100755 index 0000000000..5553aa6d73 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DefaultCellModel.java @@ -0,0 +1,149 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit 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.util.function.Function; +import javax.swing.JLabel; +import org.apache.poi.ss.usermodel.HorizontalAlignment; + +/** + * The default cell model. + */ +class DefaultCellModel { + + private final T data; + private final String text; + private HorizontalAlign horizontalAlignment; + private final String excelFormatString; + + /** + * Describes the horizontal alignment. + */ + enum HorizontalAlign { + LEFT(JLabel.LEFT, HorizontalAlignment.LEFT), + CENTER(JLabel.CENTER, HorizontalAlignment.CENTER), + RIGHT(JLabel.RIGHT, HorizontalAlignment.RIGHT); + + private final int jlabelAlignment; + private final HorizontalAlignment poiAlignment; + + /** + * Constructor for a HorizontalAlign enum. + * + * @param jlabelAlignment The corresponding JLabel horizontal alignment + * number. + * @param poiAlignment Horizontal alignment for Apache POI. + */ + HorizontalAlign(int jlabelAlignment, HorizontalAlignment poiAlignment) { + this.jlabelAlignment = jlabelAlignment; + this.poiAlignment = poiAlignment; + } + + /** + * @return The corresponding JLabel horizontal alignment (i.e. + * JLabel.LEFT). + */ + int getJLabelAlignment() { + return this.jlabelAlignment; + } + + /** + * @return Horizontal alignment for Apache POI. + */ + HorizontalAlignment getPoiAlignment() { + return poiAlignment; + } + } + + /** + * Main constructor. + * + * @param data The data to be displayed in the cell. + */ + public DefaultCellModel(T data) { + this(data, null, null); + } + + /** + * Constructor. + * + * @param data The data to be displayed in the cell. + * @param stringConverter The means of converting that data to a string or + * null to use .toString method on object. + */ + public DefaultCellModel(T data, Function stringConverter) { + this(data, stringConverter, null); + } + + /** + * Constructor. + * + * @param data The data to be displayed in the cell. + * @param stringConverter The means of converting that data to a string or + * null to use .toString method on object. + * @param excelFormatString The apache poi excel format string to use with + * the data. + * + * NOTE: Only certain data types can be exported. See + * ExcelTableExport.createCell() for types. + */ + public DefaultCellModel(T data, Function stringConverter, String excelFormatString) { + this.data = data; + this.excelFormatString = excelFormatString; + + if (stringConverter == null) { + text = this.data == null ? "" : this.data.toString(); + } else { + text = stringConverter.apply(this.data); + } + } + + public T getData() { + return this.data; + } + + public String getExcelFormatString() { + return this.excelFormatString; + } + + public String getText() { + return text; + } + + public HorizontalAlign getHorizontalAlignment() { + return horizontalAlignment; + } + + /** + * Sets the horizontal alignment for this cell model. + * + * @param alignment The horizontal alignment for the cell model. + * + * @return As a utility, returns this. + */ + public DefaultCellModel setHorizontalAlignment(HorizontalAlign alignment) { + this.horizontalAlignment = alignment; + return this; + } + + @Override + public String toString() { + return getText(); + } +} diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/ExcelExport.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExport.java similarity index 98% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/ExcelExport.java rename to Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExport.java index fab6558c4a..b7e2c04fec 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/ExcelExport.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExport.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datasourcesummary.uiutils; +package org.sleuthkit.autopsy.report.modules.datasourcesummaryexport; import java.io.File; import java.io.FileOutputStream; @@ -37,7 +37,7 @@ import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.CellModel.HorizontalAlign; +import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.DefaultCellModel.HorizontalAlign; /** * Class for handling Excel exporting. @@ -337,7 +337,7 @@ public class ExcelExport { * @param cellStyle The style to use. * @return The created cell. */ - static Cell createCell(WorksheetEnv env, Row row, int colNum, ExcelCellModel cellModel, Optional cellStyle) { + static Cell createCell(WorksheetEnv env, Row row, int colNum, DefaultCellModel cellModel, Optional cellStyle) { CellStyle cellStyleToUse = cellStyle.orElse(env.getDefaultCellStyle()); if (cellModel.getExcelFormatString() != null || cellModel.getHorizontalAlignment() != null) { diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ExcelExportAction.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java similarity index 97% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ExcelExportAction.java rename to Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java index 22e06c07ed..1c8e6fb6cb 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ExcelExportAction.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datasourcesummary.ui; +package org.sleuthkit.autopsy.report.modules.datasourcesummaryexport; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -43,9 +43,8 @@ import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.coreutils.FileUtil; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelExport; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelExport.ExcelExportException; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelExport.ExcelSheetExport; +import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExport.ExcelExportException; +import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExport.ExcelSheetExport; import org.sleuthkit.autopsy.progress.ModalDialogProgressIndicator; import org.sleuthkit.autopsy.progress.ProgressIndicator; import org.sleuthkit.datamodel.DataSource; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ExcelExportDialog.form b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportDialog.form similarity index 97% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ExcelExportDialog.form rename to Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportDialog.form index 8342ce5326..7bc59aa544 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ExcelExportDialog.form +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportDialog.form @@ -92,9 +92,6 @@ - - - diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ExcelExportDialog.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportDialog.java similarity index 98% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ExcelExportDialog.java rename to Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportDialog.java index ec16d08e46..448566b6af 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ExcelExportDialog.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportDialog.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datasourcesummary.ui; +package org.sleuthkit.autopsy.report.modules.datasourcesummaryexport; import java.awt.Cursor; import java.awt.Desktop; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/ExcelSpecialFormatExport.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelSpecialFormatExport.java similarity index 93% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/ExcelSpecialFormatExport.java rename to Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelSpecialFormatExport.java index f9c46fa5e2..71683d1d26 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/ExcelSpecialFormatExport.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelSpecialFormatExport.java @@ -16,14 +16,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datasourcesummary.uiutils; +package org.sleuthkit.autopsy.report.modules.datasourcesummaryexport; import java.util.Collections; import java.util.List; import java.util.Optional; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelExport.ExcelExportException; +import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExport.ExcelExportException; /** * An excel export that has special row-by-row formatting. @@ -108,7 +108,7 @@ public class ExcelSpecialFormatExport implements ExcelExport.ExcelSheetExport { */ public static class SingleCellExportable implements ExcelItemExportable { - private final ExcelCellModel item; + private final DefaultCellModel item; /** * Main constructor. @@ -124,7 +124,7 @@ public class ExcelSpecialFormatExport implements ExcelExport.ExcelSheetExport { * * @param item The cell model to be written. */ - public SingleCellExportable(ExcelCellModel item) { + public SingleCellExportable(DefaultCellModel item) { this.item = item; } @@ -142,8 +142,8 @@ public class ExcelSpecialFormatExport implements ExcelExport.ExcelSheetExport { */ public static class KeyValueItemExportable implements ExcelItemExportable { - private final ExcelCellModel key; - private final ExcelCellModel value; + private final DefaultCellModel key; + private final DefaultCellModel value; /** * Main constructor. @@ -151,7 +151,7 @@ public class ExcelSpecialFormatExport implements ExcelExport.ExcelSheetExport { * @param key The string key to be exported. * @param value The cell model to be exported. */ - public KeyValueItemExportable(String key, ExcelCellModel value) { + public KeyValueItemExportable(String key, DefaultCellModel value) { this(new DefaultCellModel<>(key), value); } @@ -161,7 +161,7 @@ public class ExcelSpecialFormatExport implements ExcelExport.ExcelSheetExport { * @param key The cell key to be exported. * @param value The cell model to be exported. */ - public KeyValueItemExportable(ExcelCellModel key, ExcelCellModel value) { + public KeyValueItemExportable(DefaultCellModel key, DefaultCellModel value) { this.key = key; this.value = value; } diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/ExcelTableExport.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelTableExport.java similarity index 84% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/ExcelTableExport.java rename to Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelTableExport.java index c79cb381aa..c861d5d174 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/ExcelTableExport.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelTableExport.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datasourcesummary.uiutils; +package org.sleuthkit.autopsy.report.modules.datasourcesummaryexport; import java.util.Collections; import java.util.List; @@ -24,15 +24,15 @@ import java.util.Optional; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelExport.ExcelExportException; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelExport.ExcelSheetExport; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelSpecialFormatExport.ExcelItemExportable; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelSpecialFormatExport.ItemDimensions; +import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExport.ExcelExportException; +import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExport.ExcelSheetExport; +import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelSpecialFormatExport.ExcelItemExportable; +import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelSpecialFormatExport.ItemDimensions; /** * An excel sheet export of table data. */ -public class ExcelTableExport implements ExcelSheetExport, ExcelItemExportable { +public class ExcelTableExport implements ExcelSheetExport, ExcelItemExportable { private final String sheetName; private final List> columns; @@ -104,7 +104,7 @@ public class ExcelTableExport implements ExcelSheet * @throws ExcelExportException * @return The number of rows (including the header) written. */ - private static int renderSheet( + private static int renderSheet( Sheet sheet, ExcelExport.WorksheetEnv worksheetEnv, int rowStart, @@ -127,8 +127,8 @@ public class ExcelTableExport implements ExcelSheet T rowData = safeData.get(rowNum); Row row = sheet.createRow(rowNum + rowStart + 1); for (int colNum = 0; colNum < columns.size(); colNum++) { - ColumnModel colModel = columns.get(colNum); - ExcelCellModel cellModel = colModel.getCellRenderer().apply(rowData); + ColumnModel colModel = columns.get(colNum); + DefaultCellModel cellModel = colModel.getCellRenderer().apply(rowData); ExcelExport.createCell(worksheetEnv, row, colNum + colStart, cellModel, Optional.empty()); } } diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ExportPanel.form b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportPanel.form similarity index 100% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ExportPanel.form rename to Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportPanel.form diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ExportPanel.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportPanel.java similarity index 98% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ExportPanel.java rename to Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportPanel.java index 7e635c3f64..8e2ea7989b 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ExportPanel.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportPanel.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datasourcesummary.ui; +package org.sleuthkit.autopsy.report.modules.datasourcesummaryexport; /** * The panel that provides options for exporting data source summary data. diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/PieChartExport.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/PieChartExport.java similarity index 93% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/PieChartExport.java rename to Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/PieChartExport.java index 4005a34ebc..cf37119996 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/PieChartExport.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/PieChartExport.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datasourcesummary.uiutils; +package org.sleuthkit.autopsy.report.modules.datasourcesummaryexport; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; @@ -35,10 +35,10 @@ import org.apache.poi.xssf.usermodel.XSSFClientAnchor; import org.apache.poi.xssf.usermodel.XSSFDrawing; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.openxmlformats.schemas.drawingml.x2006.chart.CTPieChart; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelExport.ExcelExportException; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelExport.ExcelSheetExport; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelSpecialFormatExport.ExcelItemExportable; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelSpecialFormatExport.ItemDimensions; +import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExport.ExcelExportException; +import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExport.ExcelSheetExport; +import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelSpecialFormatExport.ExcelItemExportable; +import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelSpecialFormatExport.ItemDimensions; /** * @@ -51,7 +51,7 @@ public class PieChartExport implements ExcelItemExportable, ExcelSheetExport { private static final int DEFAULT_ROW_PADDING = 1; private static final int DEFAULT_COL_OFFSET = 1; - private final ExcelTableExport tableExport; + private final ExcelTableExport tableExport; private final int colOffset; private final int rowPadding; private final int colSize; diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/PieChartItem.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/PieChartItem.java new file mode 100755 index 0000000000..3b18a8c41c --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/PieChartItem.java @@ -0,0 +1,67 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit 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; + +/** + * An individual pie chart slice in the pie chart. + */ +public class PieChartItem { + + private final String label; + private final double value; + private final Color color; + + /** + * Main constructor. + * + * @param label The label for this pie slice. + * @param value The value for this item. + * @param color The color for the pie slice. Can be null for + * auto-determined. + */ + public PieChartItem(String label, double value, Color color) { + this.label = label; + this.value = value; + this.color = color; + } + + /** + * @return The label for this item. + */ + public String getLabel() { + return label; + } + + /** + * @return The value for this item. + */ + public double getValue() { + return value; + } + + /** + * @return The color for the pie slice or null for auto-determined. + */ + public Color getColor() { + return color; + } + +} From e87c91a40dafcd4f90bd417e9096e7e9e59bc8d2 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Thu, 5 Aug 2021 10:08:44 -0400 Subject: [PATCH 03/33] More refacturing --- .../Bundle.properties-MERGED | 1 - .../datasourcesummaryexport/CellModel.java | 85 +++++++++++ .../datasourcesummaryexport/ColumnModel.java | 12 +- .../DefaultCellModel.java | 63 ++------ .../datasourcesummaryexport/ExcelExport.java | 8 +- .../ExcelExportAction.java | 4 +- .../ExcelExportDialog.form | 111 -------------- .../ExcelExportDialog.java | 143 ------------------ .../ExcelTableExport.java | 12 +- .../datasourcesummaryexport/ExportPanel.form | 68 --------- .../datasourcesummaryexport/ExportPanel.java | 105 ------------- 11 files changed, 112 insertions(+), 500 deletions(-) create mode 100755 Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/CellModel.java delete mode 100644 Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportDialog.form delete mode 100644 Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportDialog.java delete mode 100644 Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportPanel.form delete mode 100644 Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportPanel.java diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED index bb28c7960e..4388aad3e7 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED @@ -15,4 +15,3 @@ ExcelExportAction_runXLSXExport_progressCancelActionTitle=Cancelling... ExcelExportAction_runXLSXExport_progressCancelTitle=Cancel # {0} - dataSource ExcelExportAction_runXLSXExport_progressTitle=Exporting {0} to XLSX -ExcelExportDialog_title=Data Source Summary Exported diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/CellModel.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/CellModel.java new file mode 100755 index 0000000000..bae7d770b7 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/CellModel.java @@ -0,0 +1,85 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit 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 javax.swing.JLabel; +import org.apache.poi.ss.usermodel.HorizontalAlignment; + +/** + * Basic interface for a cell model. + */ +interface CellModel { + + /** + * Describes the horizontal alignment. + */ + enum HorizontalAlign { + LEFT(JLabel.LEFT, HorizontalAlignment.LEFT), + CENTER(JLabel.CENTER, HorizontalAlignment.CENTER), + RIGHT(JLabel.RIGHT, HorizontalAlignment.RIGHT); + + private final int jlabelAlignment; + private final HorizontalAlignment poiAlignment; + + /** + * Constructor for a HorizontalAlign enum. + * + * @param jlabelAlignment The corresponding JLabel horizontal alignment + * number. + * @param poiAlignment Horizontal alignment for Apache POI. + */ + HorizontalAlign(int jlabelAlignment, HorizontalAlignment poiAlignment) { + this.jlabelAlignment = jlabelAlignment; + this.poiAlignment = poiAlignment; + } + + /** + * @return The corresponding JLabel horizontal alignment (i.e. + * JLabel.LEFT). + */ + int getJLabelAlignment() { + return this.jlabelAlignment; + } + + /** + * @return Horizontal alignment for Apache POI. + */ + HorizontalAlignment getPoiAlignment() { + return poiAlignment; + } + } + + /** + * @return The root data object. + */ + Object getData(); + + /** + * @return The text to be shown in the cell. + */ + default String getText() { + Object data = getData(); + return (data == null) ? null : data.toString(); + } + + /** + * @return The horizontal alignment for the text in the cell. + */ + HorizontalAlign getHorizontalAlignment(); +} diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ColumnModel.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ColumnModel.java index 134f86f174..9c68de3992 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ColumnModel.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ColumnModel.java @@ -25,7 +25,7 @@ import java.util.function.Function; * getJTablePanel. 'T' represents the object that will represent rows in the * table. */ -public class ColumnModel { +class ColumnModel { private final String headerTitle; private final Function cellRenderer; @@ -38,7 +38,7 @@ public class ColumnModel { * @param cellRenderer The method that generates a CellModel for the column * based on the data. */ - public ColumnModel(String headerTitle, Function cellRenderer) { + ColumnModel(String headerTitle, Function cellRenderer) { this(headerTitle, cellRenderer, null); } @@ -50,7 +50,7 @@ public class ColumnModel { * based on the data. * @param width The preferred width of the column. */ - public ColumnModel(String headerTitle, Function cellRenderer, Integer width) { + ColumnModel(String headerTitle, Function cellRenderer, Integer width) { this.headerTitle = headerTitle; this.cellRenderer = cellRenderer; this.width = width; @@ -59,7 +59,7 @@ public class ColumnModel { /** * @return The title for the column. */ - public String getHeaderTitle() { + String getHeaderTitle() { return headerTitle; } @@ -67,14 +67,14 @@ public class ColumnModel { * @return The method that generates a CellModel for the column based on the * data. */ - public Function getCellRenderer() { + Function getCellRenderer() { return cellRenderer; } /** * @return The preferred width of the column (can be null). */ - public Integer getWidth() { + Integer getWidth() { return width; } } diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DefaultCellModel.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DefaultCellModel.java index 5553aa6d73..149d3413f6 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DefaultCellModel.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DefaultCellModel.java @@ -19,64 +19,21 @@ package org.sleuthkit.autopsy.report.modules.datasourcesummaryexport; import java.util.function.Function; -import javax.swing.JLabel; -import org.apache.poi.ss.usermodel.HorizontalAlignment; - /** * The default cell model. */ -class DefaultCellModel { +class DefaultCellModel implements CellModel { private final T data; private final String text; - private HorizontalAlign horizontalAlignment; - private final String excelFormatString; - - /** - * Describes the horizontal alignment. - */ - enum HorizontalAlign { - LEFT(JLabel.LEFT, HorizontalAlignment.LEFT), - CENTER(JLabel.CENTER, HorizontalAlignment.CENTER), - RIGHT(JLabel.RIGHT, HorizontalAlignment.RIGHT); - - private final int jlabelAlignment; - private final HorizontalAlignment poiAlignment; - - /** - * Constructor for a HorizontalAlign enum. - * - * @param jlabelAlignment The corresponding JLabel horizontal alignment - * number. - * @param poiAlignment Horizontal alignment for Apache POI. - */ - HorizontalAlign(int jlabelAlignment, HorizontalAlignment poiAlignment) { - this.jlabelAlignment = jlabelAlignment; - this.poiAlignment = poiAlignment; - } - - /** - * @return The corresponding JLabel horizontal alignment (i.e. - * JLabel.LEFT). - */ - int getJLabelAlignment() { - return this.jlabelAlignment; - } - - /** - * @return Horizontal alignment for Apache POI. - */ - HorizontalAlignment getPoiAlignment() { - return poiAlignment; - } - } + private CellModel.HorizontalAlign horizontalAlignment; /** * Main constructor. * * @param data The data to be displayed in the cell. */ - public DefaultCellModel(T data) { + DefaultCellModel(T data) { this(data, null, null); } @@ -87,7 +44,7 @@ class DefaultCellModel { * @param stringConverter The means of converting that data to a string or * null to use .toString method on object. */ - public DefaultCellModel(T data, Function stringConverter) { + DefaultCellModel(T data, Function stringConverter) { this(data, stringConverter, null); } @@ -103,9 +60,8 @@ class DefaultCellModel { * NOTE: Only certain data types can be exported. See * ExcelTableExport.createCell() for types. */ - public DefaultCellModel(T data, Function stringConverter, String excelFormatString) { + DefaultCellModel(T data, Function stringConverter, String excelFormatString) { this.data = data; - this.excelFormatString = excelFormatString; if (stringConverter == null) { text = this.data == null ? "" : this.data.toString(); @@ -114,18 +70,17 @@ class DefaultCellModel { } } + @Override public T getData() { return this.data; } - public String getExcelFormatString() { - return this.excelFormatString; - } - + @Override public String getText() { return text; } + @Override public HorizontalAlign getHorizontalAlignment() { return horizontalAlignment; } @@ -137,7 +92,7 @@ class DefaultCellModel { * * @return As a utility, returns this. */ - public DefaultCellModel setHorizontalAlignment(HorizontalAlign alignment) { + DefaultCellModel setHorizontalAlignment(CellModel.HorizontalAlign alignment) { this.horizontalAlignment = alignment; return this; } diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExport.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExport.java index b7e2c04fec..1e7a7d9a89 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExport.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExport.java @@ -37,7 +37,7 @@ import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.DefaultCellModel.HorizontalAlign; +import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.CellModel.HorizontalAlign; /** * Class for handling Excel exporting. @@ -337,11 +337,11 @@ public class ExcelExport { * @param cellStyle The style to use. * @return The created cell. */ - static Cell createCell(WorksheetEnv env, Row row, int colNum, DefaultCellModel cellModel, Optional cellStyle) { + static Cell createCell(WorksheetEnv env, Row row, int colNum, CellModel cellModel, Optional cellStyle) { CellStyle cellStyleToUse = cellStyle.orElse(env.getDefaultCellStyle()); - if (cellModel.getExcelFormatString() != null || cellModel.getHorizontalAlignment() != null) { - cellStyleToUse = env.getCellStyle(new CellStyleKey(cellModel.getExcelFormatString(), cellStyleToUse, cellModel.getHorizontalAlignment())); + if (cellModel.getText() != null || cellModel.getHorizontalAlignment() != null) { + cellStyleToUse = env.getCellStyle(new CellStyleKey(cellModel.getText(), cellStyleToUse, cellModel.getHorizontalAlignment())); } Object cellData = cellModel.getData(); diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java index 1c8e6fb6cb..b839fe8aac 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java @@ -285,13 +285,13 @@ class ExcelExportAction implements Consumer { dataSource); // and show finished dialog - SwingUtilities.invokeLater(() -> { + /* ELTODO SwingUtilities.invokeLater(() -> { ExcelExportDialog dialog = new ExcelExportDialog(WindowManager.getDefault().getMainWindow(), path); dialog.setResizable(false); dialog.setLocationRelativeTo(WindowManager.getDefault().getMainWindow()); dialog.setVisible(true); dialog.toFront(); - }); + });*/ } catch (NoCurrentCaseException | TskCoreException ex) { logger.log(Level.WARNING, "There was an error attaching report to case.", ex); diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportDialog.form b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportDialog.form deleted file mode 100644 index 7bc59aa544..0000000000 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportDialog.form +++ /dev/null @@ -1,111 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportDialog.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportDialog.java deleted file mode 100644 index 448566b6af..0000000000 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportDialog.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2021 Basis Technology Corp. - * Contact: carrier sleuthkit 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.Cursor; -import java.awt.Desktop; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.io.File; -import java.io.IOException; -import java.util.logging.Level; -import javax.swing.SwingUtilities; -import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.coreutils.Logger; - -/** - * Dialog showing where the data source summary excel export can be located. - */ -@Messages({ - "ExcelExportDialog_title=Data Source Summary Exported" -}) -public class ExcelExportDialog extends javax.swing.JDialog { - - private static final Logger logger = Logger.getLogger(ExcelExportDialog.class.getName()); - - /** - * Creates new form ExcelExportDialog - */ - public ExcelExportDialog(java.awt.Frame parent, File filePath) { - super(parent, true); - - initComponents(); - setTitle(Bundle.ExcelExportDialog_title()); - - this.linkText.setText(filePath.getAbsolutePath()); - this.linkText.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent e) { - SwingUtilities.invokeLater(() -> { - try { - Desktop.getDesktop().open(filePath); - } catch (IOException ex) { - logger.log(Level.WARNING, "Unable to open: " + filePath.getAbsolutePath(), ex); - } - }); - } - - }); - this.linkText.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - } - - /** - * This method is called from within the constructor to initialize the form. - * WARNING: Do NOT modify this code. The content of this method is always - * regenerated by the Form Editor. - */ - @SuppressWarnings("unchecked") - // //GEN-BEGIN:initComponents - private void initComponents() { - - javax.swing.JLabel titleLabel = new javax.swing.JLabel(); - javax.swing.JButton okButton = new javax.swing.JButton(); - javax.swing.JScrollPane linkTextScrollPane = new javax.swing.JScrollPane(); - linkText = new javax.swing.JTextArea(); - - setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); - - org.openide.awt.Mnemonics.setLocalizedText(titleLabel, org.openide.util.NbBundle.getMessage(ExcelExportDialog.class, "ExcelExportDialog.titleLabel.text")); // NOI18N - - org.openide.awt.Mnemonics.setLocalizedText(okButton, org.openide.util.NbBundle.getMessage(ExcelExportDialog.class, "ExcelExportDialog.okButton.text")); // NOI18N - okButton.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - okButtonActionPerformed(evt); - } - }); - - linkText.setEditable(false); - linkText.setBackground(null); - linkText.setColumns(20); - linkText.setForeground(java.awt.Color.BLUE); - linkText.setLineWrap(true); - linkText.setRows(1); - linkText.setWrapStyleWord(true); - linkText.setBorder(null); - linkText.setOpaque(false); - linkTextScrollPane.setViewportView(linkText); - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); - getContentPane().setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(linkTextScrollPane) - .addGroup(layout.createSequentialGroup() - .addGap(0, 0, Short.MAX_VALUE) - .addComponent(okButton)) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() - .addComponent(titleLabel) - .addGap(0, 116, Short.MAX_VALUE))) - .addContainerGap()) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addComponent(titleLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(linkTextScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 39, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(okButton) - .addContainerGap()) - ); - - pack(); - }// //GEN-END:initComponents - - private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed - dispose(); - }//GEN-LAST:event_okButtonActionPerformed - - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JTextArea linkText; - // End of variables declaration//GEN-END:variables -} diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelTableExport.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelTableExport.java index c861d5d174..b31c7da507 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelTableExport.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelTableExport.java @@ -32,7 +32,7 @@ import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelSpecial /** * An excel sheet export of table data. */ -public class ExcelTableExport implements ExcelSheetExport, ExcelItemExportable { +class ExcelTableExport implements ExcelSheetExport, ExcelItemExportable { private final String sheetName; private final List> columns; @@ -47,7 +47,7 @@ public class ExcelTableExport implements ExcelShe * @param columns The columns of the table. * @param data The data to export. */ - public ExcelTableExport(String sheetName, List> columns, List data) { + ExcelTableExport(String sheetName, List> columns, List data) { this(sheetName, columns, data, 0); } @@ -60,7 +60,7 @@ public class ExcelTableExport implements ExcelShe * @param data The data to export. * @param columnIndent The column indent. */ - public ExcelTableExport(String sheetName, List> columns, List data, int columnIndent) { + ExcelTableExport(String sheetName, List> columns, List data, int columnIndent) { this.sheetName = sheetName; this.columns = columns; this.data = data; @@ -104,7 +104,7 @@ public class ExcelTableExport implements ExcelShe * @throws ExcelExportException * @return The number of rows (including the header) written. */ - private static int renderSheet( + private static int renderSheet( Sheet sheet, ExcelExport.WorksheetEnv worksheetEnv, int rowStart, @@ -127,8 +127,8 @@ public class ExcelTableExport implements ExcelShe T rowData = safeData.get(rowNum); Row row = sheet.createRow(rowNum + rowStart + 1); for (int colNum = 0; colNum < columns.size(); colNum++) { - ColumnModel colModel = columns.get(colNum); - DefaultCellModel cellModel = colModel.getCellRenderer().apply(rowData); + ColumnModel colModel = columns.get(colNum); + CellModel cellModel = colModel.getCellRenderer().apply(rowData); ExcelExport.createCell(worksheetEnv, row, colNum + colStart, cellModel, Optional.empty()); } } diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportPanel.form b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportPanel.form deleted file mode 100644 index 908facb8d6..0000000000 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportPanel.form +++ /dev/null @@ -1,68 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportPanel.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportPanel.java deleted file mode 100644 index 8e2ea7989b..0000000000 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportPanel.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2021 Basis Technology Corp. - * Contact: carrier sleuthkit 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; - -/** - * The panel that provides options for exporting data source summary data. - */ -public class ExportPanel extends javax.swing.JPanel { - - private Runnable xlsxExportAction; - - /** - * Creates new form ExportPanel - */ - public ExportPanel() { - initComponents(); - } - - /** - * Returns the action that handles exporting to excel. - * - * @return The action that handles exporting to excel. - */ - public Runnable getXlsxExportAction() { - return xlsxExportAction; - } - - /** - * Sets the action that handles exporting to excel. - * - * @param onXlsxExport The action that handles exporting to excel. - */ - public void setXlsxExportAction(Runnable onXlsxExport) { - this.xlsxExportAction = onXlsxExport; - } - - /** - * This method is called from within the constructor to initialize the form. - * WARNING: Do NOT modify this code. The content of this method is always - * regenerated by the Form Editor. - */ - @SuppressWarnings("unchecked") - // //GEN-BEGIN:initComponents - private void initComponents() { - - javax.swing.JButton xlsxExportButton = new javax.swing.JButton(); - javax.swing.JLabel xlsxExportMessage = new javax.swing.JLabel(); - - org.openide.awt.Mnemonics.setLocalizedText(xlsxExportButton, org.openide.util.NbBundle.getMessage(ExportPanel.class, "ExportPanel.xlsxExportButton.text")); // NOI18N - xlsxExportButton.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - xlsxExportButtonActionPerformed(evt); - } - }); - - org.openide.awt.Mnemonics.setLocalizedText(xlsxExportMessage, org.openide.util.NbBundle.getMessage(ExportPanel.class, "ExportPanel.xlsxExportMessage.text")); // NOI18N - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); - this.setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(xlsxExportMessage) - .addComponent(xlsxExportButton)) - .addContainerGap(62, Short.MAX_VALUE)) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addComponent(xlsxExportMessage) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(xlsxExportButton) - .addContainerGap(250, Short.MAX_VALUE)) - ); - }// //GEN-END:initComponents - - private void xlsxExportButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_xlsxExportButtonActionPerformed - if (this.xlsxExportAction != null) { - xlsxExportAction.run(); - } - }//GEN-LAST:event_xlsxExportButtonActionPerformed - - - // Variables declaration - do not modify//GEN-BEGIN:variables - // End of variables declaration//GEN-END:variables -} From 71206158efd9c0de2ba81d32debb2a6b644dc449 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Thu, 5 Aug 2021 10:34:16 -0400 Subject: [PATCH 04/33] Refactoring --- .../datasourcesummary/ui/AnalysisPanel.java | 2 +- .../datasourcesummary/ui/ContainerPanel.java | 4 +- .../ui/GeolocationPanel.java | 2 +- .../ui/IngestJobExcelExport.java | 4 +- .../datasourcesummary/ui/PastCasesPanel.java | 2 +- .../ui/RecentFilesPanel.java | 2 +- .../datasourcesummary/ui/TimelinePanel.java | 2 +- .../datasourcesummary/ui/TypesPanel.java | 6 +-- .../ui/UserActivityPanel.java | 2 +- .../uiutils/DefaultCellModel.java | 2 +- .../BarChartExport.java | 10 ++--- .../DataSourceSummaryReport.java | 2 +- .../datasourcesummaryexport/ExcelExport.java | 25 ++++++------ .../ExcelSpecialFormatExport.java | 40 +++++++++---------- .../PieChartExport.java | 8 ++-- 15 files changed, 56 insertions(+), 57 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/AnalysisPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/AnalysisPanel.java index 99da8fbd5a..10f0df97dd 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/AnalysisPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/AnalysisPanel.java @@ -226,7 +226,7 @@ public class AnalysisPanel extends BaseDataSourceSummaryPanel { ); }// //GEN-END:initComponents - /* ELODO + /* ELTODO @Override List getExports(DataSource dataSource) { return Stream.of( diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java index 0fc66a4c72..1f46f48d48 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java @@ -480,7 +480,7 @@ class ContainerPanel extends BaseDataSourceSummaryPanel { * @return The list of key value pairs that can be incorporated into the * excel export. */ - /* ELODO + /* ELTODO private static List getAcquisitionDetails(String acquisitionDetails) { if (StringUtils.isBlank(acquisitionDetails)) { return Collections.emptyList(); @@ -492,7 +492,7 @@ class ContainerPanel extends BaseDataSourceSummaryPanel { } }*/ - /* ELODO + /* ELTODO @Messages({ "ContainerPanel_export_displayName=Display Name:", "ContainerPanel_export_originalName=Name:", diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/GeolocationPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/GeolocationPanel.java index fd3ad98dcc..595209f064 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/GeolocationPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/GeolocationPanel.java @@ -348,7 +348,7 @@ public class GeolocationPanel extends BaseDataSourceSummaryPanel { onNewDataSource(dataFetchComponents, tables, dataSource); } - /* ELODO + /* ELTODO @Override List getExports(DataSource dataSource) { GeolocationViewModel model = getFetchResult(geolocationFetcher, "Geolocation sheets", dataSource); diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/IngestJobExcelExport.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/IngestJobExcelExport.java index 07d789c0fa..5ec92353e2 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/IngestJobExcelExport.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/IngestJobExcelExport.java @@ -52,7 +52,7 @@ import org.sleuthkit.datamodel.TskCoreException; "IngestJobExcelExport_versionColumn=Module Version", "IngestJobExcelExport_sheetName=Ingest History" }) -class IngestJobExcelExport { +class IngestJobExcelExport { // ELTODO remove this class /** * An entry to display in an excel export. @@ -209,7 +209,7 @@ class IngestJobExcelExport { * @param dataSource The data source. * @return The list of sheets to be included in an export. */ - /* ELODO + /* ELTODO static List getExports(DataSource dataSource) { if (dataSource == null) { return Collections.emptyList(); diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesPanel.java index d49bcfdff0..cdce933a1c 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesPanel.java @@ -124,7 +124,7 @@ public class PastCasesPanel extends BaseDataSourceSummaryPanel { onNewDataSource(dataFetchComponents, tables, dataSource); } - /* ELODO + /* ELTODO @Override List getExports(DataSource dataSource) { PastCasesResult result = getFetchResult(pastCasesFetcher, "Past cases sheets", dataSource); diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesPanel.java index 6bb0ba78af..52e0721cc8 100755 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesPanel.java @@ -186,7 +186,7 @@ public final class RecentFilesPanel extends BaseDataSourceSummaryPanel { onNewDataSource(dataFetchComponents, tablePanelList, dataSource); } - /* ELODO + /* ELTODO @Override List getExports(DataSource dataSource) { return Stream.of( diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java index d2dfb8d261..318da42943 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java @@ -299,7 +299,7 @@ public class TimelinePanel extends BaseDataSourceSummaryPanel { return new DefaultCellModel<>(date, (dt) -> dt == null ? "" : EARLIEST_LATEST_FORMAT.format(dt), EARLIEST_LATEST_FORMAT_STR); } - /* ELODO + /* ELTODO @Messages({ "TimelinePanel_getExports_sheetName=Timeline", "TimelinePanel_getExports_activityRange=Activity Range", diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java index 3f1b19e1a4..3e9ec03ea0 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java @@ -416,7 +416,7 @@ class TypesPanel extends BaseDataSourceSummaryPanel { * @param dataSource The data source containing the data. * @return The key value pair to be exported. */ - /* ELODO private static KeyValueItemExportable getStrExportable(DataFetcher fetcher, String key, DataSource dataSource) { + /* ELTODO private static KeyValueItemExportable getStrExportable(DataFetcher fetcher, String key, DataSource dataSource) { String result = getFetchResult(fetcher, "Types", dataSource); return (result == null) ? null : new KeyValueItemExportable(key, new DefaultCellModel<>(result)); } @@ -430,13 +430,13 @@ class TypesPanel extends BaseDataSourceSummaryPanel { * @param dataSource The data source. * @return The key value pair. */ - /* ELODOprivate static KeyValueItemExportable getCountExportable(DataFetcher fetcher, String key, DataSource dataSource) { + /* ELTODOprivate static KeyValueItemExportable getCountExportable(DataFetcher fetcher, String key, DataSource dataSource) { Long count = getFetchResult(fetcher, "Types", dataSource); return (count == null) ? null : new KeyValueItemExportable(key, new DefaultCellModel(count, COMMA_FORMATTER::format, COMMA_FORMAT_STR)); } - /* ELODO + /* ELTODO @Override List getExports(DataSource dataSource) { if (dataSource == null) { diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivityPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivityPanel.java index 72f19ada78..2d58c09742 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivityPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivityPanel.java @@ -362,7 +362,7 @@ public class UserActivityPanel extends BaseDataSourceSummaryPanel { super.close(); } - /* ELODO + /* ELTODO @Override List getExports(DataSource dataSource) { return Stream.of( diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DefaultCellModel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DefaultCellModel.java index de0319ebf8..3d2e4e6a5a 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DefaultCellModel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DefaultCellModel.java @@ -35,7 +35,7 @@ public class DefaultCellModel implements GuiCellModel { private CellModel.HorizontalAlign horizontalAlignment; private List popupMenu; private Supplier> menuItemSupplier; - private final String excelFormatString; + private final String excelFormatString; // ELTODO /** * Main constructor. diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/BarChartExport.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/BarChartExport.java index edb71c21a9..8ff16075e3 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/BarChartExport.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/BarChartExport.java @@ -57,7 +57,7 @@ import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelSpecial /** * Class that creates an excel stacked bar chart along with data table. */ -public class BarChartExport implements ExcelItemExportable, ExcelSheetExport { +class BarChartExport implements ExcelItemExportable, ExcelSheetExport { /** * Creates an excel table model to be written to an excel sheet and used as @@ -70,7 +70,7 @@ public class BarChartExport implements ExcelItemExportable, ExcelSheetExport { * @return An excel table export to be used as the data source for the chart * in the excel document. */ - private static ExcelTableExport>, ? extends DefaultCellModel> getTableModel( + private static ExcelTableExport>, ? extends CellModel> getTableModel( List categories, String keyColumnHeader, String chartTitle) { // get the row keys by finding the series with the largest set of bar items @@ -134,7 +134,7 @@ public class BarChartExport implements ExcelItemExportable, ExcelSheetExport { private static final int DEFAULT_ROW_PADDING = 1; private static final int DEFAULT_COL_OFFSET = 1; - private final ExcelTableExport>, ? extends DefaultCellModel> tableExport; + private final ExcelTableExport>, ? extends CellModel> tableExport; private final int colOffset; private final int rowPadding; private final int colSize; @@ -154,7 +154,7 @@ public class BarChartExport implements ExcelItemExportable, ExcelSheetExport { * @param chartTitle The title for the chart. * @param categories The categories along with data. */ - public BarChartExport(String keyColumnHeader, + BarChartExport(String keyColumnHeader, String valueFormatString, String chartTitle, List categories) { @@ -177,7 +177,7 @@ public class BarChartExport implements ExcelItemExportable, ExcelSheetExport { * @param colSize The column size of the chart. * @param rowSize The row size of the chart. */ - public BarChartExport(String keyColumnHeader, String valueFormatString, + BarChartExport(String keyColumnHeader, String valueFormatString, String chartTitle, String sheetName, List categories, int colOffset, int rowPadding, int colSize, int rowSize) { diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DataSourceSummaryReport.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DataSourceSummaryReport.java index e4b4483675..4713fa8f0e 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DataSourceSummaryReport.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DataSourceSummaryReport.java @@ -69,7 +69,7 @@ class DataSourceSummaryReport implements GeneralReportModule { @Override public JPanel getConfigurationPanel() { - return null; // No configuration panel + return null; // ELTODO } @Override diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExport.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExport.java index 1e7a7d9a89..434ab34e96 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExport.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExport.java @@ -42,19 +42,19 @@ import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.CellModel.Ho /** * Class for handling Excel exporting. */ -public class ExcelExport { +class ExcelExport { /** * Exception thrown in the event of an excel export issue. */ - public static class ExcelExportException extends Exception { + static class ExcelExportException extends Exception { /** * Constructor. * * @param string The message. */ - public ExcelExportException(String string) { + ExcelExportException(String string) { super(string); } @@ -64,7 +64,7 @@ public class ExcelExport { * @param string The message. * @param thrwbl The inner exception. */ - public ExcelExportException(String string, Throwable thrwbl) { + ExcelExportException(String string, Throwable thrwbl) { super(string, thrwbl); } } @@ -153,7 +153,7 @@ public class ExcelExport { /** * Class detailing aspects of the worksheet. */ - public static class WorksheetEnv { + static class WorksheetEnv { private final CellStyle headerStyle; private final Workbook parentWorkbook; @@ -182,7 +182,7 @@ public class ExcelExport { * @param cellStyleKey The key. * @return The cell style representing this key. */ - public CellStyle getCellStyle(CellStyleKey cellStyleKey) { + CellStyle getCellStyle(CellStyleKey cellStyleKey) { return cellStyleCache.computeIfAbsent(cellStyleKey, (pair) -> { CellStyle computed = this.parentWorkbook.createCellStyle(); computed.cloneStyleFrom(cellStyleKey.getCellStyle() == null ? defaultStyle : cellStyleKey.getCellStyle()); @@ -203,7 +203,7 @@ public class ExcelExport { * * @return The cell style to use for headers. */ - public CellStyle getHeaderStyle() { + CellStyle getHeaderStyle() { return headerStyle; } @@ -212,7 +212,7 @@ public class ExcelExport { * * @return The cell style for default items. */ - public CellStyle getDefaultCellStyle() { + CellStyle getDefaultCellStyle() { return defaultStyle; } @@ -221,7 +221,7 @@ public class ExcelExport { * * @return The parent workbook. */ - public Workbook getParentWorkbook() { + Workbook getParentWorkbook() { return parentWorkbook; } } @@ -229,7 +229,7 @@ public class ExcelExport { /** * An item to be exported as a sheet during export. */ - public static interface ExcelSheetExport { + static interface ExcelSheetExport { /** * Returns the name of the sheet to use with this item. @@ -257,7 +257,7 @@ public class ExcelExport { * * @return The instance. */ - public static ExcelExport getInstance() { + static ExcelExport getInstance() { if (instance == null) { instance = new ExcelExport(); } @@ -266,7 +266,6 @@ public class ExcelExport { } private ExcelExport() { - } /** @@ -281,7 +280,7 @@ public class ExcelExport { "# {0} - sheetNumber", "ExcelExport_writeExcel_noSheetName=Sheet {0}" }) - public void writeExcel(List exports, File path) throws IOException, ExcelExportException { + void writeExcel(List exports, File path) throws IOException, ExcelExportException { // Create a Workbook Workbook workbook = new XSSFWorkbook(); // new HSSFWorkbook() for generating `.xls` file diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelSpecialFormatExport.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelSpecialFormatExport.java index 71683d1d26..cd30e7d816 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelSpecialFormatExport.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelSpecialFormatExport.java @@ -28,13 +28,13 @@ import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExport. /** * An excel export that has special row-by-row formatting. */ -public class ExcelSpecialFormatExport implements ExcelExport.ExcelSheetExport { +class ExcelSpecialFormatExport implements ExcelExport.ExcelSheetExport { /** * The dimensions consumed by an item in an ExcelSpecialFormatExport list of * items to be rendered. */ - public static class ItemDimensions { + static class ItemDimensions { private final int rowStart; private final int rowEnd; @@ -49,7 +49,7 @@ public class ExcelSpecialFormatExport implements ExcelExport.ExcelSheetExport { * @param rowEnd The last excel row of the the item. * @param colEnd The last excel column of the item. */ - public ItemDimensions(int rowStart, int colStart, int rowEnd, int colEnd) { + ItemDimensions(int rowStart, int colStart, int rowEnd, int colEnd) { this.rowStart = rowStart; this.colStart = colStart; this.rowEnd = rowEnd; @@ -59,28 +59,28 @@ public class ExcelSpecialFormatExport implements ExcelExport.ExcelSheetExport { /** * @return The starting excel row of the item. */ - public int getRowStart() { + int getRowStart() { return rowStart; } /** * @return The last excel row of the the item. */ - public int getRowEnd() { + int getRowEnd() { return rowEnd; } /** * @return The starting excel column of the item. */ - public int getColStart() { + int getColStart() { return colStart; } /** * @return The last excel column of the item. */ - public int getColEnd() { + int getColEnd() { return colEnd; } } @@ -88,7 +88,7 @@ public class ExcelSpecialFormatExport implements ExcelExport.ExcelSheetExport { /** * An item to be exported in a specially formatted excel export. */ - public interface ExcelItemExportable { + interface ExcelItemExportable { /** * Writes the item to the sheet in the special format export sheet. @@ -106,16 +106,16 @@ public class ExcelSpecialFormatExport implements ExcelExport.ExcelSheetExport { /** * Writes a string to a single cell in a specially formatted excel export. */ - public static class SingleCellExportable implements ExcelItemExportable { + static class SingleCellExportable implements ExcelItemExportable { - private final DefaultCellModel item; + private final CellModel item; /** * Main constructor. * * @param key The text to be written. */ - public SingleCellExportable(String key) { + SingleCellExportable(String key) { this(new DefaultCellModel<>(key)); } @@ -124,7 +124,7 @@ public class ExcelSpecialFormatExport implements ExcelExport.ExcelSheetExport { * * @param item The cell model to be written. */ - public SingleCellExportable(DefaultCellModel item) { + SingleCellExportable(CellModel item) { this.item = item; } @@ -140,10 +140,10 @@ public class ExcelSpecialFormatExport implements ExcelExport.ExcelSheetExport { * Writes a row consisting of first column as a key and second column as a * value. */ - public static class KeyValueItemExportable implements ExcelItemExportable { + static class KeyValueItemExportable implements ExcelItemExportable { - private final DefaultCellModel key; - private final DefaultCellModel value; + private final CellModel key; + private final CellModel value; /** * Main constructor. @@ -151,7 +151,7 @@ public class ExcelSpecialFormatExport implements ExcelExport.ExcelSheetExport { * @param key The string key to be exported. * @param value The cell model to be exported. */ - public KeyValueItemExportable(String key, DefaultCellModel value) { + KeyValueItemExportable(String key, CellModel value) { this(new DefaultCellModel<>(key), value); } @@ -161,7 +161,7 @@ public class ExcelSpecialFormatExport implements ExcelExport.ExcelSheetExport { * @param key The cell key to be exported. * @param value The cell model to be exported. */ - public KeyValueItemExportable(DefaultCellModel key, DefaultCellModel value) { + KeyValueItemExportable(CellModel key, CellModel value) { this.key = key; this.value = value; } @@ -186,7 +186,7 @@ public class ExcelSpecialFormatExport implements ExcelExport.ExcelSheetExport { * item 2 * */ - public static class TitledExportable implements ExcelItemExportable { + static class TitledExportable implements ExcelItemExportable { private static final int DEFAULT_INDENT = 1; @@ -199,7 +199,7 @@ public class ExcelSpecialFormatExport implements ExcelExport.ExcelSheetExport { * @param title The title for the export. * @param children The children to be indented and enumerated. */ - public TitledExportable(String title, List children) { + TitledExportable(String title, List children) { this.title = title; this.children = children; } @@ -232,7 +232,7 @@ public class ExcelSpecialFormatExport implements ExcelExport.ExcelSheetExport { * @param sheetName The name of the sheet. * @param exports The row-by-row items to be exported. */ - public ExcelSpecialFormatExport(String sheetName, List exports) { + ExcelSpecialFormatExport(String sheetName, List exports) { this.sheetName = sheetName; this.exports = exports == null ? Collections.emptyList() : exports; } diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/PieChartExport.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/PieChartExport.java index cf37119996..33ed70cb21 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/PieChartExport.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/PieChartExport.java @@ -44,14 +44,14 @@ import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelSpecial * * Class that creates an excel pie chart along with data table. */ -public class PieChartExport implements ExcelItemExportable, ExcelSheetExport { +class PieChartExport implements ExcelItemExportable, ExcelSheetExport { private static final int DEFAULT_ROW_SIZE = 20; private static final int DEFAULT_COL_SIZE = 10; private static final int DEFAULT_ROW_PADDING = 1; private static final int DEFAULT_COL_OFFSET = 1; - private final ExcelTableExport tableExport; + private final ExcelTableExport tableExport; private final int colOffset; private final int rowPadding; private final int colSize; @@ -69,7 +69,7 @@ public class PieChartExport implements ExcelItemExportable, ExcelSheetExport { * @param chartTitle The title for the chart. * @param slices The values for the pie slices. */ - public PieChartExport(String keyColumnHeader, + PieChartExport(String keyColumnHeader, String valueColumnHeader, String valueFormatString, String chartTitle, List slices) { @@ -93,7 +93,7 @@ public class PieChartExport implements ExcelItemExportable, ExcelSheetExport { * @param colSize The column size of the chart. * @param rowSize The row size of the chart. */ - public PieChartExport(String keyColumnHeader, + PieChartExport(String keyColumnHeader, String valueColumnHeader, String valueFormatString, String chartTitle, String sheetName, List slices, From 356206bf505d31efc536372330c0f83023724271 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Thu, 5 Aug 2021 11:21:34 -0400 Subject: [PATCH 05/33] Moved excel tab generation code to report --- .../ui/BaseDataSourceSummaryPanel.java | 98 ------------- .../Bundle.properties-MERGED | 8 ++ .../datasourcesummaryexport/DataFetcher.java | 43 ++++++ .../ExcelExportAction.java | 120 +++++++++++++++- .../ExportRecentFiles.java | 129 ++++++++++++++++++ 5 files changed, 299 insertions(+), 99 deletions(-) create mode 100755 Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DataFetcher.java create mode 100755 Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportRecentFiles.java diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/BaseDataSourceSummaryPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/BaseDataSourceSummaryPanel.java index 97965ec9e8..2241cbedd9 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/BaseDataSourceSummaryPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/BaseDataSourceSummaryPanel.java @@ -473,104 +473,6 @@ abstract class BaseDataSourceSummaryPanel extends JPanel { } } - /** - * Function that converts data into a excel sheet data. - */ - // ELTODO protected interface ExcelExportFunction { - - /** - * Function that converts data into an excel sheet. - * - * @param data The data. - * @return The excel sheet export. - * @throws ExcelExportException - */ - // ExcelSheetExport convert(T data) throws ExcelExportException; - //} - - /** - * Helper method that converts data into an excel sheet export handling - * possible excel exceptions. - * - * @param excelConverter Function to convert data to an excel sheet export. - * @param data The data. If data is null, null will be returned. - * @param sheetName The name(s) of the sheet (to be used in the error - * message). - * @return The excel sheet export. - */ - /* ELTODO - protected static ExcelSheetExport convertToExcel(ExcelExportFunction excelConverter, T data, String sheetName) { - if (data == null) { - return null; - } - - try { - return excelConverter.convert(data); - } catch (ExcelExportException ex) { - logger.log(Level.WARNING, - String.format("There was an error while preparing export of worksheet(s): '%s'", - sheetName == null ? "" : sheetName), ex); - return null; - } - }*/ - - /** - * Returns an excel sheet export given the fetching of data or null if no - * export created. - * - * @param dataFetcher The means of fetching data. - * @param excelConverter The means of converting data to excel. - * @param sheetName The name of the sheet (for error handling reporting). - * @param ds The data source to use for fetching data. - * @return The excel sheet export or null if no export could be generated. - */ - /* ELTODO - protected static ExcelSheetExport getExport( - DataFetcher dataFetcher, ExcelExportFunction excelConverter, - String sheetName, DataSource ds) { - - T data = getFetchResult(dataFetcher, sheetName, ds); - return convertToExcel(excelConverter, data, sheetName); - }*/ - - /** - * Returns an excel table export of the data or null if no export created. - * - * @param columnsModel The model for the columns. - * @param sheetName The name for the sheet. - * @param data The data to be exported. - * @return The excel table export or null if no export could be generated. - */ - /* ELTODO - protected static ExcelSheetExport getTableExport(List> columnsModel, - String sheetName, List data) { - - return convertToExcel((dataList) -> new ExcelTableExport(sheetName, columnsModel, dataList), - data, - sheetName); - }*/ - - /** - * Returns an excel table export of the data or null if no export created. - * - * @param dataFetcher The means of fetching data for the data source and the - * export. - * @param columnsModel The model for the columns. - * @param sheetName The name for the sheet. - * @param ds The data source. - * @return The excel export or null if no export created. - */ - /* ELTODO - protected static ExcelSheetExport getTableExport( - DataFetcher> dataFetcher, List> columnsModel, - String sheetName, DataSource ds) { - - return getExport(dataFetcher, - (dataList) -> new ExcelTableExport(sheetName, columnsModel, dataList), - sheetName, - ds); - }*/ - /** * Utility method that shows a loading screen with loadable components, * create swing workers from the datafetch components and data source diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED index 4388aad3e7..d754073fdc 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED @@ -15,3 +15,11 @@ ExcelExportAction_runXLSXExport_progressCancelActionTitle=Cancelling... ExcelExportAction_runXLSXExport_progressCancelTitle=Cancel # {0} - dataSource ExcelExportAction_runXLSXExport_progressTitle=Exporting {0} to XLSX +RecentFilePanel_col_header_domain=Domain +RecentFilePanel_col_header_path=Path +RecentFilePanel_col_header_sender=Sender +RecentFilePanel_emailParserModuleName=Email Parser +RecentFilesPanel_attachmentsTable_tabName=Recent Attachments +RecentFilesPanel_col_head_date=Date +RecentFilesPanel_docsTable_tabName=Recently Opened Documents +RecentFilesPanel_downloadsTable_tabName=Recently Downloads diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DataFetcher.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DataFetcher.java new file mode 100755 index 0000000000..f3b0b0fe6c --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DataFetcher.java @@ -0,0 +1,43 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier sleuthkit 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; + +/** + * A function that accepts input of type I and outputs type O. This function is + * meant to be utilized with DataFetchWorker and can therefore, throw an + * interrupted exception if the processing is cancelled or an Exception of on + * another type in the event that the fetching encountered an error. + */ +@FunctionalInterface +public interface DataFetcher { + + /** + * A function that accepts an input argument and outputs a result. Since it + * is meant to be used with the DataFetchWorker, it may throw an interrupted + * exception if the thread has been interrupted. It throws another type of + * exception if there is an error during fetching. + * + * @param input The input argument. + * + * @return The output result. + * + * @throws Exception + */ + O runQuery(I input) throws Exception; +} diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java index b839fe8aac..460c9bc554 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java @@ -34,7 +34,6 @@ import java.util.concurrent.ExecutionException; import java.util.function.Consumer; import java.util.logging.Level; import javax.swing.JOptionPane; -import javax.swing.SwingUtilities; import javax.swing.SwingWorker; import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; @@ -297,4 +296,123 @@ class ExcelExportAction implements Consumer { logger.log(Level.WARNING, "There was an error attaching report to case.", ex); } } + + /** + * Function that converts data into a excel sheet data. + */ + protected interface ExcelExportFunction { + + /** + * Function that converts data into an excel sheet. + * + * @param data The data. + * @return The excel sheet export. + * @throws ExcelExportException + */ + ExcelSheetExport convert(T data) throws ExcelExportException; + } + + /** + * Runs a data fetcher and returns the result handling any possible errors + * with a log message. + * + * @param dataFetcher The means of fetching the data. + * @param sheetName The name of the sheet. + * @param ds The data source. + * + * @return The fetched data. + */ + protected static T getFetchResult( + DataFetcher dataFetcher, + String sheetName, DataSource ds) { + + try { + return dataFetcher.runQuery(ds); + } catch (Exception ex) { + logger.log(Level.WARNING, + String.format("There was an error while acquiring data for exporting worksheet(s): '%s' for dataSource: %s", + sheetName == null ? "" : sheetName, + ds == null || ds.getName() == null ? "" : ds.getName()), ex); + return null; + } + } + + /** + * Helper method that converts data into an excel sheet export handling + * possible excel exceptions. + * + * @param excelConverter Function to convert data to an excel sheet export. + * @param data The data. If data is null, null will be returned. + * @param sheetName The name(s) of the sheet (to be used in the error + * message). + * @return The excel sheet export. + */ + protected static ExcelSheetExport convertToExcel(ExcelExportFunction excelConverter, T data, String sheetName) { + if (data == null) { + return null; + } + + try { + return excelConverter.convert(data); + } catch (ExcelExportException ex) { + logger.log(Level.WARNING, + String.format("There was an error while preparing export of worksheet(s): '%s'", + sheetName == null ? "" : sheetName), ex); + return null; + } + } + + /** + * Returns an excel sheet export given the fetching of data or null if no + * export created. + * + * @param dataFetcher The means of fetching data. + * @param excelConverter The means of converting data to excel. + * @param sheetName The name of the sheet (for error handling reporting). + * @param ds The data source to use for fetching data. + * @return The excel sheet export or null if no export could be generated. + */ + protected static ExcelSheetExport getExport( + DataFetcher dataFetcher, ExcelExportFunction excelConverter, + String sheetName, DataSource ds) { + + T data = getFetchResult(dataFetcher, sheetName, ds); + return convertToExcel(excelConverter, data, sheetName); + } + + /** + * Returns an excel table export of the data or null if no export created. + * + * @param columnsModel The model for the columns. + * @param sheetName The name for the sheet. + * @param data The data to be exported. + * @return The excel table export or null if no export could be generated. + */ + protected static ExcelSheetExport getTableExport(List> columnsModel, + String sheetName, List data) { + + return convertToExcel((dataList) -> new ExcelTableExport(sheetName, columnsModel, dataList), + data, + sheetName); + } + + /** + * Returns an excel table export of the data or null if no export created. + * + * @param dataFetcher The means of fetching data for the data source and the + * export. + * @param columnsModel The model for the columns. + * @param sheetName The name for the sheet. + * @param ds The data source. + * @return The excel export or null if no export created. + */ + protected static ExcelSheetExport getTableExport( + DataFetcher> dataFetcher, List> columnsModel, + String sheetName, DataSource ds) { + + return getExport(dataFetcher, + (dataList) -> new ExcelTableExport(sheetName, columnsModel, dataList), + sheetName, + ds); + } } diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportRecentFiles.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportRecentFiles.java new file mode 100755 index 0000000000..efa328c294 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportRecentFiles.java @@ -0,0 +1,129 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit 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.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Locale; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.contentutils.RecentFilesSummary; +import org.sleuthkit.autopsy.contentutils.RecentFilesSummary.RecentAttachmentDetails; +import org.sleuthkit.autopsy.contentutils.RecentFilesSummary.RecentDownloadDetails; +import org.sleuthkit.autopsy.contentutils.RecentFilesSummary.RecentFileDetails; +import org.sleuthkit.datamodel.DataSource; + +/** + * Data Source Summary recent files panel. + */ +@Messages({ + "RecentFilesPanel_docsTable_tabName=Recently Opened Documents", + "RecentFilesPanel_downloadsTable_tabName=Recently Downloads", + "RecentFilesPanel_attachmentsTable_tabName=Recent Attachments",}) +final class ExportRecentFiles { + + private static final String DATETIME_FORMAT_STR = "yyyy/MM/dd HH:mm:ss"; + private static final DateFormat DATETIME_FORMAT = new SimpleDateFormat(DATETIME_FORMAT_STR, Locale.getDefault()); + + private final DataFetcher> docsFetcher; + private final DataFetcher> downloadsFetcher; + private final DataFetcher> attachmentsFetcher; + + private final List>> docsTemplate = Arrays.asList( + new ColumnModel<>(Bundle.RecentFilePanel_col_header_path(), + (prog) -> { + return new DefaultCellModel<>(prog.getPath()); + }, 250), + new ColumnModel<>(Bundle.RecentFilesPanel_col_head_date(), + getDateFunct(), + 80)); + + private final List>> downloadsTemplate = Arrays.asList( + new ColumnModel<>(Bundle.RecentFilePanel_col_header_domain(), + (prog) -> { + return new DefaultCellModel<>(prog.getWebDomain()); + }, 100), + new ColumnModel<>(Bundle.RecentFilePanel_col_header_path(), + (prog) -> { + return new DefaultCellModel<>(prog.getPath()); + }, 250), + new ColumnModel<>(Bundle.RecentFilesPanel_col_head_date(), + getDateFunct(), + 80)); + + private final List>> attachmentsTemplate = Arrays.asList( + new ColumnModel<>(Bundle.RecentFilePanel_col_header_path(), + (prog) -> { + return new DefaultCellModel<>(prog.getPath()); + }, 250), + new ColumnModel<>(Bundle.RecentFilesPanel_col_head_date(), + getDateFunct(), + 80), + new ColumnModel<>(Bundle.RecentFilePanel_col_header_sender(), + (prog) -> { + return new DefaultCellModel<>(prog.getSender()); + }, 150)); + + /** + * Default constructor. + */ + @Messages({ + "RecentFilesPanel_col_head_date=Date", + "RecentFilePanel_col_header_domain=Domain", + "RecentFilePanel_col_header_path=Path", + "RecentFilePanel_col_header_sender=Sender", + "RecentFilePanel_emailParserModuleName=Email Parser" + }) + + /** + * Creates new form RecentFilesPanel + */ + ExportRecentFiles() { + docsFetcher = (dataSource) -> RecentFilesSummary.getRecentlyOpenedDocuments(dataSource, 10); + downloadsFetcher = (dataSource) -> RecentFilesSummary.getRecentDownloads(dataSource, 10); + attachmentsFetcher = (dataSource) -> RecentFilesSummary.getRecentAttachments(dataSource, 10); + } + + /** + * Returns a function that gets the date from the RecentFileDetails object and + * converts into a DefaultCellModel to be displayed in a table. + * + * @return The function that determines the date cell from a RecentFileDetails object. + */ + private Function> getDateFunct() { + return (T lastAccessed) -> { + Function dateParser = (dt) -> dt == null ? "" : DATETIME_FORMAT.format(dt); + return new DefaultCellModel<>(new Date(lastAccessed.getDateAsLong() * 1000), dateParser, DATETIME_FORMAT_STR); + }; + } + + List getExports(DataSource dataSource) { + return Stream.of( + ExcelExportAction.getTableExport(docsFetcher, docsTemplate, Bundle.RecentFilesPanel_docsTable_tabName(), dataSource), + ExcelExportAction.getTableExport(downloadsFetcher, downloadsTemplate, Bundle.RecentFilesPanel_downloadsTable_tabName(), dataSource), + ExcelExportAction.getTableExport(attachmentsFetcher, attachmentsTemplate, Bundle.RecentFilesPanel_attachmentsTable_tabName(), dataSource)) + .filter(sheet -> sheet != null) + .collect(Collectors.toList()); + } +} From 1e2a8efbc5f7a23120f16a95e0a0122a535935e9 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Thu, 5 Aug 2021 14:59:07 -0400 Subject: [PATCH 06/33] Making excel reports work in report module --- .../ui/BaseDataSourceSummaryPanel.java | 1 - .../Bundle.properties-MERGED | 9 +- .../DataSourceSummaryReport.java | 40 +++- .../datasourcesummaryexport/ExcelExport.java | 17 +- .../ExcelExportAction.java | 215 +++--------------- .../ExportRecentFiles.java | 27 +-- 6 files changed, 76 insertions(+), 233 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/BaseDataSourceSummaryPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/BaseDataSourceSummaryPanel.java index 2241cbedd9..6ac490eb11 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/BaseDataSourceSummaryPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/BaseDataSourceSummaryPanel.java @@ -38,7 +38,6 @@ import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ColumnModel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents; diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED index d754073fdc..220e32dcca 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED @@ -4,17 +4,10 @@ DataSourceSummaryReport.endReport.srcModuleName.text=Excel Report # {0} - sheetNumber ExcelExport_writeExcel_noSheetName=Sheet {0} ExcelExportAction_exportToXLSX_beginExport=Beginning Export... -# {0} - tabName -ExcelExportAction_exportToXLSX_gatheringTabData=Fetching Data for {0} Tab... +ExcelExportAction_exportToXLSX_gatheringRecentActivityData=Fetching Recent Activity Data ExcelExportAction_exportToXLSX_writingToFile=Writing to File... ExcelExportAction_getXLSXPath_directory=DataSourceSummary ExcelExportAction_moduleName=Data Source Summary -ExcelExportAction_runXLSXExport_errorMessage=There was an error while exporting. -ExcelExportAction_runXLSXExport_errorTitle=Error While Exporting -ExcelExportAction_runXLSXExport_progressCancelActionTitle=Cancelling... -ExcelExportAction_runXLSXExport_progressCancelTitle=Cancel -# {0} - dataSource -ExcelExportAction_runXLSXExport_progressTitle=Exporting {0} to XLSX RecentFilePanel_col_header_domain=Domain RecentFilePanel_col_header_path=Path RecentFilePanel_col_header_sender=Sender diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DataSourceSummaryReport.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DataSourceSummaryReport.java index 4713fa8f0e..1b659dd23e 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DataSourceSummaryReport.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DataSourceSummaryReport.java @@ -18,10 +18,13 @@ */ package org.sleuthkit.autopsy.report.modules.datasourcesummaryexport; +import java.io.IOException; +import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.stream.Collectors; import javax.swing.JPanel; +import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; @@ -30,6 +33,7 @@ import org.sleuthkit.autopsy.report.GeneralReportModule; import org.sleuthkit.autopsy.report.GeneralReportSettings; import org.sleuthkit.autopsy.report.ReportProgressPanel; import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.TskCoreException; class DataSourceSummaryReport implements GeneralReportModule { @@ -79,6 +83,7 @@ class DataSourceSummaryReport implements GeneralReportModule { @Override public void generateReport(GeneralReportSettings settings, ReportProgressPanel progressPanel) { + progressPanel.start(); Case currentCase = null; try { currentCase = Case.getCurrentCaseThrows(); @@ -87,31 +92,46 @@ class DataSourceSummaryReport implements GeneralReportModule { return; } + String errorMessage = ""; + ReportProgressPanel.ReportStatus result = ReportProgressPanel.ReportStatus.COMPLETE; + List selectedDataSources = new ArrayList<>(); if(settings.getSelectedDataSources() == null) { // Process all data sources if the list is null. try { - List selectedDataSources = currentCase.getDataSources() - .stream() - .map(Content::getId) - .collect(Collectors.toList()); - settings.setSelectedDataSources(selectedDataSources); + selectedDataSources = currentCase.getDataSources(); + // ELTODO settings.setSelectedDataSources(selectedDataSources); } catch (TskCoreException ex) { + result = ReportProgressPanel.ReportStatus.ERROR; + // ELTODO errorMessage = Bundle.KMLReport_failedToCompleteReport(); logger.log(Level.SEVERE, "Could not get the datasources from the case", ex); + progressPanel.complete(result, errorMessage); return; } } String baseReportDir = settings.getReportDirectoryPath(); // Start the progress bar and setup the report - progressPanel.setIndeterminate(true); - progressPanel.start(); + // ELTODO progressPanel.setIndeterminate(true); + //progressPanel.updateStatusLabel(NbBundle.getMessage(this.getClass(), "ReportKML.progress.querying")); String reportFullPath = baseReportDir + getRelativeFilePath(); //NON-NLS - String errorMessage = ""; - //progressPanel.updateStatusLabel(NbBundle.getMessage(this.getClass(), "ReportKML.progress.loading")); + + // looop over all data sources + for (Content dataSource : selectedDataSources){ + if (dataSource instanceof DataSource) { + try { + new ExcelExportAction().exportToXLSX(progressPanel, (DataSource) dataSource, reportFullPath); + } catch (IOException | ExcelExport.ExcelExportException ex) { + // ELTODO errorMessage = Bundle.KMLReport_kmlFileWriteError(); + logger.log(Level.SEVERE, errorMessage, ex); //NON-NLS + progressPanel.complete(ReportProgressPanel.ReportStatus.ERROR, errorMessage); + return; + } + } + } - ReportProgressPanel.ReportStatus result = ReportProgressPanel.ReportStatus.COMPLETE; + progressPanel.complete(result, errorMessage); } } diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExport.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExport.java index 434ab34e96..4cc589bba8 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExport.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExport.java @@ -250,21 +250,6 @@ class ExcelExport { void renderSheet(Sheet sheet, WorksheetEnv env) throws ExcelExportException; } - private static ExcelExport instance = null; - - /** - * Retrieves a singleton instance of this class. - * - * @return The instance. - */ - static ExcelExport getInstance() { - if (instance == null) { - instance = new ExcelExport(); - } - - return instance; - } - private ExcelExport() { } @@ -280,7 +265,7 @@ class ExcelExport { "# {0} - sheetNumber", "ExcelExport_writeExcel_noSheetName=Sheet {0}" }) - void writeExcel(List exports, File path) throws IOException, ExcelExportException { + static void writeExcel(List exports, File path) throws IOException, ExcelExportException { // Create a Workbook Workbook workbook = new XSSFWorkbook(); // new HSSFWorkbook() for generating `.xls` file diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java index 460c9bc554..71007094a2 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java @@ -18,34 +18,24 @@ */ package org.sleuthkit.autopsy.report.modules.datasourcesummaryexport; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.io.File; import java.io.IOException; import java.nio.file.Paths; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; -import java.util.Collections; import java.util.Date; import java.util.List; -import java.util.concurrent.CancellationException; -import java.util.concurrent.ExecutionException; -import java.util.function.Consumer; import java.util.logging.Level; -import javax.swing.JOptionPane; -import javax.swing.SwingWorker; import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; -import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.coreutils.FileUtil; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.report.ReportProgressPanel; import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExport.ExcelExportException; import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExport.ExcelSheetExport; -import org.sleuthkit.autopsy.progress.ModalDialogProgressIndicator; -import org.sleuthkit.autopsy.progress.ProgressIndicator; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.TskCoreException; @@ -54,61 +44,16 @@ import org.sleuthkit.datamodel.TskCoreException; */ @Messages({ "ExcelExportAction_moduleName=Data Source Summary",}) -class ExcelExportAction implements Consumer { +class ExcelExportAction { private static final Logger logger = Logger.getLogger(ExcelExportAction.class.getName()); - /** - * A tab that can be exported. - */ - interface ExportableTab { - - /** - * Returns the name of the tab. - * - * @return The tab name. - */ - String getTabTitle(); - - /** - * Given the data source, provides the excel exports for this tab. - * - * @param dataSource The data source. - * @return The excel exports or null. - */ - List getExcelExports(DataSource dataSource); - } - - private final ExcelExport excelExport = ExcelExport.getInstance(); - private final List tabExports; - /** * Main constructor. * * @param tabExports The different tabs that may have excel exports. */ - ExcelExportAction(List tabExports) { - this.tabExports = Collections.unmodifiableList(new ArrayList<>(tabExports)); - } - - /** - * Accepts the data source for which this export pertains, prompts user for - * output location, and exports the data. - * - * @param ds The data source. - */ - @Override - public void accept(DataSource ds) { - if (ds == null) { - return; - } - - File outputLoc = getXLSXPath(ds.getName()); - if (outputLoc == null) { - return; - } - - runXLSXExport(ds, outputLoc); + ExcelExportAction() { } /** @@ -140,99 +85,10 @@ class ExcelExportAction implements Consumer { return null; } - /** - * An action listener that handles cancellation of the export process. - */ - private class CancelExportListener implements ActionListener { - - private SwingWorker worker = null; - - @Override - public void actionPerformed(ActionEvent e) { - if (worker != null && !worker.isCancelled() && !worker.isDone()) { - worker.cancel(true); - } - } - - /** - * Returns the swing worker that could be cancelled. - * - * @return The swing worker that could be cancelled. - */ - SwingWorker getWorker() { - return worker; - } - - /** - * Sets the swing worker that could be cancelled. - * - * @param worker The swing worker that could be cancelled. - */ - void setWorker(SwingWorker worker) { - this.worker = worker; - } - } - - /** - * Handles managing the gui and exporting data from the tabs into an excel - * document. - * - * @param dataSource The data source. - * @param path The output path. - */ - @NbBundle.Messages({ - "# {0} - dataSource", - "ExcelExportAction_runXLSXExport_progressTitle=Exporting {0} to XLSX", - "ExcelExportAction_runXLSXExport_progressCancelTitle=Cancel", - "ExcelExportAction_runXLSXExport_progressCancelActionTitle=Cancelling...", - "ExcelExportAction_runXLSXExport_errorTitle=Error While Exporting", - "ExcelExportAction_runXLSXExport_errorMessage=There was an error while exporting.", - }) - private void runXLSXExport(DataSource dataSource, File path) { - - CancelExportListener cancelButtonListener = new CancelExportListener(); - - ProgressIndicator progressIndicator = new ModalDialogProgressIndicator( - WindowManager.getDefault().getMainWindow(), - Bundle.ExcelExportAction_runXLSXExport_progressTitle(dataSource.getName()), - new String[]{Bundle.ExcelExportAction_runXLSXExport_progressCancelTitle()}, - Bundle.ExcelExportAction_runXLSXExport_progressCancelTitle(), - cancelButtonListener - ); - - SwingWorker worker = new SwingWorker() { - @Override - protected Boolean doInBackground() throws Exception { - exportToXLSX(progressIndicator, dataSource, path); - return true; - } - - @Override - protected void done() { - try { - get(); - } catch (ExecutionException ex) { - logger.log(Level.WARNING, "Error while trying to export data source summary to xlsx.", ex); - JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), - Bundle.ExcelExportAction_runXLSXExport_errorMessage(), - Bundle.ExcelExportAction_runXLSXExport_errorTitle(), - JOptionPane.ERROR_MESSAGE); - } catch (InterruptedException | CancellationException ex) { - // no op on cancellation - } finally { - progressIndicator.finish(); - } - } - }; - - cancelButtonListener.setWorker(worker); - worker.execute(); - } - /** * Action that handles updating progress and exporting data from the tabs. * - * @param progressIndicator The progress indicator. + * @param progressPanel The progress indicator. * @param dataSource The data source to be exported. * @param path The path of the excel export. * @throws InterruptedException @@ -241,57 +97,52 @@ class ExcelExportAction implements Consumer { */ @NbBundle.Messages({ "ExcelExportAction_exportToXLSX_beginExport=Beginning Export...", - "# {0} - tabName", - "ExcelExportAction_exportToXLSX_gatheringTabData=Fetching Data for {0} Tab...", + "ExcelExportAction_exportToXLSX_gatheringRecentActivityData=Fetching Recent Activity Data", "ExcelExportAction_exportToXLSX_writingToFile=Writing to File...",}) - private void exportToXLSX(ProgressIndicator progressIndicator, DataSource dataSource, File path) - throws InterruptedException, IOException, ExcelExport.ExcelExportException { + void exportToXLSX(ReportProgressPanel progressPanel, DataSource dataSource, String path) + throws IOException, ExcelExport.ExcelExportException { - int exportWeight = 3; - int totalWeight = tabExports.size() + exportWeight; - progressIndicator.start(Bundle.ExcelExportAction_exportToXLSX_beginExport(), totalWeight); + File reportFile = new File(path); + int totalWeight = 10; + progressPanel.setIndeterminate(false); + progressPanel.setMaximumProgress(totalWeight); + progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_beginExport()); List sheetExports = new ArrayList<>(); - for (int i = 0; i < tabExports.size(); i++) { - if (Thread.interrupted()) { - throw new InterruptedException("Export has been cancelled."); - } - ExportableTab tab = tabExports.get(i); - progressIndicator.progress(Bundle.ExcelExportAction_exportToXLSX_gatheringTabData(tab == null ? "" : tab.getTabTitle()), i); + progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_gatheringRecentActivityData()); + progressPanel.setProgress(1); - List exports = tab.getExcelExports(dataSource); - if (exports != null) { - sheetExports.addAll(exports); - } + // Export Recent Activity data + List exports = ExportRecentFiles.getExports(dataSource); + if (exports != null) { + sheetExports.addAll(exports); } - if (Thread.interrupted()) { - throw new InterruptedException("Export has been cancelled."); - } + progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_writingToFile()); + progressPanel.setProgress(2); + ExcelExport.writeExcel(sheetExports, reportFile); - progressIndicator.progress(Bundle.ExcelExportAction_exportToXLSX_writingToFile(), tabExports.size()); - excelExport.writeExcel(sheetExports, path); - - progressIndicator.finish(); + progressPanel.complete(ReportProgressPanel.ReportStatus.COMPLETE, ""); try { // add to reports Case curCase = Case.getCurrentCaseThrows(); - curCase.addReport(path.getParent(), + curCase.addReport(reportFile.getParent(), Bundle.ExcelExportAction_moduleName(), - path.getName(), + reportFile.getName(), dataSource); // and show finished dialog - /* ELTODO SwingUtilities.invokeLater(() -> { - ExcelExportDialog dialog = new ExcelExportDialog(WindowManager.getDefault().getMainWindow(), path); - dialog.setResizable(false); - dialog.setLocationRelativeTo(WindowManager.getDefault().getMainWindow()); - dialog.setVisible(true); - dialog.toFront(); - });*/ - + /* + * ELTODO SwingUtilities.invokeLater(() -> { ExcelExportDialog + * dialog = new + * ExcelExportDialog(WindowManager.getDefault().getMainWindow(), + * path); dialog.setResizable(false); + * dialog.setLocationRelativeTo(WindowManager.getDefault().getMainWindow()); + * dialog.setVisible(true); dialog.toFront(); + }); + */ } catch (NoCurrentCaseException | TskCoreException ex) { logger.log(Level.WARNING, "There was an error attaching report to case.", ex); } diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportRecentFiles.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportRecentFiles.java index efa328c294..b6cfd6a027 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportRecentFiles.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportRecentFiles.java @@ -46,11 +46,7 @@ final class ExportRecentFiles { private static final String DATETIME_FORMAT_STR = "yyyy/MM/dd HH:mm:ss"; private static final DateFormat DATETIME_FORMAT = new SimpleDateFormat(DATETIME_FORMAT_STR, Locale.getDefault()); - private final DataFetcher> docsFetcher; - private final DataFetcher> downloadsFetcher; - private final DataFetcher> attachmentsFetcher; - - private final List>> docsTemplate = Arrays.asList( + private static final List>> docsTemplate = Arrays.asList( new ColumnModel<>(Bundle.RecentFilePanel_col_header_path(), (prog) -> { return new DefaultCellModel<>(prog.getPath()); @@ -59,7 +55,7 @@ final class ExportRecentFiles { getDateFunct(), 80)); - private final List>> downloadsTemplate = Arrays.asList( + private static final List>> downloadsTemplate = Arrays.asList( new ColumnModel<>(Bundle.RecentFilePanel_col_header_domain(), (prog) -> { return new DefaultCellModel<>(prog.getWebDomain()); @@ -72,7 +68,7 @@ final class ExportRecentFiles { getDateFunct(), 80)); - private final List>> attachmentsTemplate = Arrays.asList( + private static final List>> attachmentsTemplate = Arrays.asList( new ColumnModel<>(Bundle.RecentFilePanel_col_header_path(), (prog) -> { return new DefaultCellModel<>(prog.getPath()); @@ -96,13 +92,7 @@ final class ExportRecentFiles { "RecentFilePanel_emailParserModuleName=Email Parser" }) - /** - * Creates new form RecentFilesPanel - */ - ExportRecentFiles() { - docsFetcher = (dataSource) -> RecentFilesSummary.getRecentlyOpenedDocuments(dataSource, 10); - downloadsFetcher = (dataSource) -> RecentFilesSummary.getRecentDownloads(dataSource, 10); - attachmentsFetcher = (dataSource) -> RecentFilesSummary.getRecentAttachments(dataSource, 10); + private ExportRecentFiles() { } /** @@ -111,14 +101,19 @@ final class ExportRecentFiles { * * @return The function that determines the date cell from a RecentFileDetails object. */ - private Function> getDateFunct() { + private static Function> getDateFunct() { return (T lastAccessed) -> { Function dateParser = (dt) -> dt == null ? "" : DATETIME_FORMAT.format(dt); return new DefaultCellModel<>(new Date(lastAccessed.getDateAsLong() * 1000), dateParser, DATETIME_FORMAT_STR); }; } - List getExports(DataSource dataSource) { + static List getExports(DataSource dataSource) { + + DataFetcher> docsFetcher = (ds) -> RecentFilesSummary.getRecentlyOpenedDocuments(ds, 10); + DataFetcher> downloadsFetcher = (ds) -> RecentFilesSummary.getRecentDownloads(ds, 10); + DataFetcher> attachmentsFetcher = (ds) -> RecentFilesSummary.getRecentAttachments(ds, 10); + return Stream.of( ExcelExportAction.getTableExport(docsFetcher, docsTemplate, Bundle.RecentFilesPanel_docsTable_tabName(), dataSource), ExcelExportAction.getTableExport(downloadsFetcher, downloadsTemplate, Bundle.RecentFilesPanel_downloadsTable_tabName(), dataSource), From 7e2354c91484ae63377d572b8ae867661550e1c5 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Thu, 5 Aug 2021 16:02:35 -0400 Subject: [PATCH 07/33] bug fixes and improvements --- .../DataSourceSummaryReport.java | 35 +++++++++++++++---- .../ExcelExportAction.java | 21 ++++------- 2 files changed, 35 insertions(+), 21 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DataSourceSummaryReport.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DataSourceSummaryReport.java index 1b659dd23e..5eba7e2a36 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DataSourceSummaryReport.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DataSourceSummaryReport.java @@ -26,6 +26,7 @@ import java.util.stream.Collectors; import javax.swing.JPanel; import org.openide.util.Exceptions; import org.openide.util.NbBundle; +import org.openide.util.lookup.ServiceProvider; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.coreutils.Logger; @@ -36,7 +37,12 @@ import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.TskCoreException; -class DataSourceSummaryReport implements GeneralReportModule { +/** + * Instances of this class plug in to the reporting infrastructure to provide a + * convenient way to extract data source summary information into Excel. + */ +@ServiceProvider(service = GeneralReportModule.class) +public class DataSourceSummaryReport implements GeneralReportModule { private static final Logger logger = Logger.getLogger(DataSourceSummaryReport.class.getName()); private static DataSourceSummaryReport instance; @@ -49,8 +55,7 @@ class DataSourceSummaryReport implements GeneralReportModule { return instance; } - // Hidden constructor - private DataSourceSummaryReport() { + public DataSourceSummaryReport() { } @@ -62,7 +67,7 @@ class DataSourceSummaryReport implements GeneralReportModule { @Override public String getRelativeFilePath() { - return "DataSourceSummaryReport.xlsx"; //NON-NLS + return ""; //ELTODO "DataSourceSummaryReport.xlsx"; //NON-NLS } @Override @@ -98,8 +103,12 @@ class DataSourceSummaryReport implements GeneralReportModule { if(settings.getSelectedDataSources() == null) { // Process all data sources if the list is null. try { - selectedDataSources = currentCase.getDataSources(); - // ELTODO settings.setSelectedDataSources(selectedDataSources); + selectedDataSources = currentCase.getDataSources(); + List dsIDs = selectedDataSources + .stream() + .map(Content::getId) + .collect(Collectors.toList()); + settings.setSelectedDataSources(dsIDs); } catch (TskCoreException ex) { result = ReportProgressPanel.ReportStatus.ERROR; // ELTODO errorMessage = Bundle.KMLReport_failedToCompleteReport(); @@ -107,6 +116,18 @@ class DataSourceSummaryReport implements GeneralReportModule { progressPanel.complete(result, errorMessage); return; } + } else { + for (Long dsID : settings.getSelectedDataSources()) { + try { + selectedDataSources.add(currentCase.getSleuthkitCase().getContentById(dsID)); + } catch (TskCoreException ex) { + result = ReportProgressPanel.ReportStatus.ERROR; + // ELTODO errorMessage = Bundle.KMLReport_failedToCompleteReport(); + logger.log(Level.SEVERE, "Could not get the datasources from the case", ex); + progressPanel.complete(result, errorMessage); + return; + } + } } String baseReportDir = settings.getReportDirectoryPath(); @@ -121,7 +142,7 @@ class DataSourceSummaryReport implements GeneralReportModule { for (Content dataSource : selectedDataSources){ if (dataSource instanceof DataSource) { try { - new ExcelExportAction().exportToXLSX(progressPanel, (DataSource) dataSource, reportFullPath); + new ExcelExportAction().exportToXLSX(progressPanel, (DataSource) dataSource, baseReportDir); } catch (IOException | ExcelExport.ExcelExportException ex) { // ELTODO errorMessage = Bundle.KMLReport_kmlFileWriteError(); logger.log(Level.SEVERE, errorMessage, ex); //NON-NLS diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java index 71007094a2..0f957acb31 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java @@ -65,24 +65,17 @@ class ExcelExportAction { */ @NbBundle.Messages({ "ExcelExportAction_getXLSXPath_directory=DataSourceSummary",}) - private File getXLSXPath(String dataSourceName) { + File getXLSXPath(String dataSourceName, String baseReportDir) { // set initial path to reports directory with filename that is // a combination of the data source name and time stamp DateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy-HH-mm-ss"); String fileName = String.format("%s-%s.xlsx", dataSourceName == null ? "" : FileUtil.escapeFileName(dataSourceName), dateFormat.format(new Date())); - try { - String reportsDir = Case.getCurrentCaseThrows().getReportDirectory(); - File reportsDirFile = Paths.get(reportsDir, Bundle.ExcelExportAction_getXLSXPath_directory()).toFile(); - if (!reportsDirFile.exists()) { - reportsDirFile.mkdirs(); - } - - return Paths.get(reportsDirFile.getAbsolutePath(), fileName).toFile(); - } catch (NoCurrentCaseException ex) { - logger.log(Level.WARNING, "Unable to find reports directory.", ex); + File reportsDirFile = Paths.get(baseReportDir, Bundle.ExcelExportAction_getXLSXPath_directory()).toFile(); + if (!reportsDirFile.exists()) { + reportsDirFile.mkdirs(); } - return null; + return Paths.get(reportsDirFile.getAbsolutePath(), fileName).toFile(); } /** @@ -100,10 +93,10 @@ class ExcelExportAction { "ExcelExportAction_exportToXLSX_gatheringRecentActivityData=Fetching Recent Activity Data", "ExcelExportAction_exportToXLSX_writingToFile=Writing to File...",}) - void exportToXLSX(ReportProgressPanel progressPanel, DataSource dataSource, String path) + void exportToXLSX(ReportProgressPanel progressPanel, DataSource dataSource, String baseReportDir) throws IOException, ExcelExport.ExcelExportException { - File reportFile = new File(path); + File reportFile = getXLSXPath(dataSource.getName(), baseReportDir); int totalWeight = 10; progressPanel.setIndeterminate(false); progressPanel.setMaximumProgress(totalWeight); From da1ec9bef647e27fbd9fb668ce3c36babc442255 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Thu, 5 Aug 2021 16:40:00 -0400 Subject: [PATCH 08/33] Refactoring --- .../Bundle.properties-MERGED | 16 +++---- .../DataSourceSummaryReport.java | 1 - .../ExportRecentFiles.java | 44 +++++++++---------- 3 files changed, 28 insertions(+), 33 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED index 220e32dcca..6c96e246b0 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED @@ -8,11 +8,11 @@ ExcelExportAction_exportToXLSX_gatheringRecentActivityData=Fetching Recent Activ ExcelExportAction_exportToXLSX_writingToFile=Writing to File... ExcelExportAction_getXLSXPath_directory=DataSourceSummary ExcelExportAction_moduleName=Data Source Summary -RecentFilePanel_col_header_domain=Domain -RecentFilePanel_col_header_path=Path -RecentFilePanel_col_header_sender=Sender -RecentFilePanel_emailParserModuleName=Email Parser -RecentFilesPanel_attachmentsTable_tabName=Recent Attachments -RecentFilesPanel_col_head_date=Date -RecentFilesPanel_docsTable_tabName=Recently Opened Documents -RecentFilesPanel_downloadsTable_tabName=Recently Downloads +ExportRecentFiles_attachmentsTable_tabName=Recent Attachments +ExportRecentFiles_col_head_date=Date +ExportRecentFiles_col_header_domain=Domain +ExportRecentFiles_col_header_path=Path +ExportRecentFiles_col_header_sender=Sender +ExportRecentFiles_docsTable_tabName=Recently Opened Documents +ExportRecentFiles_downloadsTable_tabName=Recently Downloads +ExportRecentFiles_emailParserModuleName=Email Parser diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DataSourceSummaryReport.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DataSourceSummaryReport.java index 5eba7e2a36..693667ceb1 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DataSourceSummaryReport.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DataSourceSummaryReport.java @@ -24,7 +24,6 @@ import java.util.List; import java.util.logging.Level; import java.util.stream.Collectors; import javax.swing.JPanel; -import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.openide.util.lookup.ServiceProvider; import org.sleuthkit.autopsy.casemodule.Case; diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportRecentFiles.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportRecentFiles.java index b6cfd6a027..2b9f244d3f 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportRecentFiles.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportRecentFiles.java @@ -38,59 +38,55 @@ import org.sleuthkit.datamodel.DataSource; * Data Source Summary recent files panel. */ @Messages({ - "RecentFilesPanel_docsTable_tabName=Recently Opened Documents", - "RecentFilesPanel_downloadsTable_tabName=Recently Downloads", - "RecentFilesPanel_attachmentsTable_tabName=Recent Attachments",}) + "ExportRecentFiles_docsTable_tabName=Recently Opened Documents", + "ExportRecentFiles_downloadsTable_tabName=Recently Downloads", + "ExportRecentFiles_attachmentsTable_tabName=Recent Attachments", + "ExportRecentFiles_col_head_date=Date", + "ExportRecentFiles_col_header_domain=Domain", + "ExportRecentFiles_col_header_path=Path", + "ExportRecentFiles_col_header_sender=Sender", + "ExportRecentFiles_emailParserModuleName=Email Parser" +}) final class ExportRecentFiles { private static final String DATETIME_FORMAT_STR = "yyyy/MM/dd HH:mm:ss"; private static final DateFormat DATETIME_FORMAT = new SimpleDateFormat(DATETIME_FORMAT_STR, Locale.getDefault()); private static final List>> docsTemplate = Arrays.asList( - new ColumnModel<>(Bundle.RecentFilePanel_col_header_path(), + new ColumnModel<>(Bundle.ExportRecentFiles_col_header_path(), (prog) -> { return new DefaultCellModel<>(prog.getPath()); }, 250), - new ColumnModel<>(Bundle.RecentFilesPanel_col_head_date(), + new ColumnModel<>(Bundle.ExportRecentFiles_col_head_date(), getDateFunct(), 80)); private static final List>> downloadsTemplate = Arrays.asList( - new ColumnModel<>(Bundle.RecentFilePanel_col_header_domain(), + new ColumnModel<>(Bundle.ExportRecentFiles_col_header_domain(), (prog) -> { return new DefaultCellModel<>(prog.getWebDomain()); }, 100), - new ColumnModel<>(Bundle.RecentFilePanel_col_header_path(), + new ColumnModel<>(Bundle.ExportRecentFiles_col_header_path(), (prog) -> { return new DefaultCellModel<>(prog.getPath()); }, 250), - new ColumnModel<>(Bundle.RecentFilesPanel_col_head_date(), + new ColumnModel<>(Bundle.ExportRecentFiles_col_head_date(), getDateFunct(), 80)); private static final List>> attachmentsTemplate = Arrays.asList( - new ColumnModel<>(Bundle.RecentFilePanel_col_header_path(), + new ColumnModel<>(Bundle.ExportRecentFiles_col_header_path(), (prog) -> { return new DefaultCellModel<>(prog.getPath()); }, 250), - new ColumnModel<>(Bundle.RecentFilesPanel_col_head_date(), + new ColumnModel<>(Bundle.ExportRecentFiles_col_head_date(), getDateFunct(), 80), - new ColumnModel<>(Bundle.RecentFilePanel_col_header_sender(), + new ColumnModel<>(Bundle.ExportRecentFiles_col_header_sender(), (prog) -> { return new DefaultCellModel<>(prog.getSender()); }, 150)); - /** - * Default constructor. - */ - @Messages({ - "RecentFilesPanel_col_head_date=Date", - "RecentFilePanel_col_header_domain=Domain", - "RecentFilePanel_col_header_path=Path", - "RecentFilePanel_col_header_sender=Sender", - "RecentFilePanel_emailParserModuleName=Email Parser" - }) private ExportRecentFiles() { } @@ -115,9 +111,9 @@ final class ExportRecentFiles { DataFetcher> attachmentsFetcher = (ds) -> RecentFilesSummary.getRecentAttachments(ds, 10); return Stream.of( - ExcelExportAction.getTableExport(docsFetcher, docsTemplate, Bundle.RecentFilesPanel_docsTable_tabName(), dataSource), - ExcelExportAction.getTableExport(downloadsFetcher, downloadsTemplate, Bundle.RecentFilesPanel_downloadsTable_tabName(), dataSource), - ExcelExportAction.getTableExport(attachmentsFetcher, attachmentsTemplate, Bundle.RecentFilesPanel_attachmentsTable_tabName(), dataSource)) + ExcelExportAction.getTableExport(docsFetcher, docsTemplate, Bundle.ExportRecentFiles_docsTable_tabName(), dataSource), + ExcelExportAction.getTableExport(downloadsFetcher, downloadsTemplate, Bundle.ExportRecentFiles_downloadsTable_tabName(), dataSource), + ExcelExportAction.getTableExport(attachmentsFetcher, attachmentsTemplate, Bundle.ExportRecentFiles_attachmentsTable_tabName(), dataSource)) .filter(sheet -> sheet != null) .collect(Collectors.toList()); } From 1a9f8bd8883d98c9b6da29345acddece9cc44825 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Thu, 5 Aug 2021 17:26:32 -0400 Subject: [PATCH 09/33] Bug fix for dates in Excel file --- .../datasourcesummaryexport/Bundle.properties-MERGED | 1 - .../report/modules/datasourcesummaryexport/CellModel.java | 6 ++++++ .../modules/datasourcesummaryexport/DefaultCellModel.java | 7 +++++++ .../modules/datasourcesummaryexport/ExcelExport.java | 4 ++-- .../modules/datasourcesummaryexport/ExportRecentFiles.java | 3 +-- 5 files changed, 16 insertions(+), 5 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED index 6c96e246b0..42143965be 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED @@ -15,4 +15,3 @@ ExportRecentFiles_col_header_path=Path ExportRecentFiles_col_header_sender=Sender ExportRecentFiles_docsTable_tabName=Recently Opened Documents ExportRecentFiles_downloadsTable_tabName=Recently Downloads -ExportRecentFiles_emailParserModuleName=Email Parser diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/CellModel.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/CellModel.java index bae7d770b7..ce072525ea 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/CellModel.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/CellModel.java @@ -82,4 +82,10 @@ interface CellModel { * @return The horizontal alignment for the text in the cell. */ HorizontalAlign getHorizontalAlignment(); + + /** + * @return The format string to be used with Apache POI during excel + * export or null if none necessary. + */ + String getExcelFormatString(); } diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DefaultCellModel.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DefaultCellModel.java index 149d3413f6..c2e2b7d085 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DefaultCellModel.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DefaultCellModel.java @@ -27,6 +27,7 @@ class DefaultCellModel implements CellModel { private final T data; private final String text; private CellModel.HorizontalAlign horizontalAlignment; + private final String excelFormatString; /** * Main constructor. @@ -62,6 +63,7 @@ class DefaultCellModel implements CellModel { */ DefaultCellModel(T data, Function stringConverter, String excelFormatString) { this.data = data; + this.excelFormatString = excelFormatString; if (stringConverter == null) { text = this.data == null ? "" : this.data.toString(); @@ -84,6 +86,11 @@ class DefaultCellModel implements CellModel { public HorizontalAlign getHorizontalAlignment() { return horizontalAlignment; } + + @Override + public String getExcelFormatString() { + return this.excelFormatString; + } /** * Sets the horizontal alignment for this cell model. diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExport.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExport.java index 4cc589bba8..47087dd985 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExport.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExport.java @@ -324,8 +324,8 @@ class ExcelExport { static Cell createCell(WorksheetEnv env, Row row, int colNum, CellModel cellModel, Optional cellStyle) { CellStyle cellStyleToUse = cellStyle.orElse(env.getDefaultCellStyle()); - if (cellModel.getText() != null || cellModel.getHorizontalAlignment() != null) { - cellStyleToUse = env.getCellStyle(new CellStyleKey(cellModel.getText(), cellStyleToUse, cellModel.getHorizontalAlignment())); + if (cellModel.getExcelFormatString() != null || cellModel.getHorizontalAlignment() != null) { + cellStyleToUse = env.getCellStyle(new CellStyleKey(cellModel.getExcelFormatString(), cellStyleToUse, cellModel.getHorizontalAlignment())); } Object cellData = cellModel.getData(); diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportRecentFiles.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportRecentFiles.java index 2b9f244d3f..1864dc5332 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportRecentFiles.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportRecentFiles.java @@ -44,8 +44,7 @@ import org.sleuthkit.datamodel.DataSource; "ExportRecentFiles_col_head_date=Date", "ExportRecentFiles_col_header_domain=Domain", "ExportRecentFiles_col_header_path=Path", - "ExportRecentFiles_col_header_sender=Sender", - "ExportRecentFiles_emailParserModuleName=Email Parser" + "ExportRecentFiles_col_header_sender=Sender" }) final class ExportRecentFiles { From 343b8c792a29428e791ad9484ceadd4f2e8f69ac Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Thu, 5 Aug 2021 17:27:12 -0400 Subject: [PATCH 10/33] Minor --- .../ui/RecentFilesPanel.java | 30 ++++++------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesPanel.java index 52e0721cc8..3b082e5849 100755 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesPanel.java @@ -66,7 +66,7 @@ public final class RecentFilesPanel extends BaseDataSourceSummaryPanel { private final DataFetcher> attachmentsFetcher; private final List>> docsTemplate = Arrays.asList( - new ColumnModel<>(Bundle.RecentFilePanel_col_header_path(), + new ColumnModel<>(Bundle.RecentFilesPanel_col_header_path(), (prog) -> { return new DefaultCellModel<>(prog.getPath()) .setPopupMenuRetriever(getPopupFunct(prog)); @@ -76,12 +76,12 @@ public final class RecentFilesPanel extends BaseDataSourceSummaryPanel { 80)); private final List>> downloadsTemplate = Arrays.asList( - new ColumnModel<>(Bundle.RecentFilePanel_col_header_domain(), + new ColumnModel<>(Bundle.RecentFilesPanel_col_header_domain(), (prog) -> { return new DefaultCellModel<>(prog.getWebDomain()) .setPopupMenuRetriever(getPopupFunct(prog)); }, 100), - new ColumnModel<>(Bundle.RecentFilePanel_col_header_path(), + new ColumnModel<>(Bundle.RecentFilesPanel_col_header_path(), (prog) -> { return new DefaultCellModel<>(prog.getPath()) .setPopupMenuRetriever(getPopupFunct(prog)); @@ -91,7 +91,7 @@ public final class RecentFilesPanel extends BaseDataSourceSummaryPanel { 80)); private final List>> attachmentsTemplate = Arrays.asList( - new ColumnModel<>(Bundle.RecentFilePanel_col_header_path(), + new ColumnModel<>(Bundle.RecentFilesPanel_col_header_path(), (prog) -> { return new DefaultCellModel<>(prog.getPath()) .setPopupMenuRetriever(getPopupFunct(prog)); @@ -99,7 +99,7 @@ public final class RecentFilesPanel extends BaseDataSourceSummaryPanel { new ColumnModel<>(Bundle.RecentFilesPanel_col_head_date(), getDateFunct(), 80), - new ColumnModel<>(Bundle.RecentFilePanel_col_header_sender(), + new ColumnModel<>(Bundle.RecentFilesPanel_col_header_sender(), (prog) -> { return new DefaultCellModel<>(prog.getSender()) .setPopupMenuRetriever(getPopupFunct(prog)); @@ -110,10 +110,9 @@ public final class RecentFilesPanel extends BaseDataSourceSummaryPanel { */ @Messages({ "RecentFilesPanel_col_head_date=Date", - "RecentFilePanel_col_header_domain=Domain", - "RecentFilePanel_col_header_path=Path", - "RecentFilePanel_col_header_sender=Sender", - "RecentFilePanel_emailParserModuleName=Email Parser" + "RecentFilesPanel_col_header_domain=Domain", + "RecentFilesPanel_col_header_path=Path", + "RecentFilesPanel_col_header_sender=Sender" }) public RecentFilesPanel() { this(new RecentFilesGetter()); @@ -186,17 +185,6 @@ public final class RecentFilesPanel extends BaseDataSourceSummaryPanel { onNewDataSource(dataFetchComponents, tablePanelList, dataSource); } - /* ELTODO - @Override - List getExports(DataSource dataSource) { - return Stream.of( - getTableExport(docsFetcher, docsTemplate, Bundle.RecentFilesPanel_docsTable_tabName(), dataSource), - getTableExport(downloadsFetcher, downloadsTemplate, Bundle.RecentFilesPanel_downloadsTable_tabName(), dataSource), - getTableExport(attachmentsFetcher, attachmentsTemplate, Bundle.RecentFilesPanel_attachmentsTable_tabName(), dataSource)) - .filter(sheet -> sheet != null) - .collect(Collectors.toList()); - }*/ - @Override public void close() { ingestRunningLabel.unregister(); @@ -213,7 +201,7 @@ public final class RecentFilesPanel extends BaseDataSourceSummaryPanel { } @Messages({ - "RecentFilePanel_no_open_documents=No recently open documents found." + "RecentFilesPanel_no_open_documents=No recently open documents found." }) /** * Setup the data model and columns for the recently open table. From 5fe0b036129ea5354251b5344db19d2d5fe89137 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Fri, 6 Aug 2021 10:31:19 -0400 Subject: [PATCH 11/33] moved data fetchers out of ContainerPanel into contentutils package --- .../contentutils/ContainerSummary.java | 434 ++++++++++++++++++ .../datamodel/ContainerSummary.java | 235 ---------- .../datamodel/ContainerSummaryGetter.java | 144 ++++++ .../ui/Bundle.properties-MERGED | 9 +- .../datasourcesummary/ui/ContainerPanel.java | 298 +----------- .../datasourcesummary/ui/TypesPanel.java | 6 +- 6 files changed, 602 insertions(+), 524 deletions(-) create mode 100755 Core/src/org/sleuthkit/autopsy/contentutils/ContainerSummary.java delete mode 100644 Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummary.java create mode 100644 Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummaryGetter.java diff --git a/Core/src/org/sleuthkit/autopsy/contentutils/ContainerSummary.java b/Core/src/org/sleuthkit/autopsy/contentutils/ContainerSummary.java new file mode 100755 index 0000000000..0f0e9cb72e --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentutils/ContainerSummary.java @@ -0,0 +1,434 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2020-2021 Basis Technology Corp. + * Contact: carrier sleuthkit 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.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 org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.BlackboardAttribute; +import org.sleuthkit.datamodel.DataSource; +import org.sleuthkit.datamodel.Image; +import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.datamodel.TskData; + +/** + * Provides methods to query for data source overview details. + */ +public class ContainerSummary { + + private static final Set ARTIFACT_UPDATE_TYPE_IDS = new HashSet<>(Arrays.asList( + BlackboardArtifact.ARTIFACT_TYPE.TSK_OS_INFO.getTypeID(), + BlackboardArtifact.ARTIFACT_TYPE.TSK_DATA_SOURCE_USAGE.getTypeID() + )); + + private ContainerSummary() { + } + + public static Set getArtifactTypeIdsForRefresh() { + return Collections.unmodifiableSet(ARTIFACT_UPDATE_TYPE_IDS); + } + + /** + * Gets the size of unallocated files in a particular datasource. + * + * @param currentDataSource The data source. + * + * @return The size or null if the query could not be executed. + * + * @throws NoCurrentCaseException + * @throws TskCoreException + * @throws SQLException + */ + public static Long getSizeOfUnallocatedFiles(DataSource currentDataSource) + throws TskCoreException, SQLException, NoCurrentCaseException { + if (currentDataSource == null) { + return null; + } + + final String valueParam = "value"; + final String countParam = "count"; + String query = "SELECT SUM(size) AS " + valueParam + ", COUNT(*) AS " + countParam + + " FROM tsk_files" + + " WHERE " + DataSourceInfoUtilities.getMetaFlagsContainsStatement(TskData.TSK_FS_META_FLAG_ENUM.UNALLOC) + + " AND type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType() + + " AND type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType() + + " AND dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue() + + " AND name<>''" + + " AND data_source_obj_id=" + currentDataSource.getId(); + + DataSourceInfoUtilities.ResultSetHandler handler = (resultSet) -> { + if (resultSet.next()) { + // ensure that there is an unallocated count result that is attached to this data source + long resultCount = resultSet.getLong(valueParam); + return (resultCount > 0) ? resultSet.getLong(valueParam) : null; + } else { + return null; + } + }; + + return DataSourceInfoUtilities.getBaseQueryResult(query, handler); + } + + /** + * Retrieves the concatenation of operating system attributes for a + * particular data source. + * + * @param dataSource The data source. + * + * @return The concatenated value or null if the query could not be + * executed. + * + * @throws NoCurrentCaseException + * @throws TskCoreException + * @throws SQLException + */ + public static String getOperatingSystems(DataSource dataSource) + throws TskCoreException, SQLException, NoCurrentCaseException { + + if (dataSource == null) { + return null; + } + + return getConcattedAttrValue(dataSource.getId(), + BlackboardArtifact.ARTIFACT_TYPE.TSK_OS_INFO.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID()); + } + + /** + * Retrieves the concatenation of data source usage for a particular data + * source. + * + * @param dataSource The data source. + * + * @return The concatenated value or null if the query could not be + * executed. + * + * @throws NoCurrentCaseException + * @throws TskCoreException + * @throws SQLException + */ + public static String getDataSourceType(DataSource dataSource) + throws TskCoreException, SQLException, NoCurrentCaseException { + + if (dataSource == null) { + return null; + } + + return getConcattedAttrValue(dataSource.getId(), + BlackboardArtifact.ARTIFACT_TYPE.TSK_DATA_SOURCE_USAGE.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION.getTypeID()); + } + + /** + * Generates a string which is a concatenation of the value received from + * the result set. + * + * @param query The query. + * @param valueParam The parameter for the value in the result set. + * @param separator The string separator used in concatenation. + * + * @return The concatenated string or null if the query could not be + * executed. + * + * @throws NoCurrentCaseException + * @throws TskCoreException + * @throws SQLException + */ + private static String getConcattedStringsResult(String query, String valueParam, String separator) + throws TskCoreException, SQLException, NoCurrentCaseException { + + DataSourceInfoUtilities.ResultSetHandler handler = (resultSet) -> { + String toRet = ""; + boolean first = true; + while (resultSet.next()) { + if (first) { + first = false; + } else { + toRet += separator; + } + toRet += resultSet.getString(valueParam); + } + + return toRet; + }; + + return DataSourceInfoUtilities.getBaseQueryResult(query, handler); + } + + /** + * Generates a concatenated string value based on the text value of a + * particular attribute in a particular artifact for a specific data source. + * + * @param dataSourceId The data source id. + * @param artifactTypeId The artifact type id. + * @param attributeTypeId The attribute type id. + * + * @return The concatenated value or null if the query could not be + * executed. + * + * @throws NoCurrentCaseException + * @throws TskCoreException + * @throws SQLException + */ + private static String getConcattedAttrValue(long dataSourceId, int artifactTypeId, int attributeTypeId) + throws TskCoreException, SQLException, NoCurrentCaseException { + + final String valueParam = "concatted_attribute_value"; + String query = "SELECT attr.value_text AS " + valueParam + + " FROM blackboard_artifacts bba " + + " INNER JOIN blackboard_attributes attr ON bba.artifact_id = attr.artifact_id " + + " WHERE bba.data_source_obj_id = " + dataSourceId + + " AND bba.artifact_type_id = " + artifactTypeId + + " AND attr.attribute_type_id = " + attributeTypeId; + + String separator = ", "; + return getConcattedStringsResult(query, valueParam, separator); + } + + /** + * Data model data for data source images. + */ + public static class ImageDetails { + + private final long unallocatedSize; + private final long size; + private final long sectorSize; + + private final String timeZone; + private final String imageType; + + private final List paths; + private final String md5Hash; + private final String sha1Hash; + private final String sha256Hash; + + /** + * Main constructor. + * + * @param unallocatedSize Size in bytes of unallocated space. + * @param size Total size in bytes. + * @param sectorSize Sector size in bytes. + * @param timeZone The time zone. + * @param imageType The type of image. + * @param paths The source paths for the image. + * @param md5Hash The md5 hash or null. + * @param sha1Hash The sha1 hash or null. + * @param sha256Hash The sha256 hash or null. + */ + ImageDetails(long unallocatedSize, long size, long sectorSize, + String timeZone, String imageType, List paths, String md5Hash, + String sha1Hash, String sha256Hash) { + this.unallocatedSize = unallocatedSize; + this.size = size; + this.sectorSize = sectorSize; + this.timeZone = timeZone; + this.imageType = imageType; + this.paths = paths == null ? Collections.emptyList() : new ArrayList<>(paths); + this.md5Hash = md5Hash; + this.sha1Hash = sha1Hash; + this.sha256Hash = sha256Hash; + } + + /** + * @return Size in bytes of unallocated space. + */ + public long getUnallocatedSize() { + return unallocatedSize; + } + + /** + * @return Total size in bytes. + */ + public long getSize() { + return size; + } + + /** + * @return Sector size in bytes. + */ + public long getSectorSize() { + return sectorSize; + } + + /** + * @return The time zone. + */ + public String getTimeZone() { + return timeZone; + } + + /** + * @return The type of image. + */ + public String getImageType() { + return imageType; + } + + /** + * @return The source paths for the image. + */ + public List getPaths() { + return Collections.unmodifiableList(paths); + } + + /** + * @return The md5 hash or null. + */ + public String getMd5Hash() { + return md5Hash; + } + + /** + * @return The sha1 hash or null. + */ + public String getSha1Hash() { + return sha1Hash; + } + + /** + * @return The sha256 hash or null. + */ + public String getSha256Hash() { + return sha256Hash; + } + } + + /** + * Data model for container data. + */ + public static class ContainerDetails { + + private final String displayName; + private final String originalName; + private final String deviceIdValue; + private final String acquisitionDetails; + private final ImageDetails imageDetails; + + /** + * Main constructor. + * + * @param displayName The display name for this data source. + * @param originalName The original name for this data source. + * @param deviceIdValue The device id value for this data source. + * @param acquisitionDetails The acquisition details for this data + * source or null. + * @param imageDetails If the data source is an image, the image + * data model for this data source or null if + * non-image. + */ + ContainerDetails(String displayName, String originalName, String deviceIdValue, + String acquisitionDetails, ImageDetails imageDetails) { + this.displayName = displayName; + this.originalName = originalName; + this.deviceIdValue = deviceIdValue; + this.acquisitionDetails = acquisitionDetails; + this.imageDetails = imageDetails; + } + + /** + * @return The display name for this data source. + */ + public String getDisplayName() { + return displayName; + } + + /** + * @return The original name for this data source. + */ + public String getOriginalName() { + return originalName; + } + + /** + * @return The device id value for this data source. + */ + public String getDeviceId() { + return deviceIdValue; + } + + /** + * @return The acquisition details for this data source or null. + */ + public String getAcquisitionDetails() { + return acquisitionDetails; + } + + /** + * @return If the data source is an image, the image details for this + * data source or null if non-image. + */ + public ImageDetails getImageDetails() { + return imageDetails; + } + } + + /** + * Generates a container data model object containing data about + * the data source. + * + * @param ds The data source. + * + * @return The generated view model. + */ + public static ContainerDetails getContainerDetails(DataSource ds) throws TskCoreException, SQLException, NoCurrentCaseException { + if (ds == null) { + return null; + } + + return new ContainerDetails( + ds.getName(), + ds.getName(), + ds.getDeviceId(), + ds.getAcquisitionDetails(), + ds instanceof Image ? getImageDetails((Image) ds) : null + ); + } + + /** + * Generates an image data model object containing data about the + * image. + * + * @param image The image. + * + * @return The generated view model. + */ + public static ImageDetails getImageDetails(Image image) throws TskCoreException, SQLException, NoCurrentCaseException { + if (image == null) { + return null; + } + + Long unallocSize = getSizeOfUnallocatedFiles(image); + String imageType = image.getType().getName(); + Long size = image.getSize(); + Long sectorSize = image.getSsize(); + String timeZone = image.getTimeZone(); + List paths = image.getPaths() == null ? Collections.emptyList() : Arrays.asList(image.getPaths()); + String md5 = image.getMd5(); + String sha1 = image.getSha1(); + String sha256 = image.getSha256(); + + return new ImageDetails(unallocSize, size, sectorSize, timeZone, imageType, paths, md5, sha1, sha256); + } +} diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummary.java deleted file mode 100644 index eb11b99b2a..0000000000 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummary.java +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2020 Basis Technology Corp. - * Contact: carrier sleuthkit org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sleuthkit.autopsy.datasourcesummary.datamodel; - -import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultArtifactUpdateGovernor; -import java.sql.SQLException; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; -import org.sleuthkit.autopsy.contentutils.DataSourceInfoUtilities; -import org.sleuthkit.autopsy.ingest.ModuleContentEvent; -import org.sleuthkit.datamodel.AbstractFile; -import org.sleuthkit.datamodel.BlackboardArtifact; -import org.sleuthkit.datamodel.BlackboardAttribute; -import org.sleuthkit.datamodel.DataSource; -import org.sleuthkit.datamodel.TskCoreException; -import org.sleuthkit.datamodel.TskData; - -/** - * Provides methods to query for data source overview details. - */ -public class ContainerSummary implements DefaultArtifactUpdateGovernor { - - private static final Set ARTIFACT_UPDATE_TYPE_IDS = new HashSet<>(Arrays.asList( - BlackboardArtifact.ARTIFACT_TYPE.TSK_OS_INFO.getTypeID(), - BlackboardArtifact.ARTIFACT_TYPE.TSK_DATA_SOURCE_USAGE.getTypeID() - )); - - private final SleuthkitCaseProvider provider; - - /** - * Main constructor. - */ - public ContainerSummary() { - this(SleuthkitCaseProvider.DEFAULT); - } - - /** - * Main constructor. - * - * @param provider The means of obtaining a sleuthkit case. - */ - public ContainerSummary(SleuthkitCaseProvider provider) { - this.provider = provider; - } - - @Override - public boolean isRefreshRequired(ModuleContentEvent evt) { - return true; - } - - @Override - public boolean isRefreshRequired(AbstractFile file) { - return true; - } - - @Override - public Set getArtifactTypeIdsForRefresh() { - return ARTIFACT_UPDATE_TYPE_IDS; - } - - /** - * Gets the size of unallocated files in a particular datasource. - * - * @param currentDataSource The data source. - * - * @return The size or null if the query could not be executed. - * - * @throws SleuthkitCaseProviderException - * @throws TskCoreException - * @throws SQLException - */ - public Long getSizeOfUnallocatedFiles(DataSource currentDataSource) - throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException { - if (currentDataSource == null) { - return null; - } - - final String valueParam = "value"; - final String countParam = "count"; - String query = "SELECT SUM(size) AS " + valueParam + ", COUNT(*) AS " + countParam - + " FROM tsk_files" - + " WHERE " + DataSourceInfoUtilities.getMetaFlagsContainsStatement(TskData.TSK_FS_META_FLAG_ENUM.UNALLOC) - + " AND type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType() - + " AND type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType() - + " AND dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue() - + " AND name<>''" - + " AND data_source_obj_id=" + currentDataSource.getId(); - - DataSourceInfoUtilities.ResultSetHandler handler = (resultSet) -> { - if (resultSet.next()) { - // ensure that there is an unallocated count result that is attached to this data source - long resultCount = resultSet.getLong(valueParam); - return (resultCount > 0) ? resultSet.getLong(valueParam) : null; - } else { - return null; - } - }; - - return DataSourceInfoUtilities.getBaseQueryResult(provider.get(), query, handler); - } - - /** - * Retrieves the concatenation of operating system attributes for a - * particular data source. - * - * @param dataSource The data source. - * - * @return The concatenated value or null if the query could not be - * executed. - * - * @throws SleuthkitCaseProviderException - * @throws TskCoreException - * @throws SQLException - */ - public String getOperatingSystems(DataSource dataSource) - throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException { - - if (dataSource == null) { - return null; - } - - return getConcattedAttrValue(dataSource.getId(), - BlackboardArtifact.ARTIFACT_TYPE.TSK_OS_INFO.getTypeID(), - BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID()); - } - - /** - * Retrieves the concatenation of data source usage for a particular data - * source. - * - * @param dataSource The data source. - * - * @return The concatenated value or null if the query could not be - * executed. - * - * @throws SleuthkitCaseProviderException - * @throws TskCoreException - * @throws SQLException - */ - public String getDataSourceType(DataSource dataSource) - throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException { - - if (dataSource == null) { - return null; - } - - return getConcattedAttrValue(dataSource.getId(), - BlackboardArtifact.ARTIFACT_TYPE.TSK_DATA_SOURCE_USAGE.getTypeID(), - BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION.getTypeID()); - } - - /** - * Generates a string which is a concatenation of the value received from - * the result set. - * - * @param query The query. - * @param valueParam The parameter for the value in the result set. - * @param separator The string separator used in concatenation. - * - * @return The concatenated string or null if the query could not be - * executed. - * - * @throws SleuthkitCaseProviderException - * @throws TskCoreException - * @throws SQLException - */ - private String getConcattedStringsResult(String query, String valueParam, String separator) - throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException { - - DataSourceInfoUtilities.ResultSetHandler handler = (resultSet) -> { - String toRet = ""; - boolean first = true; - while (resultSet.next()) { - if (first) { - first = false; - } else { - toRet += separator; - } - toRet += resultSet.getString(valueParam); - } - - return toRet; - }; - - return DataSourceInfoUtilities.getBaseQueryResult(provider.get(), query, handler); - } - - /** - * Generates a concatenated string value based on the text value of a - * particular attribute in a particular artifact for a specific data source. - * - * @param dataSourceId The data source id. - * @param artifactTypeId The artifact type id. - * @param attributeTypeId The attribute type id. - * - * @return The concatenated value or null if the query could not be - * executed. - * - * @throws SleuthkitCaseProviderException - * @throws TskCoreException - * @throws SQLException - */ - private String getConcattedAttrValue(long dataSourceId, int artifactTypeId, int attributeTypeId) - throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException { - - final String valueParam = "concatted_attribute_value"; - String query = "SELECT attr.value_text AS " + valueParam - + " FROM blackboard_artifacts bba " - + " INNER JOIN blackboard_attributes attr ON bba.artifact_id = attr.artifact_id " - + " WHERE bba.data_source_obj_id = " + dataSourceId - + " AND bba.artifact_type_id = " + artifactTypeId - + " AND attr.attribute_type_id = " + attributeTypeId; - - String separator = ", "; - return getConcattedStringsResult(query, valueParam, separator); - } -} diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummaryGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummaryGetter.java new file mode 100644 index 0000000000..1238a36bd1 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummaryGetter.java @@ -0,0 +1,144 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.datasourcesummary.datamodel; + +import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultArtifactUpdateGovernor; +import java.sql.SQLException; +import java.util.Set; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.autopsy.contentutils.ContainerSummary; +import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.autopsy.ingest.ModuleContentEvent; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.DataSource; +import org.sleuthkit.datamodel.TskCoreException; + +/** + * Wrapper class for converting org.sleuthkit.autopsy.contentutils.ContainerSummary functionality into + * a DefaultArtifactUpdateGovernor used by Container tab. + */ +public class ContainerSummaryGetter implements DefaultArtifactUpdateGovernor { + + /** + * Main constructor. + */ + public ContainerSummaryGetter() { + } + + @Override + public boolean isRefreshRequired(ModuleContentEvent evt) { + return true; + } + + @Override + public boolean isRefreshRequired(AbstractFile file) { + return true; + } + + @Override + public Set getArtifactTypeIdsForRefresh() { + return ContainerSummary.getArtifactTypeIdsForRefresh(); + } + + /** + * Gets the size of unallocated files in a particular datasource. + * + * @param currentDataSource The data source. + * + * @return The size or null if the query could not be executed. + * + * @throws SleuthkitCaseProviderException + * @throws TskCoreException + * @throws SQLException + */ + public Long getSizeOfUnallocatedFiles(DataSource currentDataSource) + throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException { + try { + return ContainerSummary.getSizeOfUnallocatedFiles(currentDataSource); + } catch (NoCurrentCaseException ex) { + throw new SleuthkitCaseProviderException("No currently open case.", ex); + } + } + + /** + * Retrieves the concatenation of operating system attributes for a + * particular data source. + * + * @param dataSource The data source. + * + * @return The concatenated value or null if the query could not be + * executed. + * + * @throws SleuthkitCaseProviderException + * @throws TskCoreException + * @throws SQLException + */ + public String getOperatingSystems(DataSource dataSource) + throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException { + try { + return ContainerSummary.getOperatingSystems(dataSource); + } catch (NoCurrentCaseException ex) { + throw new SleuthkitCaseProviderException("No currently open case.", ex); + } + } + + /** + * Retrieves the concatenation of data source usage for a particular data + * source. + * + * @param dataSource The data source. + * + * @return The concatenated value or null if the query could not be + * executed. + * + * @throws SleuthkitCaseProviderException + * @throws TskCoreException + * @throws SQLException + */ + public String getDataSourceType(DataSource dataSource) + throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException { + try { + return ContainerSummary.getDataSourceType(dataSource); + } catch (NoCurrentCaseException ex) { + throw new SleuthkitCaseProviderException("No currently open case.", ex); + } + } + + /** + * Retrieves a container data model object containing data about + * the data source. + * + * @param dataSource The data source. + * + * @return The concatenated value or null if the query could not be + * executed. + * + * @throws SleuthkitCaseProviderException + * @throws TskCoreException + * @throws SQLException + */ + public ContainerSummary.ContainerDetails getContainerDetails(DataSource dataSource) + throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException { + try { + return ContainerSummary.getContainerDetails(dataSource); + } catch (NoCurrentCaseException ex) { + throw new SleuthkitCaseProviderException("No currently open case.", ex); + } + } +} diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties-MERGED index 2f5056ae25..b3c57b15dc 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties-MERGED @@ -73,15 +73,14 @@ PastCasesPanel_countColumn_title=Count PastCasesPanel_notableFileTable_tabName=Cases with Common Notable PastCasesPanel_onNoCrIngest_message=No results will be shown because the Central Repository module was not run. PastCasesPanel_sameIdsTable_tabName=Past Cases with the Same Devices -RecentFilePanel_col_header_domain=Domain -RecentFilePanel_col_header_path=Path -RecentFilePanel_col_header_sender=Sender -RecentFilePanel_emailParserModuleName=Email Parser -RecentFilePanel_no_open_documents=No recently open documents found. RecentFilesPanel_attachmentsTable_tabName=Recent Attachments RecentFilesPanel_col_head_date=Date +RecentFilesPanel_col_header_domain=Domain +RecentFilesPanel_col_header_path=Path +RecentFilesPanel_col_header_sender=Sender RecentFilesPanel_docsTable_tabName=Recently Opened Documents RecentFilesPanel_downloadsTable_tabName=Recently Downloads +RecentFilesPanel_no_open_documents=No recently open documents found. SizeRepresentationUtil_units_bytes=bytes SizeRepresentationUtil_units_gigabytes=GB SizeRepresentationUtil_units_kilobytes=KB diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java index 1f46f48d48..1ab2c83afd 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019 Basis Technology Corp. + * Copyright 2019-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,31 +19,24 @@ package org.sleuthkit.autopsy.datasourcesummary.ui; import java.beans.PropertyChangeEvent; -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.logging.Level; -import java.util.stream.Collectors; -import java.util.stream.Stream; import org.sleuthkit.autopsy.coreutils.Logger; import javax.swing.table.DefaultTableModel; -import org.apache.commons.lang.StringUtils; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.ContainerSummary; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.autopsy.contentutils.ContainerSummary.ContainerDetails; +import org.sleuthkit.autopsy.contentutils.ContainerSummary.ImageDetails; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.ContainerSummaryGetter; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult.ResultType; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetcher; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultUpdateGovernor; import org.sleuthkit.autopsy.datasourcesummary.uiutils.UpdateGovernor; import org.sleuthkit.datamodel.DataSource; -import org.sleuthkit.datamodel.Image; -import org.sleuthkit.datamodel.TskCoreException; /** * Panel to display additional details associated with a specific DataSource @@ -53,182 +46,6 @@ import org.sleuthkit.datamodel.TskCoreException; }) class ContainerPanel extends BaseDataSourceSummaryPanel { - /** - * View model data for data source images. - */ - private static class ImageViewModel { - - private final long unallocatedSize; - private final long size; - private final long sectorSize; - - private final String timeZone; - private final String imageType; - - private final List paths; - private final String md5Hash; - private final String sha1Hash; - private final String sha256Hash; - - /** - * Main constructor. - * - * @param unallocatedSize Size in bytes of unallocated space. - * @param size Total size in bytes. - * @param sectorSize Sector size in bytes. - * @param timeZone The time zone. - * @param imageType The type of image. - * @param paths The source paths for the image. - * @param md5Hash The md5 hash or null. - * @param sha1Hash The sha1 hash or null. - * @param sha256Hash The sha256 hash or null. - */ - ImageViewModel(long unallocatedSize, long size, long sectorSize, - String timeZone, String imageType, List paths, String md5Hash, - String sha1Hash, String sha256Hash) { - this.unallocatedSize = unallocatedSize; - this.size = size; - this.sectorSize = sectorSize; - this.timeZone = timeZone; - this.imageType = imageType; - this.paths = paths == null ? Collections.emptyList() : new ArrayList<>(paths); - this.md5Hash = md5Hash; - this.sha1Hash = sha1Hash; - this.sha256Hash = sha256Hash; - } - - /** - * @return Size in bytes of unallocated space. - */ - long getUnallocatedSize() { - return unallocatedSize; - } - - /** - * @return Total size in bytes. - */ - long getSize() { - return size; - } - - /** - * @return Sector size in bytes. - */ - long getSectorSize() { - return sectorSize; - } - - /** - * @return The time zone. - */ - String getTimeZone() { - return timeZone; - } - - /** - * @return The type of image. - */ - String getImageType() { - return imageType; - } - - /** - * @return The source paths for the image. - */ - List getPaths() { - return paths; - } - - /** - * @return The md5 hash or null. - */ - String getMd5Hash() { - return md5Hash; - } - - /** - * @return The sha1 hash or null. - */ - String getSha1Hash() { - return sha1Hash; - } - - /** - * @return The sha256 hash or null. - */ - String getSha256Hash() { - return sha256Hash; - } - } - - /** - * View model for container data. - */ - private static class ContainerViewModel { - - private final String displayName; - private final String originalName; - private final String deviceIdValue; - private final String acquisitionDetails; - private final ImageViewModel imageViewModel; - - /** - * Main constructor. - * - * @param displayName The display name for this data source. - * @param originalName The original name for this data source. - * @param deviceIdValue The device id value for this data source. - * @param acquisitionDetails The acquisition details for this data - * source or null. - * @param imageViewModel If the data source is an image, the image view - * model for this data source or null if non-image. - */ - ContainerViewModel(String displayName, String originalName, String deviceIdValue, - String acquisitionDetails, ImageViewModel imageViewModel) { - this.displayName = displayName; - this.originalName = originalName; - this.deviceIdValue = deviceIdValue; - this.acquisitionDetails = acquisitionDetails; - this.imageViewModel = imageViewModel; - } - - /** - * @return The display name for this data source. - */ - String getDisplayName() { - return displayName; - } - - /** - * @return The original name for this data source. - */ - String getOriginalName() { - return originalName; - } - - /** - * @return The device id value for this data source. - */ - String getDeviceId() { - return deviceIdValue; - } - - /** - * @return The acquisition details for this data source or null. - */ - String getAcquisitionDetails() { - return acquisitionDetails; - } - - /** - * @return If the data source is an image, the image view model for this - * data source or null if non-image. - */ - ImageViewModel getImageViewModel() { - return imageViewModel; - } - } - // set of case events for which to call update (if the name changes, that will impact data shown) private static final Set CASE_EVENT_SET = new HashSet<>(Arrays.asList( Case.Events.DATA_SOURCE_NAME_CHANGED @@ -254,29 +71,29 @@ class ContainerPanel extends BaseDataSourceSummaryPanel { private static final Logger logger = Logger.getLogger(ContainerPanel.class.getName()); private final List> dataFetchComponents; - private final DataFetcher containerDataFetcher; + private final DataFetcher containerDataFetcher; /** * Creates a new form ContainerPanel. */ ContainerPanel() { - this(new ContainerSummary()); + this(new ContainerSummaryGetter()); } /** * Creates new form ContainerPanel. */ - ContainerPanel(ContainerSummary containerSummary) { + ContainerPanel(ContainerSummaryGetter containerSummary) { super(containerSummary, CONTAINER_UPDATES); - containerDataFetcher = (dataSource) -> getContainerViewModel(containerSummary, dataSource); + containerDataFetcher = (dataSource) -> containerSummary.getContainerDetails(dataSource); dataFetchComponents = Arrays.asList( new DataFetchComponents<>( containerDataFetcher, (result) -> { if (result != null && result.getResultType() == ResultType.SUCCESS) { - ContainerViewModel data = result.getData(); + ContainerDetails data = result.getData(); updateDetailsPanelData(data); } else { if (result == null) { @@ -305,92 +122,12 @@ class ContainerPanel extends BaseDataSourceSummaryPanel { fetchInformation(dataFetchComponents, dataSource); } - /** - * A means of retrieving data that could potentially throw an exception. - */ - private interface Retriever { - - /** - * Retrieves data of a certain type and possibly throws an exception. - * - * @return The data type. - * @throws TskCoreException - * @throws SleuthkitCaseProviderException - * @throws SQLException - */ - O retrieve() throws TskCoreException, SleuthkitCaseProviderException, SQLException; - } - - /** - * Retrieves data of a particular type and handles any exceptions that may - * be thrown by logging. - * - * @param retriever The retrieving function. - * @return The retrieved data. - */ - private static O retrieve(Retriever retriever) { - try { - return retriever.retrieve(); - } catch (TskCoreException | SleuthkitCaseProviderException | SQLException ex) { - logger.log(Level.WARNING, "Error while retrieving data.", ex); - return null; - } - } - - /** - * Generates a container view model object containing data to display about - * the data source. - * - * @param containerSummary The service providing data about the data source. - * @param ds The data source. - * @return The generated view model. - */ - private static ContainerViewModel getContainerViewModel(ContainerSummary containerSummary, DataSource ds) { - if (ds == null) { - return null; - } - - return new ContainerViewModel( - ds.getName(), - ds.getName(), - ds.getDeviceId(), - retrieve(() -> ds.getAcquisitionDetails()), - ds instanceof Image ? getImageViewModel(containerSummary, (Image) ds) : null - ); - } - - /** - * Generates an image view model object containing data to display about the - * image. - * - * @param containerSummary The service providing data about the image. - * @param image The image. - * @return The generated view model. - */ - private static ImageViewModel getImageViewModel(ContainerSummary containerSummary, Image image) { - if (image == null) { - return null; - } - - Long unallocSize = retrieve(() -> containerSummary.getSizeOfUnallocatedFiles(image)); - String imageType = image.getType().getName(); - Long size = image.getSize(); - Long sectorSize = image.getSsize(); - String timeZone = image.getTimeZone(); - List paths = image.getPaths() == null ? Collections.emptyList() : Arrays.asList(image.getPaths()); - String md5 = retrieve(() -> image.getMd5()); - String sha1 = retrieve(() -> image.getSha1()); - String sha256 = retrieve(() -> image.getSha256()); - - return new ImageViewModel(unallocSize, size, sectorSize, timeZone, imageType, paths, md5, sha1, sha256); - } - /** * Update the swing components with fetched data. * * @param viewModel The data source view model data. */ - private void updateDetailsPanelData(ContainerViewModel viewModel) { + private void updateDetailsPanelData(ContainerDetails viewModel) { clearTableValues(); if (viewModel == null) { return; @@ -401,8 +138,8 @@ class ContainerPanel extends BaseDataSourceSummaryPanel { deviceIdValue.setText(viewModel.getDeviceId()); acquisitionDetailsTextArea.setText(viewModel.getAcquisitionDetails()); - if (viewModel.getImageViewModel() != null) { - setFieldsForImage(viewModel.getImageViewModel()); + if (viewModel.getImageDetails() != null) { + setFieldsForImage(viewModel.getImageDetails()); } else { setFieldsForNonImageDataSource(); } @@ -437,7 +174,7 @@ class ContainerPanel extends BaseDataSourceSummaryPanel { * * @param viewModel The image view model data. */ - private void setFieldsForImage(ImageViewModel viewModel) { + private void setFieldsForImage(ImageDetails viewModel) { unallocatedSizeValue.setText(SizeRepresentationUtil.getSizeString(viewModel.getUnallocatedSize())); imageTypeValue.setText(viewModel.getImageType()); sizeValue.setText(SizeRepresentationUtil.getSizeString(viewModel.getSize())); @@ -490,9 +227,8 @@ class ContainerPanel extends BaseDataSourceSummaryPanel { .filter(item -> item != null) .collect(Collectors.toList()); } - }*/ + } - /* ELTODO @Messages({ "ContainerPanel_export_displayName=Display Name:", "ContainerPanel_export_originalName=Name:", @@ -508,7 +244,7 @@ class ContainerPanel extends BaseDataSourceSummaryPanel { "ContainerPanel_export_unallocatedSize=Unallocated Space:", "ContainerPanel_export_filePaths=File Paths:",}) protected List getExports(DataSource ds) { - ContainerViewModel result = getFetchResult(containerDataFetcher, "Container sheets", ds); + ContainerDetails result = getFetchResult(containerDataFetcher, "Container sheets", ds); if (ds == null || result == null) { return Collections.emptyList(); } @@ -516,7 +252,7 @@ class ContainerPanel extends BaseDataSourceSummaryPanel { String NA = Bundle.ContainerPanel_setFieldsForNonImageDataSource_na(); DefaultCellModel NACell = new DefaultCellModel<>(NA); - ImageViewModel imageModel = result.getImageViewModel(); + ImageDetails imageModel = result.getImageDetails(); boolean hasImage = imageModel != null; DefaultCellModel timeZone = hasImage ? new DefaultCellModel<>(imageModel.getTimeZone()) : NACell; @@ -527,7 +263,7 @@ class ContainerPanel extends BaseDataSourceSummaryPanel { DefaultCellModel sha1 = hasImage ? new DefaultCellModel<>(imageModel.getSha1Hash()) : NACell; DefaultCellModel sha256 = hasImage ? new DefaultCellModel<>(imageModel.getSha256Hash()) : NACell; DefaultCellModel unallocatedSize = hasImage ? SizeRepresentationUtil.getBytesCell(imageModel.getUnallocatedSize()) : NACell; - List paths = result.getImageViewModel() == null ? Collections.singletonList(NA) : result.getImageViewModel().getPaths(); + List paths = result.getImageDetails() == null ? Collections.singletonList(NA) : result.getImageDetails().getPaths(); List cellPaths = paths.stream() .map(SingleCellExportable::new) .collect(Collectors.toList()); diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java index 3e9ec03ea0..e333888d0c 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java @@ -32,7 +32,7 @@ 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.datasourcesummary.datamodel.ContainerSummary; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.ContainerSummaryGetter; import org.sleuthkit.autopsy.datasourcesummary.datamodel.MimeTypeSummary; import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult; @@ -233,7 +233,7 @@ class TypesPanel extends BaseDataSourceSummaryPanel { * Creates a new TypesPanel. */ public TypesPanel() { - this(new MimeTypeSummary(), new TypesSummary(), new ContainerSummary()); + this(new MimeTypeSummary(), new TypesSummary(), new ContainerSummaryGetter()); } @Override @@ -252,7 +252,7 @@ class TypesPanel extends BaseDataSourceSummaryPanel { public TypesPanel( MimeTypeSummary mimeTypeData, TypesSummary typeData, - ContainerSummary containerData) { + ContainerSummaryGetter containerData) { super(mimeTypeData, typeData, containerData); From e1eda761eb25ff943fb860c0822183fd3d9318dd Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Fri, 6 Aug 2021 11:25:11 -0400 Subject: [PATCH 12/33] Moved Container summary Excel functionality to report module --- .../contentutils/ContainerSummary.java | 11 +- .../contentutils/DataSourceInfoUtilities.java | 12 +- .../contentutils/RecentFilesSummary.java | 2 +- .../datamodel/ContainerSummaryGetter.java | 2 +- .../datamodel/RecentFilesGetter.java | 21 +- .../datasourcesummary/ui/ContainerPanel.java | 78 -------- .../ui/RecentFilesPanel.java | 12 +- .../ui/SizeRepresentationUtil.java | 8 +- .../Bundle.properties-MERGED | 22 +++ .../ExcelExportAction.java | 14 +- .../ExportContainerInfo.java | 126 ++++++++++++ .../ExportRecentFiles.java | 10 +- .../SizeRepresentationUtil.java | 179 ++++++++++++++++++ 13 files changed, 378 insertions(+), 119 deletions(-) create mode 100755 Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportContainerInfo.java create mode 100755 Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/SizeRepresentationUtil.java diff --git a/Core/src/org/sleuthkit/autopsy/contentutils/ContainerSummary.java b/Core/src/org/sleuthkit/autopsy/contentutils/ContainerSummary.java index 0f0e9cb72e..87a78093ca 100755 --- a/Core/src/org/sleuthkit/autopsy/contentutils/ContainerSummary.java +++ b/Core/src/org/sleuthkit/autopsy/contentutils/ContainerSummary.java @@ -385,10 +385,10 @@ public class ContainerSummary { } /** - * Generates a container data model object containing data about - * the data source. + * Generates a container data model object containing data about the data + * source. * - * @param ds The data source. + * @param ds The data source. * * @return The generated view model. */ @@ -407,10 +407,9 @@ public class ContainerSummary { } /** - * Generates an image data model object containing data about the - * image. + * Generates an image data model object containing data about the image. * - * @param image The image. + * @param image The image. * * @return The generated view model. */ diff --git a/Core/src/org/sleuthkit/autopsy/contentutils/DataSourceInfoUtilities.java b/Core/src/org/sleuthkit/autopsy/contentutils/DataSourceInfoUtilities.java index 8fef1c54f0..b8bc2a54b6 100644 --- a/Core/src/org/sleuthkit/autopsy/contentutils/DataSourceInfoUtilities.java +++ b/Core/src/org/sleuthkit/autopsy/contentutils/DataSourceInfoUtilities.java @@ -29,6 +29,8 @@ import java.util.TreeMap; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; import org.apache.commons.lang.StringUtils; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute.Type; @@ -123,7 +125,6 @@ public final class DataSourceInfoUtilities { /** * Retrieves a result based on the provided query. * - * @param skCase The current SleuthkitCase. * @param query The query. * @param processor The result set handler. * @@ -132,10 +133,11 @@ public final class DataSourceInfoUtilities { * * @throws TskCoreException * @throws SQLException + * @throws NoCurrentCaseException */ - public static T getBaseQueryResult(SleuthkitCase skCase, String query, ResultSetHandler processor) - throws TskCoreException, SQLException { - try (SleuthkitCase.CaseDbQuery dbQuery = skCase.executeQuery(query)) { + public static T getBaseQueryResult(String query, ResultSetHandler processor) + throws TskCoreException, SQLException, NoCurrentCaseException { + try (SleuthkitCase.CaseDbQuery dbQuery = Case.getCurrentCaseThrows().getSleuthkitCase().executeQuery(query)) { ResultSet resultSet = dbQuery.getResultSet(); return processor.process(resultSet); } @@ -398,7 +400,7 @@ public final class DataSourceInfoUtilities { BlackboardAttribute attr = getAttributeOrNull(artifact, attributeType); return (attr == null) ? null : attr.getValueLong(); } - + /** * Retrieves the int value of a certain attribute type from an artifact. * diff --git a/Core/src/org/sleuthkit/autopsy/contentutils/RecentFilesSummary.java b/Core/src/org/sleuthkit/autopsy/contentutils/RecentFilesSummary.java index 62b80516cd..502e2c76a1 100755 --- a/Core/src/org/sleuthkit/autopsy/contentutils/RecentFilesSummary.java +++ b/Core/src/org/sleuthkit/autopsy/contentutils/RecentFilesSummary.java @@ -73,7 +73,7 @@ public class RecentFilesSummary { } public static Set getArtifactTypeIdsForRefresh() { - return ARTIFACT_UPDATE_TYPE_IDS; + return Collections.unmodifiableSet(ARTIFACT_UPDATE_TYPE_IDS); } /** diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummaryGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummaryGetter.java index 1238a36bd1..69946a4b80 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummaryGetter.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummaryGetter.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2020 Basis Technology Corp. + * Copyright 2020-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesGetter.java index 446659ebef..045394d7cc 100755 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesGetter.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesGetter.java @@ -31,8 +31,9 @@ import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; /** - * Wrapper class for converting org.sleuthkit.autopsy.contentutils.RecentFilesSummary functionality into - * a DefaultArtifactUpdateGovernor used by Recent Files Data Summary tab. + * Wrapper class for converting + * org.sleuthkit.autopsy.contentutils.RecentFilesSummary functionality into a + * DefaultArtifactUpdateGovernor used by Recent Files Data Summary tab. */ public class RecentFilesGetter implements DefaultArtifactUpdateGovernor { @@ -52,11 +53,11 @@ public class RecentFilesGetter implements DefaultArtifactUpdateGovernor { * TSK_RECENT_OBJECT artifact. * * @param dataSource The data source to query. - * @param maxCount The maximum number of results to return, pass 0 to get a - * list of all results. + * @param maxCount The maximum number of results to return, pass 0 to get + * a list of all results. * * @return A list RecentFileDetails representing the most recently opened - * documents or an empty list if none were found. + * documents or an empty list if none were found. * * @throws SleuthkitCaseProviderException * @throws TskCoreException @@ -74,11 +75,11 @@ public class RecentFilesGetter implements DefaultArtifactUpdateGovernor { * artifact TSK_DATETIME_ACCESSED attribute. * * @param dataSource Data source to query. - * @param maxCount Maximum number of results to return, passing 0 will - * return all results. + * @param maxCount Maximum number of results to return, passing 0 will + * return all results. * * @return A list of RecentFileDetails objects or empty list if none were - * found. + * found. * * @throws TskCoreException * @throws SleuthkitCaseProviderException @@ -95,8 +96,8 @@ public class RecentFilesGetter implements DefaultArtifactUpdateGovernor { * Returns a list of the most recent message attachments. * * @param dataSource Data source to query. - * @param maxCount Maximum number of results to return, passing 0 will - * return all results. + * @param maxCount Maximum number of results to return, passing 0 will + * return all results. * * @return A list of RecentFileDetails of the most recent attachments. * diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java index 1ab2c83afd..75e826f625 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java @@ -209,84 +209,6 @@ class ContainerPanel extends BaseDataSourceSummaryPanel { ((DefaultTableModel) filePathsTable.getModel()).setRowCount(0); } - /** - * Divides acquisition details into key/value pairs to be displayed in - * separate cells in an excel export. - * - * @param acquisitionDetails The acquisition details. - * @return The list of key value pairs that can be incorporated into the - * excel export. - */ - /* ELTODO - private static List getAcquisitionDetails(String acquisitionDetails) { - if (StringUtils.isBlank(acquisitionDetails)) { - return Collections.emptyList(); - } else { - return Stream.of(acquisitionDetails.split("\\r?\\n")) - .map((line) -> (StringUtils.isBlank(line)) ? null : new SingleCellExportable(line)) - .filter(item -> item != null) - .collect(Collectors.toList()); - } - } - - @Messages({ - "ContainerPanel_export_displayName=Display Name:", - "ContainerPanel_export_originalName=Name:", - "ContainerPanel_export_deviceId=Device ID:", - "ContainerPanel_export_timeZone=Time Zone:", - "ContainerPanel_export_acquisitionDetails=Acquisition Details:", - "ContainerPanel_export_imageType=Image Type:", - "ContainerPanel_export_size=Size:", - "ContainerPanel_export_sectorSize=Sector Size:", - "ContainerPanel_export_md5=MD5:", - "ContainerPanel_export_sha1=SHA1:", - "ContainerPanel_export_sha256=SHA256:", - "ContainerPanel_export_unallocatedSize=Unallocated Space:", - "ContainerPanel_export_filePaths=File Paths:",}) - protected List getExports(DataSource ds) { - ContainerDetails result = getFetchResult(containerDataFetcher, "Container sheets", ds); - if (ds == null || result == null) { - return Collections.emptyList(); - } - - String NA = Bundle.ContainerPanel_setFieldsForNonImageDataSource_na(); - DefaultCellModel NACell = new DefaultCellModel<>(NA); - - ImageDetails imageModel = result.getImageDetails(); - boolean hasImage = imageModel != null; - - DefaultCellModel timeZone = hasImage ? new DefaultCellModel<>(imageModel.getTimeZone()) : NACell; - DefaultCellModel imageType = hasImage ? new DefaultCellModel<>(imageModel.getImageType()) : NACell; - DefaultCellModel size = hasImage ? SizeRepresentationUtil.getBytesCell(imageModel.getSize()) : NACell; - DefaultCellModel sectorSize = hasImage ? SizeRepresentationUtil.getBytesCell(imageModel.getSectorSize()) : NACell; - DefaultCellModel md5 = hasImage ? new DefaultCellModel<>(imageModel.getMd5Hash()) : NACell; - DefaultCellModel sha1 = hasImage ? new DefaultCellModel<>(imageModel.getSha1Hash()) : NACell; - DefaultCellModel sha256 = hasImage ? new DefaultCellModel<>(imageModel.getSha256Hash()) : NACell; - DefaultCellModel unallocatedSize = hasImage ? SizeRepresentationUtil.getBytesCell(imageModel.getUnallocatedSize()) : NACell; - List paths = result.getImageDetails() == null ? Collections.singletonList(NA) : result.getImageDetails().getPaths(); - List cellPaths = paths.stream() - .map(SingleCellExportable::new) - .collect(Collectors.toList()); - - return Arrays.asList( - new ExcelSpecialFormatExport(Bundle.ContainerPanel_tabName(), Arrays.asList( - new KeyValueItemExportable(Bundle.ContainerPanel_export_displayName(), new DefaultCellModel<>(result.getDisplayName())), - new KeyValueItemExportable(Bundle.ContainerPanel_export_originalName(), new DefaultCellModel<>(result.getOriginalName())), - new KeyValueItemExportable(Bundle.ContainerPanel_export_deviceId(), new DefaultCellModel<>(result.getDeviceId())), - new KeyValueItemExportable(Bundle.ContainerPanel_export_timeZone(), timeZone), - new TitledExportable(Bundle.ContainerPanel_export_acquisitionDetails(), getAcquisitionDetails(result.getAcquisitionDetails())), - new KeyValueItemExportable(Bundle.ContainerPanel_export_imageType(), imageType), - new KeyValueItemExportable(Bundle.ContainerPanel_export_size(), size), - new KeyValueItemExportable(Bundle.ContainerPanel_export_sectorSize(), sectorSize), - new KeyValueItemExportable(Bundle.ContainerPanel_export_md5(), md5), - new KeyValueItemExportable(Bundle.ContainerPanel_export_sha1(), sha1), - new KeyValueItemExportable(Bundle.ContainerPanel_export_sha256(), sha256), - new KeyValueItemExportable(Bundle.ContainerPanel_export_unallocatedSize(), unallocatedSize), - new TitledExportable(Bundle.ContainerPanel_export_filePaths(), cellPaths) - ))); - - }*/ - /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesPanel.java index 3b082e5849..e2f38b38b6 100755 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesPanel.java @@ -132,10 +132,11 @@ public final class RecentFilesPanel extends BaseDataSourceSummaryPanel { } /** - * Returns a function that gets the date from the RecentFileDetails object and - * converts into a DefaultCellModel to be displayed in a table. + * Returns a function that gets the date from the RecentFileDetails object + * and converts into a DefaultCellModel to be displayed in a table. * - * @return The function that determines the date cell from a RecentFileDetails object. + * @return The function that determines the date cell from a + * RecentFileDetails object. */ private Function> getDateFunct() { return (T lastAccessed) -> { @@ -150,9 +151,10 @@ public final class RecentFilesPanel extends BaseDataSourceSummaryPanel { * items. * * @param record The RecentFileDetails instance. + * * @return The menu items list containing one action or navigating to the - * appropriate artifact/file and closing the data source summary dialog if - * open. + * appropriate artifact/file and closing the data source summary + * dialog if open. */ private Supplier> getPopupFunct(RecentFileDetails record) { return () -> { diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/SizeRepresentationUtil.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/SizeRepresentationUtil.java index 74b9be06a8..3c48da8db0 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/SizeRepresentationUtil.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/SizeRepresentationUtil.java @@ -19,8 +19,6 @@ package org.sleuthkit.autopsy.datasourcesummary.ui; import java.text.DecimalFormat; -import java.util.Arrays; -import java.util.List; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultCellModel; @@ -53,7 +51,7 @@ public final class SizeRepresentationUtil { PB(Bundle.SizeRepresentationUtil_units_petabytes(), "#,##0.00,,,,,", 5); private final String suffix; - private final String excelFormatString; + private final String excelFormatString; // ELTODO private final long divisor; /** @@ -126,14 +124,14 @@ public final class SizeRepresentationUtil { } /** - * Get a long size in bytes as a string formated to be read by users. + * Get a long size in bytes as a string formatted to be read by users. * * @param size Long value representing a size in byte.s * @param format The means of formatting the number. * @param showFullSize Optionally show the number of bytes in the * datasource. * - * @return Return a string formated with a user friendly version of the size + * @return Return a string formatted with a user friendly version of the size * as a string, returns empty String when provided empty size. */ static String getSizeString(Long size, DecimalFormat format, boolean showFullSize) { diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED index 42143965be..f93c0bc1c3 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED @@ -4,10 +4,26 @@ DataSourceSummaryReport.endReport.srcModuleName.text=Excel Report # {0} - sheetNumber ExcelExport_writeExcel_noSheetName=Sheet {0} ExcelExportAction_exportToXLSX_beginExport=Beginning Export... +ExcelExportAction_exportToXLSX_gatheringContainerData=Fetching Container & Image Data ExcelExportAction_exportToXLSX_gatheringRecentActivityData=Fetching Recent Activity Data ExcelExportAction_exportToXLSX_writingToFile=Writing to File... ExcelExportAction_getXLSXPath_directory=DataSourceSummary ExcelExportAction_moduleName=Data Source Summary +ExportContainerInfo_export_acquisitionDetails=Acquisition Details: +ExportContainerInfo_export_deviceId=Device ID: +ExportContainerInfo_export_displayName=Display Name: +ExportContainerInfo_export_filePaths=File Paths: +ExportContainerInfo_export_imageType=Image Type: +ExportContainerInfo_export_md5=MD5: +ExportContainerInfo_export_originalName=Name: +ExportContainerInfo_export_sectorSize=Sector Size: +ExportContainerInfo_export_sha1=SHA1: +ExportContainerInfo_export_sha256=SHA256: +ExportContainerInfo_export_size=Size: +ExportContainerInfo_export_timeZone=Time Zone: +ExportContainerInfo_export_unallocatedSize=Unallocated Space: +ExportContainerInfo_setFieldsForNonImageDataSource_na=N/A +ExportContainerInfo_tabName=Container ExportRecentFiles_attachmentsTable_tabName=Recent Attachments ExportRecentFiles_col_head_date=Date ExportRecentFiles_col_header_domain=Domain @@ -15,3 +31,9 @@ ExportRecentFiles_col_header_path=Path ExportRecentFiles_col_header_sender=Sender ExportRecentFiles_docsTable_tabName=Recently Opened Documents ExportRecentFiles_downloadsTable_tabName=Recently Downloads +SizeRepresentationUtil_units_bytes=bytes +SizeRepresentationUtil_units_gigabytes=GB +SizeRepresentationUtil_units_kilobytes=KB +SizeRepresentationUtil_units_megabytes=MB +SizeRepresentationUtil_units_petabytes=PB +SizeRepresentationUtil_units_terabytes=TB diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java index 0f957acb31..e8416453b3 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java @@ -91,6 +91,7 @@ class ExcelExportAction { @NbBundle.Messages({ "ExcelExportAction_exportToXLSX_beginExport=Beginning Export...", "ExcelExportAction_exportToXLSX_gatheringRecentActivityData=Fetching Recent Activity Data", + "ExcelExportAction_exportToXLSX_gatheringContainerData=Fetching Container & Image Data", "ExcelExportAction_exportToXLSX_writingToFile=Writing to File...",}) void exportToXLSX(ReportProgressPanel progressPanel, DataSource dataSource, String baseReportDir) @@ -103,17 +104,24 @@ class ExcelExportAction { progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_beginExport()); List sheetExports = new ArrayList<>(); + // Export Recent Activity data progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_gatheringRecentActivityData()); progressPanel.setProgress(1); - - // Export Recent Activity data List exports = ExportRecentFiles.getExports(dataSource); if (exports != null) { sheetExports.addAll(exports); } + + // Export Container & Image info data + progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_gatheringContainerData()); + progressPanel.setProgress(2); + exports = ExportContainerInfo.getExports(dataSource); + if (exports != null) { + sheetExports.addAll(exports); + } progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_writingToFile()); - progressPanel.setProgress(2); + progressPanel.setProgress(3); ExcelExport.writeExcel(sheetExports, reportFile); progressPanel.complete(ReportProgressPanel.ReportStatus.COMPLETE, ""); diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportContainerInfo.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportContainerInfo.java new file mode 100755 index 0000000000..6d297abc0f --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportContainerInfo.java @@ -0,0 +1,126 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit 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.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.apache.commons.lang.StringUtils; +import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.contentutils.ContainerSummary; +import org.sleuthkit.autopsy.contentutils.ContainerSummary.ContainerDetails; +import org.sleuthkit.autopsy.contentutils.ContainerSummary.ImageDetails; +import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExport.ExcelSheetExport; +import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelSpecialFormatExport.ExcelItemExportable; +import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelSpecialFormatExport.KeyValueItemExportable; +import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelSpecialFormatExport.SingleCellExportable; +import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelSpecialFormatExport.TitledExportable; +import org.sleuthkit.datamodel.DataSource; + +/** + * Class to export additional details associated with a specific DataSource + */ +class ExportContainerInfo { + + /** + * Creates new form ExportContainerInfo. + */ + private ExportContainerInfo() { + } + + /** + * Divides acquisition details into key/value pairs to be displayed in + * separate cells in an excel export. + * + * @param acquisitionDetails The acquisition details. + * @return The list of key value pairs that can be incorporated into the + * excel export. + */ + private static List getAcquisitionDetails(String acquisitionDetails) { + if (StringUtils.isBlank(acquisitionDetails)) { + return Collections.emptyList(); + } else { + return Stream.of(acquisitionDetails.split("\\r?\\n")) + .map((line) -> (StringUtils.isBlank(line)) ? null : new SingleCellExportable(line)) + .filter(item -> item != null) + .collect(Collectors.toList()); + } + } + + @Messages({ + "ExportContainerInfo_setFieldsForNonImageDataSource_na=N/A", + "ExportContainerInfo_tabName=Container", + "ExportContainerInfo_export_displayName=Display Name:", + "ExportContainerInfo_export_originalName=Name:", + "ExportContainerInfo_export_deviceId=Device ID:", + "ExportContainerInfo_export_timeZone=Time Zone:", + "ExportContainerInfo_export_acquisitionDetails=Acquisition Details:", + "ExportContainerInfo_export_imageType=Image Type:", + "ExportContainerInfo_export_size=Size:", + "ExportContainerInfo_export_sectorSize=Sector Size:", + "ExportContainerInfo_export_md5=MD5:", + "ExportContainerInfo_export_sha1=SHA1:", + "ExportContainerInfo_export_sha256=SHA256:", + "ExportContainerInfo_export_unallocatedSize=Unallocated Space:", + "ExportContainerInfo_export_filePaths=File Paths:",}) + static List getExports(DataSource ds) { + DataFetcher containerDataFetcher = (dataSource) -> ContainerSummary.getContainerDetails(dataSource); + ContainerDetails containerDetails = ExcelExportAction.getFetchResult(containerDataFetcher, "Container sheets", ds); + if (ds == null || containerDetails == null) { + return Collections.emptyList(); + } + + String NA = Bundle.ExportContainerInfo_setFieldsForNonImageDataSource_na(); + DefaultCellModel NACell = new DefaultCellModel<>(NA); + + ImageDetails imageDetails = containerDetails.getImageDetails(); + boolean hasImage = imageDetails != null; + + DefaultCellModel timeZone = hasImage ? new DefaultCellModel<>(imageDetails.getTimeZone()) : NACell; + DefaultCellModel imageType = hasImage ? new DefaultCellModel<>(imageDetails.getImageType()) : NACell; + DefaultCellModel size = hasImage ? SizeRepresentationUtil.getBytesCell(imageDetails.getSize()) : NACell; + DefaultCellModel sectorSize = hasImage ? SizeRepresentationUtil.getBytesCell(imageDetails.getSectorSize()) : NACell; + DefaultCellModel md5 = hasImage ? new DefaultCellModel<>(imageDetails.getMd5Hash()) : NACell; + DefaultCellModel sha1 = hasImage ? new DefaultCellModel<>(imageDetails.getSha1Hash()) : NACell; + DefaultCellModel sha256 = hasImage ? new DefaultCellModel<>(imageDetails.getSha256Hash()) : NACell; + DefaultCellModel unallocatedSize = hasImage ? SizeRepresentationUtil.getBytesCell(imageDetails.getUnallocatedSize()) : NACell; + List paths = containerDetails.getImageDetails() == null ? Collections.singletonList(NA) : containerDetails.getImageDetails().getPaths(); + List cellPaths = paths.stream() + .map(SingleCellExportable::new) + .collect(Collectors.toList()); + + return Arrays.asList(new ExcelSpecialFormatExport(Bundle.ExportContainerInfo_tabName(), Arrays.asList(new KeyValueItemExportable(Bundle.ExportContainerInfo_export_displayName(), new DefaultCellModel<>(containerDetails.getDisplayName())), + new KeyValueItemExportable(Bundle.ExportContainerInfo_export_originalName(), new DefaultCellModel<>(containerDetails.getOriginalName())), + new KeyValueItemExportable(Bundle.ExportContainerInfo_export_deviceId(), new DefaultCellModel<>(containerDetails.getDeviceId())), + new KeyValueItemExportable(Bundle.ExportContainerInfo_export_timeZone(), timeZone), + new TitledExportable(Bundle.ExportContainerInfo_export_acquisitionDetails(), getAcquisitionDetails(containerDetails.getAcquisitionDetails())), + new KeyValueItemExportable(Bundle.ExportContainerInfo_export_imageType(), imageType), + new KeyValueItemExportable(Bundle.ExportContainerInfo_export_size(), size), + new KeyValueItemExportable(Bundle.ExportContainerInfo_export_sectorSize(), sectorSize), + new KeyValueItemExportable(Bundle.ExportContainerInfo_export_md5(), md5), + new KeyValueItemExportable(Bundle.ExportContainerInfo_export_sha1(), sha1), + new KeyValueItemExportable(Bundle.ExportContainerInfo_export_sha256(), sha256), + new KeyValueItemExportable(Bundle.ExportContainerInfo_export_unallocatedSize(), unallocatedSize), + new TitledExportable(Bundle.ExportContainerInfo_export_filePaths(), cellPaths) + ))); + + } +} diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportRecentFiles.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportRecentFiles.java index 1864dc5332..c9a57cc3aa 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportRecentFiles.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportRecentFiles.java @@ -35,7 +35,7 @@ import org.sleuthkit.autopsy.contentutils.RecentFilesSummary.RecentFileDetails; import org.sleuthkit.datamodel.DataSource; /** - * Data Source Summary recent files panel. + * Class to export data source summary info. */ @Messages({ "ExportRecentFiles_docsTable_tabName=Recently Opened Documents", @@ -86,15 +86,15 @@ final class ExportRecentFiles { return new DefaultCellModel<>(prog.getSender()); }, 150)); - private ExportRecentFiles() { } /** - * Returns a function that gets the date from the RecentFileDetails object and - * converts into a DefaultCellModel to be displayed in a table. + * Returns a function that gets the date from the RecentFileDetails object + * and converts into a DefaultCellModel to be displayed in a table. * - * @return The function that determines the date cell from a RecentFileDetails object. + * @return The function that determines the date cell from a + * RecentFileDetails object. */ private static Function> getDateFunct() { return (T lastAccessed) -> { diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/SizeRepresentationUtil.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/SizeRepresentationUtil.java new file mode 100755 index 0000000000..664401c684 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/SizeRepresentationUtil.java @@ -0,0 +1,179 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit 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.text.DecimalFormat; +import org.openide.util.NbBundle; + +/** + * This class provides utilities for representing storage size in most relevant + * units (i.e. bytes, megabytes, etc.). + */ +final class SizeRepresentationUtil { + + private static final int SIZE_CONVERSION_CONSTANT = 1000; + private static final DecimalFormat APPROXIMATE_SIZE_FORMAT = new DecimalFormat("#.##"); + + /** + * A size unit corresponding to orders of magnitude of bytes (kilobyte, gigabytes, etc.). + */ + @NbBundle.Messages({ + "SizeRepresentationUtil_units_bytes=bytes", + "SizeRepresentationUtil_units_kilobytes=KB", + "SizeRepresentationUtil_units_megabytes=MB", + "SizeRepresentationUtil_units_gigabytes=GB", + "SizeRepresentationUtil_units_terabytes=TB", + "SizeRepresentationUtil_units_petabytes=PB" + }) + enum SizeUnit { + BYTES(Bundle.SizeRepresentationUtil_units_bytes(), "#", 0), + KB(Bundle.SizeRepresentationUtil_units_kilobytes(), "#,##0.00,", 1), + MB(Bundle.SizeRepresentationUtil_units_megabytes(), "#,##0.00,,", 2), + GB(Bundle.SizeRepresentationUtil_units_gigabytes(), "#,##0.00,,,", 3), + TB(Bundle.SizeRepresentationUtil_units_terabytes(), "#,##0.00,,,,", 4), + PB(Bundle.SizeRepresentationUtil_units_petabytes(), "#,##0.00,,,,,", 5); + + private final String suffix; + private final String excelFormatString; + private final long divisor; + + /** + * Main constructor. + * @param suffix The string suffix to use for size unit. + * @param excelFormatString The excel format string to use for this size unit. + * @param power The power of 1000 of bytes for this size unit. + */ + SizeUnit(String suffix, String excelFormatString, int power) { + this.suffix = suffix; + + // based on https://www.mrexcel.com/board/threads/how-do-i-format-cells-to-show-gb-mb-kb.140135/ + this.excelFormatString = String.format("%s \"%s\"", excelFormatString, suffix); + this.divisor = (long) Math.pow(SIZE_CONVERSION_CONSTANT, power); + } + + /** + * @return The string suffix to use for size unit. + */ + String getSuffix() { + return suffix; + } + + /** + * @return The excel format string to use for this size unit. + */ + String getExcelFormatString() { + return excelFormatString; + } + + /** + * @return The divisor to convert from bytes to this unit. + */ + long getDivisor() { + return divisor; + } + } + + /** + * Get a long size in bytes as a string formated to be read by users. + * + * @param size Long value representing a size in bytes. + * + * @return Return a string formated with a user friendly version of the size + * as a string, returns empty String when provided empty size. + */ + static String getSizeString(Long size) { + return getSizeString(size, APPROXIMATE_SIZE_FORMAT, true); + } + + /** + * Determines the relevant size unit that should be used for a particular size. + * @param size The size in bytes. + * @return The relevant size unit. + */ + static SizeUnit getSizeUnit(Long size) { + if (size == null) { + return SizeUnit.values()[0]; + } + + for (int unitsIndex = 0; unitsIndex < SizeUnit.values().length; unitsIndex++) { + SizeUnit unit = SizeUnit.values()[unitsIndex]; + long result = size / unit.getDivisor(); + if (result < SIZE_CONVERSION_CONSTANT) { + return unit; + } + } + + return SizeUnit.values()[SizeUnit.values().length - 1]; + } + + /** + * Get a long size in bytes as a string formatted to be read by users. + * + * @param size Long value representing a size in byte.s + * @param format The means of formatting the number. + * @param showFullSize Optionally show the number of bytes in the + * datasource. + * + * @return Return a string formatted with a user friendly version of the size + * as a string, returns empty String when provided empty size. + */ + static String getSizeString(Long size, DecimalFormat format, boolean showFullSize) { + if (size == null) { + return ""; + } + + SizeUnit sizeUnit = getSizeUnit(size); + if (sizeUnit == null) { + sizeUnit = SizeUnit.BYTES; + } + + String closestUnitSize = String.format("%s %s", + format.format(((double) size) / sizeUnit.getDivisor()), sizeUnit.getSuffix()); + + String fullSize = String.format("%d %s", size, SizeUnit.BYTES.getSuffix()); + if (sizeUnit.equals(SizeUnit.BYTES)) { + return fullSize; + } else if (showFullSize) { + return String.format("%s (%s)", closestUnitSize, fullSize); + } else { + return closestUnitSize; + } + } + + /** + * Returns a default cell model using size units. + * @param bytes The number of bytes. + * @return The default cell model. + */ + static DefaultCellModel getBytesCell(Long bytes) { + if (bytes == null) { + return new DefaultCellModel<>(""); + } else { + SizeUnit unit = SizeRepresentationUtil.getSizeUnit(bytes); + if (unit == null) { + unit = SizeUnit.BYTES; + } + + return new DefaultCellModel(bytes, SizeRepresentationUtil::getSizeString, unit.getExcelFormatString()); + } + } + + private SizeRepresentationUtil() { + } +} From 0aa708388c3505ada0e55f7deb31b86925d9c92e Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Fri, 6 Aug 2021 14:45:06 -0400 Subject: [PATCH 13/33] Moved timeline getters and export functionality out of datasourcesummary --- .../contentutils/ContainerSummary.java | 11 +- .../contentutils/RecentFilesSummary.java | 12 - .../TimelineSummary.java | 213 ++++++++++-------- .../datamodel/ContainerSummaryGetter.java | 28 ++- .../datamodel/RecentFilesGetter.java | 14 +- .../datamodel/TimelineDataSourceUtils.java | 95 -------- .../datamodel/TimelineSummaryGetter.java | 89 ++++++++ .../datasourcesummary/ui/TimelinePanel.java | 108 ++------- .../BarChartSeries.java | 99 +++++++- .../Bundle.properties-MERGED | 12 + .../ExcelExportAction.java | 11 +- .../ExportTimeline.java | 139 ++++++++++++ 12 files changed, 507 insertions(+), 324 deletions(-) rename Core/src/org/sleuthkit/autopsy/{datasourcesummary/datamodel => contentutils}/TimelineSummary.java (63%) mode change 100644 => 100755 delete mode 100644 Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineDataSourceUtils.java create mode 100644 Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummaryGetter.java create mode 100755 Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTimeline.java diff --git a/Core/src/org/sleuthkit/autopsy/contentutils/ContainerSummary.java b/Core/src/org/sleuthkit/autopsy/contentutils/ContainerSummary.java index 87a78093ca..13f7eec7bf 100755 --- a/Core/src/org/sleuthkit/autopsy/contentutils/ContainerSummary.java +++ b/Core/src/org/sleuthkit/autopsy/contentutils/ContainerSummary.java @@ -38,18 +38,9 @@ import org.sleuthkit.datamodel.TskData; */ public class ContainerSummary { - private static final Set ARTIFACT_UPDATE_TYPE_IDS = new HashSet<>(Arrays.asList( - BlackboardArtifact.ARTIFACT_TYPE.TSK_OS_INFO.getTypeID(), - BlackboardArtifact.ARTIFACT_TYPE.TSK_DATA_SOURCE_USAGE.getTypeID() - )); - private ContainerSummary() { } - - public static Set getArtifactTypeIdsForRefresh() { - return Collections.unmodifiableSet(ARTIFACT_UPDATE_TYPE_IDS); - } - + /** * Gets the size of unallocated files in a particular datasource. * diff --git a/Core/src/org/sleuthkit/autopsy/contentutils/RecentFilesSummary.java b/Core/src/org/sleuthkit/autopsy/contentutils/RecentFilesSummary.java index 502e2c76a1..f298602351 100755 --- a/Core/src/org/sleuthkit/autopsy/contentutils/RecentFilesSummary.java +++ b/Core/src/org/sleuthkit/autopsy/contentutils/RecentFilesSummary.java @@ -58,24 +58,12 @@ public class RecentFilesSummary { private static final DateFormat DATETIME_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss", Locale.getDefault()); - private static final Set ARTIFACT_UPDATE_TYPE_IDS = new HashSet<>(Arrays.asList( - ARTIFACT_TYPE.TSK_RECENT_OBJECT.getTypeID(), - ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID(), - ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT.getTypeID(), - ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID(), - ARTIFACT_TYPE.TSK_MESSAGE.getTypeID() - )); - /** * Default constructor. */ private RecentFilesSummary() { } - public static Set getArtifactTypeIdsForRefresh() { - return Collections.unmodifiableSet(ARTIFACT_UPDATE_TYPE_IDS); - } - /** * Removes fileDetails entries with redundant paths, sorts by date * descending and limits to the limit provided. diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java b/Core/src/org/sleuthkit/autopsy/contentutils/TimelineSummary.java old mode 100644 new mode 100755 similarity index 63% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java rename to Core/src/org/sleuthkit/autopsy/contentutils/TimelineSummary.java index a43d46764b..345cda6332 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java +++ b/Core/src/org/sleuthkit/autopsy/contentutils/TimelineSummary.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2020 Basis Technology Corp. + * Copyright 2020-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,8 +16,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datasourcesummary.datamodel; +package org.sleuthkit.autopsy.contentutils; +import java.text.DateFormat; +import java.text.SimpleDateFormat; import java.time.Instant; import java.util.ArrayList; import java.util.Arrays; @@ -26,51 +28,34 @@ import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.TimeZone; import org.joda.time.Interval; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultUpdateGovernor; -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.TimelineEvent; import org.sleuthkit.datamodel.TimelineEventType; import org.sleuthkit.datamodel.TimelineFilter.RootFilter; import org.sleuthkit.datamodel.TimelineManager; import org.sleuthkit.datamodel.TskCoreException; -import java.util.function.Supplier; +import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.core.UserPreferences; +import org.sleuthkit.autopsy.timeline.TimeLineController; +import org.sleuthkit.autopsy.timeline.TimeLineModule; +import org.sleuthkit.autopsy.timeline.ui.filtering.datamodel.FilterState; +import org.sleuthkit.autopsy.timeline.ui.filtering.datamodel.RootFilterState; +import org.sleuthkit.datamodel.TimelineFilter; /** * Provides data source summary information pertaining to Timeline data. */ -public class TimelineSummary implements DefaultUpdateGovernor { +public class TimelineSummary { - /** - * A function for obtaining a Timeline RootFilter filtered to the specific - * data source. - */ - public interface DataSourceFilterFunction { - - /** - * Obtains a Timeline RootFilter filtered to the specific data source. - * - * @param dataSource The data source. - * @return The timeline root filter. - * @throws NoCurrentCaseException - * @throws TskCoreException - */ - RootFilter apply(DataSource dataSource) throws NoCurrentCaseException, TskCoreException; - } + private static final TimeZone timeZone = TimeZone.getTimeZone(UserPreferences.getTimeZoneForDisplays()); private static final long DAY_SECS = 24 * 60 * 60; - private static final Set INGEST_JOB_EVENTS = new HashSet<>( - Arrays.asList(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED)); - private static final Set FILE_SYSTEM_EVENTS = new HashSet<>(Arrays.asList( TimelineEventType.FILE_MODIFIED, @@ -78,68 +63,24 @@ public class TimelineSummary implements DefaultUpdateGovernor { TimelineEventType.FILE_CREATED, TimelineEventType.FILE_CHANGED)); - private final SleuthkitCaseProvider caseProvider; - private final Supplier timeZoneProvider; - private final DataSourceFilterFunction filterFunction; - - /** - * Default constructor. - */ - public TimelineSummary() { - this(SleuthkitCaseProvider.DEFAULT, - () -> TimeZone.getTimeZone(UserPreferences.getTimeZoneForDisplays()), - (ds) -> TimelineDataSourceUtils.getInstance().getDataSourceFilter(ds)); - } - - /** - * Construct object with given SleuthkitCaseProvider - * - * @param caseProvider SleuthkitCaseProvider provider; cannot be null. - * @param timeZoneProvider The timezone provider; cannot be null. - * @param filterFunction Provides the default root filter function filtered - * to the data source; cannot be null. - */ - public TimelineSummary(SleuthkitCaseProvider caseProvider, Supplier timeZoneProvider, DataSourceFilterFunction filterFunction) { - this.caseProvider = caseProvider; - this.timeZoneProvider = timeZoneProvider; - this.filterFunction = filterFunction; - } - - @Override - public boolean isRefreshRequired(ModuleContentEvent evt) { - return true; - } - - @Override - public boolean isRefreshRequired(AbstractFile file) { - return true; - } - - @Override - public boolean isRefreshRequired(IngestManager.IngestJobEvent evt) { - return (evt != null && INGEST_JOB_EVENTS.contains(evt)); - } - - @Override - public Set getIngestJobEventUpdates() { - return INGEST_JOB_EVENTS; + private TimelineSummary() { } /** * Retrieves timeline summary data. * - * @param dataSource The data source for which timeline data will be - * retrieved. + * @param dataSource The data source for which timeline data will be + * retrieved. * @param recentDaysNum The maximum number of most recent days' activity to - * include. + * include. + * * @return The retrieved data. - * @throws SleuthkitCaseProviderException + * * @throws TskCoreException * @throws NoCurrentCaseException */ - public TimelineSummaryData getData(DataSource dataSource, int recentDaysNum) throws SleuthkitCaseProviderException, TskCoreException, NoCurrentCaseException { - TimeZone timeZone = this.timeZoneProvider.get(); - TimelineManager timelineManager = this.caseProvider.get().getTimelineManager(); + public static TimelineSummaryData getTimelineSummaryData(DataSource dataSource, int recentDaysNum) throws TskCoreException, NoCurrentCaseException { + TimelineManager timelineManager = Case.getCurrentCaseThrows().getSleuthkitCase().getTimelineManager(); // get a mapping of days from epoch to the activity for that day Map dateCounts = getTimelineEventsByDay(dataSource, timelineManager, timeZone); @@ -174,13 +115,14 @@ public class TimelineSummary implements DefaultUpdateGovernor { * Given activity by day, converts to most recent days' activity handling * empty values. * - * @param dateCounts The day from epoch mapped to activity amounts for that - * day. + * @param dateCounts The day from epoch mapped to activity amounts for + * that day. * @param minRecentDay The minimum recent day in days from epoch. - * @param maxDay The maximum recent day in days from epoch; + * @param maxDay The maximum recent day in days from epoch; + * * @return The most recent daily activity amounts. */ - private List getMostRecentActivityAmounts(Map dateCounts, long minRecentDay, long maxDay) { + private static List getMostRecentActivityAmounts(Map dateCounts, long minRecentDay, long maxDay) { List mostRecentActivityAmt = new ArrayList<>(); for (long curRecentDay = minRecentDay; curRecentDay <= maxDay; curRecentDay++) { @@ -197,18 +139,20 @@ public class TimelineSummary implements DefaultUpdateGovernor { /** * Fetches timeline events per day for a particular data source. * - * @param dataSource The data source. + * @param dataSource The data source. * @param timelineManager The timeline manager to use while fetching the - * data. - * @param timeZone The time zone to use to determine which day activity - * belongs. + * data. + * @param timeZone The time zone to use to determine which day + * activity belongs. + * * @return A Map mapping days from epoch to the activity for that day. + * * @throws TskCoreException * @throws NoCurrentCaseException */ - private Map getTimelineEventsByDay(DataSource dataSource, TimelineManager timelineManager, TimeZone timeZone) + private static Map getTimelineEventsByDay(DataSource dataSource, TimelineManager timelineManager, TimeZone timeZone) throws TskCoreException, NoCurrentCaseException { - RootFilter rootFilter = this.filterFunction.apply(dataSource); + RootFilter rootFilter = getDataSourceFilter(dataSource); // get events for data source long curRunTime = System.currentTimeMillis(); @@ -251,12 +195,14 @@ public class TimelineSummary implements DefaultUpdateGovernor { /** * Main constructor. * - * @param minDate Earliest usage date recorded for the data source. - * @param maxDate Latest usage date recorded for the data source. + * @param minDate Earliest usage date recorded for the data + * source. + * @param maxDate Latest usage date recorded for the data + * source. * @param recentDaysActivity A list of activity prior to and including - * max date sorted by min to max date. - * @param dataSource The data source for which this data applies. the - * latest usage date by day. + * max date sorted by min to max date. + * @param dataSource The data source for which this data + * applies. the latest usage date by day. */ TimelineSummaryData(Date minDate, Date maxDate, List recentDaysActivity, DataSource dataSource) { this.minDate = minDate; @@ -281,7 +227,7 @@ public class TimelineSummary implements DefaultUpdateGovernor { /** * @return A list of activity prior to and including the latest usage - * date by day sorted min to max date. + * date by day sorted min to max date. */ public List getMostRecentDaysActivity() { return histogramActivity; @@ -307,8 +253,10 @@ public class TimelineSummary implements DefaultUpdateGovernor { /** * Main constructor. * - * @param day The day for which activity is being measured. - * @param fileActivityCount The amount of file activity timeline events. + * @param day The day for which activity is being + * measured. + * @param fileActivityCount The amount of file activity timeline + * events. * @param artifactActivityCount The amount of artifact timeline events. */ DailyActivityAmount(Date day, long fileActivityCount, long artifactActivityCount) { @@ -337,6 +285,73 @@ public class TimelineSummary implements DefaultUpdateGovernor { public long getArtifactActivityCount() { return artifactActivityCount; } - } + + /** + * Retrieves a RootFilter based on the default filter state but only the + * specified dataSource is selected. + * + * @param dataSource The data source. + * + * @return The root filter representing a default filter with only this data + * source selected. + * + * @throws NoCurrentCaseException + * @throws TskCoreException + */ + public static RootFilter getDataSourceFilter(DataSource dataSource) throws NoCurrentCaseException, TskCoreException { + RootFilterState filterState = getDataSourceFilterState(dataSource); + return filterState == null ? null : filterState.getActiveFilter(); + } + + /** + * Retrieves a TimeLineController based on the default filter state but only + * the specified dataSource is selected. + * + * @param dataSource The data source. + * + * @return The root filter state representing a default filter with only + * this data source selected. + * + * @throws NoCurrentCaseException + * @throws TskCoreException + */ + public static RootFilterState getDataSourceFilterState(DataSource dataSource) throws NoCurrentCaseException, TskCoreException { + TimeLineController controller = TimeLineModule.getController(); + RootFilterState dataSourceState = controller.getEventsModel().getDefaultEventFilterState().copyOf(); + + for (FilterState filterState : dataSourceState.getDataSourcesFilterState().getSubFilterStates()) { + TimelineFilter.DataSourceFilter dsFilter = filterState.getFilter(); + if (dsFilter != null) { + filterState.setSelected(dsFilter.getDataSourceID() == dataSource.getId()); + } + + } + + return dataSourceState; + } + + /** + * Creates a DateFormat formatter that uses UTC for time zone. + * + * @param formatString The date format string. + * @return The data format. + */ + public static DateFormat getUtcFormat(String formatString) { + return new SimpleDateFormat(formatString, Locale.getDefault()); + } + + /** + * Formats a date using a DateFormat. In the event that the date is null, + * returns a null string. + * + * @param date The date to format. + * @param formatter The DateFormat to use to format the date. + * + * @return The formatted string generated from the formatter or null if the + * date is null. + */ + public static String formatDate(Date date, DateFormat formatter) { + return date == null ? null : formatter.format(date); + } } diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummaryGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummaryGetter.java index 69946a4b80..9cf43f408e 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummaryGetter.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummaryGetter.java @@ -20,21 +20,31 @@ package org.sleuthkit.autopsy.datasourcesummary.datamodel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultArtifactUpdateGovernor; import java.sql.SQLException; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; import java.util.Set; import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.autopsy.contentutils.ContainerSummary; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.ingest.ModuleContentEvent; import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.TskCoreException; /** - * Wrapper class for converting org.sleuthkit.autopsy.contentutils.ContainerSummary functionality into - * a DefaultArtifactUpdateGovernor used by Container tab. + * Wrapper class for converting + * org.sleuthkit.autopsy.contentutils.ContainerSummary functionality into a + * DefaultArtifactUpdateGovernor used by Container tab. */ public class ContainerSummaryGetter implements DefaultArtifactUpdateGovernor { + private static final Set ARTIFACT_UPDATE_TYPE_IDS = new HashSet<>(Arrays.asList( + BlackboardArtifact.ARTIFACT_TYPE.TSK_OS_INFO.getTypeID(), + BlackboardArtifact.ARTIFACT_TYPE.TSK_DATA_SOURCE_USAGE.getTypeID() + )); + /** * Main constructor. */ @@ -53,7 +63,7 @@ public class ContainerSummaryGetter implements DefaultArtifactUpdateGovernor { @Override public Set getArtifactTypeIdsForRefresh() { - return ContainerSummary.getArtifactTypeIdsForRefresh(); + return Collections.unmodifiableSet(ARTIFACT_UPDATE_TYPE_IDS); } /** @@ -73,7 +83,7 @@ public class ContainerSummaryGetter implements DefaultArtifactUpdateGovernor { return ContainerSummary.getSizeOfUnallocatedFiles(currentDataSource); } catch (NoCurrentCaseException ex) { throw new SleuthkitCaseProviderException("No currently open case.", ex); - } + } } /** @@ -95,7 +105,7 @@ public class ContainerSummaryGetter implements DefaultArtifactUpdateGovernor { return ContainerSummary.getOperatingSystems(dataSource); } catch (NoCurrentCaseException ex) { throw new SleuthkitCaseProviderException("No currently open case.", ex); - } + } } /** @@ -117,12 +127,12 @@ public class ContainerSummaryGetter implements DefaultArtifactUpdateGovernor { return ContainerSummary.getDataSourceType(dataSource); } catch (NoCurrentCaseException ex) { throw new SleuthkitCaseProviderException("No currently open case.", ex); - } + } } - + /** - * Retrieves a container data model object containing data about - * the data source. + * Retrieves a container data model object containing data about the data + * source. * * @param dataSource The data source. * diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesGetter.java index 045394d7cc..668c0085df 100755 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesGetter.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesGetter.java @@ -18,6 +18,9 @@ */ package org.sleuthkit.autopsy.datasourcesummary.datamodel; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultArtifactUpdateGovernor; import java.util.List; import java.util.Set; @@ -29,6 +32,7 @@ import org.sleuthkit.autopsy.contentutils.RecentFilesSummary.RecentFileDetails; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.datamodel.BlackboardArtifact; /** * Wrapper class for converting @@ -37,6 +41,14 @@ import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.S */ public class RecentFilesGetter implements DefaultArtifactUpdateGovernor { + private static final Set ARTIFACT_UPDATE_TYPE_IDS = new HashSet<>(Arrays.asList( + BlackboardArtifact.ARTIFACT_TYPE.TSK_RECENT_OBJECT.getTypeID(), + BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID(), + BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT.getTypeID(), + BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID(), + BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE.getTypeID() + )); + /** * Default constructor. */ @@ -45,7 +57,7 @@ public class RecentFilesGetter implements DefaultArtifactUpdateGovernor { @Override public Set getArtifactTypeIdsForRefresh() { - return RecentFilesSummary.getArtifactTypeIdsForRefresh(); + return Collections.unmodifiableSet(ARTIFACT_UPDATE_TYPE_IDS); } /** diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineDataSourceUtils.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineDataSourceUtils.java deleted file mode 100644 index 40f76cce80..0000000000 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineDataSourceUtils.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2020 Basis Technology Corp. - * Contact: carrier sleuthkit org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sleuthkit.autopsy.datasourcesummary.datamodel; - -import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; -import org.sleuthkit.autopsy.timeline.TimeLineController; -import org.sleuthkit.autopsy.timeline.TimeLineModule; -import org.sleuthkit.autopsy.timeline.ui.filtering.datamodel.FilterState; -import org.sleuthkit.autopsy.timeline.ui.filtering.datamodel.RootFilterState; -import org.sleuthkit.datamodel.DataSource; -import org.sleuthkit.datamodel.TimelineFilter; -import org.sleuthkit.datamodel.TimelineFilter.DataSourceFilter; -import org.sleuthkit.datamodel.TimelineFilter.RootFilter; -import org.sleuthkit.datamodel.TskCoreException; - -/** - * Utilities for interacting with Timeline in relation to data sources. - */ -public class TimelineDataSourceUtils { - - private static TimelineDataSourceUtils instance = null; - - /** - * @return Singleton instance of this class. - */ - public static TimelineDataSourceUtils getInstance() { - if (instance == null) { - instance = new TimelineDataSourceUtils(); - } - - return instance; - } - - /** - * Main constructor. Should be instantiated through getInstance(). - */ - private TimelineDataSourceUtils() { - } - - /** - * Retrieves a RootFilter based on the default filter state but only the - * specified dataSource is selected. - * - * @param dataSource The data source. - * @return The root filter representing a default filter with only this data - * source selected. - * @throws NoCurrentCaseException - * @throws TskCoreException - */ - public RootFilter getDataSourceFilter(DataSource dataSource) throws NoCurrentCaseException, TskCoreException { - RootFilterState filterState = getDataSourceFilterState(dataSource); - return filterState == null ? null : filterState.getActiveFilter(); - } - - /** - * Retrieves a TimeLineController based on the default filter state but only - * the specified dataSource is selected. - * - * @param dataSource The data source. - * @return The root filter state representing a default filter with only - * this data source selected. - * @throws NoCurrentCaseException - * @throws TskCoreException - */ - public RootFilterState getDataSourceFilterState(DataSource dataSource) throws NoCurrentCaseException, TskCoreException { - TimeLineController controller = TimeLineModule.getController(); - RootFilterState dataSourceState = controller.getEventsModel().getDefaultEventFilterState().copyOf(); - - for (FilterState filterState : dataSourceState.getDataSourcesFilterState().getSubFilterStates()) { - DataSourceFilter dsFilter = filterState.getFilter(); - if (dsFilter != null) { - filterState.setSelected(dsFilter.getDataSourceID() == dataSource.getId()); - } - - } - - return dataSourceState; - } -} diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummaryGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummaryGetter.java new file mode 100644 index 0000000000..3331cd45ed --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummaryGetter.java @@ -0,0 +1,89 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.datasourcesummary.datamodel; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultUpdateGovernor; +import org.sleuthkit.autopsy.contentutils.TimelineSummary; +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.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.autopsy.contentutils.TimelineSummary.TimelineSummaryData; + +/** + * Provides data source summary information pertaining to Timeline data. + */ +public class TimelineSummaryGetter implements DefaultUpdateGovernor { + + private static final Set INGEST_JOB_EVENTS = new HashSet<>( + Arrays.asList(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED)); + + /** + * Default constructor. + */ + public TimelineSummaryGetter() { + } + + @Override + public boolean isRefreshRequired(ModuleContentEvent evt) { + return true; + } + + @Override + public boolean isRefreshRequired(AbstractFile file) { + return true; + } + + @Override + public boolean isRefreshRequired(IngestManager.IngestJobEvent evt) { + return (evt != null && INGEST_JOB_EVENTS.contains(evt)); + } + + @Override + public Set getIngestJobEventUpdates() { + return Collections.unmodifiableSet(INGEST_JOB_EVENTS); + } + + /** + * Retrieves timeline summary data. + * + * @param dataSource The data source for which timeline data will be + * retrieved. + * @param recentDaysNum The maximum number of most recent days' activity to + * include. + * @return The retrieved data. + * @throws SleuthkitCaseProviderException + * @throws TskCoreException + * @throws NoCurrentCaseException + */ + public TimelineSummaryData getData(DataSource dataSource, int recentDaysNum) throws SleuthkitCaseProviderException, TskCoreException, NoCurrentCaseException { + try { + return TimelineSummary.getTimelineSummaryData(dataSource, recentDaysNum); + } catch (NoCurrentCaseException ex) { + throw new SleuthkitCaseProviderException("No currently open case.", ex); + } + } +} diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java index 318da42943..dab41e9cc8 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2020 Basis Technology Corp. + * Copyright 2020-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,13 +20,10 @@ package org.sleuthkit.autopsy.datasourcesummary.ui; import java.awt.Color; import java.text.DateFormat; -import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.Date; import java.util.List; -import java.util.Locale; import java.util.logging.Level; import org.apache.commons.collections.CollectionUtils; import org.joda.time.DateTime; @@ -35,10 +32,10 @@ import org.openide.util.NbBundle.Messages; import org.openide.util.actions.CallableSystemAction; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineDataSourceUtils; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary.DailyActivityAmount; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary.TimelineSummaryData; +import org.sleuthkit.autopsy.contentutils.TimelineSummary; +import org.sleuthkit.autopsy.contentutils.TimelineSummary.DailyActivityAmount; +import org.sleuthkit.autopsy.contentutils.TimelineSummary.TimelineSummaryData; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummaryGetter; import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartPanel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartSeries; import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartPanel.OrderedKey; @@ -47,7 +44,6 @@ import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetcher; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultCellModel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.IngestRunningLabel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.LoadableComponent; import org.sleuthkit.autopsy.datasourcesummary.uiutils.LoadableLabel; @@ -73,26 +69,15 @@ public class TimelinePanel extends BaseDataSourceSummaryPanel { private static final long serialVersionUID = 1L; private static final String EARLIEST_LATEST_FORMAT_STR = "MMM d, yyyy"; - private static final DateFormat EARLIEST_LATEST_FORMAT = getUtcFormat(EARLIEST_LATEST_FORMAT_STR); - private static final DateFormat CHART_FORMAT = getUtcFormat("MMM d, yyyy"); + private static final DateFormat EARLIEST_LATEST_FORMAT = TimelineSummary.getUtcFormat(EARLIEST_LATEST_FORMAT_STR); + private static final DateFormat CHART_FORMAT = TimelineSummary.getUtcFormat("MMM d, yyyy"); private static final int MOST_RECENT_DAYS_COUNT = 30; - /** - * Creates a DateFormat formatter that uses UTC for time zone. - * - * @param formatString The date format string. - * @return The data format. - */ - private static DateFormat getUtcFormat(String formatString) { - return new SimpleDateFormat(formatString, Locale.getDefault()); - } - // components displayed in the tab private final IngestRunningLabel ingestRunningLabel = new IngestRunningLabel(); private final LoadableLabel earliestLabel = new LoadableLabel(Bundle.TimelinePanel_earliestLabel_title()); private final LoadableLabel latestLabel = new LoadableLabel(Bundle.TimelinePanel_latestLabel_title()); private final BarChartPanel last30DaysChart = new BarChartPanel(Bundle.TimlinePanel_last30DaysChart_title(), "", ""); - private final TimelineDataSourceUtils timelineUtils = TimelineDataSourceUtils.getInstance(); // all loadable components on this tab private final List> loadableComponents = Arrays.asList(earliestLabel, latestLabel, last30DaysChart); @@ -103,16 +88,16 @@ public class TimelinePanel extends BaseDataSourceSummaryPanel { private final List> dataFetchComponents; public TimelinePanel() { - this(new TimelineSummary()); + this(new TimelineSummaryGetter()); } /** * Creates new form PastCasesPanel */ - public TimelinePanel(TimelineSummary timelineData) { + public TimelinePanel(TimelineSummaryGetter timelineData) { super(timelineData); - dataFetcher = (dataSource) -> timelineData.getData(dataSource, MOST_RECENT_DAYS_COUNT); + dataFetcher = (dataSource) -> TimelineSummary.getTimelineSummaryData(dataSource, MOST_RECENT_DAYS_COUNT); // set up data acquisition methods dataFetchComponents = Arrays.asList( @@ -121,29 +106,18 @@ public class TimelinePanel extends BaseDataSourceSummaryPanel { initComponents(); } - /** - * Formats a date using a DateFormat. In the event that the date is null, - * returns a null string. - * - * @param date The date to format. - * @param formatter The DateFormat to use to format the date. - * @return The formatted string generated from the formatter or null if the - * date is null. - */ - private static String formatDate(Date date, DateFormat formatter) { - return date == null ? null : formatter.format(date); - } - private static final Color FILE_EVT_COLOR = new Color(228, 22, 28); private static final Color ARTIFACT_EVT_COLOR = new Color(21, 227, 100); /** - * Converts DailyActivityAmount data retrieved from TimelineSummary into - * data to be displayed as a bar chart. + * Converts DailyActivityAmount data retrieved from TimelineSummaryGetter + * into data to be displayed as a bar chart. * - * @param recentDaysActivity The data retrieved from TimelineSummary. + * @param recentDaysActivity The data retrieved from + * TimelineSummaryGetter. * @param showIntermediateDates If true, shows all dates. If false, shows - * only first and last date. + * only first and last date. + * * @return The data to be displayed in the BarChart. */ private List parseChartData(List recentDaysActivity, boolean showIntermediateDates) { @@ -162,7 +136,7 @@ public class TimelinePanel extends BaseDataSourceSummaryPanel { long fileAmt = curItem.getFileActivityCount(); long artifactAmt = curItem.getArtifactActivityCount() * 100; String formattedDate = (showIntermediateDates || i == 0 || i == recentDaysActivity.size() - 1) - ? formatDate(curItem.getDay(), CHART_FORMAT) : ""; + ? TimelineSummary.formatDate(curItem.getDay(), CHART_FORMAT) : ""; OrderedKey thisKey = new OrderedKey(formattedDate, i); fileEvtCounts.add(new BarChartItem(thisKey, fileAmt)); @@ -186,8 +160,8 @@ public class TimelinePanel extends BaseDataSourceSummaryPanel { * @param result The result to be displayed on this tab. */ private void handleResult(DataFetchResult result) { - earliestLabel.showDataFetchResult(DataFetchResult.getSubResult(result, r -> formatDate(r.getMinDate(), EARLIEST_LATEST_FORMAT))); - latestLabel.showDataFetchResult(DataFetchResult.getSubResult(result, r -> formatDate(r.getMaxDate(), EARLIEST_LATEST_FORMAT))); + earliestLabel.showDataFetchResult(DataFetchResult.getSubResult(result, r -> TimelineSummary.formatDate(r.getMinDate(), EARLIEST_LATEST_FORMAT))); + latestLabel.showDataFetchResult(DataFetchResult.getSubResult(result, r -> TimelineSummary.formatDate(r.getMaxDate(), EARLIEST_LATEST_FORMAT))); last30DaysChart.showDataFetchResult(DataFetchResult.getSubResult(result, r -> parseChartData(r.getMostRecentDaysActivity(), false))); if (result != null @@ -237,8 +211,8 @@ public class TimelinePanel extends BaseDataSourceSummaryPanel { * Action that occurs when 'View in Timeline' button is pressed. * * @param dataSource The data source to filter to. - * @param minDate The min date for the zoom of the window. - * @param maxDate The max date for the zoom of the window. + * @param minDate The min date for the zoom of the window. + * @param maxDate The max date for the zoom of the window. */ private void openFilteredChart(DataSource dataSource, Date minDate, Date maxDate) { OpenTimelineAction openTimelineAction = CallableSystemAction.get(OpenTimelineAction.class); @@ -255,7 +229,7 @@ public class TimelinePanel extends BaseDataSourceSummaryPanel { final TimeLineController controller = TimeLineModule.getController(); if (dataSource != null) { - controller.pushFilters(timelineUtils.getDataSourceFilterState(dataSource)); + controller.pushFilters(TimelineSummary.getDataSourceFilterState(dataSource)); } if (minDate != null && maxDate != null) { @@ -288,44 +262,6 @@ public class TimelinePanel extends BaseDataSourceSummaryPanel { super.close(); } - /** - * Create a default cell model to be use with excel export in the earliest / - * latest date format. - * - * @param date The date. - * @return The cell model. - */ - private static DefaultCellModel getEarliestLatestCell(Date date) { - return new DefaultCellModel<>(date, (dt) -> dt == null ? "" : EARLIEST_LATEST_FORMAT.format(dt), EARLIEST_LATEST_FORMAT_STR); - } - - /* ELTODO - @Messages({ - "TimelinePanel_getExports_sheetName=Timeline", - "TimelinePanel_getExports_activityRange=Activity Range", - "TimelinePanel_getExports_earliest=Earliest:", - "TimelinePanel_getExports_latest=Latest:", - "TimelinePanel_getExports_dateColumnHeader=Date", - "TimelinePanel_getExports_chartName=Last 30 Days",}) - @Override - List getExports(DataSource dataSource) { - TimelineSummaryData summaryData = getFetchResult(dataFetcher, "Timeline", dataSource); - if (summaryData == null) { - return Collections.emptyList(); - } - - return Arrays.asList( - new ExcelSpecialFormatExport(Bundle.TimelinePanel_getExports_sheetName(), - Arrays.asList( - new TitledExportable(Bundle.TimelinePanel_getExports_activityRange(), Collections.emptyList()), - new KeyValueItemExportable(Bundle.TimelinePanel_getExports_earliest(), getEarliestLatestCell(summaryData.getMinDate())), - new KeyValueItemExportable(Bundle.TimelinePanel_getExports_latest(), getEarliestLatestCell(summaryData.getMaxDate())), - new BarChartExport(Bundle.TimelinePanel_getExports_dateColumnHeader(), - "#,###", - Bundle.TimelinePanel_getExports_chartName(), - parseChartData(summaryData.getMostRecentDaysActivity(), true))))); - }*/ - /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/BarChartSeries.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/BarChartSeries.java index f7c48a2f30..99a5d1b557 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/BarChartSeries.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/BarChartSeries.java @@ -25,12 +25,12 @@ import java.util.List; /** * Represents a series in a bar chart where all items pertain to one category. */ -public class BarChartSeries { +class BarChartSeries { /** * An individual bar to be displayed in the bar chart. */ - public static class BarChartItem { + static class BarChartItem { private final Comparable key; private final double value; @@ -38,10 +38,10 @@ public class BarChartSeries { /** * Main constructor. * - * @param key The key. + * @param key The key. * @param value The value for this item. */ - public BarChartItem(Comparable key, double value) { + BarChartItem(Comparable key, double value) { this.key = key; this.value = value; } @@ -49,14 +49,14 @@ public class BarChartSeries { /** * @return The key for this item. */ - public Comparable getKey() { + Comparable getKey() { return key; } /** * @return The value for this item. */ - public double getValue() { + double getValue() { return value; } } @@ -67,11 +67,11 @@ public class BarChartSeries { /** * Main constructor. * - * @param key The key. + * @param key The key. * @param color The color for this series. * @param items The bars to be displayed for this series. */ - public BarChartSeries(Comparable key, Color color, List items) { + BarChartSeries(Comparable key, Color color, List items) { this.key = key; this.color = color; this.items = (items == null) ? Collections.emptyList() : Collections.unmodifiableList(items); @@ -80,22 +80,99 @@ public class BarChartSeries { /** * @return The color for this series. */ - public Color getColor() { + Color getColor() { return color; } /** * @return The bars to be displayed for this series. */ - public List getItems() { + List getItems() { return items; } /** * @return The key for this item. */ - public Comparable getKey() { + Comparable getKey() { return key; } + /** + * JFreeChart bar charts don't preserve the order of bars provided to the + * chart, but instead uses the comparable nature to order items. This + * provides order using a provided index as well as the value for the axis. + */ + static class OrderedKey implements Comparable { + + private final Object keyValue; + private final int keyIndex; + + /** + * Main constructor. + * + * @param keyValue The value for the key to be displayed in the domain + * axis. + * @param keyIndex The index at which it will be displayed. + */ + OrderedKey(Object keyValue, int keyIndex) { + this.keyValue = keyValue; + this.keyIndex = keyIndex; + } + + /** + * @return The value for the key to be displayed in the domain axis. + */ + Object getKeyValue() { + return keyValue; + } + + /** + * @return The index at which it will be displayed. + */ + int getKeyIndex() { + return keyIndex; + } + + @Override + public int compareTo(OrderedKey o) { + // this will have a higher value than null. + if (o == null) { + return 1; + } + + // compare by index + return Integer.compare(this.getKeyIndex(), o.getKeyIndex()); + } + + @Override + public int hashCode() { + int hash = 3; + return hash; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final OrderedKey other = (OrderedKey) obj; + if (this.keyIndex != other.keyIndex) { + return false; + } + return true; + } + + @Override + public String toString() { + // use toString on the key. + return this.getKeyValue() == null ? null : this.getKeyValue().toString(); + } + } } diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED index f93c0bc1c3..07d26f8e14 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED @@ -6,6 +6,7 @@ ExcelExport_writeExcel_noSheetName=Sheet {0} ExcelExportAction_exportToXLSX_beginExport=Beginning Export... ExcelExportAction_exportToXLSX_gatheringContainerData=Fetching Container & Image Data ExcelExportAction_exportToXLSX_gatheringRecentActivityData=Fetching Recent Activity Data +ExcelExportAction_exportToXLSX_gatheringTimelineData=Fetching Timeline Data ExcelExportAction_exportToXLSX_writingToFile=Writing to File... ExcelExportAction_getXLSXPath_directory=DataSourceSummary ExcelExportAction_moduleName=Data Source Summary @@ -37,3 +38,14 @@ SizeRepresentationUtil_units_kilobytes=KB SizeRepresentationUtil_units_megabytes=MB SizeRepresentationUtil_units_petabytes=PB SizeRepresentationUtil_units_terabytes=TB +TimelinePanel_earliestLabel_title=Earliest +TimelinePanel_getExports_activityRange=Activity Range +TimelinePanel_getExports_chartName=Last 30 Days +TimelinePanel_getExports_dateColumnHeader=Date +TimelinePanel_getExports_earliest=Earliest: +TimelinePanel_getExports_latest=Latest: +TimelinePanel_getExports_sheetName=Timeline +TimelinePanel_latestLabel_title=Latest +TimlinePanel_last30DaysChart_artifactEvts_title=Result Events +TimlinePanel_last30DaysChart_fileEvts_title=File Events +TimlinePanel_last30DaysChart_title=Last 30 Days diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java index e8416453b3..8492b4aca6 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java @@ -92,6 +92,7 @@ class ExcelExportAction { "ExcelExportAction_exportToXLSX_beginExport=Beginning Export...", "ExcelExportAction_exportToXLSX_gatheringRecentActivityData=Fetching Recent Activity Data", "ExcelExportAction_exportToXLSX_gatheringContainerData=Fetching Container & Image Data", + "ExcelExportAction_exportToXLSX_gatheringTimelineData=Fetching Timeline Data", "ExcelExportAction_exportToXLSX_writingToFile=Writing to File...",}) void exportToXLSX(ReportProgressPanel progressPanel, DataSource dataSource, String baseReportDir) @@ -120,8 +121,16 @@ class ExcelExportAction { sheetExports.addAll(exports); } - progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_writingToFile()); + // Export Timeline data + progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_gatheringTimelineData()); progressPanel.setProgress(3); + exports = ExportTimeline.getExports(dataSource); + if (exports != null) { + sheetExports.addAll(exports); + } + + progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_writingToFile()); + progressPanel.setProgress(9); ExcelExport.writeExcel(sheetExports, reportFile); progressPanel.complete(ReportProgressPanel.ReportStatus.COMPLETE, ""); diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTimeline.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTimeline.java new file mode 100755 index 0000000000..e845093f08 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTimeline.java @@ -0,0 +1,139 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit 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.text.DateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import org.apache.commons.collections.CollectionUtils; +import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.contentutils.TimelineSummary; +import org.sleuthkit.autopsy.contentutils.TimelineSummary.DailyActivityAmount; +import org.sleuthkit.autopsy.contentutils.TimelineSummary.TimelineSummaryData; +import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.BarChartSeries.BarChartItem; +import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.BarChartSeries.OrderedKey; +import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelSpecialFormatExport.KeyValueItemExportable; +import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelSpecialFormatExport.TitledExportable; +import org.sleuthkit.datamodel.DataSource; + +/** + * Class to export information about a data source's timeline events. + */ +@Messages({ + "TimelinePanel_earliestLabel_title=Earliest", + "TimelinePanel_latestLabel_title=Latest", + "TimlinePanel_last30DaysChart_title=Last 30 Days", + "TimlinePanel_last30DaysChart_fileEvts_title=File Events", + "TimlinePanel_last30DaysChart_artifactEvts_title=Result Events",}) +class ExportTimeline { + + private static final String EARLIEST_LATEST_FORMAT_STR = "MMM d, yyyy"; + private static final DateFormat EARLIEST_LATEST_FORMAT = TimelineSummary.getUtcFormat(EARLIEST_LATEST_FORMAT_STR); + private static final DateFormat CHART_FORMAT = TimelineSummary.getUtcFormat("MMM d, yyyy"); + private static final int MOST_RECENT_DAYS_COUNT = 30; + + private static final Color FILE_EVT_COLOR = new Color(228, 22, 28); + private static final Color ARTIFACT_EVT_COLOR = new Color(21, 227, 100); + + /** + * Creates new form PastCasesPanel + */ + private ExportTimeline() { + } + + /** + * Converts DailyActivityAmount data retrieved from TimelineSummaryGetter + * into data to be displayed as a bar chart. + * + * @param recentDaysActivity The data retrieved from + * TimelineSummaryGetter. + * @param showIntermediateDates If true, shows all dates. If false, shows + * only first and last date. + * + * @return The data to be displayed in the BarChart. + */ + private static List parseChartData(List recentDaysActivity, boolean showIntermediateDates) { + // if no data, return null indicating no result. + if (CollectionUtils.isEmpty(recentDaysActivity)) { + return null; + } + + // Create a bar chart item for each recent days activity item + List fileEvtCounts = new ArrayList<>(); + List artifactEvtCounts = new ArrayList<>(); + + for (int i = 0; i < recentDaysActivity.size(); i++) { + DailyActivityAmount curItem = recentDaysActivity.get(i); + + long fileAmt = curItem.getFileActivityCount(); + long artifactAmt = curItem.getArtifactActivityCount() * 100; + String formattedDate = (showIntermediateDates || i == 0 || i == recentDaysActivity.size() - 1) + ? TimelineSummary.formatDate(curItem.getDay(), CHART_FORMAT) : ""; + + OrderedKey thisKey = new OrderedKey(formattedDate, i); + fileEvtCounts.add(new BarChartItem(thisKey, fileAmt)); + artifactEvtCounts.add(new BarChartItem(thisKey, artifactAmt)); + } + + return Arrays.asList( + new BarChartSeries(Bundle.TimlinePanel_last30DaysChart_fileEvts_title(), FILE_EVT_COLOR, fileEvtCounts), + new BarChartSeries(Bundle.TimlinePanel_last30DaysChart_artifactEvts_title(), ARTIFACT_EVT_COLOR, artifactEvtCounts)); + } + + /** + * Create a default cell model to be use with excel export in the earliest / + * latest date format. + * + * @param date The date. + * @return The cell model. + */ + private static DefaultCellModel getEarliestLatestCell(Date date) { + return new DefaultCellModel<>(date, (dt) -> dt == null ? "" : EARLIEST_LATEST_FORMAT.format(dt), EARLIEST_LATEST_FORMAT_STR); + } + + @Messages({ + "TimelinePanel_getExports_sheetName=Timeline", + "TimelinePanel_getExports_activityRange=Activity Range", + "TimelinePanel_getExports_earliest=Earliest:", + "TimelinePanel_getExports_latest=Latest:", + "TimelinePanel_getExports_dateColumnHeader=Date", + "TimelinePanel_getExports_chartName=Last 30 Days",}) + static List getExports(DataSource dataSource) { + DataFetcher dataFetcher = (ds) -> TimelineSummary.getTimelineSummaryData(ds, MOST_RECENT_DAYS_COUNT); + TimelineSummaryData summaryData = ExcelExportAction.getFetchResult(dataFetcher, "Timeline", dataSource); + if (summaryData == null) { + return Collections.emptyList(); + } + + return Arrays.asList( + new ExcelSpecialFormatExport(Bundle.TimelinePanel_getExports_sheetName(), + Arrays.asList( + new TitledExportable(Bundle.TimelinePanel_getExports_activityRange(), Collections.emptyList()), + new KeyValueItemExportable(Bundle.TimelinePanel_getExports_earliest(), getEarliestLatestCell(summaryData.getMinDate())), + new KeyValueItemExportable(Bundle.TimelinePanel_getExports_latest(), getEarliestLatestCell(summaryData.getMaxDate())), + new BarChartExport(Bundle.TimelinePanel_getExports_dateColumnHeader(), + "#,###", + Bundle.TimelinePanel_getExports_chartName(), + parseChartData(summaryData.getMostRecentDaysActivity(), true))))); + } +} From e948b14c86f35e7ba04d2a77192aaace7a692ecd Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Fri, 6 Aug 2021 17:31:44 -0400 Subject: [PATCH 14/33] Moved file type export functionality --- .../contentutils/DataSourceInfoUtilities.java | 51 ++- .../contentutils/RecentFilesSummary.java | 3 - .../autopsy/contentutils/TypesSummary.java | 182 ++++++++++ ...ummary.java => MimeTypeSummaryGetter.java} | 68 ++-- ...esSummary.java => TypesSummaryGetter.java} | 69 ++-- .../datasourcesummary/ui/TypesPanel.java | 135 ++------ .../Bundle.properties-MERGED | 20 ++ .../ExcelExportAction.java | 11 +- .../datasourcesummaryexport/ExportTypes.java | 312 ++++++++++++++++++ 9 files changed, 653 insertions(+), 198 deletions(-) create mode 100755 Core/src/org/sleuthkit/autopsy/contentutils/TypesSummary.java rename Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/{MimeTypeSummary.java => MimeTypeSummaryGetter.java} (77%) rename Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/{TypesSummary.java => TypesSummaryGetter.java} (72%) create mode 100755 Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTypes.java diff --git a/Core/src/org/sleuthkit/autopsy/contentutils/DataSourceInfoUtilities.java b/Core/src/org/sleuthkit/autopsy/contentutils/DataSourceInfoUtilities.java index b8bc2a54b6..2b69808eba 100644 --- a/Core/src/org/sleuthkit/autopsy/contentutils/DataSourceInfoUtilities.java +++ b/Core/src/org/sleuthkit/autopsy/contentutils/DataSourceInfoUtilities.java @@ -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); + } } diff --git a/Core/src/org/sleuthkit/autopsy/contentutils/RecentFilesSummary.java b/Core/src/org/sleuthkit/autopsy/contentutils/RecentFilesSummary.java index f298602351..fd2d8341e7 100755 --- a/Core/src/org/sleuthkit/autopsy/contentutils/RecentFilesSummary.java +++ b/Core/src/org/sleuthkit/autopsy/contentutils/RecentFilesSummary.java @@ -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; diff --git a/Core/src/org/sleuthkit/autopsy/contentutils/TypesSummary.java b/Core/src/org/sleuthkit/autopsy/contentutils/TypesSummary.java new file mode 100755 index 0000000000..4c6944de37 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentutils/TypesSummary.java @@ -0,0 +1,182 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2019 - 2021 Basis Technology Corp. + * Contact: carrier sleuthkit 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 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 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 getMimeTypes() { + return mimeTypes; + } + + /** + * @return The color associated with this category. + */ + public Color getColor() { + return color; + } + } +} diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/MimeTypeSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/MimeTypeSummaryGetter.java similarity index 77% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/MimeTypeSummary.java rename to Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/MimeTypeSummaryGetter.java index 1b8ac3fc1c..a0b29e8a7f 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/MimeTypeSummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/MimeTypeSummaryGetter.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2020 Basis Technology Corp. + * Copyright 2020-2021 Basis Technology Corp. * Contact: carrier sleuthkit 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 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 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 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 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); + } } /** diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TypesSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TypesSummaryGetter.java similarity index 72% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TypesSummary.java rename to Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TypesSummaryGetter.java index 3b21654c14..7e0129382d 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TypesSummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TypesSummaryGetter.java @@ -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 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 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); + } } } diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java index e333888d0c..a5040a355e 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019 Basis Technology Corp. + * Copyright 2019-2021 Basis Technology Corp. * Contact: carrier sleuthkit 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 pieSlices, boolean usefulContent) { + TypesPieChartData(List pieSlices, boolean usefulContent) { this.pieSlices = pieSlices; this.usefulContent = usefulContent; } @@ -98,78 +98,20 @@ class TypesPanel extends BaseDataSourceSummaryPanel { /** * @return The pie chart data. */ - public List getPieSlices() { + List 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 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 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 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 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 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 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 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. * diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED index 07d26f8e14..6b90d2414d 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED @@ -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 diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java index 8492b4aca6..842ad9179a 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java @@ -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); diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTypes.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTypes.java new file mode 100755 index 0000000000..5453a879c8 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTypes.java @@ -0,0 +1,312 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2019-2021 Basis Technology Corp. + * Contact: carrier sleuthkit 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 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 pieSlices, boolean usefulContent) { + this.pieSlices = pieSlices; + this.usefulContent = usefulContent; + } + + /** + * @return The pie chart data. + */ + List 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 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 setValues) { + List quotedValues = setValues + .stream() + .map(str -> String.format("'%s'", str.replace("'", ""))) + .collect(Collectors.toList()); + + String commaSeparatedQuoted = String.join(", ", quotedValues); + return String.format("(%s) ", commaSeparatedQuoted); + } + + /** + * 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 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 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 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 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 fetcher, String key, DataSource dataSource) { + Long count = ExcelExportAction.getFetchResult(fetcher, "Types", dataSource); + return (count == null) ? null : new KeyValueItemExportable(key, + new DefaultCellModel(count, DataSourceInfoUtilities.COMMA_FORMATTER::format, DataSourceInfoUtilities.COMMA_FORMAT_STR)); + } + + static List getExports(DataSource dataSource) { + if (dataSource == null) { + return Collections.emptyList(); + } + + DataFetcher usageFetcher = (ds) -> ContainerSummary.getDataSourceType(ds); + DataFetcher osFetcher = (ds) -> ContainerSummary.getOperatingSystems(ds); + DataFetcher sizeFetcher = (ds) -> ds == null ? null : ds.getSize(); + + DataFetcher typesFetcher = (ds) -> getMimeTypeCategoriesModel(ds); + + DataFetcher allocatedFetcher = (ds) -> TypesSummary.getCountOfAllocatedFiles(ds); + DataFetcher unallocatedFetcher = (ds) -> TypesSummary.getCountOfUnallocatedFiles(ds); + DataFetcher slackFetcher = (ds) -> TypesSummary.getCountOfSlackFiles(ds); + DataFetcher 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()) + )); + } +} From df4964f94083625c3c6ce905f267bf4b8a864b19 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Mon, 9 Aug 2021 11:23:40 -0400 Subject: [PATCH 15/33] Refactored AnalysisPanel --- .../AnalysisSummary.java | 61 +++------- .../datamodel/AnalysisSummaryGetter.java | 115 ++++++++++++++++++ .../datasourcesummary/ui/AnalysisPanel.java | 20 +-- .../Bundle.properties-MERGED | 7 ++ .../ExcelExportAction.java | 59 +++++---- .../ExportAnalysisResults.java | 75 ++++++++++++ 6 files changed, 254 insertions(+), 83 deletions(-) rename Core/src/org/sleuthkit/autopsy/{datasourcesummary/datamodel => contentutils}/AnalysisSummary.java (68%) mode change 100644 => 100755 create mode 100644 Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/AnalysisSummaryGetter.java create mode 100755 Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportAnalysisResults.java diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/AnalysisSummary.java b/Core/src/org/sleuthkit/autopsy/contentutils/AnalysisSummary.java old mode 100644 new mode 100755 similarity index 68% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/AnalysisSummary.java rename to Core/src/org/sleuthkit/autopsy/contentutils/AnalysisSummary.java index db9bc067c2..dc12c9edad --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/AnalysisSummary.java +++ b/Core/src/org/sleuthkit/autopsy/contentutils/AnalysisSummary.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2020 Basis Technology Corp. + * Copyright 2020-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,11 +16,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datasourcesummary.datamodel; +package org.sleuthkit.autopsy.contentutils; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultArtifactUpdateGovernor; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.List; @@ -30,53 +28,25 @@ import java.util.function.Function; import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; -import org.sleuthkit.autopsy.contentutils.DataSourceInfoUtilities; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; import org.sleuthkit.datamodel.DataSource; -import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; /** - * Providing data for the data source analysis tab. + * Helper class for getting hash set hits, keyword hits, and interesting item + * hits within a datasource. */ -public class AnalysisSummary implements DefaultArtifactUpdateGovernor { +public class AnalysisSummary { private static final BlackboardAttribute.Type TYPE_SET_NAME = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_SET_NAME); - private static final Set EXCLUDED_KEYWORD_SEARCH_ITEMS = new HashSet<>(); - private static final Set ARTIFACT_UPDATE_TYPE_IDS = new HashSet<>(Arrays.asList( - ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID(), - ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID(), - ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID(), - ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID() - )); - - private final SleuthkitCaseProvider provider; - - /** - * Main constructor. - */ - public AnalysisSummary() { - this(SleuthkitCaseProvider.DEFAULT); - } - - /** - * Main constructor. - * - * @param provider The means of obtaining a sleuthkit case. - */ - public AnalysisSummary(SleuthkitCaseProvider provider) { - this.provider = provider; - } - - @Override - public Set getArtifactTypeIdsForRefresh() { - return ARTIFACT_UPDATE_TYPE_IDS; + private AnalysisSummary() { } /** @@ -89,7 +59,7 @@ public class AnalysisSummary implements DefaultArtifactUpdateGovernor { * @throws SleuthkitCaseProviderException * @throws TskCoreException */ - public List> getHashsetCounts(DataSource dataSource) throws SleuthkitCaseProviderException, TskCoreException { + public static List> getHashsetCounts(DataSource dataSource) throws NoCurrentCaseException, TskCoreException { return getCountsData(dataSource, TYPE_SET_NAME, ARTIFACT_TYPE.TSK_HASHSET_HIT); } @@ -103,7 +73,7 @@ public class AnalysisSummary implements DefaultArtifactUpdateGovernor { * @throws SleuthkitCaseProviderException * @throws TskCoreException */ - public List> getKeywordCounts(DataSource dataSource) throws SleuthkitCaseProviderException, TskCoreException { + public static List> getKeywordCounts(DataSource dataSource) throws NoCurrentCaseException, TskCoreException { return getCountsData(dataSource, TYPE_SET_NAME, ARTIFACT_TYPE.TSK_KEYWORD_HIT).stream() // make sure we have a valid set and that that set does not belong to the set of excluded items .filter((pair) -> pair != null && pair.getKey() != null && !EXCLUDED_KEYWORD_SEARCH_ITEMS.contains(pair.getKey().toUpperCase().trim())) @@ -122,7 +92,7 @@ public class AnalysisSummary implements DefaultArtifactUpdateGovernor { * @throws SleuthkitCaseProviderException * @throws TskCoreException */ - public List> getInterestingItemCounts(DataSource dataSource) throws SleuthkitCaseProviderException, TskCoreException { + public static List> getInterestingItemCounts(DataSource dataSource) throws NoCurrentCaseException, TskCoreException { return getCountsData(dataSource, TYPE_SET_NAME, ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT); } @@ -137,22 +107,21 @@ public class AnalysisSummary implements DefaultArtifactUpdateGovernor { * value and the value is the count of items found. This list is * sorted by the count descending max to min. * - * @throws SleuthkitCaseProviderException + * @throws NoCurrentCaseException * @throws TskCoreException */ - private List> getCountsData(DataSource dataSource, BlackboardAttribute.Type keyType, ARTIFACT_TYPE... artifactTypes) - throws SleuthkitCaseProviderException, TskCoreException { + private static List> getCountsData(DataSource dataSource, BlackboardAttribute.Type keyType, ARTIFACT_TYPE... artifactTypes) + throws NoCurrentCaseException, TskCoreException { if (dataSource == null) { return Collections.emptyList(); } List artifacts = new ArrayList<>(); - SleuthkitCase skCase = provider.get(); // get all artifacts in one list for each artifact type for (ARTIFACT_TYPE type : artifactTypes) { - artifacts.addAll(skCase.getBlackboard().getArtifacts(type.getTypeID(), dataSource.getId())); + artifacts.addAll(Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboard().getArtifacts(type.getTypeID(), dataSource.getId())); } // group those based on the value of the attribute type that should serve as a key diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/AnalysisSummaryGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/AnalysisSummaryGetter.java new file mode 100644 index 0000000000..33cf925fba --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/AnalysisSummaryGetter.java @@ -0,0 +1,115 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2020-2021 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.datasourcesummary.datamodel; + +import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultArtifactUpdateGovernor; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.apache.commons.lang3.tuple.Pair; +import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.autopsy.contentutils.AnalysisSummary; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; +import org.sleuthkit.datamodel.DataSource; +import org.sleuthkit.datamodel.TskCoreException; + +/** + * Wrapper class for converting + * org.sleuthkit.autopsy.contentutils.AnalysisSummary functionality into a + * DefaultArtifactUpdateGovernor used by data source analysis tab. + */ +public class AnalysisSummaryGetter implements DefaultArtifactUpdateGovernor { + + private static final Set ARTIFACT_UPDATE_TYPE_IDS = new HashSet<>(Arrays.asList( + ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID(), + ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID(), + ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID(), + ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID() + )); + + /** + * Main constructor. + */ + public AnalysisSummaryGetter() { + } + + @Override + public Set getArtifactTypeIdsForRefresh() { + return Collections.unmodifiableSet(ARTIFACT_UPDATE_TYPE_IDS); + } + + /** + * Gets counts for hashset hits. + * + * @param dataSource The datasource for which to identify hashset hits. + * + * @return The hashset set name with the number of hits in descending order. + * + * @throws SleuthkitCaseProviderException + * @throws TskCoreException + */ + public List> getHashsetCounts(DataSource dataSource) throws SleuthkitCaseProviderException, TskCoreException { + try { + return AnalysisSummary.getHashsetCounts(dataSource); + } catch (NoCurrentCaseException ex) { + throw new SleuthkitCaseProviderException("No currently open case.", ex); + } + } + + /** + * Gets counts for keyword hits. + * + * @param dataSource The datasource for which to identify keyword hits. + * + * @return The keyword set name with the number of hits in descending order. + * + * @throws SleuthkitCaseProviderException + * @throws TskCoreException + */ + public List> getKeywordCounts(DataSource dataSource) throws SleuthkitCaseProviderException, TskCoreException { + try { + return AnalysisSummary.getKeywordCounts(dataSource); + } catch (NoCurrentCaseException ex) { + throw new SleuthkitCaseProviderException("No currently open case.", ex); + } + } + + /** + * Gets counts for interesting item hits. + * + * @param dataSource The datasource for which to identify interesting item + * hits. + * + * @return The interesting item set name with the number of hits in + * descending order. + * + * @throws SleuthkitCaseProviderException + * @throws TskCoreException + */ + public List> getInterestingItemCounts(DataSource dataSource) throws SleuthkitCaseProviderException, TskCoreException { + try { + return AnalysisSummary.getInterestingItemCounts(dataSource); + } catch (NoCurrentCaseException ex) { + throw new SleuthkitCaseProviderException("No currently open case.", ex); + } + } +} diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/AnalysisPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/AnalysisPanel.java index 10f0df97dd..df86d973b1 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/AnalysisPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/AnalysisPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2020 Basis Technology Corp. + * Copyright 2020-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,7 +23,7 @@ import java.util.List; import java.util.function.Function; import org.apache.commons.lang3.tuple.Pair; import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.AnalysisSummary; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.AnalysisSummaryGetter; import org.sleuthkit.autopsy.datasourcesummary.uiutils.ColumnModel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetcher; @@ -98,10 +98,10 @@ public class AnalysisPanel extends BaseDataSourceSummaryPanel { * Creates a new DataSourceUserActivityPanel. */ public AnalysisPanel() { - this(new AnalysisSummary()); + this(new AnalysisSummaryGetter()); } - public AnalysisPanel(AnalysisSummary analysisData) { + public AnalysisPanel(AnalysisSummaryGetter analysisData) { super(analysisData); hashsetsFetcher = (dataSource) -> analysisData.getHashsetCounts(dataSource); @@ -226,18 +226,6 @@ public class AnalysisPanel extends BaseDataSourceSummaryPanel { ); }// //GEN-END:initComponents - /* ELTODO - @Override - List getExports(DataSource dataSource) { - return Stream.of( - getTableExport(hashsetsFetcher, DEFAULT_COLUMNS, Bundle.AnalysisPanel_hashsetHits_tabName(), dataSource), - getTableExport(keywordsFetcher, DEFAULT_COLUMNS, Bundle.AnalysisPanel_keywordHits_tabName(), dataSource), - getTableExport(interestingItemsFetcher, DEFAULT_COLUMNS, Bundle.AnalysisPanel_interestingItemHits_tabName(), dataSource)) - .filter(sheet -> sheet != null) - .collect(Collectors.toList()); - }*/ - - // Variables declaration - do not modify//GEN-BEGIN:variables // End of variables declaration//GEN-END:variables } diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED index 6b90d2414d..e66edab769 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED @@ -4,6 +4,7 @@ DataSourceSummaryReport.endReport.srcModuleName.text=Excel Report # {0} - sheetNumber ExcelExport_writeExcel_noSheetName=Sheet {0} ExcelExportAction_exportToXLSX_beginExport=Beginning Export... +ExcelExportAction_exportToXLSX_gatheringAnalysisData=Fetching Analysis Data ExcelExportAction_exportToXLSX_gatheringContainerData=Fetching Container & Image Data ExcelExportAction_exportToXLSX_gatheringFileData=Fetching File and MIME Type Data ExcelExportAction_exportToXLSX_gatheringRecentActivityData=Fetching Recent Activity Data @@ -11,6 +12,12 @@ ExcelExportAction_exportToXLSX_gatheringTimelineData=Fetching Timeline Data ExcelExportAction_exportToXLSX_writingToFile=Writing to File... ExcelExportAction_getXLSXPath_directory=DataSourceSummary ExcelExportAction_moduleName=Data Source Summary +ExportAnalysisResults_countColumn_title=Count +ExportAnalysisResults_hashsetHits_tabName=Hashset Hits +ExportAnalysisResults_interestingItemHits_tabName=Interesting Item Hits +ExportAnalysisResults_keyColumn_title=Name +ExportAnalysisResults_keywordHits_tabName=Keyword Hits +ExportAnalysisResults_keywordSearchModuleName=Keyword Search ExportContainerInfo_export_acquisitionDetails=Acquisition Details: ExportContainerInfo_export_deviceId=Device ID: ExportContainerInfo_export_displayName=Display Name: diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java index 842ad9179a..4524104515 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java @@ -60,8 +60,9 @@ class ExcelExportAction { * Generates an xlsx path for the data source summary export. * * @param dataSourceName The name of the data source. + * * @return The file to which the excel document should be written or null if - * file already exists or cancellation. + * file already exists or cancellation. */ @NbBundle.Messages({ "ExcelExportAction_getXLSXPath_directory=DataSourceSummary",}) @@ -82,8 +83,9 @@ class ExcelExportAction { * Action that handles updating progress and exporting data from the tabs. * * @param progressPanel The progress indicator. - * @param dataSource The data source to be exported. - * @param path The path of the excel export. + * @param dataSource The data source to be exported. + * @param path The path of the excel export. + * * @throws InterruptedException * @throws IOException * @throws ExcelExportException @@ -94,6 +96,7 @@ class ExcelExportAction { "ExcelExportAction_exportToXLSX_gatheringContainerData=Fetching Container & Image Data", "ExcelExportAction_exportToXLSX_gatheringTimelineData=Fetching Timeline Data", "ExcelExportAction_exportToXLSX_gatheringFileData=Fetching File and MIME Type Data", + "ExcelExportAction_exportToXLSX_gatheringAnalysisData=Fetching Analysis Data", "ExcelExportAction_exportToXLSX_writingToFile=Writing to File...",}) void exportToXLSX(ReportProgressPanel progressPanel, DataSource dataSource, String baseReportDir) @@ -113,7 +116,7 @@ class ExcelExportAction { if (exports != null) { sheetExports.addAll(exports); } - + // Export Container & Image info data progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_gatheringContainerData()); progressPanel.setProgress(2); @@ -129,7 +132,7 @@ class ExcelExportAction { if (exports != null) { sheetExports.addAll(exports); } - + // Export file and MIME type data progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_gatheringFileData()); progressPanel.setProgress(4); @@ -137,7 +140,15 @@ class ExcelExportAction { if (exports != null) { sheetExports.addAll(exports); } - + + // Export hash set hits, keyword hits, and interesting item hits + progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_gatheringAnalysisData()); + progressPanel.setProgress(5); + exports = ExportAnalysisResults.getExports(dataSource); + if (exports != null) { + sheetExports.addAll(exports); + } + progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_writingToFile()); progressPanel.setProgress(9); ExcelExport.writeExcel(sheetExports, reportFile); @@ -159,14 +170,13 @@ class ExcelExportAction { * ExcelExportDialog(WindowManager.getDefault().getMainWindow(), * path); dialog.setResizable(false); * dialog.setLocationRelativeTo(WindowManager.getDefault().getMainWindow()); - * dialog.setVisible(true); dialog.toFront(); - }); + * dialog.setVisible(true); dialog.toFront(); }); */ } catch (NoCurrentCaseException | TskCoreException ex) { logger.log(Level.WARNING, "There was an error attaching report to case.", ex); } } - + /** * Function that converts data into a excel sheet data. */ @@ -176,7 +186,9 @@ class ExcelExportAction { * Function that converts data into an excel sheet. * * @param data The data. + * * @return The excel sheet export. + * * @throws ExcelExportException */ ExcelSheetExport convert(T data) throws ExcelExportException; @@ -212,9 +224,10 @@ class ExcelExportAction { * possible excel exceptions. * * @param excelConverter Function to convert data to an excel sheet export. - * @param data The data. If data is null, null will be returned. - * @param sheetName The name(s) of the sheet (to be used in the error - * message). + * @param data The data. If data is null, null will be returned. + * @param sheetName The name(s) of the sheet (to be used in the error + * message). + * * @return The excel sheet export. */ protected static ExcelSheetExport convertToExcel(ExcelExportFunction excelConverter, T data, String sheetName) { @@ -236,10 +249,12 @@ class ExcelExportAction { * Returns an excel sheet export given the fetching of data or null if no * export created. * - * @param dataFetcher The means of fetching data. + * @param dataFetcher The means of fetching data. * @param excelConverter The means of converting data to excel. - * @param sheetName The name of the sheet (for error handling reporting). - * @param ds The data source to use for fetching data. + * @param sheetName The name of the sheet (for error handling + * reporting). + * @param ds The data source to use for fetching data. + * * @return The excel sheet export or null if no export could be generated. */ protected static ExcelSheetExport getExport( @@ -254,8 +269,9 @@ class ExcelExportAction { * Returns an excel table export of the data or null if no export created. * * @param columnsModel The model for the columns. - * @param sheetName The name for the sheet. - * @param data The data to be exported. + * @param sheetName The name for the sheet. + * @param data The data to be exported. + * * @return The excel table export or null if no export could be generated. */ protected static ExcelSheetExport getTableExport(List> columnsModel, @@ -269,11 +285,12 @@ class ExcelExportAction { /** * Returns an excel table export of the data or null if no export created. * - * @param dataFetcher The means of fetching data for the data source and the - * export. + * @param dataFetcher The means of fetching data for the data source and + * the export. * @param columnsModel The model for the columns. - * @param sheetName The name for the sheet. - * @param ds The data source. + * @param sheetName The name for the sheet. + * @param ds The data source. + * * @return The excel export or null if no export created. */ protected static ExcelSheetExport getTableExport( diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportAnalysisResults.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportAnalysisResults.java new file mode 100755 index 0000000000..6ae7bb0381 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportAnalysisResults.java @@ -0,0 +1,75 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit 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.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.apache.commons.lang3.tuple.Pair; +import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.contentutils.AnalysisSummary; +import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExport.ExcelSheetExport; +import static org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExportAction.getTableExport; +import org.sleuthkit.datamodel.DataSource; + +/** + * Class to export data hash set hits, keyword hits, and interesting item hits + * within a datasource. + */ +@Messages({ + "ExportAnalysisResults_keyColumn_title=Name", + "ExportAnalysisResults_countColumn_title=Count", + "ExportAnalysisResults_keywordSearchModuleName=Keyword Search", + "ExportAnalysisResults_hashsetHits_tabName=Hashset Hits", + "ExportAnalysisResults_keywordHits_tabName=Keyword Hits", + "ExportAnalysisResults_interestingItemHits_tabName=Interesting Item Hits",}) +class ExportAnalysisResults { + + // Default Column definitions for each table + private static final List, DefaultCellModel>> DEFAULT_COLUMNS = Arrays.asList( + new ColumnModel<>( + Bundle.ExportAnalysisResults_keyColumn_title(), + (pair) -> new DefaultCellModel<>(pair.getKey()), + 300 + ), + new ColumnModel<>( + Bundle.ExportAnalysisResults_countColumn_title(), + (pair) -> new DefaultCellModel<>(pair.getValue()), + 100 + ) + ); + + private ExportAnalysisResults() { + } + + static List getExports(DataSource dataSource) { + + DataFetcher>> hashsetsFetcher = (ds) -> AnalysisSummary.getHashsetCounts(ds); + DataFetcher>> keywordsFetcher = (ds) -> AnalysisSummary.getKeywordCounts(ds); + DataFetcher>> interestingItemsFetcher = (ds) -> AnalysisSummary.getInterestingItemCounts(ds); + + return Stream.of( + getTableExport(hashsetsFetcher, DEFAULT_COLUMNS, Bundle.ExportAnalysisResults_hashsetHits_tabName(), dataSource), + getTableExport(keywordsFetcher, DEFAULT_COLUMNS, Bundle.ExportAnalysisResults_keywordHits_tabName(), dataSource), + getTableExport(interestingItemsFetcher, DEFAULT_COLUMNS, Bundle.ExportAnalysisResults_interestingItemHits_tabName(), dataSource)) + .filter(sheet -> sheet != null) + .collect(Collectors.toList()); + } +} From 44ad30fd8085d29221513da9b21cf85da56d09a0 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Mon, 9 Aug 2021 15:36:33 -0400 Subject: [PATCH 16/33] Refactored PastCasesSummary --- .../PastCasesSummary.java | 84 ++++++------------- .../datamodel/PastCasesSummaryGetter.java | 76 +++++++++++++++++ .../datasourcesummary/ui/PastCasesPanel.java | 26 ++---- .../Bundle.properties-MERGED | 5 ++ .../ExcelExportAction.java | 9 ++ .../ExportPastCases.java | 76 +++++++++++++++++ .../datasourcesummaryexport/ExportTypes.java | 2 +- 7 files changed, 197 insertions(+), 81 deletions(-) rename Core/src/org/sleuthkit/autopsy/{datasourcesummary/datamodel => contentutils}/PastCasesSummary.java (78%) mode change 100644 => 100755 create mode 100644 Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/PastCasesSummaryGetter.java create mode 100755 Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportPastCases.java diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/PastCasesSummary.java b/Core/src/org/sleuthkit/autopsy/contentutils/PastCasesSummary.java old mode 100644 new mode 100755 similarity index 78% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/PastCasesSummary.java rename to Core/src/org/sleuthkit/autopsy/contentutils/PastCasesSummary.java index e7776fbf62..d50f2b44d5 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/PastCasesSummary.java +++ b/Core/src/org/sleuthkit/autopsy/contentutils/PastCasesSummary.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019 Basis Technology Corp. + * Copyright 2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datasourcesummary.datamodel; +package org.sleuthkit.autopsy.contentutils; import java.util.ArrayList; import java.util.Arrays; @@ -25,14 +25,12 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.logging.Level; import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.commons.lang3.tuple.Pair; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.centralrepository.ingestmodule.CentralRepoIngestModuleFactory; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultArtifactUpdateGovernor; -import org.sleuthkit.autopsy.contentutils.DataSourceInfoUtilities; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import org.sleuthkit.datamodel.BlackboardAttribute; @@ -63,7 +61,7 @@ import org.sleuthkit.datamodel.TskCoreException; * d) The content of that TSK_COMMENT attribute will be of the form "Previous * Case: case1,case2...caseN" */ -public class PastCasesSummary implements DefaultArtifactUpdateGovernor { +public class PastCasesSummary { /** * Return type for results items in the past cases tab. @@ -99,11 +97,6 @@ public class PastCasesSummary implements DefaultArtifactUpdateGovernor { } } - private static final Set ARTIFACT_UPDATE_TYPE_IDS = new HashSet<>(Arrays.asList( - ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID(), - ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID() - )); - private static final String CENTRAL_REPO_INGEST_NAME = CentralRepoIngestModuleFactory.getModuleName().toUpperCase().trim(); private static final BlackboardAttribute.Type TYPE_COMMENT = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_COMMENT); private static final BlackboardAttribute.Type TYPE_ASSOCIATED_ARTIFACT = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT); @@ -118,39 +111,7 @@ public class PastCasesSummary implements DefaultArtifactUpdateGovernor { private static final String CASE_SEPARATOR = ","; private static final String PREFIX_END = ":"; - private final SleuthkitCaseProvider caseProvider; - private final java.util.logging.Logger logger; - - /** - * Main constructor. - */ - public PastCasesSummary() { - this( - SleuthkitCaseProvider.DEFAULT, - org.sleuthkit.autopsy.coreutils.Logger.getLogger(PastCasesSummary.class.getName()) - ); - - } - - /** - * Main constructor with external dependencies specified. This constructor - * is designed with unit testing in mind since mocked dependencies can be - * utilized. - * - * @param provider The object providing the current SleuthkitCase. - * @param logger The logger to use. - */ - public PastCasesSummary( - SleuthkitCaseProvider provider, - java.util.logging.Logger logger) { - - this.caseProvider = provider; - this.logger = logger; - } - - @Override - public Set getArtifactTypeIdsForRefresh() { - return ARTIFACT_UPDATE_TYPE_IDS; + private PastCasesSummary() { } /** @@ -225,7 +186,7 @@ public class PastCasesSummary implements DefaultArtifactUpdateGovernor { * @return The list of unique cases and their occurrences sorted from max to * min. */ - private List> getCaseCounts(Stream cases) { + private static List> getCaseCounts(Stream cases) { Collection> groupedCases = cases // group by case insensitive compare of cases .collect(Collectors.groupingBy((caseStr) -> caseStr.toUpperCase().trim())) @@ -250,21 +211,24 @@ public class PastCasesSummary implements DefaultArtifactUpdateGovernor { * * @return The artifact if found or null if not. * - * @throws SleuthkitCaseProviderException + * @throws NoCurrentCaseException */ - private BlackboardArtifact getParentArtifact(BlackboardArtifact artifact) throws SleuthkitCaseProviderException { + private static BlackboardArtifact getParentArtifact(BlackboardArtifact artifact) throws NoCurrentCaseException { Long parentId = DataSourceInfoUtilities.getLongOrNull(artifact, TYPE_ASSOCIATED_ARTIFACT); if (parentId == null) { return null; } - SleuthkitCase skCase = caseProvider.get(); try { - return skCase.getArtifactByArtifactId(parentId); - } catch (TskCoreException ex) { - logger.log(Level.WARNING, - String.format("There was an error fetching the parent artifact of a TSK_INTERESTING_ARTIFACT_HIT (parent id: %d)", parentId), - ex); + return Case.getCurrentCaseThrows().getSleuthkitCase().getArtifactByArtifactId(parentId); + } catch (TskCoreException ignore) { + /* + * I'm not certain why we ignore this, but it was previously simply + * logged as warning so I'm keeping the original logic + * logger.log(Level.WARNING, String.format("There was an error + * fetching the parent artifact of a TSK_INTERESTING_ARTIFACT_HIT + * (parent id: %d)", parentId), ex); + */ return null; } } @@ -276,9 +240,9 @@ public class PastCasesSummary implements DefaultArtifactUpdateGovernor { * * @return True if there is a device associated artifact. * - * @throws SleuthkitCaseProviderException + * @throws NoCurrentCaseException */ - private boolean hasDeviceAssociatedArtifact(BlackboardArtifact artifact) throws SleuthkitCaseProviderException { + private static boolean hasDeviceAssociatedArtifact(BlackboardArtifact artifact) throws NoCurrentCaseException { BlackboardArtifact parent = getParentArtifact(artifact); if (parent == null) { return false; @@ -294,17 +258,17 @@ public class PastCasesSummary implements DefaultArtifactUpdateGovernor { * * @return The retrieved data or null if null dataSource. * - * @throws SleuthkitCaseProviderException + * @throws NoCurrentCaseException * @throws TskCoreException */ - public PastCasesResult getPastCasesData(DataSource dataSource) - throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException { + public static PastCasesResult getPastCasesData(DataSource dataSource) + throws NoCurrentCaseException, TskCoreException { if (dataSource == null) { return null; } - SleuthkitCase skCase = caseProvider.get(); + SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase(); List deviceArtifactCases = new ArrayList<>(); List nonDeviceArtifactCases = new ArrayList<>(); diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/PastCasesSummaryGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/PastCasesSummaryGetter.java new file mode 100644 index 0000000000..4d33ad6757 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/PastCasesSummaryGetter.java @@ -0,0 +1,76 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2019 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.datasourcesummary.datamodel; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultArtifactUpdateGovernor; +import org.sleuthkit.autopsy.contentutils.PastCasesSummary; +import org.sleuthkit.autopsy.contentutils.PastCasesSummary.PastCasesResult; +import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; +import org.sleuthkit.datamodel.DataSource; +import org.sleuthkit.datamodel.TskCoreException; + +/** + * Wrapper class for converting org.sleuthkit.autopsy.contentutils.PastCasesSummary + * functionality into a DefaultArtifactUpdateGovernor used by PastCases tab. + */ +public class PastCasesSummaryGetter implements DefaultArtifactUpdateGovernor { + + private static final Set ARTIFACT_UPDATE_TYPE_IDS = new HashSet<>(Arrays.asList( + ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID(), + ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID() + )); + + public PastCasesSummaryGetter() { + } + + @Override + public Set getArtifactTypeIdsForRefresh() { + return Collections.unmodifiableSet(ARTIFACT_UPDATE_TYPE_IDS); + } + + /** + * Returns the past cases data to be shown in the past cases tab. + * + * @param dataSource The data source. + * + * @return The retrieved data or null if null dataSource. + * + * @throws SleuthkitCaseProviderException + * @throws TskCoreException + */ + public PastCasesResult getPastCasesData(DataSource dataSource) + throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException { + + if (dataSource == null) { + return null; + } + + try { + return PastCasesSummary.getPastCasesData(dataSource); + } catch (NoCurrentCaseException ex) { + throw new SleuthkitCaseProviderException("No currently open case.", ex); + } + } +} diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesPanel.java index cdce933a1c..5886457530 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesPanel.java @@ -22,8 +22,8 @@ import java.util.Arrays; import java.util.List; import org.apache.commons.lang3.tuple.Pair; import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.PastCasesSummary; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.PastCasesSummary.PastCasesResult; +import org.sleuthkit.autopsy.contentutils.PastCasesSummary.PastCasesResult; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.PastCasesSummaryGetter; import org.sleuthkit.autopsy.datasourcesummary.uiutils.ColumnModel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; @@ -80,19 +80,19 @@ public class PastCasesPanel extends BaseDataSourceSummaryPanel { private final IngestRunningLabel ingestRunningLabel = new IngestRunningLabel(); private final DataFetcher pastCasesFetcher; - + public PastCasesPanel() { - this(new PastCasesSummary()); + this(new PastCasesSummaryGetter()); } /** * Creates new form PastCasesPanel */ - public PastCasesPanel(PastCasesSummary pastCaseData) { + public PastCasesPanel(PastCasesSummaryGetter pastCaseData) { super(pastCaseData); this.pastCasesFetcher = (dataSource) -> pastCaseData.getPastCasesData(dataSource); - + // set up data acquisition methods dataFetchComponents = Arrays.asList( new DataFetchWorker.DataFetchComponents<>( @@ -124,20 +124,6 @@ public class PastCasesPanel extends BaseDataSourceSummaryPanel { onNewDataSource(dataFetchComponents, tables, dataSource); } - /* ELTODO - @Override - List getExports(DataSource dataSource) { - PastCasesResult result = getFetchResult(pastCasesFetcher, "Past cases sheets", dataSource); - if (result == null) { - return Collections.emptyList(); - } - - return Arrays.asList( - getTableExport(DEFAULT_TEMPLATE, Bundle.PastCasesPanel_notableFileTable_tabName(), result.getTaggedNotable()), - getTableExport(DEFAULT_TEMPLATE, Bundle.PastCasesPanel_sameIdsTable_tabName(), result.getSameIdsResults()) - ); - }*/ - @Override public void close() { ingestRunningLabel.unregister(); diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED index e66edab769..a0c9bb1d6e 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED @@ -33,6 +33,11 @@ ExportContainerInfo_export_timeZone=Time Zone: ExportContainerInfo_export_unallocatedSize=Unallocated Space: ExportContainerInfo_setFieldsForNonImageDataSource_na=N/A ExportContainerInfo_tabName=Container +ExportPastCases_caseColumn_title=Case +ExportPastCases_countColumn_title=Count +ExportPastCases_notableFileTable_tabName=Cases with Common Notable +ExportPastCases_onNoCrIngest_message=No results will be shown because the Central Repository module was not run. +ExportPastCases_sameIdsTable_tabName=Past Cases with the Same Devices ExportRecentFiles_attachmentsTable_tabName=Recent Attachments ExportRecentFiles_col_head_date=Date ExportRecentFiles_col_header_domain=Domain diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java index 4524104515..50dd05a18c 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java @@ -97,6 +97,7 @@ class ExcelExportAction { "ExcelExportAction_exportToXLSX_gatheringTimelineData=Fetching Timeline Data", "ExcelExportAction_exportToXLSX_gatheringFileData=Fetching File and MIME Type Data", "ExcelExportAction_exportToXLSX_gatheringAnalysisData=Fetching Analysis Data", + "ExcelExportAction_exportToXLSX_gatheringPastData=Fetching Historical Data", "ExcelExportAction_exportToXLSX_writingToFile=Writing to File...",}) void exportToXLSX(ReportProgressPanel progressPanel, DataSource dataSource, String baseReportDir) @@ -148,6 +149,14 @@ class ExcelExportAction { if (exports != null) { sheetExports.addAll(exports); } + + // Export hash set hits, keyword hits, and interesting item hits + progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_gatheringPastData()); + progressPanel.setProgress(6); + exports = ExportPastCases.getExports(dataSource); + if (exports != null) { + sheetExports.addAll(exports); + } progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_writingToFile()); progressPanel.setProgress(9); diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportPastCases.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportPastCases.java new file mode 100755 index 0000000000..6448adb369 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportPastCases.java @@ -0,0 +1,76 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit 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.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.apache.commons.lang3.tuple.Pair; +import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.contentutils.PastCasesSummary; +import org.sleuthkit.autopsy.contentutils.PastCasesSummary.PastCasesResult; +import static org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExportAction.getFetchResult; +import static org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExportAction.getTableExport; +import org.sleuthkit.datamodel.DataSource; + +/** + * Class to export information about a datasource and how it pertains to other + * cases. + */ +@Messages({ + "ExportPastCases_caseColumn_title=Case", + "ExportPastCases_countColumn_title=Count", + "ExportPastCases_notableFileTable_tabName=Cases with Common Notable", + "ExportPastCases_sameIdsTable_tabName=Past Cases with the Same Devices",}) +class ExportPastCases { + + // model for column indicating the case + private static final ColumnModel, DefaultCellModel> CASE_COL = new ColumnModel<>( + Bundle.ExportPastCases_caseColumn_title(), + (pair) -> new DefaultCellModel<>(pair.getKey()), + 300 + ); + + // model for column indicating the count + private static final ColumnModel, DefaultCellModel> COUNT_COL = new ColumnModel<>( + Bundle.ExportPastCases_countColumn_title(), + (pair) -> new DefaultCellModel<>(pair.getValue()), + 100 + ); + + // the template for columns in both tables in this tab + private static List, DefaultCellModel>> DEFAULT_TEMPLATE + = Arrays.asList(CASE_COL, COUNT_COL); + + private ExportPastCases() { + } + + static List getExports(DataSource dataSource) { + DataFetcher pastCasesFetcher = (ds) -> PastCasesSummary.getPastCasesData(ds); + PastCasesResult result = getFetchResult(pastCasesFetcher, "Past cases sheets", dataSource); + if (result == null) { + return Collections.emptyList(); + } + + return Arrays.asList( + getTableExport(DEFAULT_TEMPLATE, Bundle.ExportPastCases_notableFileTable_tabName(), result.getTaggedNotable()), + getTableExport(DEFAULT_TEMPLATE, Bundle.ExportPastCases_sameIdsTable_tabName(), result.getSameIdsResults()) + ); + } +} diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTypes.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTypes.java index 5453a879c8..9253b5b09b 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTypes.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTypes.java @@ -40,7 +40,7 @@ import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.TskCoreException; /** - * Panel for displaying summary information on the known files present in the + * Class to export summary information on the known files present in the * specified DataSource. */ @Messages({ From 3d26fb30f0b3e24f061aa953d6307cc4b333d5c1 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Tue, 10 Aug 2021 10:05:24 -0400 Subject: [PATCH 17/33] Refactored UserActivity tab --- .../contentutils/Bundle.properties-MERGED | 2 + .../UserActivitySummary.java | 262 ++++++++---------- .../datamodel/UserActivitySummaryGetter.java | 237 ++++++++++++++++ .../ui/UserActivityPanel.java | 40 +-- .../Bundle.properties-MERGED | 25 +- .../ExcelExportAction.java | 11 +- .../ExportUserActivity.java | 248 +++++++++++++++++ .../UserActivitySummaryTests.java | 12 +- .../datamodel/UserActivitySummaryTest.java | 114 ++++---- 9 files changed, 709 insertions(+), 242 deletions(-) create mode 100755 Core/src/org/sleuthkit/autopsy/contentutils/Bundle.properties-MERGED rename Core/src/org/sleuthkit/autopsy/{datasourcesummary/datamodel => contentutils}/UserActivitySummary.java (83%) mode change 100644 => 100755 create mode 100644 Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummaryGetter.java create mode 100755 Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportUserActivity.java diff --git a/Core/src/org/sleuthkit/autopsy/contentutils/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/contentutils/Bundle.properties-MERGED new file mode 100755 index 0000000000..2e019a0248 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentutils/Bundle.properties-MERGED @@ -0,0 +1,2 @@ +DataSourceUserActivitySummary_getRecentAccounts_calllogMessage=Call Log +DataSourceUserActivitySummary_getRecentAccounts_emailMessage=Email Message diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummary.java b/Core/src/org/sleuthkit/autopsy/contentutils/UserActivitySummary.java old mode 100644 new mode 100755 similarity index 83% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummary.java rename to Core/src/org/sleuthkit/autopsy/contentutils/UserActivitySummary.java index 5151617775..1d46523ebd --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummary.java +++ b/Core/src/org/sleuthkit/autopsy/contentutils/UserActivitySummary.java @@ -16,10 +16,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datasourcesummary.datamodel; +package org.sleuthkit.autopsy.contentutils; import java.io.File; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultArtifactUpdateGovernor; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -32,14 +31,13 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.Function; -import java.util.logging.Level; import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; -import org.sleuthkit.autopsy.contentutils.DataSourceInfoUtilities; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.DataSource; @@ -55,7 +53,7 @@ import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; * time, the data being provided for domains is fictitious and is done as a * placeholder. */ -public class UserActivitySummary implements DefaultArtifactUpdateGovernor { +public class UserActivitySummary { /** * Functions that determine the folder name of a list of path elements. If @@ -139,16 +137,6 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor { .compareToIgnoreCase((b.getProgramName() == null ? "" : b.getProgramName())); }; - private static final Set ARTIFACT_UPDATE_TYPE_IDS = new HashSet<>(Arrays.asList( - ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY.getTypeID(), - ARTIFACT_TYPE.TSK_MESSAGE.getTypeID(), - ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID(), - ARTIFACT_TYPE.TSK_CALLLOG.getTypeID(), - ARTIFACT_TYPE.TSK_DEVICE_ATTACHED.getTypeID(), - ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID(), - ARTIFACT_TYPE.TSK_PROG_RUN.getTypeID() - )); - private static final Set DEVICE_EXCLUDE_LIST = new HashSet<>(Arrays.asList("ROOT_HUB", "ROOT_HUB20")); private static final Set DOMAIN_EXCLUDE_LIST = new HashSet<>(Arrays.asList("127.0.0.1", "LOCALHOST")); @@ -156,40 +144,7 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor { private static final long DOMAIN_WINDOW_DAYS = 30; private static final long DOMAIN_WINDOW_MS = DOMAIN_WINDOW_DAYS * MS_PER_DAY; - private final SleuthkitCaseProvider caseProvider; - private final TextTranslationService translationService; - private final java.util.logging.Logger logger; - - /** - * Main constructor. - */ - public UserActivitySummary() { - this(SleuthkitCaseProvider.DEFAULT, TextTranslationService.getInstance(), - org.sleuthkit.autopsy.coreutils.Logger.getLogger(UserActivitySummary.class.getName())); - } - - /** - * Main constructor with external dependencies specified. This constructor - * is designed with unit testing in mind since mocked dependencies can be - * utilized. - * - * @param provider The object providing the current SleuthkitCase. - * @param translationService The translation service. - * @param logger The logger to use. - */ - public UserActivitySummary( - SleuthkitCaseProvider provider, - TextTranslationService translationService, - java.util.logging.Logger logger) { - - this.caseProvider = provider; - this.translationService = translationService; - this.logger = logger; - } - - @Override - public Set getArtifactTypeIdsForRefresh() { - return ARTIFACT_UPDATE_TYPE_IDS; + private UserActivitySummary() { } /** @@ -197,23 +152,57 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor { * * @param count The count being checked. */ - private void assertValidCount(int count) { + private static void assertValidCount(int count) { if (count <= 0) { throw new IllegalArgumentException("Count must be greater than 0"); } } + + /** + * Determines a short folder name if any. Otherwise, returns empty string. + * + * @param strPath The string path. + * @param applicationName The application name. + * + * @return The short folder name or empty string if not found. + */ + public static String getShortFolderName(String strPath, String applicationName) { + if (strPath == null) { + return ""; + } + + List pathEls = new ArrayList<>(Arrays.asList(applicationName)); + + File file = new File(strPath); + while (file != null && org.apache.commons.lang.StringUtils.isNotBlank(file.getName())) { + pathEls.add(file.getName()); + file = file.getParentFile(); + } + + Collections.reverse(pathEls); + + for (Function, String> matchEntry : SHORT_FOLDER_MATCHERS) { + String result = matchEntry.apply(pathEls); + if (org.apache.commons.lang.StringUtils.isNotBlank(result)) { + return result; + } + } + + return ""; + } /** * Gets a list of recent domains based on the datasource. * * @param dataSource The datasource to query for recent domains. - * @param count The max count of items to return. + * @param count The max count of items to return. * * @return The list of items retrieved from the database. * - * @throws InterruptedException + * @throws TskCoreException + * @throws NoCurrentCaseException */ - public List getRecentDomains(DataSource dataSource, int count) throws TskCoreException, SleuthkitCaseProviderException { + public static List getRecentDomains(DataSource dataSource, int count) throws TskCoreException, NoCurrentCaseException { assertValidCount(count); if (dataSource == null) { @@ -243,15 +232,15 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor { * Creates a TopDomainsResult from data or null if no visit date exists * within DOMAIN_WINDOW_MS of mostRecentMs. * - * @param domain The domain. - * @param visits The list of the artifact and its associated time in - * milliseconds. + * @param domain The domain. + * @param visits The list of the artifact and its associated time in + * milliseconds. * @param mostRecentMs The most recent visit of any domain. * * @return The TopDomainsResult or null if no visits to this domain within - * 30 days of mostRecentMs. + * 30 days of mostRecentMs. */ - private TopDomainsResult getDomainsResult(String domain, List> visits, long mostRecentMs) { + private static TopDomainsResult getDomainsResult(String domain, List> visits, long mostRecentMs) { long visitCount = 0; Long thisMostRecentMs = null; BlackboardArtifact thisMostRecentArtifact = null; @@ -289,15 +278,15 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor { * @param dataSource The datasource. * * @return A tuple where the first value is the latest web history accessed - * date in milliseconds and the second value maps normalized (lowercase; - * trimmed) domain names to when those domains were visited and the relevant - * artifact. + * date in milliseconds and the second value maps normalized + * (lowercase; trimmed) domain names to when those domains were + * visited and the relevant artifact. * * @throws TskCoreException - * @throws SleuthkitCaseProviderException + * @throws NoCurrentCaseException */ - private Pair>>> getDomainGroupsAndMostRecent(DataSource dataSource) throws TskCoreException, SleuthkitCaseProviderException { - List artifacts = DataSourceInfoUtilities.getArtifacts(caseProvider.get(), TYPE_WEB_HISTORY, + private static Pair>>> getDomainGroupsAndMostRecent(DataSource dataSource) throws TskCoreException, NoCurrentCaseException { + List artifacts = DataSourceInfoUtilities.getArtifacts(Case.getCurrentCaseThrows().getSleuthkitCase(), TYPE_WEB_HISTORY, dataSource, TYPE_DATETIME_ACCESSED, DataSourceInfoUtilities.SortOrder.DESCENDING, 0); Long mostRecentMs = null; @@ -358,7 +347,7 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor { * @param artifact The artifact. * * @return The TopWebSearchResult or null if the search string or date - * accessed cannot be determined. + * accessed cannot be determined. */ private static TopWebSearchResult getWebSearchResult(BlackboardArtifact artifact) { String searchString = DataSourceInfoUtilities.getStringOrNull(artifact, TYPE_TEXT); @@ -373,16 +362,16 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor { * term. * * @param dataSource The data source. - * @param count The maximum number of records to be shown (must be > 0). + * @param count The maximum number of records to be shown (must be > + * 0). * * @return The list of most recent web searches where most recent search - * appears first. + * appears first. * - * @throws - * org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException + * @throws NoCurrentCaseException * @throws TskCoreException */ - public List getMostRecentWebSearches(DataSource dataSource, int count) throws SleuthkitCaseProviderException, TskCoreException { + public static List getMostRecentWebSearches(DataSource dataSource, int count) throws NoCurrentCaseException, TskCoreException { assertValidCount(count); if (dataSource == null) { @@ -390,7 +379,7 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor { } // get the artifacts - List webSearchArtifacts = caseProvider.get().getBlackboard() + List webSearchArtifacts = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboard() .getArtifacts(ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY.getTypeID(), dataSource.getId()); // group by search string (case insensitive) @@ -417,6 +406,7 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor { .collect(Collectors.toList()); // get translation if possible + TextTranslationService translationService = TextTranslationService.getInstance(); if (translationService.hasProvider()) { for (TopWebSearchResult result : results) { result.setTranslatedResult(getTranslationOrNull(result.getSearchString())); @@ -433,9 +423,10 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor { * @param original The original text. * * @return The translated text or null if no translation can be determined - * or exists. + * or exists. */ - private String getTranslationOrNull(String original) { + private static String getTranslationOrNull(String original) { + TextTranslationService translationService = TextTranslationService.getInstance(); if (!translationService.hasProvider() || StringUtils.isBlank(original)) { return null; } @@ -443,8 +434,9 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor { String translated = null; try { translated = translationService.translate(original); - } catch (NoServiceProviderException | TranslationException ex) { - logger.log(Level.WARNING, String.format("There was an error translating text: '%s'", original), ex); + } catch (NoServiceProviderException | TranslationException ignore) { + // Original logic ignored this error and simply logged it as warning so i'm keeping the same logic + // logger.log(Level.WARNING, String.format("There was an error translating text: '%s'", original), ex); } // if there is no translation or the translation is the same as the original, return null. @@ -463,10 +455,11 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor { * * @param r1 A result. * @param r2 Another result. + * * @return The most recent one with a non-null date. */ - private TopDeviceAttachedResult getMostRecentDevice(TopDeviceAttachedResult r1, TopDeviceAttachedResult r2) { - if (r2.getLastAccessed()== null) { + private static TopDeviceAttachedResult getMostRecentDevice(TopDeviceAttachedResult r1, TopDeviceAttachedResult r2) { + if (r2.getLastAccessed() == null) { return r1; } @@ -481,23 +474,23 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor { * Retrieves most recent devices used by most recent date attached. * * @param dataSource The data source. - * @param count The maximum number of records to be shown (must be > 0). + * @param count The maximum number of records to be shown (must be > + * 0). * * @return The list of most recent devices attached where most recent device - * attached appears first. + * attached appears first. * - * @throws - * org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException + * @throws NoCurrentCaseException * @throws TskCoreException */ - public List getRecentDevices(DataSource dataSource, int count) throws SleuthkitCaseProviderException, TskCoreException { + public static List getRecentDevices(DataSource dataSource, int count) throws NoCurrentCaseException, TskCoreException { assertValidCount(count); if (dataSource == null) { return Collections.emptyList(); } - Collection results = DataSourceInfoUtilities.getArtifacts(caseProvider.get(), TYPE_DEVICE_ATTACHED, + Collection results = DataSourceInfoUtilities.getArtifacts(Case.getCurrentCaseThrows().getSleuthkitCase(), TYPE_DEVICE_ATTACHED, dataSource, TYPE_DATETIME, DataSourceInfoUtilities.SortOrder.DESCENDING, 0) .stream() .map(artifact -> { @@ -529,7 +522,7 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor { * @param artifact The artifact. * * @return The TopAccountResult or null if the account type or message date - * cannot be determined. + * cannot be determined. */ private static TopAccountResult getMessageAccountResult(BlackboardArtifact artifact) { String type = DataSourceInfoUtilities.getStringOrNull(artifact, TYPE_MESSAGE_TYPE); @@ -543,12 +536,12 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor { * Obtains a TopAccountResult from a blackboard artifact. The date is * maximum of any found dates for attribute types provided. * - * @param artifact The artifact. + * @param artifact The artifact. * @param messageType The type of message this is. - * @param dateAttrs The date attribute types. + * @param dateAttrs The date attribute types. * * @return The TopAccountResult or null if the account type or max date are - * not provided. + * not provided. */ private static TopAccountResult getAccountResult(BlackboardArtifact artifact, String messageType, BlackboardAttribute.Type... dateAttrs) { String type = messageType; @@ -572,30 +565,30 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor { * sent. * * @param dataSource The data source. - * @param count The maximum number of records to be shown (must be > 0). + * @param count The maximum number of records to be shown (must be > + * 0). * * @return The list of most recent accounts used where the most recent - * account by last message sent occurs first. + * account by last message sent occurs first. * - * @throws - * org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException + * @throws NoCurrentCaseException * @throws TskCoreException */ @Messages({ "DataSourceUserActivitySummary_getRecentAccounts_emailMessage=Email Message", "DataSourceUserActivitySummary_getRecentAccounts_calllogMessage=Call Log",}) - public List getRecentAccounts(DataSource dataSource, int count) throws SleuthkitCaseProviderException, TskCoreException { + public static List getRecentAccounts(DataSource dataSource, int count) throws NoCurrentCaseException, TskCoreException { assertValidCount(count); if (dataSource == null) { return Collections.emptyList(); } - Stream messageResults = caseProvider.get().getBlackboard().getArtifacts(ARTIFACT_TYPE.TSK_MESSAGE.getTypeID(), dataSource.getId()) + Stream messageResults = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboard().getArtifacts(ARTIFACT_TYPE.TSK_MESSAGE.getTypeID(), dataSource.getId()) .stream() .map((art) -> getMessageAccountResult(art)); - Stream emailResults = caseProvider.get().getBlackboard().getArtifacts(ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID(), dataSource.getId()) + Stream emailResults = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboard().getArtifacts(ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID(), dataSource.getId()) .stream() .map((art) -> { return getAccountResult( @@ -605,7 +598,7 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor { TYPE_DATETIME_SENT); }); - Stream calllogResults = caseProvider.get().getBlackboard().getArtifacts(ARTIFACT_TYPE.TSK_CALLLOG.getTypeID(), dataSource.getId()) + Stream calllogResults = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboard().getArtifacts(ARTIFACT_TYPE.TSK_CALLLOG.getTypeID(), dataSource.getId()) .stream() .map((art) -> { return getAccountResult( @@ -639,39 +632,6 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor { .collect(Collectors.toList()); } - /** - * Determines a short folder name if any. Otherwise, returns empty string. - * - * @param strPath The string path. - * @param applicationName The application name. - * - * @return The short folder name or empty string if not found. - */ - public String getShortFolderName(String strPath, String applicationName) { - if (strPath == null) { - return ""; - } - - List pathEls = new ArrayList<>(Arrays.asList(applicationName)); - - File file = new File(strPath); - while (file != null && org.apache.commons.lang.StringUtils.isNotBlank(file.getName())) { - pathEls.add(file.getName()); - file = file.getParentFile(); - } - - Collections.reverse(pathEls); - - for (Function, String> matchEntry : SHORT_FOLDER_MATCHERS) { - String result = matchEntry.apply(pathEls); - if (org.apache.commons.lang.StringUtils.isNotBlank(result)) { - return result; - } - } - - return ""; - } - /** * Creates a TopProgramsResult from a TSK_PROG_RUN blackboard artifact. * @@ -679,7 +639,7 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor { * * @return The generated TopProgramsResult. */ - private TopProgramsResult getTopProgramsResult(BlackboardArtifact artifact) { + private static TopProgramsResult getTopProgramsResult(BlackboardArtifact artifact) { String programName = DataSourceInfoUtilities.getStringOrNull(artifact, TYPE_PROG_NAME); // ignore items with no name or a ntos boot identifier @@ -731,7 +691,7 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor { * @param long2 Second possibly null long. * * @return Returns the compare value: 1,0,-1 favoring the higher non-null - * value. + * value. */ private static int nullableCompare(Long long1, Long long2) { if (long1 == null && long2 == null) { @@ -765,17 +725,17 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor { * be ignored and all items will be returned. * * @param dataSource The datasource. If the datasource is null, an empty - * list will be returned. - * @param count The number of results to return. This value must be > 0 or - * an IllegalArgumentException will be thrown. + * list will be returned. + * @param count The number of results to return. This value must be > 0 + * or an IllegalArgumentException will be thrown. * * @return The sorted list and limited to the count if last run or run count - * information is available on any item. + * information is available on any item. * - * @throws SleuthkitCaseProviderException + * @throws NoCurrentCaseException * @throws TskCoreException */ - public List getTopPrograms(DataSource dataSource, int count) throws SleuthkitCaseProviderException, TskCoreException { + public static List getTopPrograms(DataSource dataSource, int count) throws NoCurrentCaseException, TskCoreException { assertValidCount(count); if (dataSource == null) { @@ -783,7 +743,7 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor { } // Get TopProgramsResults for each TSK_PROG_RUN artifact - Collection results = caseProvider.get().getBlackboard().getArtifacts(ARTIFACT_TYPE.TSK_PROG_RUN.getTypeID(), dataSource.getId()) + Collection results = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboard().getArtifacts(ARTIFACT_TYPE.TSK_PROG_RUN.getTypeID(), dataSource.getId()) .stream() // convert to a TopProgramsResult object or null if missing critical information .map((art) -> getTopProgramsResult(art)) @@ -841,7 +801,7 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor { * Main constructor. * * @param lastAccessed The date of last access. - * @param artifact The relevant blackboard artifact. + * @param artifact The relevant blackboard artifact. */ public LastAccessedArtifact(Date lastAccessed, BlackboardArtifact artifact) { this.lastAccessed = lastAccessed; @@ -876,7 +836,7 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor { * * @param searchString The search string. * @param dateAccessed The latest date searched. - * @param artifact The relevant blackboard artifact. + * @param artifact The relevant blackboard artifact. */ public TopWebSearchResult(String searchString, Date dateAccessed, BlackboardArtifact artifact) { super(dateAccessed, artifact); @@ -919,11 +879,11 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor { /** * Main constructor. * - * @param deviceId The device id. + * @param deviceId The device id. * @param dateAccessed The date last attached. - * @param deviceMake The device make. - * @param deviceModel The device model. - * @param artifact The relevant blackboard artifact. + * @param deviceMake The device make. + * @param deviceModel The device model. + * @param artifact The relevant blackboard artifact. */ public TopDeviceAttachedResult(String deviceId, Date dateAccessed, String deviceMake, String deviceModel, BlackboardArtifact artifact) { super(dateAccessed, artifact); @@ -966,8 +926,8 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor { * Main constructor. * * @param accountType The account type. - * @param lastAccess The date the account was last accessed. - * @param artifact The artifact indicating last access. + * @param lastAccess The date the account was last accessed. + * @param artifact The artifact indicating last access. */ public TopAccountResult(String accountType, Date lastAccess, BlackboardArtifact artifact) { super(lastAccess, artifact); @@ -993,10 +953,10 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor { /** * Describes a top domain result. * - * @param domain The domain. + * @param domain The domain. * @param visitTimes The number of times it was visited. - * @param lastVisit The date of the last visit. - * @param artifact The relevant blackboard artifact. + * @param lastVisit The date of the last visit. + * @param artifact The relevant blackboard artifact. */ public TopDomainsResult(String domain, Long visitTimes, Date lastVisit, BlackboardArtifact artifact) { super(lastVisit, artifact); @@ -1033,8 +993,8 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor { * * @param programName The name of the program. * @param programPath The path of the program. - * @param runTimes The number of runs. - * @param artifact The relevant blackboard artifact. + * @param runTimes The number of runs. + * @param artifact The relevant blackboard artifact. */ TopProgramsResult(String programName, String programPath, Long runTimes, Date lastRun, BlackboardArtifact artifact) { super(lastRun, artifact); diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummaryGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummaryGetter.java new file mode 100644 index 0000000000..73ac071470 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummaryGetter.java @@ -0,0 +1,237 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2020-2021 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.datasourcesummary.datamodel; + +import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultArtifactUpdateGovernor; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.datamodel.DataSource; +import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.autopsy.contentutils.UserActivitySummary; +import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopAccountResult; +import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopDeviceAttachedResult; +import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopDomainsResult; +import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopProgramsResult; +import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopWebSearchResult; +import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; + +/** + * Wrapper class for converting + * org.sleuthkit.autopsy.contentutils.UserActivitySummary functionality into a + * DefaultArtifactUpdateGovernor used by UserActivityPanel tab. + */ +public class UserActivitySummaryGetter implements DefaultArtifactUpdateGovernor { + + private static final Set ARTIFACT_UPDATE_TYPE_IDS = new HashSet<>(Arrays.asList( + ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY.getTypeID(), + ARTIFACT_TYPE.TSK_MESSAGE.getTypeID(), + ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID(), + ARTIFACT_TYPE.TSK_CALLLOG.getTypeID(), + ARTIFACT_TYPE.TSK_DEVICE_ATTACHED.getTypeID(), + ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID(), + ARTIFACT_TYPE.TSK_PROG_RUN.getTypeID() + )); + + public UserActivitySummaryGetter() { + } + + @Override + public Set getArtifactTypeIdsForRefresh() { + return Collections.unmodifiableSet(ARTIFACT_UPDATE_TYPE_IDS); + } + + /** + * Throws an IllegalArgumentException if count <= 0. + * + * @param count The count being checked. + */ + private void assertValidCount(int count) { + if (count <= 0) { + throw new IllegalArgumentException("Count must be greater than 0"); + } + } + + /** + * Gets a list of recent domains based on the datasource. + * + * @param dataSource The datasource to query for recent domains. + * @param count The max count of items to return. + * + * @return The list of items retrieved from the database. + * + * @throws InterruptedException + */ + public List getRecentDomains(DataSource dataSource, int count) throws TskCoreException, SleuthkitCaseProviderException { + assertValidCount(count); + + if (dataSource == null) { + return Collections.emptyList(); + } + + try { + return UserActivitySummary.getRecentDomains(dataSource, count); + } catch (NoCurrentCaseException ex) { + throw new SleuthkitCaseProviderException("No currently open case.", ex); + } + } + + /** + * Retrieves most recent web searches by most recent date grouped by search + * term. + * + * @param dataSource The data source. + * @param count The maximum number of records to be shown (must be > + * 0). + * + * @return The list of most recent web searches where most recent search + * appears first. + * + * @throws + * org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException + * @throws TskCoreException + */ + public List getMostRecentWebSearches(DataSource dataSource, int count) throws SleuthkitCaseProviderException, TskCoreException { + assertValidCount(count); + + if (dataSource == null) { + return Collections.emptyList(); + } + + try { + return UserActivitySummary.getMostRecentWebSearches(dataSource, count); + } catch (NoCurrentCaseException ex) { + throw new SleuthkitCaseProviderException("No currently open case.", ex); + } + } + + /** + * Retrieves most recent devices used by most recent date attached. + * + * @param dataSource The data source. + * @param count The maximum number of records to be shown (must be > + * 0). + * + * @return The list of most recent devices attached where most recent device + * attached appears first. + * + * @throws + * org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException + * @throws TskCoreException + */ + public List getRecentDevices(DataSource dataSource, int count) throws SleuthkitCaseProviderException, TskCoreException { + assertValidCount(count); + + if (dataSource == null) { + return Collections.emptyList(); + } + + try { + return UserActivitySummary.getRecentDevices(dataSource, count); + } catch (NoCurrentCaseException ex) { + throw new SleuthkitCaseProviderException("No currently open case.", ex); + } + } + + /** + * Retrieves most recent account used by most recent date for a message + * sent. + * + * @param dataSource The data source. + * @param count The maximum number of records to be shown (must be > + * 0). + * + * @return The list of most recent accounts used where the most recent + * account by last message sent occurs first. + * + * @throws + * org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException + * @throws TskCoreException + */ + @Messages({ + "DataSourceUserActivitySummary_getRecentAccounts_emailMessage=Email Message", + "DataSourceUserActivitySummary_getRecentAccounts_calllogMessage=Call Log",}) + public List getRecentAccounts(DataSource dataSource, int count) throws SleuthkitCaseProviderException, TskCoreException { + assertValidCount(count); + + if (dataSource == null) { + return Collections.emptyList(); + } + + try { + return UserActivitySummary.getRecentAccounts(dataSource, count); + } catch (NoCurrentCaseException ex) { + throw new SleuthkitCaseProviderException("No currently open case.", ex); + } + } + + /** + * Determines a short folder name if any. Otherwise, returns empty string. + * + * @param strPath The string path. + * @param applicationName The application name. + * + * @return The short folder name or empty string if not found. + */ + public String getShortFolderName(String strPath, String applicationName) { + if (strPath == null) { + return ""; + } + + return UserActivitySummary.getShortFolderName(strPath, applicationName); + } + + /** + * Retrieves the top programs results for the given data source limited to + * the count provided as a parameter. The highest run times are at the top + * of the list. If that information isn't available the last run date is + * used. If both, the last run date and the number of run times are + * unavailable, the programs will be sorted alphabetically, the count will + * be ignored and all items will be returned. + * + * @param dataSource The datasource. If the datasource is null, an empty + * list will be returned. + * @param count The number of results to return. This value must be > 0 + * or an IllegalArgumentException will be thrown. + * + * @return The sorted list and limited to the count if last run or run count + * information is available on any item. + * + * @throws SleuthkitCaseProviderException + * @throws TskCoreException + */ + public List getTopPrograms(DataSource dataSource, int count) throws SleuthkitCaseProviderException, TskCoreException { + assertValidCount(count); + + if (dataSource == null) { + return Collections.emptyList(); + } + + try { + return UserActivitySummary.getTopPrograms(dataSource, count); + } catch (NoCurrentCaseException ex) { + throw new SleuthkitCaseProviderException("No currently open case.", ex); + } + } +} diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivityPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivityPanel.java index 2d58c09742..c6d13260b9 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivityPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivityPanel.java @@ -28,13 +28,13 @@ import java.util.Locale; import java.util.function.Function; import org.apache.commons.lang.StringUtils; import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.LastAccessedArtifact; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopAccountResult; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopDeviceAttachedResult; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopWebSearchResult; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopDomainsResult; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopProgramsResult; +import org.sleuthkit.autopsy.contentutils.UserActivitySummary.LastAccessedArtifact; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummaryGetter; +import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopAccountResult; +import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopDeviceAttachedResult; +import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopDomainsResult; +import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopProgramsResult; +import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopWebSearchResult; import org.sleuthkit.autopsy.datasourcesummary.uiutils.ColumnModel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetcher; @@ -261,22 +261,22 @@ public class UserActivityPanel extends BaseDataSourceSummaryPanel { private final IngestRunningLabel ingestRunningLabel = new IngestRunningLabel(); private final List> dataFetchComponents; - private final UserActivitySummary userActivityData; + private final UserActivitySummaryGetter userActivityData; /** * Creates a new UserActivityPanel. */ public UserActivityPanel() { - this(new UserActivitySummary()); + this(new UserActivitySummaryGetter()); } /** * Creates a new UserActivityPanel. * * @param userActivityData Class from which to obtain remaining user - * activity data. + * activity data. */ - public UserActivityPanel(UserActivitySummary userActivityData) { + public UserActivityPanel(UserActivitySummaryGetter userActivityData) { super(userActivityData); this.userActivityData = userActivityData; @@ -328,7 +328,8 @@ public class UserActivityPanel extends BaseDataSourceSummaryPanel { * @param record The LastAccessedArtifact instance. * * @return The menu items list containing one action or navigating to the - * appropriate artifact and closing the data source summary dialog if open. + * appropriate artifact and closing the data source summary dialog + * if open. */ private List getPopup(LastAccessedArtifact record) { return record == null ? null : Arrays.asList(getArtifactNavigateItem(record.getArtifact())); @@ -337,7 +338,7 @@ public class UserActivityPanel extends BaseDataSourceSummaryPanel { /** * Queries DataSourceTopProgramsSummary instance for short folder name. * - * @param path The path for the application. + * @param path The path for the application. * @param appName The application name. * * @return The underlying short folder name if one exists. @@ -362,19 +363,6 @@ public class UserActivityPanel extends BaseDataSourceSummaryPanel { super.close(); } - /* ELTODO - @Override - List getExports(DataSource dataSource) { - return Stream.of( - getTableExport(topProgramsFetcher, topProgramsTemplate, Bundle.UserActivityPanel_TopProgramsTableModel_tabName(), dataSource), - getTableExport(topDomainsFetcher, topDomainsTemplate, Bundle.UserActivityPanel_TopDomainsTableModel_tabName(), dataSource), - getTableExport(topWebSearchesFetcher, topWebSearchesTemplate, Bundle.UserActivityPanel_TopWebSearchTableModel_tabName(), dataSource), - getTableExport(topDevicesAttachedFetcher, topDevicesTemplate, Bundle.UserActivityPanel_TopDeviceAttachedTableModel_tabName(), dataSource), - getTableExport(topAccountsFetcher, topAccountsTemplate, Bundle.UserActivityPanel_TopAccountTableModel_tabName(), dataSource)) - .filter(sheet -> sheet != null) - .collect(Collectors.toList()); - }*/ - /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED index a0c9bb1d6e..d6ca349440 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED @@ -7,8 +7,10 @@ ExcelExportAction_exportToXLSX_beginExport=Beginning Export... ExcelExportAction_exportToXLSX_gatheringAnalysisData=Fetching Analysis Data ExcelExportAction_exportToXLSX_gatheringContainerData=Fetching Container & Image Data ExcelExportAction_exportToXLSX_gatheringFileData=Fetching File and MIME Type Data +ExcelExportAction_exportToXLSX_gatheringPastData=Fetching Historical Data ExcelExportAction_exportToXLSX_gatheringRecentActivityData=Fetching Recent Activity Data ExcelExportAction_exportToXLSX_gatheringTimelineData=Fetching Timeline Data +ExcelExportAction_exportToXLSX_gatheringUserData=Fetching User Activity Data ExcelExportAction_exportToXLSX_writingToFile=Writing to File... ExcelExportAction_getXLSXPath_directory=DataSourceSummary ExcelExportAction_moduleName=Data Source Summary @@ -36,7 +38,6 @@ ExportContainerInfo_tabName=Container ExportPastCases_caseColumn_title=Case ExportPastCases_countColumn_title=Count ExportPastCases_notableFileTable_tabName=Cases with Common Notable -ExportPastCases_onNoCrIngest_message=No results will be shown because the Central Repository module was not run. ExportPastCases_sameIdsTable_tabName=Past Cases with the Same Devices ExportRecentFiles_attachmentsTable_tabName=Recent Attachments ExportRecentFiles_col_head_date=Date @@ -64,6 +65,28 @@ ExportTypes_filesByCategoryTable_unallocatedRow_title=Unallocated Files ExportTypes_osLabel_title=OS ExportTypes_sizeLabel_title=Size ExportTypes_usageLabel_title=Usage +ExportUserActivity_noDataExists=No communication data exists +ExportUserActivity_tab_title=User Activity +ExportUserActivity_TopAccountTableModel_accountType_header=Account Type +ExportUserActivity_TopAccountTableModel_lastAccess_header=Last Accessed +ExportUserActivity_TopAccountTableModel_tabName=Recent Account Types Used +ExportUserActivity_TopDeviceAttachedTableModel_dateAccessed_header=Last Accessed +ExportUserActivity_TopDeviceAttachedTableModel_deviceId_header=Device Id +ExportUserActivity_TopDeviceAttachedTableModel_makeModel_header=Make and Model +ExportUserActivity_TopDeviceAttachedTableModel_tabName=Recent Devices Attached +ExportUserActivity_TopDomainsTableModel_count_header=Visits +ExportUserActivity_TopDomainsTableModel_domain_header=Domain +ExportUserActivity_TopDomainsTableModel_lastAccess_header=Last Accessed +ExportUserActivity_TopDomainsTableModel_tabName=Recent Domains +ExportUserActivity_TopProgramsTableModel_count_header=Run Times +ExportUserActivity_TopProgramsTableModel_folder_header=Folder +ExportUserActivity_TopProgramsTableModel_lastrun_header=Last Run +ExportUserActivity_TopProgramsTableModel_name_header=Program +ExportUserActivity_TopProgramsTableModel_tabName=Recent Programs +ExportUserActivity_TopWebSearchTableModel_dateAccessed_header=Date Accessed +ExportUserActivity_TopWebSearchTableModel_searchString_header=Search String +ExportUserActivity_TopWebSearchTableModel_tabName=Recent Web Searches +ExportUserActivity_TopWebSearchTableModel_translatedResult_header=Translated SizeRepresentationUtil_units_bytes=bytes SizeRepresentationUtil_units_gigabytes=GB SizeRepresentationUtil_units_kilobytes=KB diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java index 50dd05a18c..44879e741f 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java @@ -98,6 +98,7 @@ class ExcelExportAction { "ExcelExportAction_exportToXLSX_gatheringFileData=Fetching File and MIME Type Data", "ExcelExportAction_exportToXLSX_gatheringAnalysisData=Fetching Analysis Data", "ExcelExportAction_exportToXLSX_gatheringPastData=Fetching Historical Data", + "ExcelExportAction_exportToXLSX_gatheringUserData=Fetching User Activity Data", "ExcelExportAction_exportToXLSX_writingToFile=Writing to File...",}) void exportToXLSX(ReportProgressPanel progressPanel, DataSource dataSource, String baseReportDir) @@ -157,7 +158,15 @@ class ExcelExportAction { if (exports != null) { sheetExports.addAll(exports); } - + + // Export user activity + progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_gatheringUserData()); + progressPanel.setProgress(6); + exports = ExportUserActivity.getExports(dataSource); + if (exports != null) { + sheetExports.addAll(exports); + } + progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_writingToFile()); progressPanel.setProgress(9); ExcelExport.writeExcel(sheetExports, reportFile); diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportUserActivity.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportUserActivity.java new file mode 100755 index 0000000000..c89c4f996a --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportUserActivity.java @@ -0,0 +1,248 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit 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.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Locale; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.apache.commons.lang.StringUtils; +import org.openide.util.NbBundle.Messages; +import org.sleuthkit.datamodel.DataSource; +import org.sleuthkit.autopsy.contentutils.UserActivitySummary; +import org.sleuthkit.autopsy.contentutils.UserActivitySummary.LastAccessedArtifact; +import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopAccountResult; +import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopDeviceAttachedResult; +import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopDomainsResult; +import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopProgramsResult; +import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopWebSearchResult; +import static org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExportAction.getTableExport; + +/** + * A panel to display user activity. + */ +@Messages({ + "ExportUserActivity_tab_title=User Activity", + "ExportUserActivity_TopProgramsTableModel_tabName=Recent Programs", + "ExportUserActivity_TopDomainsTableModel_tabName=Recent Domains", + "ExportUserActivity_TopWebSearchTableModel_tabName=Recent Web Searches", + "ExportUserActivity_TopDeviceAttachedTableModel_tabName=Recent Devices Attached", + "ExportUserActivity_TopAccountTableModel_tabName=Recent Account Types Used", + "ExportUserActivity_TopProgramsTableModel_name_header=Program", + "ExportUserActivity_TopProgramsTableModel_folder_header=Folder", + "ExportUserActivity_TopProgramsTableModel_count_header=Run Times", + "ExportUserActivity_TopProgramsTableModel_lastrun_header=Last Run", + "ExportUserActivity_TopDomainsTableModel_domain_header=Domain", + "ExportUserActivity_TopDomainsTableModel_count_header=Visits", + "ExportUserActivity_TopDomainsTableModel_lastAccess_header=Last Accessed", + "ExportUserActivity_TopWebSearchTableModel_searchString_header=Search String", + "ExportUserActivity_TopWebSearchTableModel_dateAccessed_header=Date Accessed", + "ExportUserActivity_TopWebSearchTableModel_translatedResult_header=Translated", + "ExportUserActivity_TopDeviceAttachedTableModel_deviceId_header=Device Id", + "ExportUserActivity_TopDeviceAttachedTableModel_makeModel_header=Make and Model", + "ExportUserActivity_TopDeviceAttachedTableModel_dateAccessed_header=Last Accessed", + "ExportUserActivity_TopAccountTableModel_accountType_header=Account Type", + "ExportUserActivity_TopAccountTableModel_lastAccess_header=Last Accessed", + "ExportUserActivity_noDataExists=No communication data exists"}) +class ExportUserActivity { + + private static final String DATETIME_FORMAT_STR = "yyyy/MM/dd HH:mm:ss"; + private static final DateFormat DATETIME_FORMAT = new SimpleDateFormat(DATETIME_FORMAT_STR, Locale.getDefault()); + private static final int TOP_PROGS_COUNT = 10; + private static final int TOP_DOMAINS_COUNT = 10; + private static final int TOP_SEARCHES_COUNT = 10; + private static final int TOP_ACCOUNTS_COUNT = 5; + private static final int TOP_DEVICES_COUNT = 10; + + // set up recent programs + private static final List>> topProgramsTemplate = Arrays.asList( + // program name column + new ColumnModel<>( + Bundle.ExportUserActivity_TopProgramsTableModel_name_header(), + (prog) -> { + return new DefaultCellModel<>(prog.getProgramName()); + }, + 250), + // program folder column + new ColumnModel<>( + Bundle.ExportUserActivity_TopProgramsTableModel_folder_header(), + (prog) -> { + return new DefaultCellModel<>( + getShortFolderName( + prog.getProgramPath(), + prog.getProgramName())); + }, + 150), + // run count column + new ColumnModel<>( + Bundle.ExportUserActivity_TopProgramsTableModel_count_header(), + (prog) -> { + return new DefaultCellModel<>(prog.getRunTimes(), (num) -> num == null ? "" : num.toString()); + }, + 80), + // last run date column + new ColumnModel<>( + Bundle.ExportUserActivity_TopProgramsTableModel_lastrun_header(), + getDateFunct(), + 150) + ); + + // set up recent domains + private static final List>> topDomainsTemplate = Arrays.asList( + // domain column + new ColumnModel<>( + Bundle.ExportUserActivity_TopDomainsTableModel_domain_header(), + (recentDomain) -> { + return new DefaultCellModel<>(recentDomain.getDomain()); + }, + 250), + // count column + new ColumnModel<>( + Bundle.ExportUserActivity_TopDomainsTableModel_count_header(), + (recentDomain) -> { + return new DefaultCellModel<>(recentDomain.getVisitTimes(), (num) -> num == null ? "" : num.toString()); + }, + 100), + // last accessed column + new ColumnModel<>( + Bundle.ExportUserActivity_TopDomainsTableModel_lastAccess_header(), + getDateFunct(), + 150) + ); + + // top web searches + private static final List>> topWebSearchesTemplate = Arrays.asList( + // search string column + new ColumnModel<>( + Bundle.ExportUserActivity_TopWebSearchTableModel_searchString_header(), + (webSearch) -> { + return new DefaultCellModel<>(webSearch.getSearchString()); + }, + 250 + ), + // last accessed + new ColumnModel<>( + Bundle.ExportUserActivity_TopWebSearchTableModel_dateAccessed_header(), + getDateFunct(), + 150 + ), + // translated value + new ColumnModel<>( + Bundle.ExportUserActivity_TopWebSearchTableModel_translatedResult_header(), + (webSearch) -> { + return new DefaultCellModel<>(webSearch.getTranslatedResult()); + }, + 250 + ) + ); + + // top devices attached + private static final List>> topDevicesTemplate = Arrays.asList( + // device id column + new ColumnModel<>( + Bundle.ExportUserActivity_TopDeviceAttachedTableModel_deviceId_header(), + (device) -> { + return new DefaultCellModel<>(device.getDeviceId()); + }, + 250 + ), + // last accessed + new ColumnModel<>( + Bundle.ExportUserActivity_TopDeviceAttachedTableModel_dateAccessed_header(), + getDateFunct(), + 150 + ), + // make and model + new ColumnModel<>( + Bundle.ExportUserActivity_TopDeviceAttachedTableModel_makeModel_header(), + (device) -> { + String make = StringUtils.isBlank(device.getDeviceMake()) ? "" : device.getDeviceMake().trim(); + String model = StringUtils.isBlank(device.getDeviceModel()) ? "" : device.getDeviceModel().trim(); + String makeModelString = (make.isEmpty() || model.isEmpty()) + ? make + model + : String.format("%s - %s", make, model); + return new DefaultCellModel<>(makeModelString); + }, + 250 + ) + ); + + // top accounts + private static final List>> topAccountsTemplate = Arrays.asList( + // account type column + new ColumnModel<>( + Bundle.ExportUserActivity_TopAccountTableModel_accountType_header(), + (account) -> { + return new DefaultCellModel<>(account.getAccountType()); + }, + 250 + ), + // last accessed + new ColumnModel<>( + Bundle.ExportUserActivity_TopAccountTableModel_lastAccess_header(), + getDateFunct(), + 150 + ) + ); + + private ExportUserActivity() { + } + + private static Function> getDateFunct() { + return (T lastAccessed) -> { + Function dateParser = (dt) -> dt == null ? "" : DATETIME_FORMAT.format(dt); + return new DefaultCellModel<>(lastAccessed.getLastAccessed(), dateParser, DATETIME_FORMAT_STR); + }; + } + + /** + * Queries DataSourceTopProgramsSummary instance for short folder name. + * + * @param path The path for the application. + * @param appName The application name. + * + * @return The underlying short folder name if one exists. + */ + private static String getShortFolderName(String path, String appName) { + return UserActivitySummary.getShortFolderName(path, appName); + } + + static List getExports(DataSource dataSource) { + + DataFetcher> topProgramsFetcher = (ds) -> UserActivitySummary.getTopPrograms(ds, TOP_PROGS_COUNT); + DataFetcher> topDomainsFetcher = (ds) -> UserActivitySummary.getRecentDomains(ds, TOP_DOMAINS_COUNT); + DataFetcher> topWebSearchesFetcher = (ds) -> UserActivitySummary.getMostRecentWebSearches(ds, TOP_SEARCHES_COUNT); + DataFetcher> topDevicesAttachedFetcher = (ds) -> UserActivitySummary.getRecentDevices(ds, TOP_DEVICES_COUNT); + DataFetcher> topAccountsFetcher = (ds) -> UserActivitySummary.getRecentAccounts(ds, TOP_ACCOUNTS_COUNT); + + return Stream.of( + getTableExport(topProgramsFetcher, topProgramsTemplate, Bundle.ExportUserActivity_TopProgramsTableModel_tabName(), dataSource), + getTableExport(topDomainsFetcher, topDomainsTemplate, Bundle.ExportUserActivity_TopDomainsTableModel_tabName(), dataSource), + getTableExport(topWebSearchesFetcher, topWebSearchesTemplate, Bundle.ExportUserActivity_TopWebSearchTableModel_tabName(), dataSource), + getTableExport(topDevicesAttachedFetcher, topDevicesTemplate, Bundle.ExportUserActivity_TopDeviceAttachedTableModel_tabName(), dataSource), + getTableExport(topAccountsFetcher, topAccountsTemplate, Bundle.ExportUserActivity_TopAccountTableModel_tabName(), dataSource)) + .filter(sheet -> sheet != null) + .collect(Collectors.toList()); + } +} diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/datasourcesummary/UserActivitySummaryTests.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/datasourcesummary/UserActivitySummaryTests.java index 14455b27c9..10c42eebbb 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/datasourcesummary/UserActivitySummaryTests.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/datasourcesummary/UserActivitySummaryTests.java @@ -26,8 +26,8 @@ import java.util.stream.Collectors; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopDomainsResult; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummaryGetter; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummaryGetter.TopDomainsResult; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.TskCoreException; @@ -36,14 +36,14 @@ import org.sleuthkit.autopsy.integrationtesting.IntegrationTest; import org.sleuthkit.autopsy.integrationtesting.IntegrationTestGroup; /** - * Tests for the UserActivitySummary class. + * Tests for the UserActivitySummaryGetter class. */ @ServiceProvider(service = IntegrationTestGroup.class) public class UserActivitySummaryTests implements IntegrationTestGroup { /** - * Runs UserActivitySummary.getRecentDomains for all data sources found in - * the current case. + * Runs UserActivitySummaryGetter.getRecentDomains for all data sources found in + the current case. * * @return A map where the key is the data source name and the value are the * results of that method. @@ -52,7 +52,7 @@ public class UserActivitySummaryTests implements IntegrationTestGroup { public Map>> getRecentDomainsTest() throws NoCurrentCaseException, TskCoreException, SleuthkitCaseProviderException { - UserActivitySummary userActivitySummary = new UserActivitySummary(); + UserActivitySummaryGetter userActivitySummary = new UserActivitySummaryGetter(); Map>> toRet = new HashMap<>(); for (Content c : Case.getCurrentCaseThrows().getDataSources()) { if (c instanceof DataSource) { diff --git a/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummaryTest.java b/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummaryTest.java index 2b6a1c6600..216b1b99c5 100644 --- a/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummaryTest.java +++ b/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummaryTest.java @@ -44,11 +44,11 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceSummaryMockUtils.getArtifactsTSKMock; import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopAccountResult; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopDeviceAttachedResult; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopDomainsResult; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopProgramsResult; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopWebSearchResult; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummaryGetter.TopAccountResult; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummaryGetter.TopDeviceAttachedResult; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummaryGetter.TopDomainsResult; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummaryGetter.TopProgramsResult; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummaryGetter.TopWebSearchResult; import org.sleuthkit.autopsy.testutils.TskMockUtils; import org.sleuthkit.autopsy.texttranslation.NoServiceProviderException; import org.sleuthkit.autopsy.texttranslation.TextTranslationService; @@ -63,27 +63,27 @@ import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; /** - * Tests for UserActivitySummary. + * Tests for UserActivitySummaryGetter. */ public class UserActivitySummaryTest { /** - * Function to retrieve data from UserActivitySummary with the provided - * arguments. + * Function to retrieve data from UserActivitySummaryGetter with the provided + arguments. */ private interface DataFunction { /** - * A UserActivitySummary method encapsulated in a uniform manner. + * A UserActivitySummaryGetter method encapsulated in a uniform manner. * - * @param userActivitySummary The UserActivitySummary class to use. + * @param userActivitySummary The UserActivitySummaryGetter class to use. * @param datasource The data source. * @param count The count. * @return The list of objects to return. * @throws SleuthkitCaseProviderException * @throws TskCoreException */ - List retrieve(UserActivitySummary userActivitySummary, DataSource datasource, int count) throws + List retrieve(UserActivitySummaryGetter userActivitySummary, DataSource datasource, int count) throws SleuthkitCaseProviderException, TskCoreException; } @@ -119,21 +119,21 @@ public class UserActivitySummaryTest { } /** - * Gets a UserActivitySummary class to test. + * Gets a UserActivitySummaryGetter class to test. * * @param tskCase The SleuthkitCase. * @param hasTranslation Whether the translation service is functional. * @param translateFunction Function for translation. * - * @return The UserActivitySummary class to use for testing. + * @return The UserActivitySummaryGetter class to use for testing. * * @throws NoServiceProviderException * @throws TranslationException */ - private static UserActivitySummary getTestClass(SleuthkitCase tskCase, boolean hasTranslation, Function translateFunction) + private static UserActivitySummaryGetter getTestClass(SleuthkitCase tskCase, boolean hasTranslation, Function translateFunction) throws NoServiceProviderException, TranslationException { - return new UserActivitySummary( + return new UserActivitySummaryGetter( () -> tskCase, TskMockUtils.getTextTranslationService(translateFunction, hasTranslation), TskMockUtils.getJavaLogger("UNIT TEST LOGGER") @@ -145,7 +145,7 @@ public class UserActivitySummaryTest { for (int count : new int[]{0, -1}) { Pair tskPair = getArtifactsTSKMock(null); - UserActivitySummary summary = getTestClass(tskPair.getLeft(), false, null); + UserActivitySummaryGetter summary = getTestClass(tskPair.getLeft(), false, null); try { funct.retrieve(summary, TskMockUtils.getDataSource(1), -1); @@ -183,7 +183,7 @@ public class UserActivitySummaryTest { throws TskCoreException, NoServiceProviderException, TranslationException, SleuthkitCaseProviderException { Pair tskPair = getArtifactsTSKMock(null); - UserActivitySummary summary = getTestClass(tskPair.getLeft(), false, null); + UserActivitySummaryGetter summary = getTestClass(tskPair.getLeft(), false, null); List retArr = funct.retrieve(summary, null, 10); verify(tskPair.getRight(), never() .description(String.format("Expected method %s to return empty list for null data source and not call SleuthkitCase", id))) @@ -216,7 +216,7 @@ public class UserActivitySummaryTest { long dataSourceId = 1; int count = 10; Pair tskPair = getArtifactsTSKMock(new ArrayList<>()); - UserActivitySummary summary = getTestClass(tskPair.getLeft(), false, null); + UserActivitySummaryGetter summary = getTestClass(tskPair.getLeft(), false, null); List retArr = funct.retrieve(summary, TskMockUtils.getDataSource(dataSourceId), count); Assert.assertTrue(String.format("Expected non null empty list returned from %s", id), retArr != null); @@ -290,7 +290,7 @@ public class UserActivitySummaryTest { .collect(Collectors.toList()); Pair tskPair = getArtifactsTSKMock(artifacts); - UserActivitySummary summary = getTestClass(tskPair.getLeft(), false, null); + UserActivitySummaryGetter summary = getTestClass(tskPair.getLeft(), false, null); List results = summary.getRecentDevices(ds, count); @@ -304,8 +304,8 @@ public class UserActivitySummaryTest { } /** - * Ensures that UserActivitySummary.getRecentDevices limits returned entries - * to count provided. + * Ensures that UserActivitySummaryGetter.getRecentDevices limits returned entries + to count provided. * * @throws TskCoreException * @throws NoServiceProviderException @@ -327,7 +327,7 @@ public class UserActivitySummaryTest { .collect(Collectors.toList()); Pair tskPair = getArtifactsTSKMock(returnedArtifacts); - UserActivitySummary summary = getTestClass(tskPair.getLeft(), false, null); + UserActivitySummaryGetter summary = getTestClass(tskPair.getLeft(), false, null); List results = summary.getRecentDevices(dataSource, countRequested); verifyCalled(tskPair.getRight(), ARTIFACT_TYPE.TSK_DEVICE_ATTACHED.getTypeID(), dataSourceId, @@ -348,7 +348,7 @@ public class UserActivitySummaryTest { BlackboardArtifact item3 = getRecentDeviceArtifact(1003, dataSource, "ID1", "MAKE1", "MODEL1", DAY_SECONDS + 2); Pair tskPair = getArtifactsTSKMock(Arrays.asList(item1, item2, item3)); - UserActivitySummary summary = getTestClass(tskPair.getLeft(), false, null); + UserActivitySummaryGetter summary = getTestClass(tskPair.getLeft(), false, null); List results = summary.getRecentDevices(dataSource, 10); @@ -396,7 +396,7 @@ public class UserActivitySummaryTest { List artList = Arrays.asList(art1a, art2a, art2b, art1b, art1c); Pair tskPair = getArtifactsTSKMock(artList); - UserActivitySummary summary = getTestClass(tskPair.getLeft(), false, null); + UserActivitySummaryGetter summary = getTestClass(tskPair.getLeft(), false, null); List results = summary.getMostRecentWebSearches(ds, 10); verifyCalled(tskPair.getRight(), ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY.getTypeID(), dataSourceId, "Expected getRecentDevices to call getArtifacts with correct arguments."); @@ -433,7 +433,7 @@ public class UserActivitySummaryTest { // set up a mock TextTranslationService returning a translation TextTranslationService translationService = TskMockUtils.getTextTranslationService(translator, hasProvider); - UserActivitySummary summary = new UserActivitySummary( + UserActivitySummaryGetter summary = new UserActivitySummaryGetter( () -> tskPair.getLeft(), translationService, TskMockUtils.getJavaLogger("UNIT TEST LOGGER") @@ -473,8 +473,8 @@ public class UserActivitySummaryTest { } /** - * Verify that UserActivitySummary.getMostRecentWebSearches handles - * translation appropriately. + * Verify that UserActivitySummaryGetter.getMostRecentWebSearches handles + translation appropriately. * * @throws SleuthkitCaseProviderException * @throws TskCoreException @@ -502,8 +502,8 @@ public class UserActivitySummaryTest { } /** - * Ensure that UserActivitySummary.getMostRecentWebSearches results limited - * to count. + * Ensure that UserActivitySummaryGetter.getMostRecentWebSearches results limited + to count. * * @throws TskCoreException * @throws NoServiceProviderException @@ -525,7 +525,7 @@ public class UserActivitySummaryTest { .collect(Collectors.toList()); Pair tskPair = getArtifactsTSKMock(returnedArtifacts); - UserActivitySummary summary = getTestClass(tskPair.getLeft(), false, null); + UserActivitySummaryGetter summary = getTestClass(tskPair.getLeft(), false, null); List results = summary.getMostRecentWebSearches(dataSource, countRequested); verifyCalled(tskPair.getRight(), ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY.getTypeID(), dataSourceId, @@ -558,8 +558,8 @@ public class UserActivitySummaryTest { private static final long DOMAIN_WINDOW_DAYS = 30; /** - * UserActivitySummary.getRecentDomains should return results within 30 days - * of the most recent access. + * UserActivitySummaryGetter.getRecentDomains should return results within 30 days + of the most recent access. * * @throws TskCoreException * @throws SleuthkitCaseProviderException @@ -589,7 +589,7 @@ public class UserActivitySummaryTest { Pair tskPair = getArtifactsTSKMock(retArr); - UserActivitySummary summary = getTestClass(tskPair.getLeft(), false, null); + UserActivitySummaryGetter summary = getTestClass(tskPair.getLeft(), false, null); List domains = summary.getRecentDomains(dataSource, 10); @@ -633,7 +633,7 @@ public class UserActivitySummaryTest { Pair tskPair = getArtifactsTSKMock(retArr); - UserActivitySummary summary = getTestClass(tskPair.getLeft(), false, null); + UserActivitySummaryGetter summary = getTestClass(tskPair.getLeft(), false, null); List domains = summary.getRecentDomains(dataSource, 10); @@ -670,7 +670,7 @@ public class UserActivitySummaryTest { List retArr = Arrays.asList(artifact1, artifact1a, artifact2, artifact2a, artifact2b); Pair tskPair = getArtifactsTSKMock(retArr); - UserActivitySummary summary = getTestClass(tskPair.getLeft(), false, null); + UserActivitySummaryGetter summary = getTestClass(tskPair.getLeft(), false, null); List domains = summary.getRecentDomains(dataSource, 10); @@ -689,8 +689,8 @@ public class UserActivitySummaryTest { } /** - * Ensure that UserActivitySummary.getRecentDomains limits to count - * appropriately. + * Ensure that UserActivitySummaryGetter.getRecentDomains limits to count + appropriately. * * @throws TskCoreException * @throws NoServiceProviderException @@ -719,7 +719,7 @@ public class UserActivitySummaryTest { .collect(Collectors.toList()); Pair tskPair = getArtifactsTSKMock(returnedArtifacts); - UserActivitySummary summary = getTestClass(tskPair.getLeft(), false, null); + UserActivitySummaryGetter summary = getTestClass(tskPair.getLeft(), false, null); List results = summary.getRecentDomains(dataSource, countRequested); verifyCalled(tskPair.getRight(), ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID(), dataSourceId, @@ -818,7 +818,7 @@ public class UserActivitySummaryTest { } /** - * Performs a test on UserActivitySummary.getRecentAccounts. + * Performs a test on UserActivitySummaryGetter.getRecentAccounts. * * @param dataSource The datasource to use as parameter. * @param count The count to use as a parameter. @@ -849,7 +849,7 @@ public class UserActivitySummaryTest { .collect(Collectors.toList()); }); - UserActivitySummary summary = getTestClass(mockCase, false, null); + UserActivitySummaryGetter summary = getTestClass(mockCase, false, null); List receivedResults = summary.getRecentAccounts(dataSource, count); @@ -880,8 +880,8 @@ public class UserActivitySummaryTest { } /** - * Verify that UserActivitySummary.getRecentAccounts attempts to find a date - * but if none present, the artifact is excluded. + * Verify that UserActivitySummaryGetter.getRecentAccounts attempts to find a date + but if none present, the artifact is excluded. * * @throws TskCoreException * @throws NoServiceProviderException @@ -950,8 +950,8 @@ public class UserActivitySummaryTest { } /** - * Verifies that UserActivitySummary.getRecentAccounts groups appropriately - * by account type. + * Verifies that UserActivitySummaryGetter.getRecentAccounts groups appropriately + by account type. * * @throws TskCoreException * @throws NoServiceProviderException @@ -986,8 +986,8 @@ public class UserActivitySummaryTest { } /** - * Verifies that UserActivitySummary.getRecentAccounts properly limits - * results returned. + * Verifies that UserActivitySummaryGetter.getRecentAccounts properly limits + results returned. * * @throws TskCoreException * @throws NoServiceProviderException @@ -1007,7 +1007,7 @@ public class UserActivitySummaryTest { .collect(Collectors.toList()); Pair tskPair = getArtifactsTSKMock(returnedArtifacts); - UserActivitySummary summary = getTestClass(tskPair.getLeft(), false, null); + UserActivitySummaryGetter summary = getTestClass(tskPair.getLeft(), false, null); List results = summary.getRecentAccounts(dataSource, countRequested); verifyCalled(tskPair.getRight(), ARTIFACT_TYPE.TSK_MESSAGE.getTypeID(), dataSource.getId(), @@ -1044,7 +1044,7 @@ public class UserActivitySummaryTest { expected.put("/Other Path/Item/Item.exe", ""); Pair tskPair = getArtifactsTSKMock(null); - UserActivitySummary summary = getTestClass(tskPair.getLeft(), false, null); + UserActivitySummaryGetter summary = getTestClass(tskPair.getLeft(), false, null); for (Entry path : expected.entrySet()) { Assert.assertTrue(path.getValue().equalsIgnoreCase(summary.getShortFolderName(path.getKey(), "Item.exe"))); @@ -1112,7 +1112,7 @@ public class UserActivitySummaryTest { successful, successful2 )); - UserActivitySummary summary = getTestClass(tskPair.getLeft(), false, null); + UserActivitySummaryGetter summary = getTestClass(tskPair.getLeft(), false, null); List results = summary.getTopPrograms(ds1, 10); Assert.assertEquals(2, results.size()); @@ -1150,7 +1150,7 @@ public class UserActivitySummaryTest { prog2, prog2a, prog2b, prog3, prog3a, prog3b )); - UserActivitySummary summary = getTestClass(tskPair.getLeft(), false, null); + UserActivitySummaryGetter summary = getTestClass(tskPair.getLeft(), false, null); List results = summary.getTopPrograms(ds1, 10); Assert.assertEquals(3, results.size()); @@ -1174,7 +1174,7 @@ public class UserActivitySummaryTest { throws TskCoreException, NoServiceProviderException, TranslationException, SleuthkitCaseProviderException { Pair tskPair = getArtifactsTSKMock(artifacts); - UserActivitySummary summary = getTestClass(tskPair.getLeft(), false, null); + UserActivitySummaryGetter summary = getTestClass(tskPair.getLeft(), false, null); List results = summary.getTopPrograms(ds1, 10); Assert.assertEquals(programNamesReturned.size(), results.size()); @@ -1184,8 +1184,8 @@ public class UserActivitySummaryTest { } /** - * Ensure that UserActivitySummary.getTopPrograms properly orders results - * (first by run count, then date, then program name). + * Ensure that UserActivitySummaryGetter.getTopPrograms properly orders results + (first by run count, then date, then program name). * * @throws TskCoreException * @throws NoServiceProviderException @@ -1214,8 +1214,8 @@ public class UserActivitySummaryTest { } /** - * Ensure that UserActivitySummary.getTopPrograms properly limits results - * (if no run count and no run date, then no limit). + * Ensure that UserActivitySummaryGetter.getTopPrograms properly limits results + (if no run count and no run date, then no limit). * * @throws TskCoreException * @throws NoServiceProviderException @@ -1239,7 +1239,7 @@ public class UserActivitySummaryTest { .collect(Collectors.toList()); Pair tskPair = getArtifactsTSKMock(returnedArtifacts); - UserActivitySummary summary = getTestClass(tskPair.getLeft(), false, null); + UserActivitySummaryGetter summary = getTestClass(tskPair.getLeft(), false, null); List results = summary.getTopPrograms(dataSource, countRequested); verifyCalled(tskPair.getRight(), ARTIFACT_TYPE.TSK_PROG_RUN.getTypeID(), dataSourceId, @@ -1253,7 +1253,7 @@ public class UserActivitySummaryTest { .collect(Collectors.toList()); Pair tskPairAlphabetical = getArtifactsTSKMock(returnedArtifactsAlphabetical); - UserActivitySummary summaryAlphabetical = getTestClass(tskPairAlphabetical.getLeft(), false, null); + UserActivitySummaryGetter summaryAlphabetical = getTestClass(tskPairAlphabetical.getLeft(), false, null); List resultsAlphabetical = summaryAlphabetical.getTopPrograms(dataSource, countRequested); verifyCalled(tskPairAlphabetical.getRight(), ARTIFACT_TYPE.TSK_PROG_RUN.getTypeID(), dataSourceId, From f36c6913a1dd569325aa70d504597bc6c375bc12 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Tue, 10 Aug 2021 12:11:37 -0400 Subject: [PATCH 18/33] Refactored GeolocationTab --- .../CityRecord.java | 4 +- .../ClosestCityMapper.java | 56 +++-- .../GeolocationSummary.java | 145 ++++++------ .../datamodel => contentutils}/LatLngMap.java | 15 +- .../worldcities.csv | 0 .../datamodel/GeolocationSummaryGetter.java | 81 +++++++ .../ui/GeolocationPanel.java | 58 ++--- .../Bundle.properties-MERGED | 6 + .../ExcelExportAction.java | 9 + .../ExportGeolocation.java | 223 ++++++++++++++++++ .../ExportUserActivity.java | 2 +- .../UserActivitySummaryTests.java | 2 +- .../datamodel/UserActivitySummaryTest.java | 22 +- 13 files changed, 463 insertions(+), 160 deletions(-) rename Core/src/org/sleuthkit/autopsy/{datasourcesummary/datamodel => contentutils}/CityRecord.java (96%) rename Core/src/org/sleuthkit/autopsy/{datasourcesummary/datamodel => contentutils}/ClosestCityMapper.java (84%) rename Core/src/org/sleuthkit/autopsy/{datasourcesummary/datamodel => contentutils}/GeolocationSummary.java (81%) mode change 100644 => 100755 rename Core/src/org/sleuthkit/autopsy/{datasourcesummary/datamodel => contentutils}/LatLngMap.java (95%) rename Core/src/org/sleuthkit/autopsy/{datasourcesummary/datamodel => contentutils}/worldcities.csv (100%) create mode 100644 Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/GeolocationSummaryGetter.java create mode 100755 Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportGeolocation.java diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/CityRecord.java b/Core/src/org/sleuthkit/autopsy/contentutils/CityRecord.java similarity index 96% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/CityRecord.java rename to Core/src/org/sleuthkit/autopsy/contentutils/CityRecord.java index d2a1182e6a..562fc1758d 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/CityRecord.java +++ b/Core/src/org/sleuthkit/autopsy/contentutils/CityRecord.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2020 Basis Technology Corp. + * Copyright 2020-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datasourcesummary.datamodel; +package org.sleuthkit.autopsy.contentutils; import java.util.Objects; import org.sleuthkit.autopsy.geolocation.KdTree; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ClosestCityMapper.java b/Core/src/org/sleuthkit/autopsy/contentutils/ClosestCityMapper.java similarity index 84% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ClosestCityMapper.java rename to Core/src/org/sleuthkit/autopsy/contentutils/ClosestCityMapper.java index 4427d25f23..3e39852c79 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ClosestCityMapper.java +++ b/Core/src/org/sleuthkit/autopsy/contentutils/ClosestCityMapper.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2020 Basis Technology Corp. + * Copyright 2020-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datasourcesummary.datamodel; +package org.sleuthkit.autopsy.contentutils; import java.io.BufferedReader; import java.io.IOException; @@ -60,10 +60,14 @@ class ClosestCityMapper { // singleton instance of this class private static ClosestCityMapper instance = null; + // the logger + private static final java.util.logging.Logger logger = Logger.getLogger(ClosestCityMapper.class.getName()); + /** * Retrieves singleton instance of this class. * * @return The singleton instance of this class. + * * @throws IOException */ static ClosestCityMapper getInstance() throws IOException { @@ -75,10 +79,7 @@ class ClosestCityMapper { } // data structure housing cities - private LatLngMap latLngMap = null; - - // the logger - private final java.util.logging.Logger logger; + private static LatLngMap latLngMap = null; /** * Main Constructor. @@ -86,21 +87,19 @@ class ClosestCityMapper { * @throws IOException */ private ClosestCityMapper() throws IOException { - this( - GeolocationSummary.class.getResourceAsStream(CITIES_CSV_FILENAME), - Logger.getLogger(ClosestCityMapper.class.getName())); + this(ClosestCityMapper.class.getResourceAsStream(CITIES_CSV_FILENAME)); } /** * Main Constructor loading from an input stream. * * @param citiesInputStream The input stream for the csv text file - * containing the cities. - * @param logger The logger to be used with this. + * containing the cities. + * @param logger The logger to be used with this. + * * @throws IOException */ - private ClosestCityMapper(InputStream citiesInputStream, java.util.logging.Logger logger) throws IOException { - this.logger = logger; + private ClosestCityMapper(InputStream citiesInputStream) throws IOException { latLngMap = new LatLngMap(parseCsvLines(citiesInputStream, true)); } @@ -109,9 +108,10 @@ class ClosestCityMapper { * city can be determined. * * @param point The point to locate. + * * @return The closest city or null if no close city can be found. */ - CityRecord findClosest(CityRecord point) { + static CityRecord findClosest(CityRecord point) { return latLngMap.findClosest(point); } @@ -120,9 +120,10 @@ class ClosestCityMapper { * returned. * * @param s The string to parse. + * * @return The double value or null if value cannot be parsed. */ - private Double tryParse(String s) { + private static Double tryParse(String s) { if (s == null) { return null; } @@ -138,11 +139,12 @@ class ClosestCityMapper { * Parses a country name and transforms values like "last, first" to "first * last" (i.e. "Korea, South" becomes "South Korea"). * - * @param orig The original string value. + * @param orig The original string value. * @param lineNum The line number that this country was found. + * * @return The country name. */ - private String parseCountryName(String orig, int lineNum) { + private static String parseCountryName(String orig, int lineNum) { if (StringUtils.isBlank(orig)) { logger.log(Level.WARNING, String.format("No country name determined for line %d.", lineNum)); return null; @@ -159,12 +161,13 @@ class ClosestCityMapper { /** * Parses a row from the csv creating a city record. * - * @param csvRow The row of data where each item in the list is each column - * in the row. + * @param csvRow The row of data where each item in the list is each column + * in the row. * @param lineNum The line number for this csv row. + * * @return The parsed CityRecord or null if none can be determined. */ - private CityRecord getCsvCityRecord(List csvRow, int lineNum) { + private static CityRecord getCsvCityRecord(List csvRow, int lineNum) { if (csvRow == null || csvRow.size() <= MAX_IDX) { logger.log(Level.WARNING, String.format("Row at line number %d is required to have at least %d elements and does not.", lineNum, (MAX_IDX + 1))); return null; @@ -199,11 +202,12 @@ class ClosestCityMapper { /** * Parses a row of the csv into individual column values. * - * @param line The line to parse. + * @param line The line to parse. * @param lineNum The line number in the csv where this line is. + * * @return The list of column values. */ - private List parseCsvLine(String line, int lineNum) { + private static List parseCsvLine(String line, int lineNum) { if (line == null || line.length() <= 0) { logger.log(Level.INFO, String.format("Line at %d had no content", lineNum)); return null; @@ -222,13 +226,15 @@ class ClosestCityMapper { * Parses all lines in the csv file input stream into a list of city * records. * - * @param csvInputStream The csv file input stream. + * @param csvInputStream The csv file input stream. * @param ignoreHeaderRow Whether or not there is a header row in the csv - * file. + * file. + * * @return The list of city records. + * * @throws IOException */ - private List parseCsvLines(InputStream csvInputStream, boolean ignoreHeaderRow) throws IOException { + private static List parseCsvLines(InputStream csvInputStream, boolean ignoreHeaderRow) throws IOException { List cityRecords = new ArrayList<>(); try (BufferedReader reader = new BufferedReader(new InputStreamReader(csvInputStream, "UTF-8"))) { int lineNum = 1; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/GeolocationSummary.java b/Core/src/org/sleuthkit/autopsy/contentutils/GeolocationSummary.java old mode 100644 new mode 100755 similarity index 81% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/GeolocationSummary.java rename to Core/src/org/sleuthkit/autopsy/contentutils/GeolocationSummary.java index d66bbaf30a..81b21b69d6 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/GeolocationSummary.java +++ b/Core/src/org/sleuthkit/autopsy/contentutils/GeolocationSummary.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2020 Basis Technology Corp. + * Copyright 2020-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datasourcesummary.datamodel; +package org.sleuthkit.autopsy.contentutils; import java.io.IOException; import java.util.ArrayList; @@ -31,8 +31,8 @@ import java.util.concurrent.BlockingQueue; import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.commons.lang3.tuple.Pair; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultArtifactUpdateGovernor; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.geolocation.AbstractWaypointFetcher; import org.sleuthkit.autopsy.geolocation.GeoFilter; import org.sleuthkit.autopsy.geolocation.MapWaypoint; @@ -45,7 +45,7 @@ import org.sleuthkit.datamodel.DataSource; /** * Gathers summary data about Geolocation information for a data source. */ -public class GeolocationSummary implements DefaultArtifactUpdateGovernor { +public class GeolocationSummary { /** * A count of hits for a particular city. @@ -59,8 +59,8 @@ public class GeolocationSummary implements DefaultArtifactUpdateGovernor { * Main constructor. * * @param cityRecord The record for the city including name, country, - * and location. - * @param count The number of hits in proximity to that city. + * and location. + * @param count The number of hits in proximity to that city. */ CityRecordCount(CityRecord cityRecord, int count) { this.cityRecord = cityRecord; @@ -69,7 +69,7 @@ public class GeolocationSummary implements DefaultArtifactUpdateGovernor { /** * @return The record for the city including name, country, and - * location. + * location. */ public CityRecord getCityRecord() { return cityRecord; @@ -96,8 +96,8 @@ public class GeolocationSummary implements DefaultArtifactUpdateGovernor { /** * Main constructor. * - * @param mostCommon The list of most common cities seen. - * @param mostRecent The list of most recent cities seen. + * @param mostCommon The list of most common cities seen. + * @param mostRecent The list of most recent cities seen. * @param mostRecentSeen */ CityData(CityCountsList mostCommon, CityCountsList mostRecent, Long mostRecentSeen) { @@ -122,7 +122,7 @@ public class GeolocationSummary implements DefaultArtifactUpdateGovernor { /** * @return The time stamp in seconds from epoch of the most recently - * seen city + * seen city */ public Long getMostRecentSeen() { return mostRecentSeen; @@ -142,10 +142,10 @@ public class GeolocationSummary implements DefaultArtifactUpdateGovernor { /** * Main constructor. * - * @param counts The list of cities and the count of how many points are - * closest to that city. + * @param counts The list of cities and the count of how many points + * are closest to that city. * @param otherCount The count of points where no closest city was - * determined due to not being close enough. + * determined due to not being close enough. */ CityCountsList(List counts, int otherCount) { this.counts = Collections.unmodifiableList(new ArrayList<>(counts)); @@ -154,7 +154,7 @@ public class GeolocationSummary implements DefaultArtifactUpdateGovernor { /** * @return The list of cities and the count of how many points are - * closest to that city. + * closest to that city. */ public List getCounts() { return counts; @@ -162,7 +162,7 @@ public class GeolocationSummary implements DefaultArtifactUpdateGovernor { /** * @return The count of points where no closest city was determined due - * to not being close enough. + * to not being close enough. */ public int getOtherCount() { return otherCount; @@ -183,10 +183,10 @@ public class GeolocationSummary implements DefaultArtifactUpdateGovernor { * Main constructor. * * @param mapWaypoints The way points found for the data source. - * @param tracks A list of sets where each set is a track in the data - * source. - * @param areas A list of areas where each set is an area in the data - * source. + * @param tracks A list of sets where each set is a track in the + * data source. + * @param areas A list of areas where each set is an area in the + * data source. */ private GeoResult(Set mapWaypoints, List> tracks, List> areas) { this.mapWaypoints = mapWaypoints; @@ -238,8 +238,7 @@ public class GeolocationSummary implements DefaultArtifactUpdateGovernor { private static final long DAY_SECS = 24 * 60 * 60; - private final SleuthkitCaseProvider provider; - private final SupplierWithException cityMapper; + private static final SupplierWithException cityMapper = () -> ClosestCityMapper.getInstance(); /** * A supplier of an item T that can throw an exception of type E. @@ -250,40 +249,24 @@ public class GeolocationSummary implements DefaultArtifactUpdateGovernor { * A supplier method that can throw an exception of E. * * @return The object type. + * * @throws E The exception type. */ T get() throws E; } - /** - * Default constructor. - */ - public GeolocationSummary() { - this(() -> ClosestCityMapper.getInstance(), SleuthkitCaseProvider.DEFAULT); - } - - /** - * Main constructor. - * - * @param cityMapper A means of acquiring a ClosestCityMapper that can throw - * an IOException. - * @param provider A means of acquiring a SleuthkitCaseProvider. - */ - public GeolocationSummary(SupplierWithException cityMapper, SleuthkitCaseProvider provider) { - this.cityMapper = cityMapper; - this.provider = provider; + private GeolocationSummary() { } /** * @return Returns all the geolocation artifact types. */ - public List getGeoTypes() { + public static List getGeoTypes() { return GPS_ARTIFACT_TYPES; } - @Override - public Set getArtifactTypeIdsForRefresh() { - return GPS_ARTIFACT_TYPE_IDS; + public static Set getArtifactTypeIdsForRefresh() { + return Collections.unmodifiableSet(GPS_ARTIFACT_TYPE_IDS); } /** @@ -291,13 +274,14 @@ public class GeolocationSummary implements DefaultArtifactUpdateGovernor { * the event where either time is null. * * @param minTime The minimum time. If null is provided, this function will - * return false. - * @param time The time to check. If null is provided and the min time is - * non-null, then this function will return false. + * return false. + * @param time The time to check. If null is provided and the min time is + * non-null, then this function will return false. + * * @return If minTime == null then false. If minTime != null && time == null - * then false. Otherwise time >= minTime. + * then false. Otherwise time >= minTime. */ - private boolean greaterThanOrEqual(Long minTime, Long time) { + private static boolean greaterThanOrEqual(Long minTime, Long time) { if (minTime != null && time != null && time >= minTime) { return true; } else { @@ -310,12 +294,13 @@ public class GeolocationSummary implements DefaultArtifactUpdateGovernor { * a total of waypoints whose time stamp is greater than or equal to * minTime. * - * @param points The list of way points. + * @param points The list of way points. * @param minTime The minimum time for most recent points count. + * * @return A pair where the left value is the total count of way points and - * the right is the total list of way points that are >= minTime. + * the right is the total list of way points that are >= minTime. */ - private Pair getCounts(List points, Long minTime) { + private static Pair getCounts(List points, Long minTime) { if (points == null) { return EMPTY_COUNT; } @@ -332,10 +317,11 @@ public class GeolocationSummary implements DefaultArtifactUpdateGovernor { * the point is null, null is returned. * * @param cityMapper The means of mapping a point to the closest city. - * @param pt The geolocation point. + * @param pt The geolocation point. + * * @return A tuple of the closest city and timestamp in seconds from epoch. */ - private Pair getClosestWithTime(ClosestCityMapper cityMapper, MapWaypoint pt) { + private static Pair getClosestWithTime(ClosestCityMapper cityMapper, MapWaypoint pt) { if (pt == null) { return null; } @@ -351,12 +337,14 @@ public class GeolocationSummary implements DefaultArtifactUpdateGovernor { * into a stream of the unique cities identified in this grouping and the * latest time stamp for each grouping. * - * @param points The points in the grouping. + * @param points The points in the grouping. * @param cityMapper The means of mapping a point to the closest city. + * * @return A stream of tuples where each tuple will be a unique city (or - * null if a closest is not determined) and the latest timestamp for each. + * null if a closest is not determined) and the latest timestamp for + * each. */ - private Stream> reduceGrouping(Set points, ClosestCityMapper cityMapper) { + private static Stream> reduceGrouping(Set points, ClosestCityMapper cityMapper) { if (points == null) { return Stream.empty(); } @@ -367,7 +355,7 @@ public class GeolocationSummary implements DefaultArtifactUpdateGovernor { if (pair == null) { continue; } - + CityRecord city = pair.getLeft(); Long prevTime = timeMapping.get(city); Long curTime = pair.getRight(); @@ -375,7 +363,7 @@ public class GeolocationSummary implements DefaultArtifactUpdateGovernor { timeMapping.put(city, curTime); } } - + return timeMapping.entrySet().stream() .map(e -> Pair.of(e.getKey(), e.getValue())); } @@ -385,20 +373,22 @@ public class GeolocationSummary implements DefaultArtifactUpdateGovernor { * of tuples where each tuple represents a point with the closest city and * the time stamp in seconds from epoch. * - * @param geoResult The result from the Geolocation API. + * @param geoResult The result from the Geolocation API. * @param cityMapper The means of mapping a point to the closest city. + * * @return A list of tuples where each tuple represents a point to be - * counted with a combination of the closest city and the timestamp. + * counted with a combination of the closest city and the timestamp. + * * @throws IOException */ - private Stream> processGeoResult(GeoResult geoResult, ClosestCityMapper cityMapper) { + private static Stream> processGeoResult(GeoResult geoResult, ClosestCityMapper cityMapper) { if (geoResult == null) { return Stream.empty(); } List> areas = (geoResult.getAreas() == null) ? Collections.emptyList() : geoResult.getAreas(); List> tracks = (geoResult.getTracks() == null) ? Collections.emptyList() : geoResult.getTracks(); - + Stream> reducedGroupings = Stream.of(areas, tracks) .flatMap((groupingList) -> groupingList.stream()) .flatMap((grouping) -> reduceGrouping(grouping, cityMapper)); @@ -407,7 +397,7 @@ public class GeolocationSummary implements DefaultArtifactUpdateGovernor { .flatMap((groupingList) -> groupingList.stream()) .flatMap((group) -> group.stream()) .collect(Collectors.toSet()); - + Set pointSet = geoResult.getMapWaypoints() == null ? Collections.emptySet() : geoResult.getMapWaypoints(); Stream> citiesForPoints = pointSet.stream() // it appears that AbstractWaypointFetcher.handleFilteredWaypointSet returns all points @@ -423,19 +413,19 @@ public class GeolocationSummary implements DefaultArtifactUpdateGovernor { * number of found hits (i.e. most hits is first index). * * @param dataSource The data source. - * @param daysCount Number of days to go back. - * @param maxCount Maximum number of results. + * @param daysCount Number of days to go back. + * @param maxCount Maximum number of results. * * @return The sorted list. * - * @throws SleuthkitCaseProviderException + * @throws NoCurrentCaseException * @throws GeoLocationDataException * @throws InterruptedException */ - public CityData getCityCounts(DataSource dataSource, int daysCount, int maxCount) - throws SleuthkitCaseProviderException, GeoLocationDataException, InterruptedException, IOException { + public static CityData getCityCounts(DataSource dataSource, int daysCount, int maxCount) + throws NoCurrentCaseException, GeoLocationDataException, InterruptedException, IOException { - ClosestCityMapper closestCityMapper = this.cityMapper.get(); + ClosestCityMapper closestCityMapper = cityMapper.get(); GeoResult geoResult = getGeoResult(dataSource); List> dataSourcePoints = processGeoResult(geoResult, closestCityMapper) .collect(Collectors.toList()); @@ -507,9 +497,10 @@ public class GeolocationSummary implements DefaultArtifactUpdateGovernor { * Main constructor. * * @param asyncResult Geolocation fetches results in a callback which is - * already handled by other mechanisms in data source summary. The - * BlockingQueue blocks until a result is received from geolocation. - * @param filters The applicable filters for geolocation. + * already handled by other mechanisms in data source + * summary. The BlockingQueue blocks until a result + * is received from geolocation. + * @param filters The applicable filters for geolocation. */ public PointFetcher(BlockingQueue asyncResult, GeoFilter filters) { super(filters); @@ -531,13 +522,15 @@ public class GeolocationSummary implements DefaultArtifactUpdateGovernor { * Fetches all GPS data for the data source from the current case. * * @param dataSource The data source. + * * @return The GPS data pertaining to the data source. - * @throws SleuthkitCaseProviderException + * + * @throws NoCurrentCaseException * @throws GeoLocationDataException * @throws InterruptedException */ - private GeoResult getGeoResult(DataSource dataSource) - throws SleuthkitCaseProviderException, GeoLocationDataException, InterruptedException { + private static GeoResult getGeoResult(DataSource dataSource) + throws NoCurrentCaseException, GeoLocationDataException, InterruptedException { // make asynchronous callback synchronous (the callback nature will be handled in a different level) // see the following: https://stackoverflow.com/questions/20659961/java-synchronous-callback @@ -545,7 +538,7 @@ public class GeolocationSummary implements DefaultArtifactUpdateGovernor { GeoFilter geoFilter = new GeoFilter(true, false, 0, Arrays.asList(dataSource), GPS_ARTIFACT_TYPES); - WaypointBuilder.getAllWaypoints(provider.get(), + WaypointBuilder.getAllWaypoints(Case.getCurrentCaseThrows().getSleuthkitCase(), Arrays.asList(dataSource), GPS_ARTIFACT_TYPES, true, diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/LatLngMap.java b/Core/src/org/sleuthkit/autopsy/contentutils/LatLngMap.java similarity index 95% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/LatLngMap.java rename to Core/src/org/sleuthkit/autopsy/contentutils/LatLngMap.java index 01032f61da..9d026ab11d 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/LatLngMap.java +++ b/Core/src/org/sleuthkit/autopsy/contentutils/LatLngMap.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2020 Basis Technology Corp. + * Copyright 2020-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datasourcesummary.datamodel; +package org.sleuthkit.autopsy.contentutils; import java.util.Collection; import java.util.List; @@ -64,8 +64,8 @@ class LatLngMap { * Main contructor. * * @param pointsToAdd The points to be added to the data structure. - * @param bucketSize The size of a grid square in kilometers. So, if this - * value is 100, each sqaure will be a 100 x 100 km. + * @param bucketSize The size of a grid square in kilometers. So, if this + * value is 100, each sqaure will be a 100 x 100 km. */ LatLngMap(List pointsToAdd, double bucketSize) { this.bucketSize = bucketSize; @@ -86,6 +86,7 @@ class LatLngMap { * closest neighboring buckets. * * @param point The point to calculate the bucket location pair. + * * @return The pair that was determined. */ private Pair getBucketLocation(XYZPoint point) { @@ -106,6 +107,7 @@ class LatLngMap { * Finds closest point within (.5 * bucketSize) distance. * * @param point The point for which to find closest. + * * @return Returns the found point. */ E findClosest(E point) { @@ -132,9 +134,10 @@ class LatLngMap { /** * Within the specific bucket, finds the closest point if any exists. * - * @param x The x axis bucket. - * @param y The y axis bucket. + * @param x The x axis bucket. + * @param y The y axis bucket. * @param point The point to search for. + * * @return The point, if any, that was found. */ private E findClosestInBucket(int x, int y, E point) { diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/worldcities.csv b/Core/src/org/sleuthkit/autopsy/contentutils/worldcities.csv similarity index 100% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/worldcities.csv rename to Core/src/org/sleuthkit/autopsy/contentutils/worldcities.csv diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/GeolocationSummaryGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/GeolocationSummaryGetter.java new file mode 100644 index 0000000000..9165f43561 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/GeolocationSummaryGetter.java @@ -0,0 +1,81 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2020-2021 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.datasourcesummary.datamodel; + +import java.io.IOException; +import java.util.List; +import java.util.Set; +import org.sleuthkit.autopsy.contentutils.GeolocationSummary; +import org.sleuthkit.autopsy.contentutils.GeolocationSummary.CityData; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultArtifactUpdateGovernor; +import org.sleuthkit.autopsy.geolocation.datamodel.GeoLocationDataException; +import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; +import org.sleuthkit.datamodel.DataSource; +import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; + +/** + * Wrapper class for converting + * org.sleuthkit.autopsy.contentutils.GeolocationSummary functionality into a + * DefaultArtifactUpdateGovernor used by GeolocationPanel tab. + */ +public class GeolocationSummaryGetter implements DefaultArtifactUpdateGovernor { + + /** + * Default constructor. + */ + public GeolocationSummaryGetter() { + } + + /** + * @return Returns all the geolocation artifact types. + */ + public List getGeoTypes() { + return GeolocationSummary.getGeoTypes(); + } + + @Override + public Set getArtifactTypeIdsForRefresh() { + return GeolocationSummary.getArtifactTypeIdsForRefresh(); + } + + /** + * Get this list of hits per city where the list is sorted descending by + * number of found hits (i.e. most hits is first index). + * + * @param dataSource The data source. + * @param daysCount Number of days to go back. + * @param maxCount Maximum number of results. + * + * @return The sorted list. + * + * @throws SleuthkitCaseProviderException + * @throws GeoLocationDataException + * @throws InterruptedException + */ + public CityData getCityCounts(DataSource dataSource, int daysCount, int maxCount) + throws SleuthkitCaseProviderException, GeoLocationDataException, InterruptedException, IOException { + + try { + return GeolocationSummary.getCityCounts(dataSource, daysCount, maxCount); + } catch (NoCurrentCaseException ex) { + throw new SleuthkitCaseProviderException("No currently open case.", ex); + } + } +} diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/GeolocationPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/GeolocationPanel.java index 595209f064..3e5687255e 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/GeolocationPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/GeolocationPanel.java @@ -34,11 +34,11 @@ import org.openide.util.NbBundle.Messages; import org.openide.util.actions.CallableSystemAction; import org.openide.windows.TopComponent; import org.openide.windows.WindowManager; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.GeolocationSummary; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.GeolocationSummary.CityCountsList; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.GeolocationSummary.CityData; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.GeolocationSummary.CityRecordCount; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.CityRecord; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.GeolocationSummaryGetter; +import org.sleuthkit.autopsy.contentutils.GeolocationSummary.CityCountsList; +import org.sleuthkit.autopsy.contentutils.GeolocationSummary.CityData; +import org.sleuthkit.autopsy.contentutils.GeolocationSummary.CityRecordCount; +import org.sleuthkit.autopsy.contentutils.CityRecord; import org.sleuthkit.autopsy.datasourcesummary.uiutils.ColumnModel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; @@ -78,9 +78,9 @@ public class GeolocationPanel extends BaseDataSourceSummaryPanel { * Main constructor. * * @param mostRecentData The data to be displayed in the most recent - * table. + * table. * @param mostCommonData The data to be displayed in the most common - * table. + * table. */ GeolocationViewModel(List> mostRecentData, List> mostCommonData) { this.mostRecentData = mostRecentData; @@ -146,7 +146,7 @@ public class GeolocationPanel extends BaseDataSourceSummaryPanel { private final IngestRunningLabel ingestRunningLabel = new IngestRunningLabel(); - private final GeolocationSummary whereUsedData; + private final GeolocationSummaryGetter whereUsedData; private final DataFetcher geolocationFetcher; @@ -154,15 +154,15 @@ public class GeolocationPanel extends BaseDataSourceSummaryPanel { * Main constructor. */ public GeolocationPanel() { - this(new GeolocationSummary()); + this(new GeolocationSummaryGetter()); } /** * Main constructor. * - * @param whereUsedData The GeolocationSummary instance to use. + * @param whereUsedData The GeolocationSummaryGetter instance to use. */ - public GeolocationPanel(GeolocationSummary whereUsedData) { + public GeolocationPanel(GeolocationSummaryGetter whereUsedData) { super(whereUsedData); this.whereUsedData = whereUsedData; @@ -182,7 +182,7 @@ public class GeolocationPanel extends BaseDataSourceSummaryPanel { * Means of rendering data to be shown in the tables. * * @param result The result of fetching data for a data source and - * processing into view model data. + * processing into view model data. */ private void handleData(DataFetchResult result) { showCityContent(DataFetchResult.getSubResult(result, (dr) -> dr.getMostCommonData()), mostCommonTable, commonViewInGeolocationBtn); @@ -193,6 +193,7 @@ public class GeolocationPanel extends BaseDataSourceSummaryPanel { * Retrieves the city name to display from the record. * * @param record The record for the city to display. + * * @return The display name (city, country). */ private static String getCityName(CityRecord record) { @@ -220,6 +221,7 @@ public class GeolocationPanel extends BaseDataSourceSummaryPanel { * formats the city name). * * @param cityCount The CityRecordCount representing a row. + * * @return The city/count pair to be displayed as a row. */ private Pair formatRecord(CityRecordCount cityCount) { @@ -238,7 +240,8 @@ public class GeolocationPanel extends BaseDataSourceSummaryPanel { * 'unknown'). * * @param countsList The CityCountsList object representing the data to be - * displayed in the table. + * displayed in the table. + * * @return The list of city/count tuples to be displayed as a row. */ private List> formatList(CityCountsList countsList) { @@ -262,10 +265,11 @@ public class GeolocationPanel extends BaseDataSourceSummaryPanel { } /** - * Converts CityData from GeolocationSummary into data that can be directly - * put into table in this panel. + * Converts CityData from GeolocationSummaryGetter into data that can be + * directly put into table in this panel. * * @param cityData The city data. + * * @return The view model data. */ private GeolocationViewModel convertToViewModel(CityData cityData) { @@ -279,8 +283,8 @@ public class GeolocationPanel extends BaseDataSourceSummaryPanel { /** * Shows data in a particular table. * - * @param result The result to be displayed in the table. - * @param table The table where the data will be displayed. + * @param result The result to be displayed in the table. + * @param table The table where the data will be displayed. * @param goToGeolocation The corresponding geolocation navigation button. */ private void showCityContent(DataFetchResult>> result, JTablePanel> table, JButton goToGeolocation) { @@ -295,9 +299,9 @@ public class GeolocationPanel extends BaseDataSourceSummaryPanel { * Action to open the geolocation window. * * @param dataSource The data source for which the window should filter. - * @param daysLimit The limit for how recently the waypoints should be (for - * most recent table) or null for most recent filter to not be set (for most - * common table). + * @param daysLimit The limit for how recently the waypoints should be (for + * most recent table) or null for most recent filter to + * not be set (for most common table). */ private void openGeolocationWindow(DataSource dataSource, Integer daysLimit) { // notify dialog (if in dialog) should close. @@ -348,20 +352,6 @@ public class GeolocationPanel extends BaseDataSourceSummaryPanel { onNewDataSource(dataFetchComponents, tables, dataSource); } - /* ELTODO - @Override - List getExports(DataSource dataSource) { - GeolocationViewModel model = getFetchResult(geolocationFetcher, "Geolocation sheets", dataSource); - if (model == null) { - return Collections.emptyList(); - } - - return Arrays.asList( - getTableExport(DEFAULT_TEMPLATE, Bundle.GeolocationPanel_mostRecent_tabName(), model.getMostRecentData()), - getTableExport(DEFAULT_TEMPLATE, Bundle.GeolocationPanel_mostCommon_tabName(), model.getMostCommonData()) - ); - }*/ - @Override public void close() { ingestRunningLabel.unregister(); diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED index d6ca349440..1465a25316 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED @@ -7,6 +7,7 @@ ExcelExportAction_exportToXLSX_beginExport=Beginning Export... ExcelExportAction_exportToXLSX_gatheringAnalysisData=Fetching Analysis Data ExcelExportAction_exportToXLSX_gatheringContainerData=Fetching Container & Image Data ExcelExportAction_exportToXLSX_gatheringFileData=Fetching File and MIME Type Data +ExcelExportAction_exportToXLSX_gatheringGeoData=Fetching Geolocation Data ExcelExportAction_exportToXLSX_gatheringPastData=Fetching Historical Data ExcelExportAction_exportToXLSX_gatheringRecentActivityData=Fetching Recent Activity Data ExcelExportAction_exportToXLSX_gatheringTimelineData=Fetching Timeline Data @@ -35,6 +36,11 @@ ExportContainerInfo_export_timeZone=Time Zone: ExportContainerInfo_export_unallocatedSize=Unallocated Space: ExportContainerInfo_setFieldsForNonImageDataSource_na=N/A ExportContainerInfo_tabName=Container +ExportGeolocation_cityColumn_title=Closest City +ExportGeolocation_countColumn_title=Count +ExportGeolocation_mostCommon_tabName=Most Common Cities +ExportGeolocation_mostRecent_tabName=Most Recent Cities +ExportGeolocation_unknownRow_title=Unknown ExportPastCases_caseColumn_title=Case ExportPastCases_countColumn_title=Count ExportPastCases_notableFileTable_tabName=Cases with Common Notable diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java index 44879e741f..676b7086a1 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java @@ -99,6 +99,7 @@ class ExcelExportAction { "ExcelExportAction_exportToXLSX_gatheringAnalysisData=Fetching Analysis Data", "ExcelExportAction_exportToXLSX_gatheringPastData=Fetching Historical Data", "ExcelExportAction_exportToXLSX_gatheringUserData=Fetching User Activity Data", + "ExcelExportAction_exportToXLSX_gatheringGeoData=Fetching Geolocation Data", "ExcelExportAction_exportToXLSX_writingToFile=Writing to File...",}) void exportToXLSX(ReportProgressPanel progressPanel, DataSource dataSource, String baseReportDir) @@ -167,6 +168,14 @@ class ExcelExportAction { sheetExports.addAll(exports); } + // Export geolocation data + progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_gatheringGeoData()); + progressPanel.setProgress(7); + exports = ExportGeolocation.getExports(dataSource); + if (exports != null) { + sheetExports.addAll(exports); + } + progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_writingToFile()); progressPanel.setProgress(9); ExcelExport.writeExcel(sheetExports, reportFile); diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportGeolocation.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportGeolocation.java new file mode 100755 index 0000000000..1ea449b073 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportGeolocation.java @@ -0,0 +1,223 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit 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.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.Pair; +import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.contentutils.GeolocationSummary.CityCountsList; +import org.sleuthkit.autopsy.contentutils.GeolocationSummary.CityData; +import org.sleuthkit.autopsy.contentutils.GeolocationSummary.CityRecordCount; +import org.sleuthkit.autopsy.contentutils.CityRecord; +import org.sleuthkit.autopsy.contentutils.GeolocationSummary; +import static org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExportAction.getFetchResult; +import static org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExportAction.getTableExport; +import org.sleuthkit.datamodel.DataSource; + +/** + * Class to export information about a data source's geolocation data. + */ +@Messages({ + "ExportGeolocation_cityColumn_title=Closest City", + "ExportGeolocation_countColumn_title=Count", + "ExportGeolocation_unknownRow_title=Unknown", + "ExportGeolocation_mostCommon_tabName=Most Common Cities", + "ExportGeolocation_mostRecent_tabName=Most Recent Cities",}) +class ExportGeolocation { + + /** + * Object encapsulating geolocation data. + */ + private static class GeolocationData { + + private final List> mostRecentData; + private final List> mostCommonData; + + /** + * Main constructor. + * + * @param mostRecentData The data to be displayed in the most recent + * tab. + * @param mostCommonData The data to be displayed in the most common + * tab. + */ + GeolocationData(List> mostRecentData, List> mostCommonData) { + this.mostRecentData = mostRecentData; + this.mostCommonData = mostCommonData; + } + + /** + * Returns the data to be displayed in the most recent tab. + * + * @return The data to be displayed in the most recent tab. + */ + List> getMostRecentData() { + return mostRecentData; + } + + /** + * Returns the data to be displayed in the most common tab. + * + * @return The data to be displayed in the most common tab. + */ + List> getMostCommonData() { + return mostCommonData; + } + } + + private static final int DAYS_COUNT = 30; + private static final int MAX_COUNT = 10; + + // The column indicating the city + private static final ColumnModel, DefaultCellModel> CITY_COL = new ColumnModel<>( + Bundle.ExportGeolocation_cityColumn_title(), + (pair) -> new DefaultCellModel<>(pair.getLeft()), + 300 + ); + + // The column indicating the count of points seen close to that city + private static final ColumnModel, DefaultCellModel> COUNT_COL = new ColumnModel<>( + Bundle.ExportGeolocation_countColumn_title(), + (pair) -> new DefaultCellModel<>(pair.getRight()), + 100 + ); + + private static final List, DefaultCellModel>> DEFAULT_TEMPLATE = Arrays.asList( + CITY_COL, + COUNT_COL + ); + + private ExportGeolocation() { + } + + /** + * Retrieves the city name to display from the record. + * + * @param record The record for the city to display. + * + * @return The display name (city, country). + */ + private static String getCityName(CityRecord record) { + if (record == null) { + return null; + } + + List cityIdentifiers = Stream.of(record.getCityName(), record.getState(), record.getCountry()) + .filter(StringUtils::isNotBlank) + .collect(Collectors.toList()); + + if (cityIdentifiers.size() == 1) { + return cityIdentifiers.get(0); + } else if (cityIdentifiers.size() == 2) { + return String.format("%s, %s", cityIdentifiers.get(0), cityIdentifiers.get(1)); + } else if (cityIdentifiers.size() >= 3) { + return String.format("%s, %s; %s", cityIdentifiers.get(0), cityIdentifiers.get(1), cityIdentifiers.get(2)); + } + + return null; + } + + /** + * Formats one record to be displayed as a row in the tab (specifically, + * formats the city name). + * + * @param cityCount The CityRecordCount representing a row. + * + * @return The city/count pair to be displayed as a row. + */ + private static Pair formatRecord(CityRecordCount cityCount) { + if (cityCount == null) { + return null; + } + + String cityName = getCityName(cityCount.getCityRecord()); + int count = cityCount.getCount(); + return Pair.of(cityName, count); + } + + /** + * Formats a list of records to be displayed in a tab (specifically, + * includes the count of points where no closest city could be determined as + * 'unknown'). + * + * @param countsList The CityCountsList object representing the data to be + * displayed in the tab. + * + * @return The list of city/count tuples to be displayed as a row. + */ + private static List> formatList(CityCountsList countsList) { + if (countsList == null) { + return Collections.emptyList(); + } + + Stream countsStream = ((countsList.getCounts() == null) + ? new ArrayList() + : countsList.getCounts()).stream(); + + Stream> pairStream = countsStream.map((r) -> formatRecord(r)); + + Pair unknownRecord = Pair.of(Bundle.ExportGeolocation_unknownRow_title(), countsList.getOtherCount()); + + return Stream.concat(pairStream, Stream.of(unknownRecord)) + .filter((p) -> p != null && p.getRight() != null && p.getRight() > 0) + .sorted((a, b) -> -Integer.compare(a.getRight(), b.getRight())) + .limit(MAX_COUNT) + .collect(Collectors.toList()); + } + + /** + * Converts CityData from GeolocationSummaryGetter into data that can be + * directly put into tab in this panel. + * + * @param cityData The city data. + * + * @return The geolocation data. + */ + private static GeolocationData convertToViewModel(CityData cityData) { + if (cityData == null) { + return new GeolocationData(Collections.emptyList(), Collections.emptyList()); + } else { + return new GeolocationData(formatList(cityData.getMostRecent()), formatList(cityData.getMostCommon())); + } + } + + static List getExports(DataSource dataSource) { + + DataFetcher geolocationFetcher = (ds) -> convertToViewModel(GeolocationSummary.getCityCounts(ds, DAYS_COUNT, MAX_COUNT)); + + GeolocationData model + = getFetchResult(geolocationFetcher, "Geolocation sheets", dataSource); + if (model == null) { + return Collections.emptyList(); + } + + return Arrays.asList(getTableExport(DEFAULT_TEMPLATE, + Bundle.ExportGeolocation_mostRecent_tabName(), model.getMostRecentData()), + getTableExport(DEFAULT_TEMPLATE, + Bundle.ExportGeolocation_mostCommon_tabName(), model.getMostCommonData()) + ); + } + +} diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportUserActivity.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportUserActivity.java index c89c4f996a..ba9ff135ce 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportUserActivity.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportUserActivity.java @@ -40,7 +40,7 @@ import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopWebSearchResult import static org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExportAction.getTableExport; /** - * A panel to display user activity. + * Class to export user activity present in the specified DataSource. */ @Messages({ "ExportUserActivity_tab_title=User Activity", diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/datasourcesummary/UserActivitySummaryTests.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/datasourcesummary/UserActivitySummaryTests.java index 10c42eebbb..eb14d53e51 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/datasourcesummary/UserActivitySummaryTests.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/datasourcesummary/UserActivitySummaryTests.java @@ -27,7 +27,7 @@ import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummaryGetter; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummaryGetter.TopDomainsResult; +import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopDomainsResult; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.TskCoreException; diff --git a/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummaryTest.java b/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummaryTest.java index 216b1b99c5..787153543c 100644 --- a/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummaryTest.java +++ b/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummaryTest.java @@ -44,11 +44,11 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceSummaryMockUtils.getArtifactsTSKMock; import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummaryGetter.TopAccountResult; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummaryGetter.TopDeviceAttachedResult; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummaryGetter.TopDomainsResult; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummaryGetter.TopProgramsResult; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummaryGetter.TopWebSearchResult; +import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopAccountResult; +import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopDeviceAttachedResult; +import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopDomainsResult; +import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopProgramsResult; +import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopWebSearchResult; import org.sleuthkit.autopsy.testutils.TskMockUtils; import org.sleuthkit.autopsy.texttranslation.NoServiceProviderException; import org.sleuthkit.autopsy.texttranslation.TextTranslationService; @@ -133,11 +133,7 @@ public class UserActivitySummaryTest { private static UserActivitySummaryGetter getTestClass(SleuthkitCase tskCase, boolean hasTranslation, Function translateFunction) throws NoServiceProviderException, TranslationException { - return new UserActivitySummaryGetter( - () -> tskCase, - TskMockUtils.getTextTranslationService(translateFunction, hasTranslation), - TskMockUtils.getJavaLogger("UNIT TEST LOGGER") - ); + return new UserActivitySummaryGetter(); } private void testMinCount(DataFunction funct, String id) @@ -433,11 +429,7 @@ public class UserActivitySummaryTest { // set up a mock TextTranslationService returning a translation TextTranslationService translationService = TskMockUtils.getTextTranslationService(translator, hasProvider); - UserActivitySummaryGetter summary = new UserActivitySummaryGetter( - () -> tskPair.getLeft(), - translationService, - TskMockUtils.getJavaLogger("UNIT TEST LOGGER") - ); + UserActivitySummaryGetter summary = new UserActivitySummaryGetter(); List results = summary.getMostRecentWebSearches(ds, queries.size()); From a08847583ccd71302949d966c2cef499752cfe09 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Tue, 10 Aug 2021 14:28:44 -0400 Subject: [PATCH 19/33] Refactored ingest history tab --- .../contentutils/GeolocationSummary.java | 4 +- .../ui/Bundle.properties-MERGED | 6 -- .../datasourcesummary/ui/TypesPanel.java | 61 ------------------- .../Bundle.properties-MERGED | 7 +++ .../ExcelExportAction.java | 9 +++ .../ExportIngestHistory.java} | 40 ++++++------ 6 files changed, 37 insertions(+), 90 deletions(-) rename Core/src/org/sleuthkit/autopsy/{datasourcesummary/ui/IngestJobExcelExport.java => report/modules/datasourcesummaryexport/ExportIngestHistory.java} (86%) diff --git a/Core/src/org/sleuthkit/autopsy/contentutils/GeolocationSummary.java b/Core/src/org/sleuthkit/autopsy/contentutils/GeolocationSummary.java index 81b21b69d6..ea3ffec08c 100755 --- a/Core/src/org/sleuthkit/autopsy/contentutils/GeolocationSummary.java +++ b/Core/src/org/sleuthkit/autopsy/contentutils/GeolocationSummary.java @@ -243,7 +243,7 @@ public class GeolocationSummary { /** * A supplier of an item T that can throw an exception of type E. */ - public interface SupplierWithException { + interface SupplierWithException { /** * A supplier method that can throw an exception of E. @@ -502,7 +502,7 @@ public class GeolocationSummary { * is received from geolocation. * @param filters The applicable filters for geolocation. */ - public PointFetcher(BlockingQueue asyncResult, GeoFilter filters) { + PointFetcher(BlockingQueue asyncResult, GeoFilter filters) { super(filters); this.asyncResult = asyncResult; } diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties-MERGED index b3c57b15dc..27a706c4a0 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties-MERGED @@ -62,12 +62,6 @@ GeolocationPanel_mostCommon_tabName=Most Common Cities GeolocationPanel_mostRecent_tabName=Most Recent Cities GeolocationPanel_onNoCrIngest_message=No results will be shown because the GPX Parser was not run. GeolocationPanel_unknownRow_title=Unknown -IngestJobExcelExport_endTimeColumn=End Time -IngestJobExcelExport_ingestStatusTimeColumn=Ingest Status -IngestJobExcelExport_moduleNameTimeColumn=Module Name -IngestJobExcelExport_sheetName=Ingest History -IngestJobExcelExport_startTimeColumn=Start Time -IngestJobExcelExport_versionColumn=Module Version PastCasesPanel_caseColumn_title=Case PastCasesPanel_countColumn_title=Count PastCasesPanel_notableFileTable_tabName=Cases with Common Notable diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java index a5040a355e..d892b4a9c4 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java @@ -327,67 +327,6 @@ class TypesPanel extends BaseDataSourceSummaryPanel { } } - /** - * 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. - */ - /* ELTODO private static KeyValueItemExportable getStrExportable(DataFetcher fetcher, String key, DataSource dataSource) { - String result = 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. - */ - /* ELTODOprivate static KeyValueItemExportable getCountExportable(DataFetcher fetcher, String key, DataSource dataSource) { - Long count = getFetchResult(fetcher, "Types", dataSource); - return (count == null) ? null : new KeyValueItemExportable(key, - new DefaultCellModel(count, COMMA_FORMATTER::format, COMMA_FORMAT_STR)); - } - - /* ELTODO - @Override - List getExports(DataSource dataSource) { - if (dataSource == null) { - return Collections.emptyList(); - } - - // Retrieve data to create the types pie chart - TypesPieChartData typesData = TypesPanel.getFetchResult(typesFetcher, "Types", dataSource); - PieChartExport typesChart = (typesData == null || !typesData.isUsefulContent()) ? null : - new PieChartExport( - Bundle.TypesPanel_fileMimeTypesChart_title(), - Bundle.TypesPanel_fileMimeTypesChart_valueLabel(), - "#,###", - Bundle.TypesPanel_fileMimeTypesChart_title(), - typesData.getPieSlices()); - - return Arrays.asList(new ExcelSpecialFormatExport(Bundle.TypesPanel_excelTabName(), - Stream.of( - getStrExportable(usageFetcher, Bundle.TypesPanel_usageLabel_title(), dataSource), - getStrExportable(osFetcher, Bundle.TypesPanel_osLabel_title(), dataSource), - new KeyValueItemExportable(Bundle.TypesPanel_sizeLabel_title(), - SizeRepresentationUtil.getBytesCell(getFetchResult(sizeFetcher, "Types", dataSource))), - typesChart, - getCountExportable(allocatedFetcher, Bundle.TypesPanel_filesByCategoryTable_allocatedRow_title(), dataSource), - getCountExportable(unallocatedFetcher, Bundle.TypesPanel_filesByCategoryTable_unallocatedRow_title(), dataSource), - getCountExportable(slackFetcher, Bundle.TypesPanel_filesByCategoryTable_slackRow_title(), dataSource), - getCountExportable(directoriesFetcher, Bundle.TypesPanel_filesByCategoryTable_directoryRow_title(), dataSource)) - .filter(sheet -> sheet != null) - .collect(Collectors.toList()) - )); - }*/ - /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED index 1465a25316..e9991129ff 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED @@ -8,6 +8,7 @@ ExcelExportAction_exportToXLSX_gatheringAnalysisData=Fetching Analysis Data ExcelExportAction_exportToXLSX_gatheringContainerData=Fetching Container & Image Data ExcelExportAction_exportToXLSX_gatheringFileData=Fetching File and MIME Type Data ExcelExportAction_exportToXLSX_gatheringGeoData=Fetching Geolocation Data +ExcelExportAction_exportToXLSX_gatheringIngestData=Fetching Ingest History Data ExcelExportAction_exportToXLSX_gatheringPastData=Fetching Historical Data ExcelExportAction_exportToXLSX_gatheringRecentActivityData=Fetching Recent Activity Data ExcelExportAction_exportToXLSX_gatheringTimelineData=Fetching Timeline Data @@ -41,6 +42,12 @@ ExportGeolocation_countColumn_title=Count ExportGeolocation_mostCommon_tabName=Most Common Cities ExportGeolocation_mostRecent_tabName=Most Recent Cities ExportGeolocation_unknownRow_title=Unknown +ExportIngestHistory_endTimeColumn=End Time +ExportIngestHistory_ingestStatusTimeColumn=Ingest Status +ExportIngestHistory_moduleNameTimeColumn=Module Name +ExportIngestHistory_sheetName=Ingest History +ExportIngestHistory_startTimeColumn=Start Time +ExportIngestHistory_versionColumn=Module Version ExportPastCases_caseColumn_title=Case ExportPastCases_countColumn_title=Count ExportPastCases_notableFileTable_tabName=Cases with Common Notable diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java index 676b7086a1..d6a408766f 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java @@ -100,6 +100,7 @@ class ExcelExportAction { "ExcelExportAction_exportToXLSX_gatheringPastData=Fetching Historical Data", "ExcelExportAction_exportToXLSX_gatheringUserData=Fetching User Activity Data", "ExcelExportAction_exportToXLSX_gatheringGeoData=Fetching Geolocation Data", + "ExcelExportAction_exportToXLSX_gatheringIngestData=Fetching Ingest History Data", "ExcelExportAction_exportToXLSX_writingToFile=Writing to File...",}) void exportToXLSX(ReportProgressPanel progressPanel, DataSource dataSource, String baseReportDir) @@ -176,6 +177,14 @@ class ExcelExportAction { sheetExports.addAll(exports); } + // Export ingest history + progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_gatheringIngestData()); + progressPanel.setProgress(8); + exports = ExportIngestHistory.getExports(dataSource); + if (exports != null) { + sheetExports.addAll(exports); + } + progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_writingToFile()); progressPanel.setProgress(9); ExcelExport.writeExcel(sheetExports, reportFile); diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/IngestJobExcelExport.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportIngestHistory.java similarity index 86% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/IngestJobExcelExport.java rename to Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportIngestHistory.java index 5ec92353e2..95c38f2162 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/IngestJobExcelExport.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportIngestHistory.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datasourcesummary.ui; +package org.sleuthkit.autopsy.report.modules.datasourcesummaryexport; import java.text.DateFormat; import java.text.SimpleDateFormat; @@ -34,25 +34,24 @@ import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ColumnModel; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultCellModel; +import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExport.ExcelSheetExport; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.IngestJobInfo; import org.sleuthkit.datamodel.IngestModuleInfo; import org.sleuthkit.datamodel.TskCoreException; /** - * Class that handles exporting information in IngestJobInfoPanel to excel. + * Class that handles exporting ingest job information to excel. */ @Messages({ - "IngestJobExcelExport_startTimeColumn=Start Time", - "IngestJobExcelExport_endTimeColumn=End Time", - "IngestJobExcelExport_ingestStatusTimeColumn=Ingest Status", - "IngestJobExcelExport_moduleNameTimeColumn=Module Name", - "IngestJobExcelExport_versionColumn=Module Version", - "IngestJobExcelExport_sheetName=Ingest History" + "ExportIngestHistory_startTimeColumn=Start Time", + "ExportIngestHistory_endTimeColumn=End Time", + "ExportIngestHistory_ingestStatusTimeColumn=Ingest Status", + "ExportIngestHistory_moduleNameTimeColumn=Module Name", + "ExportIngestHistory_versionColumn=Module Version", + "ExportIngestHistory_sheetName=Ingest History" }) -class IngestJobExcelExport { // ELTODO remove this class +class ExportIngestHistory { /** * An entry to display in an excel export. @@ -118,26 +117,26 @@ class IngestJobExcelExport { // ELTODO remove this class } } - private static final Logger logger = Logger.getLogger(IngestJobExcelExport.class.getName()); + private static final Logger logger = Logger.getLogger(ExportIngestHistory.class.getName()); private static final String DATETIME_FORMAT_STR = "yyyy/MM/dd HH:mm:ss"; private static final DateFormat DATETIME_FORMAT = new SimpleDateFormat(DATETIME_FORMAT_STR, Locale.getDefault()); // columns in the excel export table to be created. private static final List>> COLUMNS = Arrays.asList( new ColumnModel<>( - Bundle.IngestJobExcelExport_startTimeColumn(), + Bundle.ExportIngestHistory_startTimeColumn(), (entry) -> getDateCell(entry.getStartTime())), new ColumnModel<>( - Bundle.IngestJobExcelExport_endTimeColumn(), + Bundle.ExportIngestHistory_endTimeColumn(), (entry) -> getDateCell(entry.getEndTime())), new ColumnModel<>( - Bundle.IngestJobExcelExport_ingestStatusTimeColumn(), + Bundle.ExportIngestHistory_ingestStatusTimeColumn(), (entry) -> new DefaultCellModel<>(entry.getStatus())), new ColumnModel<>( - Bundle.IngestJobExcelExport_moduleNameTimeColumn(), + Bundle.ExportIngestHistory_moduleNameTimeColumn(), (entry) -> new DefaultCellModel<>(entry.getIngestModule())), new ColumnModel<>( - Bundle.IngestJobExcelExport_versionColumn(), + Bundle.ExportIngestHistory_versionColumn(), (entry) -> new DefaultCellModel<>(entry.getIngestModuleVersion())) ); @@ -209,7 +208,6 @@ class IngestJobExcelExport { // ELTODO remove this class * @param dataSource The data source. * @return The list of sheets to be included in an export. */ - /* ELTODO static List getExports(DataSource dataSource) { if (dataSource == null) { return Collections.emptyList(); @@ -244,9 +242,9 @@ class IngestJobExcelExport { // ELTODO remove this class .filter(item -> item != null) .collect(Collectors.toList()); - return Arrays.asList(new ExcelTableExport<>(Bundle.IngestJobExcelExport_sheetName(), COLUMNS, toDisplay)); - }*/ + return Arrays.asList(new ExcelTableExport<>(Bundle.ExportIngestHistory_sheetName(), COLUMNS, toDisplay)); + } - private IngestJobExcelExport() { + private ExportIngestHistory() { } } From 9ad3567c7ce1a152f3ba59560ca7d236fc365553 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Tue, 10 Aug 2021 14:55:31 -0400 Subject: [PATCH 20/33] Minor --- .../datasourcesummaryexport/ExportIngestHistory.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportIngestHistory.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportIngestHistory.java index 95c38f2162..4c355f10aa 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportIngestHistory.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportIngestHistory.java @@ -67,10 +67,10 @@ class ExportIngestHistory { /** * Main constructor. * - * @param startTime The ingest start time. - * @param endTime The ingest stop time. - * @param status The ingest status. - * @param ingestModule The ingest module. + * @param startTime The ingest start time. + * @param endTime The ingest stop time. + * @param status The ingest status. + * @param ingestModule The ingest module. * @param ingestModuleVersion The ingest module version. */ IngestJobEntry(Date startTime, Date endTime, String status, String ingestModule, String ingestModuleVersion) { @@ -144,6 +144,7 @@ class ExportIngestHistory { * Retrieves data for a date cell. * * @param date The date. + * * @return The data cell to be used in the excel export. */ private static DefaultCellModel getDateCell(Date date) { @@ -155,6 +156,7 @@ class ExportIngestHistory { * Retrieves all the ingest job modules and versions for a job. * * @param job The ingest job. + * * @return All of the corresponding entries sorted by module name. */ private static List getEntries(IngestJobInfo job) { @@ -187,6 +189,7 @@ class ExportIngestHistory { * to null. * * @param list The list of entries for an ingest job. + * * @return The stream of entries to be displayed. */ private static Stream showFirstRowOnly(List list) { @@ -206,6 +209,7 @@ class ExportIngestHistory { * Returns a list of sheets to be exported for the Ingest History tab. * * @param dataSource The data source. + * * @return The list of sheets to be included in an export. */ static List getExports(DataSource dataSource) { From 323f5913234a8d16dce2b1fdcaadc3ee9e518442 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Wed, 11 Aug 2021 10:38:41 -0400 Subject: [PATCH 21/33] Removed excel related parameters from datasourcesummary package --- .../ui/RecentFilesPanel.java | 2 +- .../ui/SizeRepresentationUtil.java | 30 ++++++------------- .../ui/UserActivityPanel.java | 4 +-- .../uiutils/DefaultCellModel.java | 22 ++------------ 4 files changed, 14 insertions(+), 44 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesPanel.java index e2f38b38b6..87e934dcc1 100755 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesPanel.java @@ -141,7 +141,7 @@ public final class RecentFilesPanel extends BaseDataSourceSummaryPanel { private Function> getDateFunct() { return (T lastAccessed) -> { Function dateParser = (dt) -> dt == null ? "" : DATETIME_FORMAT.format(dt); - return new DefaultCellModel<>(new Date(lastAccessed.getDateAsLong() * 1000), dateParser, DATETIME_FORMAT_STR) + return new DefaultCellModel<>(new Date(lastAccessed.getDateAsLong() * 1000), dateParser) .setPopupMenuRetriever(getPopupFunct(lastAccessed)); }; } diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/SizeRepresentationUtil.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/SizeRepresentationUtil.java index 3c48da8db0..b1b0433588 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/SizeRepresentationUtil.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/SizeRepresentationUtil.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2020 Basis Technology Corp. + * Copyright 2020-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -43,28 +43,23 @@ public final class SizeRepresentationUtil { "SizeRepresentationUtil_units_petabytes=PB" }) enum SizeUnit { - BYTES(Bundle.SizeRepresentationUtil_units_bytes(), "#", 0), - KB(Bundle.SizeRepresentationUtil_units_kilobytes(), "#,##0.00,", 1), - MB(Bundle.SizeRepresentationUtil_units_megabytes(), "#,##0.00,,", 2), - GB(Bundle.SizeRepresentationUtil_units_gigabytes(), "#,##0.00,,,", 3), - TB(Bundle.SizeRepresentationUtil_units_terabytes(), "#,##0.00,,,,", 4), - PB(Bundle.SizeRepresentationUtil_units_petabytes(), "#,##0.00,,,,,", 5); + BYTES(Bundle.SizeRepresentationUtil_units_bytes(), 0), + KB(Bundle.SizeRepresentationUtil_units_kilobytes(), 1), + MB(Bundle.SizeRepresentationUtil_units_megabytes(), 2), + GB(Bundle.SizeRepresentationUtil_units_gigabytes(), 3), + TB(Bundle.SizeRepresentationUtil_units_terabytes(), 4), + PB(Bundle.SizeRepresentationUtil_units_petabytes(), 5); private final String suffix; - private final String excelFormatString; // ELTODO private final long divisor; /** * Main constructor. * @param suffix The string suffix to use for size unit. - * @param excelFormatString The excel format string to use for this size unit. * @param power The power of 1000 of bytes for this size unit. */ - SizeUnit(String suffix, String excelFormatString, int power) { + SizeUnit(String suffix, int power) { this.suffix = suffix; - - // based on https://www.mrexcel.com/board/threads/how-do-i-format-cells-to-show-gb-mb-kb.140135/ - this.excelFormatString = String.format("%s \"%s\"", excelFormatString, suffix); this.divisor = (long) Math.pow(SIZE_CONVERSION_CONSTANT, power); } @@ -75,13 +70,6 @@ public final class SizeRepresentationUtil { return suffix; } - /** - * @return The excel format string to use for this size unit. - */ - public String getExcelFormatString() { - return excelFormatString; - } - /** * @return The divisor to convert from bytes to this unit. */ @@ -171,7 +159,7 @@ public final class SizeRepresentationUtil { unit = SizeUnit.BYTES; } - return new DefaultCellModel(bytes, SizeRepresentationUtil::getSizeString, unit.getExcelFormatString()); + return new DefaultCellModel(bytes, SizeRepresentationUtil::getSizeString); } } diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivityPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivityPanel.java index c6d13260b9..9a6cf1ee42 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivityPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivityPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2020 Basis Technology Corp. + * Copyright 2020-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -316,7 +316,7 @@ public class UserActivityPanel extends BaseDataSourceSummaryPanel { private Function> getDateFunct() { return (T lastAccessed) -> { Function dateParser = (dt) -> dt == null ? "" : DATETIME_FORMAT.format(dt); - return new DefaultCellModel<>(lastAccessed.getLastAccessed(), dateParser, DATETIME_FORMAT_STR) + return new DefaultCellModel<>(lastAccessed.getLastAccessed(), dateParser) .setPopupMenu(getPopup(lastAccessed)); }; } diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DefaultCellModel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DefaultCellModel.java index 3d2e4e6a5a..81c176954a 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DefaultCellModel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DefaultCellModel.java @@ -35,7 +35,6 @@ public class DefaultCellModel implements GuiCellModel { private CellModel.HorizontalAlign horizontalAlignment; private List popupMenu; private Supplier> menuItemSupplier; - private final String excelFormatString; // ELTODO /** * Main constructor. @@ -43,18 +42,7 @@ public class DefaultCellModel implements GuiCellModel { * @param data The data to be displayed in the cell. */ public DefaultCellModel(T data) { - this(data, null, null); - } - - /** - * Constructor. - * - * @param data The data to be displayed in the cell. - * @param stringConverter The means of converting that data to a string or - * null to use .toString method on object. - */ - public DefaultCellModel(T data, Function stringConverter) { - this(data, stringConverter, null); + this(data, null); } /** @@ -63,15 +51,9 @@ public class DefaultCellModel implements GuiCellModel { * @param data The data to be displayed in the cell. * @param stringConverter The means of converting that data to a string or * null to use .toString method on object. - * @param excelFormatString The apache poi excel format string to use with - * the data. - * - * NOTE: Only certain data types can be exported. See - * ExcelTableExport.createCell() for types. */ - public DefaultCellModel(T data, Function stringConverter, String excelFormatString) { + public DefaultCellModel(T data, Function stringConverter) { this.data = data; - this.excelFormatString = excelFormatString; if (stringConverter == null) { text = this.data == null ? "" : this.data.toString(); From 0c9892437a00cc65e401313db56b6d5db8119d3a Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Wed, 11 Aug 2021 10:50:52 -0400 Subject: [PATCH 22/33] Refactoring --- .../autopsy/contentutils/PastCasesSummary.java | 4 ++-- .../datasourcesummary/ui/SizeRepresentationUtil.java | 10 ++-------- .../SizeRepresentationUtil.java | 5 ++--- 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentutils/PastCasesSummary.java b/Core/src/org/sleuthkit/autopsy/contentutils/PastCasesSummary.java index d50f2b44d5..c82bb2b2b8 100755 --- a/Core/src/org/sleuthkit/autopsy/contentutils/PastCasesSummary.java +++ b/Core/src/org/sleuthkit/autopsy/contentutils/PastCasesSummary.java @@ -86,14 +86,14 @@ public class PastCasesSummary { * @return Data for the cases with same id table. */ public List> getSameIdsResults() { - return sameIdsResults; + return Collections.unmodifiableList(sameIdsResults); } /** * @return Data for the tagged notable table. */ public List> getTaggedNotable() { - return taggedNotable; + return Collections.unmodifiableList(taggedNotable); } } diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/SizeRepresentationUtil.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/SizeRepresentationUtil.java index b1b0433588..65f7402b04 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/SizeRepresentationUtil.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/SizeRepresentationUtil.java @@ -100,8 +100,7 @@ public final class SizeRepresentationUtil { return SizeUnit.values()[0]; } - for (int unitsIndex = 0; unitsIndex < SizeUnit.values().length; unitsIndex++) { - SizeUnit unit = SizeUnit.values()[unitsIndex]; + for (SizeUnit unit : SizeUnit.values()) { long result = size / unit.getDivisor(); if (result < SIZE_CONVERSION_CONSTANT) { return unit; @@ -154,12 +153,7 @@ public final class SizeRepresentationUtil { if (bytes == null) { return new DefaultCellModel<>(""); } else { - SizeUnit unit = SizeRepresentationUtil.getSizeUnit(bytes); - if (unit == null) { - unit = SizeUnit.BYTES; - } - - return new DefaultCellModel(bytes, SizeRepresentationUtil::getSizeString); + return new DefaultCellModel<>(bytes, SizeRepresentationUtil::getSizeString); } } diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/SizeRepresentationUtil.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/SizeRepresentationUtil.java index 664401c684..7c9018c9ff 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/SizeRepresentationUtil.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/SizeRepresentationUtil.java @@ -111,8 +111,7 @@ final class SizeRepresentationUtil { return SizeUnit.values()[0]; } - for (int unitsIndex = 0; unitsIndex < SizeUnit.values().length; unitsIndex++) { - SizeUnit unit = SizeUnit.values()[unitsIndex]; + for (SizeUnit unit : SizeUnit.values()) { long result = size / unit.getDivisor(); if (result < SIZE_CONVERSION_CONSTANT) { return unit; @@ -170,7 +169,7 @@ final class SizeRepresentationUtil { unit = SizeUnit.BYTES; } - return new DefaultCellModel(bytes, SizeRepresentationUtil::getSizeString, unit.getExcelFormatString()); + return new DefaultCellModel<>(bytes, SizeRepresentationUtil::getSizeString, unit.getExcelFormatString()); } } From 0f719112795f633bc49d6f063b6773d6379c59d0 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Fri, 13 Aug 2021 13:36:13 -0400 Subject: [PATCH 23/33] Refoctoring --- .../Bundle.properties-MERGED | 4 + .../DataSourceSummaryReport.java | 35 +++--- .../ExcelExportAction.java | 112 ++++++++---------- 3 files changed, 75 insertions(+), 76 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED index e9991129ff..1767afc028 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/Bundle.properties-MERGED @@ -1,3 +1,7 @@ +DataSourceSummaryReport.error.noDataSources=No data sources selected for report. +DataSourceSummaryReport.error.noOpenCase=No currently open case. +DataSourceSummaryReport.excelFileWriteError=Could not write the KML file. +DataSourceSummaryReport.failedToCompleteReport=Failed to complete report. DataSourceSummaryReport.getName.text=Data Source Summary Report DataSourceSummaryReport.getDesc.text=Data source summary report in Excel (XLS) format. DataSourceSummaryReport.endReport.srcModuleName.text=Excel Report diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DataSourceSummaryReport.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DataSourceSummaryReport.java index 693667ceb1..a52f897897 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DataSourceSummaryReport.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DataSourceSummaryReport.java @@ -66,7 +66,7 @@ public class DataSourceSummaryReport implements GeneralReportModule { @Override public String getRelativeFilePath() { - return ""; //ELTODO "DataSourceSummaryReport.xlsx"; //NON-NLS + return ""; } @Override @@ -77,7 +77,7 @@ public class DataSourceSummaryReport implements GeneralReportModule { @Override public JPanel getConfigurationPanel() { - return null; // ELTODO + return null; } @Override @@ -85,13 +85,19 @@ public class DataSourceSummaryReport implements GeneralReportModule { return true; } + @NbBundle.Messages({ + "DataSourceSummaryReport.error.noOpenCase=No currently open case.", + "DataSourceSummaryReport.error.noDataSources=No data sources selected for report.", + "DataSourceSummaryReport.failedToCompleteReport=Failed to complete report.", + "DataSourceSummaryReport.excelFileWriteError=Could not write the KML file.",}) @Override public void generateReport(GeneralReportSettings settings, ReportProgressPanel progressPanel) { progressPanel.start(); - Case currentCase = null; + Case currentCase; try { currentCase = Case.getCurrentCaseThrows(); } catch (NoCurrentCaseException ex) { + progressPanel.complete(ReportProgressPanel.ReportStatus.ERROR, Bundle.DataSourceSummaryReport_error_noOpenCase()); logger.log(Level.SEVERE, "Exception while getting open case.", ex); //NON-NLS return; } @@ -110,7 +116,7 @@ public class DataSourceSummaryReport implements GeneralReportModule { settings.setSelectedDataSources(dsIDs); } catch (TskCoreException ex) { result = ReportProgressPanel.ReportStatus.ERROR; - // ELTODO errorMessage = Bundle.KMLReport_failedToCompleteReport(); + errorMessage = Bundle.DataSourceSummaryReport_failedToCompleteReport(); logger.log(Level.SEVERE, "Could not get the datasources from the case", ex); progressPanel.complete(result, errorMessage); return; @@ -121,7 +127,7 @@ public class DataSourceSummaryReport implements GeneralReportModule { selectedDataSources.add(currentCase.getSleuthkitCase().getContentById(dsID)); } catch (TskCoreException ex) { result = ReportProgressPanel.ReportStatus.ERROR; - // ELTODO errorMessage = Bundle.KMLReport_failedToCompleteReport(); + errorMessage = Bundle.DataSourceSummaryReport_failedToCompleteReport(); logger.log(Level.SEVERE, "Could not get the datasources from the case", ex); progressPanel.complete(result, errorMessage); return; @@ -129,21 +135,20 @@ public class DataSourceSummaryReport implements GeneralReportModule { } } - String baseReportDir = settings.getReportDirectoryPath(); - // Start the progress bar and setup the report - // ELTODO progressPanel.setIndeterminate(true); - - //progressPanel.updateStatusLabel(NbBundle.getMessage(this.getClass(), "ReportKML.progress.querying")); - String reportFullPath = baseReportDir + getRelativeFilePath(); //NON-NLS - + if (selectedDataSources.isEmpty()) { + result = ReportProgressPanel.ReportStatus.ERROR; + progressPanel.complete(result, Bundle.DataSourceSummaryReport_error_noDataSources()); + logger.log(Level.SEVERE, "No data sources selected for report."); //NON-NLS + return; + } - // looop over all data sources + // looop over all selected data sources for (Content dataSource : selectedDataSources){ if (dataSource instanceof DataSource) { try { - new ExcelExportAction().exportToXLSX(progressPanel, (DataSource) dataSource, baseReportDir); + new ExcelExportAction().exportToXLSX(progressPanel, (DataSource) dataSource, settings.getReportDirectoryPath()); } catch (IOException | ExcelExport.ExcelExportException ex) { - // ELTODO errorMessage = Bundle.KMLReport_kmlFileWriteError(); + errorMessage = Bundle.DataSourceSummaryReport_excelFileWriteError(); logger.log(Level.SEVERE, errorMessage, ex); //NON-NLS progressPanel.complete(ReportProgressPanel.ReportStatus.ERROR, errorMessage); return; diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java index d6a408766f..f513f26b89 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java @@ -107,90 +107,90 @@ class ExcelExportAction { throws IOException, ExcelExport.ExcelExportException { File reportFile = getXLSXPath(dataSource.getName(), baseReportDir); - int totalWeight = 10; + int totalWeight = 11; + int step = 1; progressPanel.setIndeterminate(false); + progressPanel.setLabels(dataSource.getName(), reportFile.getPath()); progressPanel.setMaximumProgress(totalWeight); progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_beginExport()); List sheetExports = new ArrayList<>(); - // Export Recent Activity data - progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_gatheringRecentActivityData()); - progressPanel.setProgress(1); - List exports = ExportRecentFiles.getExports(dataSource); - if (exports != null) { - sheetExports.addAll(exports); - } - - // Export Container & Image info data - progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_gatheringContainerData()); - progressPanel.setProgress(2); - exports = ExportContainerInfo.getExports(dataSource); - if (exports != null) { - sheetExports.addAll(exports); - } - - // Export Timeline data - progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_gatheringTimelineData()); - progressPanel.setProgress(3); - 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); - } - - // Export hash set hits, keyword hits, and interesting item hits - progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_gatheringAnalysisData()); - progressPanel.setProgress(5); - exports = ExportAnalysisResults.getExports(dataSource); - if (exports != null) { - sheetExports.addAll(exports); - } - - // Export hash set hits, keyword hits, and interesting item hits - progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_gatheringPastData()); - progressPanel.setProgress(6); - exports = ExportPastCases.getExports(dataSource); + progressPanel.setProgress(step); + List exports = ExportTypes.getExports(dataSource); if (exports != null) { sheetExports.addAll(exports); } // Export user activity progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_gatheringUserData()); - progressPanel.setProgress(6); + progressPanel.setProgress(++step); exports = ExportUserActivity.getExports(dataSource); if (exports != null) { sheetExports.addAll(exports); } + // Export Recent Activity data + progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_gatheringRecentActivityData()); + progressPanel.setProgress(++step); + exports = ExportRecentFiles.getExports(dataSource); + if (exports != null) { + sheetExports.addAll(exports); + } + + // Export hash set hits, keyword hits, and interesting item hits + progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_gatheringAnalysisData()); + progressPanel.setProgress(++step); + exports = ExportAnalysisResults.getExports(dataSource); + if (exports != null) { + sheetExports.addAll(exports); + } + + // Export past cases data + progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_gatheringPastData()); + progressPanel.setProgress(++step); + exports = ExportPastCases.getExports(dataSource); + if (exports != null) { + sheetExports.addAll(exports); + } + // Export geolocation data progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_gatheringGeoData()); - progressPanel.setProgress(7); + progressPanel.setProgress(++step); exports = ExportGeolocation.getExports(dataSource); if (exports != null) { sheetExports.addAll(exports); } + // Export Timeline data + progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_gatheringTimelineData()); + progressPanel.setProgress(++step); + exports = ExportTimeline.getExports(dataSource); + if (exports != null) { + sheetExports.addAll(exports); + } + // Export ingest history progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_gatheringIngestData()); - progressPanel.setProgress(8); + progressPanel.setProgress(++step); exports = ExportIngestHistory.getExports(dataSource); if (exports != null) { sheetExports.addAll(exports); } + // Export Container & Image info data + progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_gatheringContainerData()); + progressPanel.setProgress(++step); + exports = ExportContainerInfo.getExports(dataSource); + if (exports != null) { + sheetExports.addAll(exports); + } + progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_writingToFile()); - progressPanel.setProgress(9); + progressPanel.setProgress(++step); ExcelExport.writeExcel(sheetExports, reportFile); - progressPanel.complete(ReportProgressPanel.ReportStatus.COMPLETE, ""); - try { // add to reports Case curCase = Case.getCurrentCaseThrows(); @@ -198,16 +198,6 @@ class ExcelExportAction { Bundle.ExcelExportAction_moduleName(), reportFile.getName(), dataSource); - - // and show finished dialog - /* - * ELTODO SwingUtilities.invokeLater(() -> { ExcelExportDialog - * dialog = new - * ExcelExportDialog(WindowManager.getDefault().getMainWindow(), - * path); dialog.setResizable(false); - * dialog.setLocationRelativeTo(WindowManager.getDefault().getMainWindow()); - * dialog.setVisible(true); dialog.toFront(); }); - */ } catch (NoCurrentCaseException | TskCoreException ex) { logger.log(Level.WARNING, "There was an error attaching report to case.", ex); } @@ -313,7 +303,7 @@ class ExcelExportAction { protected static ExcelSheetExport getTableExport(List> columnsModel, String sheetName, List data) { - return convertToExcel((dataList) -> new ExcelTableExport(sheetName, columnsModel, dataList), + return convertToExcel((dataList) -> new ExcelTableExport<>(sheetName, columnsModel, dataList), data, sheetName); } @@ -334,7 +324,7 @@ class ExcelExportAction { String sheetName, DataSource ds) { return getExport(dataFetcher, - (dataList) -> new ExcelTableExport(sheetName, columnsModel, dataList), + (dataList) -> new ExcelTableExport<>(sheetName, columnsModel, dataList), sheetName, ds); } From 4f493317a05f72187ad80f8d9e26c1a18095d064 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Mon, 16 Aug 2021 14:57:43 -0400 Subject: [PATCH 24/33] removed 'public' declarations --- .../modules/datasourcesummaryexport/DataFetcher.java | 2 +- .../modules/datasourcesummaryexport/PieChartItem.java | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DataFetcher.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DataFetcher.java index f3b0b0fe6c..b513762280 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DataFetcher.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DataFetcher.java @@ -25,7 +25,7 @@ package org.sleuthkit.autopsy.report.modules.datasourcesummaryexport; * another type in the event that the fetching encountered an error. */ @FunctionalInterface -public interface DataFetcher { +interface DataFetcher { /** * A function that accepts an input argument and outputs a result. Since it diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/PieChartItem.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/PieChartItem.java index 3b18a8c41c..4db4f41bfe 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/PieChartItem.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/PieChartItem.java @@ -23,7 +23,7 @@ import java.awt.Color; /** * An individual pie chart slice in the pie chart. */ -public class PieChartItem { +class PieChartItem { private final String label; private final double value; @@ -37,7 +37,7 @@ public class PieChartItem { * @param color The color for the pie slice. Can be null for * auto-determined. */ - public PieChartItem(String label, double value, Color color) { + PieChartItem(String label, double value, Color color) { this.label = label; this.value = value; this.color = color; @@ -46,21 +46,21 @@ public class PieChartItem { /** * @return The label for this item. */ - public String getLabel() { + String getLabel() { return label; } /** * @return The value for this item. */ - public double getValue() { + double getValue() { return value; } /** * @return The color for the pie slice or null for auto-determined. */ - public Color getColor() { + Color getColor() { return color; } From cccfde11f13ec9a9ec956ecbd8d71c265b19ebcd Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Wed, 18 Aug 2021 15:20:21 -0400 Subject: [PATCH 25/33] Refactored datasourcesummary packages --- .../contentutils/Bundle.properties-MERGED | 2 -- .../datamodel}/AnalysisSummary.java | 2 +- .../datamodel/Bundle.properties-MERGED | 0 .../datamodel/Bundle_ja.properties | 3 --- .../datamodel}/CityRecord.java | 2 +- .../datamodel}/ClosestCityMapper.java | 2 +- .../datamodel}/ContainerSummary.java | 2 +- .../datamodel}/DataSourceInfoUtilities.java | 2 +- .../datamodel}/GeolocationSummary.java | 2 +- .../datamodel}/LatLngMap.java | 2 +- .../datamodel}/PastCasesSummary.java | 2 +- .../datamodel}/RecentFilesSummary.java | 2 +- .../datamodel}/TimelineSummary.java | 2 +- .../datamodel}/TypesSummary.java | 2 +- .../datamodel}/UserActivitySummary.java | 2 +- .../datamodel}/worldcities.csv | 0 .../datasourcesummary/ui/AnalysisPanel.java | 1 - .../{datamodel => ui}/AnalysisSummaryGetter.java | 6 +++--- .../ui/Bundle.properties-MERGED | 2 ++ .../CaseDataSourcesSummary.java | 2 +- .../datasourcesummary/ui/ContainerPanel.java | 5 ++--- .../ContainerSummaryGetter.java | 6 +++--- .../datasourcesummary/ui/DataSourceBrowser.java | 1 - .../DataSourceLabeledValueCallback.java | 2 +- .../DataSourceSingleValueCallback.java | 2 +- .../datasourcesummary/ui/GeolocationPanel.java | 9 ++++----- .../GeolocationSummaryGetter.java | 8 ++++---- .../{datamodel => ui}/MimeTypeSummaryGetter.java | 6 +++--- .../datasourcesummary/ui/PastCasesPanel.java | 3 +-- .../PastCasesSummaryGetter.java | 8 ++++---- .../{datamodel => ui}/RecentFilesGetter.java | 12 ++++++------ .../datasourcesummary/ui/RecentFilesPanel.java | 7 +++---- .../{datamodel => ui}/SleuthkitCaseProvider.java | 2 +- .../datasourcesummary/ui/TimelinePanel.java | 7 +++---- .../{datamodel => ui}/TimelineSummaryGetter.java | 8 ++++---- .../autopsy/datasourcesummary/ui/TypesPanel.java | 9 +++------ .../{datamodel => ui}/TypesSummaryGetter.java | 6 +++--- .../datasourcesummary/ui/UserActivityPanel.java | 13 ++++++------- .../UserActivitySummaryGetter.java | 16 ++++++++-------- .../ExportAnalysisResults.java | 2 +- .../ExportContainerInfo.java | 6 +++--- .../ExportGeolocation.java | 10 +++++----- .../datasourcesummaryexport/ExportPastCases.java | 4 ++-- .../ExportRecentFiles.java | 8 ++++---- .../datasourcesummaryexport/ExportTimeline.java | 6 +++--- .../datasourcesummaryexport/ExportTypes.java | 8 ++++---- .../ExportUserActivity.java | 14 +++++++------- .../UserActivitySummaryTests.java | 6 +++--- .../datamodel/DataSourceInfoUtilitiesTest.java | 3 +-- .../datamodel/RecentFilesSummaryTest.java | 9 +++++---- .../datamodel/UserActivitySummaryTest.java | 13 +++++++------ 51 files changed, 123 insertions(+), 136 deletions(-) delete mode 100755 Core/src/org/sleuthkit/autopsy/contentutils/Bundle.properties-MERGED rename Core/src/org/sleuthkit/autopsy/{contentutils => datasourcesummary/datamodel}/AnalysisSummary.java (99%) mode change 100644 => 100755 Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/Bundle.properties-MERGED delete mode 100644 Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/Bundle_ja.properties rename Core/src/org/sleuthkit/autopsy/{contentutils => datasourcesummary/datamodel}/CityRecord.java (98%) rename Core/src/org/sleuthkit/autopsy/{contentutils => datasourcesummary/datamodel}/ClosestCityMapper.java (99%) rename Core/src/org/sleuthkit/autopsy/{contentutils => datasourcesummary/datamodel}/ContainerSummary.java (99%) rename Core/src/org/sleuthkit/autopsy/{contentutils => datasourcesummary/datamodel}/DataSourceInfoUtilities.java (99%) rename Core/src/org/sleuthkit/autopsy/{contentutils => datasourcesummary/datamodel}/GeolocationSummary.java (99%) rename Core/src/org/sleuthkit/autopsy/{contentutils => datasourcesummary/datamodel}/LatLngMap.java (99%) rename Core/src/org/sleuthkit/autopsy/{contentutils => datasourcesummary/datamodel}/PastCasesSummary.java (99%) rename Core/src/org/sleuthkit/autopsy/{contentutils => datasourcesummary/datamodel}/RecentFilesSummary.java (99%) rename Core/src/org/sleuthkit/autopsy/{contentutils => datasourcesummary/datamodel}/TimelineSummary.java (99%) rename Core/src/org/sleuthkit/autopsy/{contentutils => datasourcesummary/datamodel}/TypesSummary.java (99%) rename Core/src/org/sleuthkit/autopsy/{contentutils => datasourcesummary/datamodel}/UserActivitySummary.java (99%) rename Core/src/org/sleuthkit/autopsy/{contentutils => datasourcesummary/datamodel}/worldcities.csv (100%) rename Core/src/org/sleuthkit/autopsy/datasourcesummary/{datamodel => ui}/AnalysisSummaryGetter.java (94%) rename Core/src/org/sleuthkit/autopsy/datasourcesummary/{datamodel => ui}/CaseDataSourcesSummary.java (99%) rename Core/src/org/sleuthkit/autopsy/datasourcesummary/{datamodel => ui}/ContainerSummaryGetter.java (95%) rename Core/src/org/sleuthkit/autopsy/datasourcesummary/{datamodel => ui}/DataSourceLabeledValueCallback.java (97%) rename Core/src/org/sleuthkit/autopsy/datasourcesummary/{datamodel => ui}/DataSourceSingleValueCallback.java (97%) rename Core/src/org/sleuthkit/autopsy/datasourcesummary/{datamodel => ui}/GeolocationSummaryGetter.java (89%) rename Core/src/org/sleuthkit/autopsy/datasourcesummary/{datamodel => ui}/MimeTypeSummaryGetter.java (96%) rename Core/src/org/sleuthkit/autopsy/datasourcesummary/{datamodel => ui}/PastCasesSummaryGetter.java (88%) rename Core/src/org/sleuthkit/autopsy/datasourcesummary/{datamodel => ui}/RecentFilesGetter.java (90%) rename Core/src/org/sleuthkit/autopsy/datasourcesummary/{datamodel => ui}/SleuthkitCaseProvider.java (97%) rename Core/src/org/sleuthkit/autopsy/datasourcesummary/{datamodel => ui}/TimelineSummaryGetter.java (90%) rename Core/src/org/sleuthkit/autopsy/datasourcesummary/{datamodel => ui}/TypesSummaryGetter.java (96%) rename Core/src/org/sleuthkit/autopsy/datasourcesummary/{datamodel => ui}/UserActivitySummaryGetter.java (92%) diff --git a/Core/src/org/sleuthkit/autopsy/contentutils/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/contentutils/Bundle.properties-MERGED deleted file mode 100755 index 2e019a0248..0000000000 --- a/Core/src/org/sleuthkit/autopsy/contentutils/Bundle.properties-MERGED +++ /dev/null @@ -1,2 +0,0 @@ -DataSourceUserActivitySummary_getRecentAccounts_calllogMessage=Call Log -DataSourceUserActivitySummary_getRecentAccounts_emailMessage=Email Message diff --git a/Core/src/org/sleuthkit/autopsy/contentutils/AnalysisSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/AnalysisSummary.java similarity index 99% rename from Core/src/org/sleuthkit/autopsy/contentutils/AnalysisSummary.java rename to Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/AnalysisSummary.java index dc12c9edad..e5824b9f3f 100755 --- a/Core/src/org/sleuthkit/autopsy/contentutils/AnalysisSummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/AnalysisSummary.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.contentutils; +package org.sleuthkit.autopsy.datasourcesummary.datamodel; import java.util.ArrayList; import java.util.Collections; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/Bundle.properties-MERGED old mode 100644 new mode 100755 diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/Bundle_ja.properties deleted file mode 100644 index a8185f73ff..0000000000 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/Bundle_ja.properties +++ /dev/null @@ -1,3 +0,0 @@ -#Mon Jun 14 12:23:19 UTC 2021 -DataSourceUserActivitySummary_getRecentAccounts_calllogMessage=\u901a\u8a71\u8a18\u9332 -DataSourceUserActivitySummary_getRecentAccounts_emailMessage=\u30e1\u30fc\u30eb\u30e1\u30c3\u30bb\u30fc\u30b8 diff --git a/Core/src/org/sleuthkit/autopsy/contentutils/CityRecord.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/CityRecord.java similarity index 98% rename from Core/src/org/sleuthkit/autopsy/contentutils/CityRecord.java rename to Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/CityRecord.java index 562fc1758d..26fa46498c 100644 --- a/Core/src/org/sleuthkit/autopsy/contentutils/CityRecord.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/CityRecord.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.contentutils; +package org.sleuthkit.autopsy.datasourcesummary.datamodel; import java.util.Objects; import org.sleuthkit.autopsy.geolocation.KdTree; diff --git a/Core/src/org/sleuthkit/autopsy/contentutils/ClosestCityMapper.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ClosestCityMapper.java similarity index 99% rename from Core/src/org/sleuthkit/autopsy/contentutils/ClosestCityMapper.java rename to Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ClosestCityMapper.java index 3e39852c79..e2df913534 100644 --- a/Core/src/org/sleuthkit/autopsy/contentutils/ClosestCityMapper.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ClosestCityMapper.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.contentutils; +package org.sleuthkit.autopsy.datasourcesummary.datamodel; import java.io.BufferedReader; import java.io.IOException; diff --git a/Core/src/org/sleuthkit/autopsy/contentutils/ContainerSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummary.java similarity index 99% rename from Core/src/org/sleuthkit/autopsy/contentutils/ContainerSummary.java rename to Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummary.java index 13f7eec7bf..7bd34016f3 100755 --- a/Core/src/org/sleuthkit/autopsy/contentutils/ContainerSummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummary.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.contentutils; +package org.sleuthkit.autopsy.datasourcesummary.datamodel; import java.sql.SQLException; import java.util.ArrayList; diff --git a/Core/src/org/sleuthkit/autopsy/contentutils/DataSourceInfoUtilities.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceInfoUtilities.java similarity index 99% rename from Core/src/org/sleuthkit/autopsy/contentutils/DataSourceInfoUtilities.java rename to Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceInfoUtilities.java index 2b69808eba..2847ea4510 100644 --- a/Core/src/org/sleuthkit/autopsy/contentutils/DataSourceInfoUtilities.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceInfoUtilities.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.contentutils; +package org.sleuthkit.autopsy.datasourcesummary.datamodel; import java.sql.ResultSet; import java.sql.SQLException; diff --git a/Core/src/org/sleuthkit/autopsy/contentutils/GeolocationSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/GeolocationSummary.java similarity index 99% rename from Core/src/org/sleuthkit/autopsy/contentutils/GeolocationSummary.java rename to Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/GeolocationSummary.java index ea3ffec08c..b011dd8f4e 100755 --- a/Core/src/org/sleuthkit/autopsy/contentutils/GeolocationSummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/GeolocationSummary.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.contentutils; +package org.sleuthkit.autopsy.datasourcesummary.datamodel; import java.io.IOException; import java.util.ArrayList; diff --git a/Core/src/org/sleuthkit/autopsy/contentutils/LatLngMap.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/LatLngMap.java similarity index 99% rename from Core/src/org/sleuthkit/autopsy/contentutils/LatLngMap.java rename to Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/LatLngMap.java index 9d026ab11d..22a004c03c 100644 --- a/Core/src/org/sleuthkit/autopsy/contentutils/LatLngMap.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/LatLngMap.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.contentutils; +package org.sleuthkit.autopsy.datasourcesummary.datamodel; import java.util.Collection; import java.util.List; diff --git a/Core/src/org/sleuthkit/autopsy/contentutils/PastCasesSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/PastCasesSummary.java similarity index 99% rename from Core/src/org/sleuthkit/autopsy/contentutils/PastCasesSummary.java rename to Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/PastCasesSummary.java index c82bb2b2b8..5bfe52261c 100755 --- a/Core/src/org/sleuthkit/autopsy/contentutils/PastCasesSummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/PastCasesSummary.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.contentutils; +package org.sleuthkit.autopsy.datasourcesummary.datamodel; import java.util.ArrayList; import java.util.Arrays; diff --git a/Core/src/org/sleuthkit/autopsy/contentutils/RecentFilesSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesSummary.java similarity index 99% rename from Core/src/org/sleuthkit/autopsy/contentutils/RecentFilesSummary.java rename to Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesSummary.java index fd2d8341e7..77504394dd 100755 --- a/Core/src/org/sleuthkit/autopsy/contentutils/RecentFilesSummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesSummary.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.contentutils; +package org.sleuthkit.autopsy.datasourcesummary.datamodel; import java.nio.file.Paths; import java.text.DateFormat; diff --git a/Core/src/org/sleuthkit/autopsy/contentutils/TimelineSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java similarity index 99% rename from Core/src/org/sleuthkit/autopsy/contentutils/TimelineSummary.java rename to Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java index 345cda6332..c21927b4df 100755 --- a/Core/src/org/sleuthkit/autopsy/contentutils/TimelineSummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.contentutils; +package org.sleuthkit.autopsy.datasourcesummary.datamodel; import java.text.DateFormat; import java.text.SimpleDateFormat; diff --git a/Core/src/org/sleuthkit/autopsy/contentutils/TypesSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TypesSummary.java similarity index 99% rename from Core/src/org/sleuthkit/autopsy/contentutils/TypesSummary.java rename to Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TypesSummary.java index 4c6944de37..a0fc5c7aa9 100755 --- a/Core/src/org/sleuthkit/autopsy/contentutils/TypesSummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TypesSummary.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.contentutils; +package org.sleuthkit.autopsy.datasourcesummary.datamodel; import java.awt.Color; import java.sql.SQLException; diff --git a/Core/src/org/sleuthkit/autopsy/contentutils/UserActivitySummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummary.java similarity index 99% rename from Core/src/org/sleuthkit/autopsy/contentutils/UserActivitySummary.java rename to Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummary.java index 1d46523ebd..5b51d10461 100755 --- a/Core/src/org/sleuthkit/autopsy/contentutils/UserActivitySummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummary.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.contentutils; +package org.sleuthkit.autopsy.datasourcesummary.datamodel; import java.io.File; import java.util.ArrayList; diff --git a/Core/src/org/sleuthkit/autopsy/contentutils/worldcities.csv b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/worldcities.csv similarity index 100% rename from Core/src/org/sleuthkit/autopsy/contentutils/worldcities.csv rename to Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/worldcities.csv diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/AnalysisPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/AnalysisPanel.java index df86d973b1..929f2d2364 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/AnalysisPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/AnalysisPanel.java @@ -23,7 +23,6 @@ import java.util.List; import java.util.function.Function; import org.apache.commons.lang3.tuple.Pair; import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.AnalysisSummaryGetter; import org.sleuthkit.autopsy.datasourcesummary.uiutils.ColumnModel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetcher; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/AnalysisSummaryGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/AnalysisSummaryGetter.java similarity index 94% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/AnalysisSummaryGetter.java rename to Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/AnalysisSummaryGetter.java index 33cf925fba..9f2a19d72b 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/AnalysisSummaryGetter.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/AnalysisSummaryGetter.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datasourcesummary.datamodel; +package org.sleuthkit.autopsy.datasourcesummary.ui; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultArtifactUpdateGovernor; import java.util.Arrays; @@ -26,8 +26,8 @@ import java.util.List; import java.util.Set; import org.apache.commons.lang3.tuple.Pair; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; -import org.sleuthkit.autopsy.contentutils.AnalysisSummary; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.AnalysisSummary; +import org.sleuthkit.autopsy.datasourcesummary.ui.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.TskCoreException; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties-MERGED index 27a706c4a0..a7a4e5870f 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties-MERGED @@ -56,6 +56,8 @@ DataSourceSummaryTabbedPane_recentFileTab_title=Recent Files DataSourceSummaryTabbedPane_timelineTab_title=Timeline DataSourceSummaryTabbedPane_typesTab_title=Types DataSourceSummaryTabbedPane_userActivityTab_title=User Activity +DataSourceUserActivitySummary_getRecentAccounts_calllogMessage=Call Log +DataSourceUserActivitySummary_getRecentAccounts_emailMessage=Email Message GeolocationPanel_cityColumn_title=Closest City GeolocationPanel_countColumn_title=Count GeolocationPanel_mostCommon_tabName=Most Common Cities diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/CaseDataSourcesSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/CaseDataSourcesSummary.java similarity index 99% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/CaseDataSourcesSummary.java rename to Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/CaseDataSourcesSummary.java index 50e883e29a..4181af5b8e 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/CaseDataSourcesSummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/CaseDataSourcesSummary.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datasourcesummary.datamodel; +package org.sleuthkit.autopsy.datasourcesummary.ui; import java.util.Collections; import java.util.HashMap; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java index 75e826f625..fc313d1ef8 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java @@ -28,9 +28,8 @@ import org.sleuthkit.autopsy.coreutils.Logger; import javax.swing.table.DefaultTableModel; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.contentutils.ContainerSummary.ContainerDetails; -import org.sleuthkit.autopsy.contentutils.ContainerSummary.ImageDetails; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.ContainerSummaryGetter; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.ContainerSummary.ContainerDetails; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.ContainerSummary.ImageDetails; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult.ResultType; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetcher; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummaryGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerSummaryGetter.java similarity index 95% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummaryGetter.java rename to Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerSummaryGetter.java index 9cf43f408e..68bff3d987 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummaryGetter.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerSummaryGetter.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datasourcesummary.datamodel; +package org.sleuthkit.autopsy.datasourcesummary.ui; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultArtifactUpdateGovernor; import java.sql.SQLException; @@ -24,8 +24,8 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Set; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; -import org.sleuthkit.autopsy.contentutils.ContainerSummary; +import org.sleuthkit.autopsy.datasourcesummary.ui.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.ContainerSummary; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.ingest.ModuleContentEvent; import org.sleuthkit.datamodel.AbstractFile; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceBrowser.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceBrowser.java index 51433534e4..5d2694f9ff 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceBrowser.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceBrowser.java @@ -42,7 +42,6 @@ import static javax.swing.SwingConstants.RIGHT; import javax.swing.SwingUtilities; import javax.swing.SwingWorker; import javax.swing.table.TableColumn; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.CaseDataSourcesSummary; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.IngestJobInfo; import org.sleuthkit.datamodel.SleuthkitCase; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceLabeledValueCallback.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceLabeledValueCallback.java similarity index 97% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceLabeledValueCallback.java rename to Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceLabeledValueCallback.java index 6c9c918667..cbb4b18e86 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceLabeledValueCallback.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceLabeledValueCallback.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datasourcesummary.datamodel; +package org.sleuthkit.autopsy.datasourcesummary.ui; import java.sql.ResultSet; import java.sql.SQLException; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceSingleValueCallback.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSingleValueCallback.java similarity index 97% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceSingleValueCallback.java rename to Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSingleValueCallback.java index 6b1ff205fa..901c3d9416 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceSingleValueCallback.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSingleValueCallback.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datasourcesummary.datamodel; +package org.sleuthkit.autopsy.datasourcesummary.ui; import java.sql.ResultSet; import java.sql.SQLException; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/GeolocationPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/GeolocationPanel.java index 3e5687255e..55d37a3d2e 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/GeolocationPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/GeolocationPanel.java @@ -34,11 +34,10 @@ import org.openide.util.NbBundle.Messages; import org.openide.util.actions.CallableSystemAction; import org.openide.windows.TopComponent; import org.openide.windows.WindowManager; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.GeolocationSummaryGetter; -import org.sleuthkit.autopsy.contentutils.GeolocationSummary.CityCountsList; -import org.sleuthkit.autopsy.contentutils.GeolocationSummary.CityData; -import org.sleuthkit.autopsy.contentutils.GeolocationSummary.CityRecordCount; -import org.sleuthkit.autopsy.contentutils.CityRecord; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.GeolocationSummary.CityCountsList; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.GeolocationSummary.CityData; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.GeolocationSummary.CityRecordCount; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.CityRecord; import org.sleuthkit.autopsy.datasourcesummary.uiutils.ColumnModel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/GeolocationSummaryGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/GeolocationSummaryGetter.java similarity index 89% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/GeolocationSummaryGetter.java rename to Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/GeolocationSummaryGetter.java index 9165f43561..9a9dc7f61c 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/GeolocationSummaryGetter.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/GeolocationSummaryGetter.java @@ -16,14 +16,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datasourcesummary.datamodel; +package org.sleuthkit.autopsy.datasourcesummary.ui; import java.io.IOException; import java.util.List; import java.util.Set; -import org.sleuthkit.autopsy.contentutils.GeolocationSummary; -import org.sleuthkit.autopsy.contentutils.GeolocationSummary.CityData; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.GeolocationSummary; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.GeolocationSummary.CityData; +import org.sleuthkit.autopsy.datasourcesummary.ui.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultArtifactUpdateGovernor; import org.sleuthkit.autopsy.geolocation.datamodel.GeoLocationDataException; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/MimeTypeSummaryGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/MimeTypeSummaryGetter.java similarity index 96% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/MimeTypeSummaryGetter.java rename to Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/MimeTypeSummaryGetter.java index a0b29e8a7f..f2a96cdd92 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/MimeTypeSummaryGetter.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/MimeTypeSummaryGetter.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datasourcesummary.datamodel; +package org.sleuthkit.autopsy.datasourcesummary.ui; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultUpdateGovernor; import java.sql.SQLException; @@ -27,8 +27,8 @@ 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.datasourcesummary.ui.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceInfoUtilities; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.ModuleContentEvent; import org.sleuthkit.datamodel.AbstractFile; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesPanel.java index 5886457530..f893098313 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesPanel.java @@ -22,8 +22,7 @@ import java.util.Arrays; import java.util.List; import org.apache.commons.lang3.tuple.Pair; import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.contentutils.PastCasesSummary.PastCasesResult; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.PastCasesSummaryGetter; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.PastCasesSummary.PastCasesResult; import org.sleuthkit.autopsy.datasourcesummary.uiutils.ColumnModel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/PastCasesSummaryGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesSummaryGetter.java similarity index 88% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/PastCasesSummaryGetter.java rename to Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesSummaryGetter.java index 4d33ad6757..f7b76081f7 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/PastCasesSummaryGetter.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesSummaryGetter.java @@ -16,17 +16,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datasourcesummary.datamodel; +package org.sleuthkit.autopsy.datasourcesummary.ui; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Set; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.autopsy.datasourcesummary.ui.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultArtifactUpdateGovernor; -import org.sleuthkit.autopsy.contentutils.PastCasesSummary; -import org.sleuthkit.autopsy.contentutils.PastCasesSummary.PastCasesResult; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.PastCasesSummary; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.PastCasesSummary.PastCasesResult; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.TskCoreException; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesGetter.java similarity index 90% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesGetter.java rename to Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesGetter.java index 668c0085df..0c6db1d7e1 100755 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesGetter.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesGetter.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datasourcesummary.datamodel; +package org.sleuthkit.autopsy.datasourcesummary.ui; import java.util.Arrays; import java.util.Collections; @@ -25,13 +25,13 @@ import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultArtifactUpdateGove import java.util.List; import java.util.Set; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; -import org.sleuthkit.autopsy.contentutils.RecentFilesSummary; -import org.sleuthkit.autopsy.contentutils.RecentFilesSummary.RecentAttachmentDetails; -import org.sleuthkit.autopsy.contentutils.RecentFilesSummary.RecentDownloadDetails; -import org.sleuthkit.autopsy.contentutils.RecentFilesSummary.RecentFileDetails; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.RecentFilesSummary; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.RecentFilesSummary.RecentAttachmentDetails; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.RecentFilesSummary.RecentDownloadDetails; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.RecentFilesSummary.RecentFileDetails; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.TskCoreException; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.autopsy.datasourcesummary.ui.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.datamodel.BlackboardArtifact; /** diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesPanel.java index 87e934dcc1..1794c24aec 100755 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesPanel.java @@ -28,10 +28,9 @@ import java.util.Locale; import java.util.function.Function; import java.util.function.Supplier; import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.RecentFilesGetter; -import org.sleuthkit.autopsy.contentutils.RecentFilesSummary.RecentAttachmentDetails; -import org.sleuthkit.autopsy.contentutils.RecentFilesSummary.RecentDownloadDetails; -import org.sleuthkit.autopsy.contentutils.RecentFilesSummary.RecentFileDetails; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.RecentFilesSummary.RecentAttachmentDetails; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.RecentFilesSummary.RecentDownloadDetails; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.RecentFilesSummary.RecentFileDetails; import org.sleuthkit.autopsy.datasourcesummary.uiutils.CellModelTableCellRenderer; import org.sleuthkit.autopsy.datasourcesummary.uiutils.ColumnModel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/SleuthkitCaseProvider.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/SleuthkitCaseProvider.java similarity index 97% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/SleuthkitCaseProvider.java rename to Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/SleuthkitCaseProvider.java index 8371b2fefd..90afc2d597 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/SleuthkitCaseProvider.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/SleuthkitCaseProvider.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datasourcesummary.datamodel; +package org.sleuthkit.autopsy.datasourcesummary.ui; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java index dab41e9cc8..42a7b1ba8f 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java @@ -32,10 +32,9 @@ import org.openide.util.NbBundle.Messages; import org.openide.util.actions.CallableSystemAction; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.contentutils.TimelineSummary; -import org.sleuthkit.autopsy.contentutils.TimelineSummary.DailyActivityAmount; -import org.sleuthkit.autopsy.contentutils.TimelineSummary.TimelineSummaryData; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummaryGetter; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary.DailyActivityAmount; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary.TimelineSummaryData; import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartPanel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartSeries; import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartPanel.OrderedKey; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummaryGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelineSummaryGetter.java similarity index 90% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummaryGetter.java rename to Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelineSummaryGetter.java index 3331cd45ed..99bdc2737c 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummaryGetter.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelineSummaryGetter.java @@ -16,22 +16,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datasourcesummary.datamodel; +package org.sleuthkit.autopsy.datasourcesummary.ui; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Set; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.autopsy.datasourcesummary.ui.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultUpdateGovernor; -import org.sleuthkit.autopsy.contentutils.TimelineSummary; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary; 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.autopsy.casemodule.NoCurrentCaseException; -import org.sleuthkit.autopsy.contentutils.TimelineSummary.TimelineSummaryData; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary.TimelineSummaryData; /** * Provides data source summary information pertaining to Timeline data. diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java index d892b4a9c4..ea4a85f406 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java @@ -29,12 +29,9 @@ 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.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.MimeTypeSummaryGetter; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceInfoUtilities; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.TypesSummary.FileTypeCategoryData; +import org.sleuthkit.autopsy.datasourcesummary.ui.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult.ResultType; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TypesSummaryGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesSummaryGetter.java similarity index 96% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TypesSummaryGetter.java rename to Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesSummaryGetter.java index 7e0129382d..5bc6bf92ab 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TypesSummaryGetter.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesSummaryGetter.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datasourcesummary.datamodel; +package org.sleuthkit.autopsy.datasourcesummary.ui; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultUpdateGovernor; import java.sql.SQLException; @@ -25,8 +25,8 @@ import java.util.Collections; import java.util.HashSet; import java.util.Set; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; -import org.sleuthkit.autopsy.contentutils.TypesSummary; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.TypesSummary; +import org.sleuthkit.autopsy.datasourcesummary.ui.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.ModuleContentEvent; import org.sleuthkit.datamodel.AbstractFile; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivityPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivityPanel.java index 9a6cf1ee42..3ac26a3b1e 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivityPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivityPanel.java @@ -28,13 +28,12 @@ import java.util.Locale; import java.util.function.Function; import org.apache.commons.lang.StringUtils; import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.contentutils.UserActivitySummary.LastAccessedArtifact; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummaryGetter; -import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopAccountResult; -import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopDeviceAttachedResult; -import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopDomainsResult; -import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopProgramsResult; -import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopWebSearchResult; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.LastAccessedArtifact; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopAccountResult; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopDeviceAttachedResult; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopDomainsResult; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopProgramsResult; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopWebSearchResult; import org.sleuthkit.autopsy.datasourcesummary.uiutils.ColumnModel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetcher; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummaryGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivitySummaryGetter.java similarity index 92% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummaryGetter.java rename to Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivitySummaryGetter.java index 73ac071470..04da065833 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummaryGetter.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivitySummaryGetter.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datasourcesummary.datamodel; +package org.sleuthkit.autopsy.datasourcesummary.ui; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultArtifactUpdateGovernor; import java.util.Arrays; @@ -26,15 +26,15 @@ import java.util.List; import java.util.Set; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.autopsy.datasourcesummary.ui.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.TskCoreException; -import org.sleuthkit.autopsy.contentutils.UserActivitySummary; -import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopAccountResult; -import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopDeviceAttachedResult; -import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopDomainsResult; -import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopProgramsResult; -import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopWebSearchResult; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopAccountResult; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopDeviceAttachedResult; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopDomainsResult; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopProgramsResult; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopWebSearchResult; import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; /** diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportAnalysisResults.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportAnalysisResults.java index 6ae7bb0381..865ffddd01 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportAnalysisResults.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportAnalysisResults.java @@ -24,7 +24,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.commons.lang3.tuple.Pair; import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.contentutils.AnalysisSummary; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.AnalysisSummary; import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExport.ExcelSheetExport; import static org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExportAction.getTableExport; import org.sleuthkit.datamodel.DataSource; diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportContainerInfo.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportContainerInfo.java index 6d297abc0f..949bd853af 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportContainerInfo.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportContainerInfo.java @@ -25,9 +25,9 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.commons.lang.StringUtils; import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.contentutils.ContainerSummary; -import org.sleuthkit.autopsy.contentutils.ContainerSummary.ContainerDetails; -import org.sleuthkit.autopsy.contentutils.ContainerSummary.ImageDetails; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.ContainerSummary; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.ContainerSummary.ContainerDetails; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.ContainerSummary.ImageDetails; import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExport.ExcelSheetExport; import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelSpecialFormatExport.ExcelItemExportable; import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelSpecialFormatExport.KeyValueItemExportable; diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportGeolocation.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportGeolocation.java index 1ea449b073..d320311485 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportGeolocation.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportGeolocation.java @@ -27,11 +27,11 @@ import java.util.stream.Stream; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.contentutils.GeolocationSummary.CityCountsList; -import org.sleuthkit.autopsy.contentutils.GeolocationSummary.CityData; -import org.sleuthkit.autopsy.contentutils.GeolocationSummary.CityRecordCount; -import org.sleuthkit.autopsy.contentutils.CityRecord; -import org.sleuthkit.autopsy.contentutils.GeolocationSummary; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.GeolocationSummary.CityCountsList; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.GeolocationSummary.CityData; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.GeolocationSummary.CityRecordCount; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.CityRecord; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.GeolocationSummary; import static org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExportAction.getFetchResult; import static org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExportAction.getTableExport; import org.sleuthkit.datamodel.DataSource; diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportPastCases.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportPastCases.java index 6448adb369..de6f027ed0 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportPastCases.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportPastCases.java @@ -23,8 +23,8 @@ import java.util.Collections; import java.util.List; import org.apache.commons.lang3.tuple.Pair; import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.contentutils.PastCasesSummary; -import org.sleuthkit.autopsy.contentutils.PastCasesSummary.PastCasesResult; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.PastCasesSummary; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.PastCasesSummary.PastCasesResult; import static org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExportAction.getFetchResult; import static org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExportAction.getTableExport; import org.sleuthkit.datamodel.DataSource; diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportRecentFiles.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportRecentFiles.java index c9a57cc3aa..adb6068fe5 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportRecentFiles.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportRecentFiles.java @@ -28,10 +28,10 @@ import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.contentutils.RecentFilesSummary; -import org.sleuthkit.autopsy.contentutils.RecentFilesSummary.RecentAttachmentDetails; -import org.sleuthkit.autopsy.contentutils.RecentFilesSummary.RecentDownloadDetails; -import org.sleuthkit.autopsy.contentutils.RecentFilesSummary.RecentFileDetails; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.RecentFilesSummary; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.RecentFilesSummary.RecentAttachmentDetails; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.RecentFilesSummary.RecentDownloadDetails; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.RecentFilesSummary.RecentFileDetails; import org.sleuthkit.datamodel.DataSource; /** diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTimeline.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTimeline.java index e845093f08..3af85058a3 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTimeline.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTimeline.java @@ -27,9 +27,9 @@ import java.util.Date; import java.util.List; import org.apache.commons.collections.CollectionUtils; import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.contentutils.TimelineSummary; -import org.sleuthkit.autopsy.contentutils.TimelineSummary.DailyActivityAmount; -import org.sleuthkit.autopsy.contentutils.TimelineSummary.TimelineSummaryData; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary.DailyActivityAmount; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary.TimelineSummaryData; import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.BarChartSeries.BarChartItem; import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.BarChartSeries.OrderedKey; import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelSpecialFormatExport.KeyValueItemExportable; diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTypes.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTypes.java index 9253b5b09b..1523540f23 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTypes.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTypes.java @@ -30,11 +30,11 @@ 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.datasourcesummary.datamodel.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.datasourcesummary.datamodel.DataSourceInfoUtilities; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.TypesSummary; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.TypesSummary.FileTypeCategoryData; import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelSpecialFormatExport.KeyValueItemExportable; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.TskCoreException; diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportUserActivity.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportUserActivity.java index ba9ff135ce..6a1cb491e2 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportUserActivity.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportUserActivity.java @@ -30,13 +30,13 @@ import java.util.stream.Stream; import org.apache.commons.lang.StringUtils; import org.openide.util.NbBundle.Messages; import org.sleuthkit.datamodel.DataSource; -import org.sleuthkit.autopsy.contentutils.UserActivitySummary; -import org.sleuthkit.autopsy.contentutils.UserActivitySummary.LastAccessedArtifact; -import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopAccountResult; -import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopDeviceAttachedResult; -import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopDomainsResult; -import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopProgramsResult; -import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopWebSearchResult; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.LastAccessedArtifact; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopAccountResult; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopDeviceAttachedResult; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopDomainsResult; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopProgramsResult; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopWebSearchResult; import static org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExportAction.getTableExport; /** diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/datasourcesummary/UserActivitySummaryTests.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/datasourcesummary/UserActivitySummaryTests.java index eb14d53e51..73fc864c61 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/datasourcesummary/UserActivitySummaryTests.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/datasourcesummary/UserActivitySummaryTests.java @@ -25,9 +25,9 @@ import java.util.Map; import java.util.stream.Collectors; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummaryGetter; -import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopDomainsResult; +import org.sleuthkit.autopsy.datasourcesummary.ui.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.autopsy.datasourcesummary.ui.UserActivitySummaryGetter; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopDomainsResult; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.TskCoreException; diff --git a/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceInfoUtilitiesTest.java b/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceInfoUtilitiesTest.java index 5179b4a509..1b5d809b1f 100644 --- a/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceInfoUtilitiesTest.java +++ b/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceInfoUtilitiesTest.java @@ -27,7 +27,7 @@ import org.junit.Assert; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.sleuthkit.autopsy.contentutils.DataSourceInfoUtilities.SortOrder; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceInfoUtilities.SortOrder; import org.sleuthkit.datamodel.Blackboard; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; @@ -36,7 +36,6 @@ import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.autopsy.testutils.TskMockUtils; import static org.mockito.Mockito.*; -import org.sleuthkit.autopsy.contentutils.DataSourceInfoUtilities; import org.sleuthkit.autopsy.testutils.RandomizationUtils; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; diff --git a/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesSummaryTest.java b/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesSummaryTest.java index 302223a234..244a7da113 100644 --- a/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesSummaryTest.java +++ b/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesSummaryTest.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.datasourcesummary.datamodel; +import org.sleuthkit.autopsy.datasourcesummary.ui.RecentFilesGetter; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; @@ -40,10 +41,10 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import org.sleuthkit.autopsy.contentutils.RecentFilesSummary.RecentAttachmentDetails; -import org.sleuthkit.autopsy.contentutils.RecentFilesSummary.RecentDownloadDetails; -import org.sleuthkit.autopsy.contentutils.RecentFilesSummary.RecentFileDetails; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.RecentFilesSummary.RecentAttachmentDetails; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.RecentFilesSummary.RecentDownloadDetails; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.RecentFilesSummary.RecentFileDetails; +import org.sleuthkit.autopsy.datasourcesummary.ui.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.autopsy.testutils.RandomizationUtils; import org.sleuthkit.autopsy.testutils.TskMockUtils; import org.sleuthkit.datamodel.Blackboard; diff --git a/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummaryTest.java b/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummaryTest.java index 787153543c..0fd7b72d9c 100644 --- a/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummaryTest.java +++ b/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummaryTest.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.datasourcesummary.datamodel; +import org.sleuthkit.autopsy.datasourcesummary.ui.UserActivitySummaryGetter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -43,12 +44,12 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceSummaryMockUtils.getArtifactsTSKMock; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; -import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopAccountResult; -import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopDeviceAttachedResult; -import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopDomainsResult; -import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopProgramsResult; -import org.sleuthkit.autopsy.contentutils.UserActivitySummary.TopWebSearchResult; +import org.sleuthkit.autopsy.datasourcesummary.ui.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopAccountResult; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopDeviceAttachedResult; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopDomainsResult; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopProgramsResult; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopWebSearchResult; import org.sleuthkit.autopsy.testutils.TskMockUtils; import org.sleuthkit.autopsy.texttranslation.NoServiceProviderException; import org.sleuthkit.autopsy.texttranslation.TextTranslationService; From ffd6be1823def155e7a4761edb8deb0557f53fd2 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Wed, 18 Aug 2021 18:18:45 -0400 Subject: [PATCH 26/33] Refactoring report module --- .../datamodel/AnalysisSummary.java | 36 +- .../datamodel/ClosestCityMapper.java | 27 +- .../datamodel/ContainerSummary.java | 63 +-- .../datamodel/DataSourceInfoUtilities.java | 34 +- .../datamodel/GeolocationSummary.java | 49 ++- .../datamodel/PastCasesSummary.java | 64 +++- .../datamodel/RecentFilesSummary.java | 39 +- .../SleuthkitCaseProvider.java | 2 +- .../datamodel/TimelineDataSourceUtils.java | 92 +++++ .../datamodel/TimelineSummary.java | 113 +++--- .../datamodel/TypesSummary.java | 65 ++-- .../datamodel/UserActivitySummary.java | 103 +++-- .../ui/AnalysisSummaryGetter.java | 24 +- .../ui/ContainerSummaryGetter.java | 30 +- .../ui/GeolocationSummaryGetter.java | 12 +- .../ui/MimeTypeSummaryGetter.java | 44 +-- .../ui/PastCasesSummaryGetter.java | 17 +- .../ui/RecentFilesGetter.java | 24 +- .../datasourcesummary/ui/TimelinePanel.java | 9 +- .../ui/TimelinePanel.java.bak | 358 ++++++++++++++++++ .../ui/TimelineSummaryGetter.java | 23 +- .../datasourcesummary/ui/TypesPanel.java | 2 +- .../ui/TypesSummaryGetter.java | 42 +- .../ui/UserActivitySummaryGetter.java | 36 +- .../ExcelExportAction.java | 16 +- .../ExportAnalysisResults.java | 13 +- .../ExportContainerInfo.java | 9 +- .../ExportGeolocation.java | 9 +- .../ExportPastCases.java | 9 +- .../ExportRecentFiles.java | 13 +- .../ExportTimeline.java | 9 +- .../datasourcesummaryexport/ExportTypes.java | 38 +- .../ExportUserActivity.java | 17 +- .../UserActivitySummaryTests.java | 2 +- .../datamodel/RecentFilesSummaryTest.java | 2 +- .../datamodel/UserActivitySummaryTest.java | 2 +- 36 files changed, 991 insertions(+), 456 deletions(-) rename Core/src/org/sleuthkit/autopsy/datasourcesummary/{ui => datamodel}/SleuthkitCaseProvider.java (97%) mode change 100644 => 100755 create mode 100755 Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineDataSourceUtils.java create mode 100755 Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java.bak diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/AnalysisSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/AnalysisSummary.java index e5824b9f3f..60598f7529 100755 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/AnalysisSummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/AnalysisSummary.java @@ -28,8 +28,8 @@ import java.util.function.Function; import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; -import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import org.sleuthkit.datamodel.BlackboardAttribute; @@ -46,7 +46,22 @@ public class AnalysisSummary { private static final BlackboardAttribute.Type TYPE_SET_NAME = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_SET_NAME); private static final Set EXCLUDED_KEYWORD_SEARCH_ITEMS = new HashSet<>(); - private AnalysisSummary() { + private final SleuthkitCaseProvider provider; + + /** + * Main constructor. + */ + public AnalysisSummary() { + this(SleuthkitCaseProvider.DEFAULT); + } + + /** + * Main constructor. + * + * @param provider The means of obtaining a sleuthkit case. + */ + public AnalysisSummary(SleuthkitCaseProvider provider) { + this.provider = provider; } /** @@ -59,7 +74,7 @@ public class AnalysisSummary { * @throws SleuthkitCaseProviderException * @throws TskCoreException */ - public static List> getHashsetCounts(DataSource dataSource) throws NoCurrentCaseException, TskCoreException { + public List> getHashsetCounts(DataSource dataSource) throws SleuthkitCaseProviderException, TskCoreException { return getCountsData(dataSource, TYPE_SET_NAME, ARTIFACT_TYPE.TSK_HASHSET_HIT); } @@ -73,7 +88,7 @@ public class AnalysisSummary { * @throws SleuthkitCaseProviderException * @throws TskCoreException */ - public static List> getKeywordCounts(DataSource dataSource) throws NoCurrentCaseException, TskCoreException { + public List> getKeywordCounts(DataSource dataSource) throws SleuthkitCaseProviderException, TskCoreException { return getCountsData(dataSource, TYPE_SET_NAME, ARTIFACT_TYPE.TSK_KEYWORD_HIT).stream() // make sure we have a valid set and that that set does not belong to the set of excluded items .filter((pair) -> pair != null && pair.getKey() != null && !EXCLUDED_KEYWORD_SEARCH_ITEMS.contains(pair.getKey().toUpperCase().trim())) @@ -92,7 +107,7 @@ public class AnalysisSummary { * @throws SleuthkitCaseProviderException * @throws TskCoreException */ - public static List> getInterestingItemCounts(DataSource dataSource) throws NoCurrentCaseException, TskCoreException { + public List> getInterestingItemCounts(DataSource dataSource) throws SleuthkitCaseProviderException, TskCoreException { return getCountsData(dataSource, TYPE_SET_NAME, ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT); } @@ -107,21 +122,22 @@ public class AnalysisSummary { * value and the value is the count of items found. This list is * sorted by the count descending max to min. * - * @throws NoCurrentCaseException + * @throws SleuthkitCaseProviderException * @throws TskCoreException */ - private static List> getCountsData(DataSource dataSource, BlackboardAttribute.Type keyType, ARTIFACT_TYPE... artifactTypes) - throws NoCurrentCaseException, TskCoreException { + private List> getCountsData(DataSource dataSource, BlackboardAttribute.Type keyType, ARTIFACT_TYPE... artifactTypes) + throws SleuthkitCaseProviderException, TskCoreException { if (dataSource == null) { return Collections.emptyList(); } List artifacts = new ArrayList<>(); + SleuthkitCase skCase = provider.get(); // get all artifacts in one list for each artifact type for (ARTIFACT_TYPE type : artifactTypes) { - artifacts.addAll(Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboard().getArtifacts(type.getTypeID(), dataSource.getId())); + artifacts.addAll(skCase.getBlackboard().getArtifacts(type.getTypeID(), dataSource.getId())); } // group those based on the value of the attribute type that should serve as a key diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ClosestCityMapper.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ClosestCityMapper.java index e2df913534..ecadc0931e 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ClosestCityMapper.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ClosestCityMapper.java @@ -60,9 +60,6 @@ class ClosestCityMapper { // singleton instance of this class private static ClosestCityMapper instance = null; - // the logger - private static final java.util.logging.Logger logger = Logger.getLogger(ClosestCityMapper.class.getName()); - /** * Retrieves singleton instance of this class. * @@ -79,7 +76,10 @@ class ClosestCityMapper { } // data structure housing cities - private static LatLngMap latLngMap = null; + private LatLngMap latLngMap = null; + + // the logger + private final java.util.logging.Logger logger; /** * Main Constructor. @@ -87,7 +87,9 @@ class ClosestCityMapper { * @throws IOException */ private ClosestCityMapper() throws IOException { - this(ClosestCityMapper.class.getResourceAsStream(CITIES_CSV_FILENAME)); + this( + GeolocationSummary.class.getResourceAsStream(CITIES_CSV_FILENAME), + Logger.getLogger(ClosestCityMapper.class.getName())); } /** @@ -99,7 +101,8 @@ class ClosestCityMapper { * * @throws IOException */ - private ClosestCityMapper(InputStream citiesInputStream) throws IOException { + private ClosestCityMapper(InputStream citiesInputStream, java.util.logging.Logger logger) throws IOException { + this.logger = logger; latLngMap = new LatLngMap(parseCsvLines(citiesInputStream, true)); } @@ -111,7 +114,7 @@ class ClosestCityMapper { * * @return The closest city or null if no close city can be found. */ - static CityRecord findClosest(CityRecord point) { + CityRecord findClosest(CityRecord point) { return latLngMap.findClosest(point); } @@ -123,7 +126,7 @@ class ClosestCityMapper { * * @return The double value or null if value cannot be parsed. */ - private static Double tryParse(String s) { + private Double tryParse(String s) { if (s == null) { return null; } @@ -144,7 +147,7 @@ class ClosestCityMapper { * * @return The country name. */ - private static String parseCountryName(String orig, int lineNum) { + private String parseCountryName(String orig, int lineNum) { if (StringUtils.isBlank(orig)) { logger.log(Level.WARNING, String.format("No country name determined for line %d.", lineNum)); return null; @@ -167,7 +170,7 @@ class ClosestCityMapper { * * @return The parsed CityRecord or null if none can be determined. */ - private static CityRecord getCsvCityRecord(List csvRow, int lineNum) { + private CityRecord getCsvCityRecord(List csvRow, int lineNum) { if (csvRow == null || csvRow.size() <= MAX_IDX) { logger.log(Level.WARNING, String.format("Row at line number %d is required to have at least %d elements and does not.", lineNum, (MAX_IDX + 1))); return null; @@ -207,7 +210,7 @@ class ClosestCityMapper { * * @return The list of column values. */ - private static List parseCsvLine(String line, int lineNum) { + private List parseCsvLine(String line, int lineNum) { if (line == null || line.length() <= 0) { logger.log(Level.INFO, String.format("Line at %d had no content", lineNum)); return null; @@ -234,7 +237,7 @@ class ClosestCityMapper { * * @throws IOException */ - private static List parseCsvLines(InputStream csvInputStream, boolean ignoreHeaderRow) throws IOException { + private List parseCsvLines(InputStream csvInputStream, boolean ignoreHeaderRow) throws IOException { List cityRecords = new ArrayList<>(); try (BufferedReader reader = new BufferedReader(new InputStreamReader(csvInputStream, "UTF-8"))) { int lineNum = 1; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummary.java index 7bd34016f3..428c92047f 100755 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummary.java @@ -38,7 +38,22 @@ import org.sleuthkit.datamodel.TskData; */ public class ContainerSummary { - private ContainerSummary() { + private final SleuthkitCaseProvider provider; + + /** + * Main constructor. + */ + public ContainerSummary() { + this(SleuthkitCaseProvider.DEFAULT); + } + + /** + * Main constructor. + * + * @param provider The means of obtaining a sleuthkit case. + */ + public ContainerSummary(SleuthkitCaseProvider provider) { + this.provider = provider; } /** @@ -48,12 +63,12 @@ public class ContainerSummary { * * @return The size or null if the query could not be executed. * - * @throws NoCurrentCaseException + * @throws SleuthkitCaseProviderException * @throws TskCoreException * @throws SQLException */ - public static Long getSizeOfUnallocatedFiles(DataSource currentDataSource) - throws TskCoreException, SQLException, NoCurrentCaseException { + public Long getSizeOfUnallocatedFiles(DataSource currentDataSource) + throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException { if (currentDataSource == null) { return null; } @@ -79,7 +94,7 @@ public class ContainerSummary { } }; - return DataSourceInfoUtilities.getBaseQueryResult(query, handler); + return DataSourceInfoUtilities.getBaseQueryResult(provider.get(), query, handler); } /** @@ -91,12 +106,12 @@ public class ContainerSummary { * @return The concatenated value or null if the query could not be * executed. * - * @throws NoCurrentCaseException + * @throws SleuthkitCaseProviderException * @throws TskCoreException * @throws SQLException */ - public static String getOperatingSystems(DataSource dataSource) - throws TskCoreException, SQLException, NoCurrentCaseException { + public String getOperatingSystems(DataSource dataSource) + throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException { if (dataSource == null) { return null; @@ -116,12 +131,12 @@ public class ContainerSummary { * @return The concatenated value or null if the query could not be * executed. * - * @throws NoCurrentCaseException + * @throws SleuthkitCaseProviderException * @throws TskCoreException * @throws SQLException */ - public static String getDataSourceType(DataSource dataSource) - throws TskCoreException, SQLException, NoCurrentCaseException { + public String getDataSourceType(DataSource dataSource) + throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException { if (dataSource == null) { return null; @@ -136,19 +151,19 @@ public class ContainerSummary { * Generates a string which is a concatenation of the value received from * the result set. * - * @param query The query. - * @param valueParam The parameter for the value in the result set. - * @param separator The string separator used in concatenation. + * @param query The query. + * @param valueParam The parameter for the value in the result set. + * @param separator The string separator used in concatenation. * * @return The concatenated string or null if the query could not be * executed. * - * @throws NoCurrentCaseException + * @throws SleuthkitCaseProviderException * @throws TskCoreException * @throws SQLException */ - private static String getConcattedStringsResult(String query, String valueParam, String separator) - throws TskCoreException, SQLException, NoCurrentCaseException { + private String getConcattedStringsResult(String query, String valueParam, String separator) + throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException { DataSourceInfoUtilities.ResultSetHandler handler = (resultSet) -> { String toRet = ""; @@ -165,7 +180,7 @@ public class ContainerSummary { return toRet; }; - return DataSourceInfoUtilities.getBaseQueryResult(query, handler); + return DataSourceInfoUtilities.getBaseQueryResult(provider.get(), query, handler); } /** @@ -179,12 +194,12 @@ public class ContainerSummary { * @return The concatenated value or null if the query could not be * executed. * - * @throws NoCurrentCaseException + * @throws SleuthkitCaseProviderException * @throws TskCoreException * @throws SQLException */ - private static String getConcattedAttrValue(long dataSourceId, int artifactTypeId, int attributeTypeId) - throws TskCoreException, SQLException, NoCurrentCaseException { + private String getConcattedAttrValue(long dataSourceId, int artifactTypeId, int attributeTypeId) + throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException { final String valueParam = "concatted_attribute_value"; String query = "SELECT attr.value_text AS " + valueParam @@ -198,6 +213,8 @@ public class ContainerSummary { return getConcattedStringsResult(query, valueParam, separator); } + // ELTODO everything below is NOT in develop! + /** * Data model data for data source images. */ @@ -383,7 +400,7 @@ public class ContainerSummary { * * @return The generated view model. */ - public static ContainerDetails getContainerDetails(DataSource ds) throws TskCoreException, SQLException, NoCurrentCaseException { + public ContainerDetails getContainerDetails(DataSource ds) throws TskCoreException, SQLException, SleuthkitCaseProvider.SleuthkitCaseProviderException { if (ds == null) { return null; } @@ -404,7 +421,7 @@ public class ContainerSummary { * * @return The generated view model. */ - public static ImageDetails getImageDetails(Image image) throws TskCoreException, SQLException, NoCurrentCaseException { + public ImageDetails getImageDetails(Image image) throws TskCoreException, SQLException, SleuthkitCaseProvider.SleuthkitCaseProviderException { if (image == null) { return null; } diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceInfoUtilities.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceInfoUtilities.java index 2847ea4510..7e51a53037 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceInfoUtilities.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceInfoUtilities.java @@ -52,6 +52,7 @@ public final class DataSourceInfoUtilities { /** * 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. * @@ -59,12 +60,11 @@ public final class DataSourceInfoUtilities { * * @throws TskCoreException * @throws SQLException - * @throws NoCurrentCaseException */ - public static Long getCountOfTskFiles(DataSource currentDataSource, String additionalWhere) - throws TskCoreException, SQLException, NoCurrentCaseException { + static Long getCountOfTskFiles(SleuthkitCase skCase, DataSource currentDataSource, String additionalWhere) + throws TskCoreException, SQLException { if (currentDataSource != null) { - return Case.getCurrentCaseThrows().getSleuthkitCase().countFilesWhere( + return skCase.countFilesWhere( "data_source_obj_id=" + currentDataSource.getId() + (StringUtils.isBlank(additionalWhere) ? "" : (" AND " + additionalWhere))); } @@ -74,6 +74,7 @@ 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. * @@ -81,22 +82,22 @@ public final class DataSourceInfoUtilities { * * @throws TskCoreException * @throws SQLException - * @throws NoCurrentCaseException */ - public static Long getCountOfRegularFiles(DataSource currentDataSource, String additionalWhere) - throws TskCoreException, SQLException, NoCurrentCaseException { + static Long getCountOfRegularFiles(SleuthkitCase skCase, DataSource currentDataSource, String additionalWhere) + throws TskCoreException, SQLException { String whereClause = "meta_type=" + TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG.getValue(); if (StringUtils.isNotBlank(additionalWhere)) { whereClause += " AND " + additionalWhere; } - return getCountOfTskFiles(currentDataSource, whereClause); + return getCountOfTskFiles(skCase, 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. * @@ -104,10 +105,9 @@ public final class DataSourceInfoUtilities { * * @throws TskCoreException * @throws SQLException - * @throws NoCurrentCaseException */ - public static Long getCountOfRegNonSlackFiles(DataSource currentDataSource, String additionalWhere) - throws TskCoreException, SQLException, NoCurrentCaseException { + public static Long getCountOfRegNonSlackFiles(SleuthkitCase skCase, DataSource currentDataSource, String additionalWhere) + throws TskCoreException, SQLException { String whereClause = "meta_type=" + TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG.getValue() + " AND type<>" + TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType(); @@ -115,7 +115,7 @@ public final class DataSourceInfoUtilities { whereClause += " AND " + additionalWhere; } - return getCountOfTskFiles(currentDataSource, whereClause); + return getCountOfTskFiles(skCase, currentDataSource, whereClause); } /** @@ -129,6 +129,7 @@ public final class DataSourceInfoUtilities { /** * Retrieves a result based on the provided query. * + * @param skCase The current SleuthkitCase. * @param query The query. * @param processor The result set handler. * @@ -137,11 +138,10 @@ public final class DataSourceInfoUtilities { * * @throws TskCoreException * @throws SQLException - * @throws NoCurrentCaseException */ - public static T getBaseQueryResult(String query, ResultSetHandler processor) - throws TskCoreException, SQLException, NoCurrentCaseException { - try (SleuthkitCase.CaseDbQuery dbQuery = Case.getCurrentCaseThrows().getSleuthkitCase().executeQuery(query)) { + static T getBaseQueryResult(SleuthkitCase skCase, String query, ResultSetHandler processor) + throws TskCoreException, SQLException { + try (SleuthkitCase.CaseDbQuery dbQuery = skCase.executeQuery(query)) { ResultSet resultSet = dbQuery.getResultSet(); return processor.process(resultSet); } @@ -433,6 +433,8 @@ public final class DataSourceInfoUtilities { Long longVal = getLongOrNull(artifact, attributeType); return (longVal == null || longVal == 0) ? null : new Date(longVal * 1000); } + + // ELTODO everything below is not in develop /** * Returns the long value or zero if longVal is null. diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/GeolocationSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/GeolocationSummary.java index b011dd8f4e..1b8f2feb8e 100755 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/GeolocationSummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/GeolocationSummary.java @@ -31,8 +31,7 @@ import java.util.concurrent.BlockingQueue; import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.commons.lang3.tuple.Pair; -import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.autopsy.geolocation.AbstractWaypointFetcher; import org.sleuthkit.autopsy.geolocation.GeoFilter; import org.sleuthkit.autopsy.geolocation.MapWaypoint; @@ -238,12 +237,13 @@ public class GeolocationSummary { private static final long DAY_SECS = 24 * 60 * 60; - private static final SupplierWithException cityMapper = () -> ClosestCityMapper.getInstance(); + private final SleuthkitCaseProvider provider; + private final SupplierWithException cityMapper; /** * A supplier of an item T that can throw an exception of type E. */ - interface SupplierWithException { + public interface SupplierWithException { /** * A supplier method that can throw an exception of E. @@ -255,7 +255,23 @@ public class GeolocationSummary { T get() throws E; } - private GeolocationSummary() { + /** + * Default constructor. + */ + public GeolocationSummary() { + this(() -> ClosestCityMapper.getInstance(), SleuthkitCaseProvider.DEFAULT); + } + + /** + * Main constructor. + * + * @param cityMapper A means of acquiring a ClosestCityMapper that can throw + * an IOException. + * @param provider A means of acquiring a SleuthkitCaseProvider. + */ + public GeolocationSummary(SupplierWithException cityMapper, SleuthkitCaseProvider provider) { + this.cityMapper = cityMapper; + this.provider = provider; } /** @@ -321,7 +337,7 @@ public class GeolocationSummary { * * @return A tuple of the closest city and timestamp in seconds from epoch. */ - private static Pair getClosestWithTime(ClosestCityMapper cityMapper, MapWaypoint pt) { + private Pair getClosestWithTime(ClosestCityMapper cityMapper, MapWaypoint pt) { if (pt == null) { return null; } @@ -344,7 +360,7 @@ public class GeolocationSummary { * null if a closest is not determined) and the latest timestamp for * each. */ - private static Stream> reduceGrouping(Set points, ClosestCityMapper cityMapper) { + private Stream> reduceGrouping(Set points, ClosestCityMapper cityMapper) { if (points == null) { return Stream.empty(); } @@ -381,7 +397,7 @@ public class GeolocationSummary { * * @throws IOException */ - private static Stream> processGeoResult(GeoResult geoResult, ClosestCityMapper cityMapper) { + private Stream> processGeoResult(GeoResult geoResult, ClosestCityMapper cityMapper) { if (geoResult == null) { return Stream.empty(); } @@ -418,14 +434,14 @@ public class GeolocationSummary { * * @return The sorted list. * - * @throws NoCurrentCaseException + * @throws SleuthkitCaseProviderException * @throws GeoLocationDataException * @throws InterruptedException */ - public static CityData getCityCounts(DataSource dataSource, int daysCount, int maxCount) - throws NoCurrentCaseException, GeoLocationDataException, InterruptedException, IOException { + public CityData getCityCounts(DataSource dataSource, int daysCount, int maxCount) + throws SleuthkitCaseProviderException, GeoLocationDataException, InterruptedException, IOException { - ClosestCityMapper closestCityMapper = cityMapper.get(); + ClosestCityMapper closestCityMapper = this.cityMapper.get(); GeoResult geoResult = getGeoResult(dataSource); List> dataSourcePoints = processGeoResult(geoResult, closestCityMapper) .collect(Collectors.toList()); @@ -524,13 +540,12 @@ public class GeolocationSummary { * @param dataSource The data source. * * @return The GPS data pertaining to the data source. - * - * @throws NoCurrentCaseException + * @throws SleuthkitCaseProviderException * @throws GeoLocationDataException * @throws InterruptedException */ - private static GeoResult getGeoResult(DataSource dataSource) - throws NoCurrentCaseException, GeoLocationDataException, InterruptedException { + private GeoResult getGeoResult(DataSource dataSource) + throws SleuthkitCaseProviderException, GeoLocationDataException, InterruptedException { // make asynchronous callback synchronous (the callback nature will be handled in a different level) // see the following: https://stackoverflow.com/questions/20659961/java-synchronous-callback @@ -538,7 +553,7 @@ public class GeolocationSummary { GeoFilter geoFilter = new GeoFilter(true, false, 0, Arrays.asList(dataSource), GPS_ARTIFACT_TYPES); - WaypointBuilder.getAllWaypoints(Case.getCurrentCaseThrows().getSleuthkitCase(), + WaypointBuilder.getAllWaypoints(provider.get(), Arrays.asList(dataSource), GPS_ARTIFACT_TYPES, true, diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/PastCasesSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/PastCasesSummary.java index 5bfe52261c..66e265e128 100755 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/PastCasesSummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/PastCasesSummary.java @@ -25,12 +25,12 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.logging.Level; import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.commons.lang3.tuple.Pair; -import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.centralrepository.ingestmodule.CentralRepoIngestModuleFactory; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import org.sleuthkit.datamodel.BlackboardAttribute; @@ -111,7 +111,34 @@ public class PastCasesSummary { private static final String CASE_SEPARATOR = ","; private static final String PREFIX_END = ":"; - private PastCasesSummary() { + private final SleuthkitCaseProvider caseProvider; + private final java.util.logging.Logger logger; + + /** + * Main constructor. + */ + public PastCasesSummary() { + this( + SleuthkitCaseProvider.DEFAULT, + org.sleuthkit.autopsy.coreutils.Logger.getLogger(PastCasesSummary.class.getName()) + ); + + } + + /** + * Main constructor with external dependencies specified. This constructor + * is designed with unit testing in mind since mocked dependencies can be + * utilized. + * + * @param provider The object providing the current SleuthkitCase. + * @param logger The logger to use. + */ + public PastCasesSummary( + SleuthkitCaseProvider provider, + java.util.logging.Logger logger) { + + this.caseProvider = provider; + this.logger = logger; } /** @@ -211,24 +238,21 @@ public class PastCasesSummary { * * @return The artifact if found or null if not. * - * @throws NoCurrentCaseException + * @throws SleuthkitCaseProviderException */ - private static BlackboardArtifact getParentArtifact(BlackboardArtifact artifact) throws NoCurrentCaseException { + private BlackboardArtifact getParentArtifact(BlackboardArtifact artifact) throws SleuthkitCaseProviderException { Long parentId = DataSourceInfoUtilities.getLongOrNull(artifact, TYPE_ASSOCIATED_ARTIFACT); if (parentId == null) { return null; } + SleuthkitCase skCase = caseProvider.get(); try { - return Case.getCurrentCaseThrows().getSleuthkitCase().getArtifactByArtifactId(parentId); - } catch (TskCoreException ignore) { - /* - * I'm not certain why we ignore this, but it was previously simply - * logged as warning so I'm keeping the original logic - * logger.log(Level.WARNING, String.format("There was an error - * fetching the parent artifact of a TSK_INTERESTING_ARTIFACT_HIT - * (parent id: %d)", parentId), ex); - */ + return skCase.getArtifactByArtifactId(parentId); + } catch (TskCoreException ex) { + logger.log(Level.WARNING, + String.format("There was an error fetching the parent artifact of a TSK_INTERESTING_ARTIFACT_HIT (parent id: %d)", parentId), + ex); return null; } } @@ -240,9 +264,9 @@ public class PastCasesSummary { * * @return True if there is a device associated artifact. * - * @throws NoCurrentCaseException + * @throws SleuthkitCaseProviderException */ - private static boolean hasDeviceAssociatedArtifact(BlackboardArtifact artifact) throws NoCurrentCaseException { + private boolean hasDeviceAssociatedArtifact(BlackboardArtifact artifact) throws SleuthkitCaseProviderException { BlackboardArtifact parent = getParentArtifact(artifact); if (parent == null) { return false; @@ -258,17 +282,17 @@ public class PastCasesSummary { * * @return The retrieved data or null if null dataSource. * - * @throws NoCurrentCaseException + * @throws SleuthkitCaseProviderException * @throws TskCoreException */ - public static PastCasesResult getPastCasesData(DataSource dataSource) - throws NoCurrentCaseException, TskCoreException { + public PastCasesResult getPastCasesData(DataSource dataSource) + throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException { if (dataSource == null) { return null; } - SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase(); + SleuthkitCase skCase = caseProvider.get(); List deviceArtifactCases = new ArrayList<>(); List nonDeviceArtifactCases = new ArrayList<>(); diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesSummary.java index 77504394dd..1beb97766b 100755 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesSummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesSummary.java @@ -29,8 +29,7 @@ import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; import org.apache.commons.lang.StringUtils; -import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; @@ -55,10 +54,26 @@ public class RecentFilesSummary { private static final DateFormat DATETIME_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss", Locale.getDefault()); + private final SleuthkitCaseProvider provider; + /** * Default constructor. */ - private RecentFilesSummary() { + public RecentFilesSummary() { + this(SleuthkitCaseProvider.DEFAULT); + } + + /** + * Construct object with given SleuthkitCaseProvider + * + * @param provider SleuthkitCaseProvider provider, cannot be null. + */ + public RecentFilesSummary(SleuthkitCaseProvider provider) { + if (provider == null) { + throw new IllegalArgumentException("Unable to construct RecentFileSummary object. SleuthkitCaseProvider cannot be null"); + } + + this.provider = provider; } /** @@ -112,17 +127,17 @@ public class RecentFilesSummary { * @return A list RecentFileDetails representing the most recently opened * documents or an empty list if none were found. * - * @throws NoCurrentCaseException + * @throws SleuthkitCaseProviderException * @throws TskCoreException */ - public static List getRecentlyOpenedDocuments(DataSource dataSource, int maxCount) throws TskCoreException, NoCurrentCaseException { + public List getRecentlyOpenedDocuments(DataSource dataSource, int maxCount) throws SleuthkitCaseProviderException, TskCoreException { if (dataSource == null) { return Collections.emptyList(); } throwOnNonPositiveCount(maxCount); - List details = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboard() + List details = provider.get().getBlackboard() .getArtifacts(ARTIFACT_TYPE.TSK_RECENT_OBJECT.getTypeID(), dataSource.getId()).stream() .map(art -> getRecentlyOpenedDocument(art)) .filter(d -> d != null) @@ -173,16 +188,16 @@ public class RecentFilesSummary { * found. * * @throws TskCoreException - * @throws NoCurrentCaseException + * @throws SleuthkitCaseProviderException */ - public static List getRecentDownloads(DataSource dataSource, int maxCount) throws TskCoreException, NoCurrentCaseException { + public List getRecentDownloads(DataSource dataSource, int maxCount) throws TskCoreException, SleuthkitCaseProviderException { if (dataSource == null) { return Collections.emptyList(); } throwOnNonPositiveCount(maxCount); - List details = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboard() + List details = provider.get().getBlackboard() .getArtifacts(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID(), dataSource.getId()).stream() .map(art -> getRecentDownload(art)) .filter(d -> d != null) @@ -200,17 +215,17 @@ public class RecentFilesSummary { * * @return A list of RecentFileDetails of the most recent attachments. * - * @throws NoCurrentCaseException + * @throws SleuthkitCaseProviderException * @throws TskCoreException */ - public static List getRecentAttachments(DataSource dataSource, int maxCount) throws NoCurrentCaseException, TskCoreException { + public List getRecentAttachments(DataSource dataSource, int maxCount) throws SleuthkitCaseProviderException, TskCoreException { if (dataSource == null) { return Collections.emptyList(); } throwOnNonPositiveCount(maxCount); - SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase(); + SleuthkitCase skCase = provider.get(); List associatedArtifacts = skCase.getBlackboard() .getArtifacts(ASSOCATED_OBJ_ART.getTypeID(), dataSource.getId()); diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/SleuthkitCaseProvider.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/SleuthkitCaseProvider.java old mode 100644 new mode 100755 similarity index 97% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/SleuthkitCaseProvider.java rename to Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/SleuthkitCaseProvider.java index 90afc2d597..8371b2fefd --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/SleuthkitCaseProvider.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/SleuthkitCaseProvider.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datasourcesummary.ui; +package org.sleuthkit.autopsy.datasourcesummary.datamodel; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineDataSourceUtils.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineDataSourceUtils.java new file mode 100755 index 0000000000..6528284911 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineDataSourceUtils.java @@ -0,0 +1,92 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.datasourcesummary.datamodel; + +import org.sleuthkit.autopsy.timeline.TimeLineController; +import org.sleuthkit.autopsy.timeline.TimeLineModule; +import org.sleuthkit.autopsy.timeline.ui.filtering.datamodel.FilterState; +import org.sleuthkit.autopsy.timeline.ui.filtering.datamodel.RootFilterState; +import org.sleuthkit.datamodel.DataSource; +import org.sleuthkit.datamodel.TimelineFilter; +import org.sleuthkit.datamodel.TimelineFilter.DataSourceFilter; +import org.sleuthkit.datamodel.TimelineFilter.RootFilter; +import org.sleuthkit.datamodel.TskCoreException; + +/** + * Utilities for interacting with Timeline in relation to data sources. + */ +public class TimelineDataSourceUtils { + + private static TimelineDataSourceUtils instance = null; + + /** + * @return Singleton instance of this class. + */ + public static TimelineDataSourceUtils getInstance() { + if (instance == null) { + instance = new TimelineDataSourceUtils(); + } + + return instance; + } + + /** + * Main constructor. Should be instantiated through getInstance(). + */ + private TimelineDataSourceUtils() { + } + + /** + * Retrieves a RootFilter based on the default filter state but only the + * specified dataSource is selected. + * + * @param dataSource The data source. + * @return The root filter representing a default filter with only this data + * source selected. + * @throws TskCoreException + */ + public RootFilter getDataSourceFilter(DataSource dataSource) throws TskCoreException { + RootFilterState filterState = getDataSourceFilterState(dataSource); + return filterState == null ? null : filterState.getActiveFilter(); + } + + /** + * Retrieves a TimeLineController based on the default filter state but only + * the specified dataSource is selected. + * + * @param dataSource The data source. + * @return The root filter state representing a default filter with only + * this data source selected. + * @throws TskCoreException + */ + public RootFilterState getDataSourceFilterState(DataSource dataSource) throws TskCoreException { + TimeLineController controller = TimeLineModule.getController(); + RootFilterState dataSourceState = controller.getEventsModel().getDefaultEventFilterState().copyOf(); + + for (FilterState filterState : dataSourceState.getDataSourcesFilterState().getSubFilterStates()) { + DataSourceFilter dsFilter = filterState.getFilter(); + if (dsFilter != null) { + filterState.setSelected(dsFilter.getDataSourceID() == dataSource.getId()); + } + + } + + return dataSourceState; + } +} diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java index c21927b4df..28c616a89f 100755 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TimelineSummary.java @@ -39,21 +39,31 @@ import org.sleuthkit.datamodel.TimelineEventType; import org.sleuthkit.datamodel.TimelineFilter.RootFilter; import org.sleuthkit.datamodel.TimelineManager; import org.sleuthkit.datamodel.TskCoreException; -import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import java.util.function.Supplier; import org.sleuthkit.autopsy.core.UserPreferences; -import org.sleuthkit.autopsy.timeline.TimeLineController; -import org.sleuthkit.autopsy.timeline.TimeLineModule; -import org.sleuthkit.autopsy.timeline.ui.filtering.datamodel.FilterState; -import org.sleuthkit.autopsy.timeline.ui.filtering.datamodel.RootFilterState; -import org.sleuthkit.datamodel.TimelineFilter; /** * Provides data source summary information pertaining to Timeline data. */ public class TimelineSummary { - private static final TimeZone timeZone = TimeZone.getTimeZone(UserPreferences.getTimeZoneForDisplays()); + /** + * A function for obtaining a Timeline RootFilter filtered to the specific + * data source. + */ + public interface DataSourceFilterFunction { + + /** + * Obtains a Timeline RootFilter filtered to the specific data source. + * + * @param dataSource The data source. + * @return The timeline root filter. + * @throws SleuthkitCaseProviderException + * @throws TskCoreException + */ + RootFilter apply(DataSource dataSource) throws SleuthkitCaseProviderException, TskCoreException; + } private static final long DAY_SECS = 24 * 60 * 60; private static final Set FILE_SYSTEM_EVENTS @@ -63,7 +73,31 @@ public class TimelineSummary { TimelineEventType.FILE_CREATED, TimelineEventType.FILE_CHANGED)); - private TimelineSummary() { + private final SleuthkitCaseProvider caseProvider; + private final Supplier timeZoneProvider; + private final DataSourceFilterFunction filterFunction; + + /** + * Default constructor. + */ + public TimelineSummary() { + this(SleuthkitCaseProvider.DEFAULT, + () -> TimeZone.getTimeZone(UserPreferences.getTimeZoneForDisplays()), + (ds) -> TimelineDataSourceUtils.getInstance().getDataSourceFilter(ds)); + } + + /** + * Construct object with given SleuthkitCaseProvider + * + * @param caseProvider SleuthkitCaseProvider provider; cannot be null. + * @param timeZoneProvider The timezone provider; cannot be null. + * @param filterFunction Provides the default root filter function filtered + * to the data source; cannot be null. + */ + public TimelineSummary(SleuthkitCaseProvider caseProvider, Supplier timeZoneProvider, DataSourceFilterFunction filterFunction) { + this.caseProvider = caseProvider; + this.timeZoneProvider = timeZoneProvider; + this.filterFunction = filterFunction; } /** @@ -75,12 +109,12 @@ public class TimelineSummary { * include. * * @return The retrieved data. - * + * @throws SleuthkitCaseProviderException * @throws TskCoreException - * @throws NoCurrentCaseException */ - public static TimelineSummaryData getTimelineSummaryData(DataSource dataSource, int recentDaysNum) throws TskCoreException, NoCurrentCaseException { - TimelineManager timelineManager = Case.getCurrentCaseThrows().getSleuthkitCase().getTimelineManager(); + public TimelineSummaryData getTimelineSummaryData(DataSource dataSource, int recentDaysNum) throws SleuthkitCaseProviderException, TskCoreException { + TimeZone timeZone = this.timeZoneProvider.get(); + TimelineManager timelineManager = this.caseProvider.get().getTimelineManager(); // get a mapping of days from epoch to the activity for that day Map dateCounts = getTimelineEventsByDay(dataSource, timelineManager, timeZone); @@ -122,7 +156,7 @@ public class TimelineSummary { * * @return The most recent daily activity amounts. */ - private static List getMostRecentActivityAmounts(Map dateCounts, long minRecentDay, long maxDay) { + private List getMostRecentActivityAmounts(Map dateCounts, long minRecentDay, long maxDay) { List mostRecentActivityAmt = new ArrayList<>(); for (long curRecentDay = minRecentDay; curRecentDay <= maxDay; curRecentDay++) { @@ -148,11 +182,10 @@ public class TimelineSummary { * @return A Map mapping days from epoch to the activity for that day. * * @throws TskCoreException - * @throws NoCurrentCaseException */ - private static Map getTimelineEventsByDay(DataSource dataSource, TimelineManager timelineManager, TimeZone timeZone) - throws TskCoreException, NoCurrentCaseException { - RootFilter rootFilter = getDataSourceFilter(dataSource); + private Map getTimelineEventsByDay(DataSource dataSource, TimelineManager timelineManager, TimeZone timeZone) + throws TskCoreException, SleuthkitCaseProviderException { + RootFilter rootFilter = this.filterFunction.apply(dataSource); // get events for data source long curRunTime = System.currentTimeMillis(); @@ -287,50 +320,6 @@ public class TimelineSummary { } } - /** - * Retrieves a RootFilter based on the default filter state but only the - * specified dataSource is selected. - * - * @param dataSource The data source. - * - * @return The root filter representing a default filter with only this data - * source selected. - * - * @throws NoCurrentCaseException - * @throws TskCoreException - */ - public static RootFilter getDataSourceFilter(DataSource dataSource) throws NoCurrentCaseException, TskCoreException { - RootFilterState filterState = getDataSourceFilterState(dataSource); - return filterState == null ? null : filterState.getActiveFilter(); - } - - /** - * Retrieves a TimeLineController based on the default filter state but only - * the specified dataSource is selected. - * - * @param dataSource The data source. - * - * @return The root filter state representing a default filter with only - * this data source selected. - * - * @throws NoCurrentCaseException - * @throws TskCoreException - */ - public static RootFilterState getDataSourceFilterState(DataSource dataSource) throws NoCurrentCaseException, TskCoreException { - TimeLineController controller = TimeLineModule.getController(); - RootFilterState dataSourceState = controller.getEventsModel().getDefaultEventFilterState().copyOf(); - - for (FilterState filterState : dataSourceState.getDataSourcesFilterState().getSubFilterStates()) { - TimelineFilter.DataSourceFilter dsFilter = filterState.getFilter(); - if (dsFilter != null) { - filterState.setSelected(dsFilter.getDataSourceID() == dataSource.getId()); - } - - } - - return dataSourceState; - } - /** * Creates a DateFormat formatter that uses UTC for time zone. * diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TypesSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TypesSummary.java index a0fc5c7aa9..6c1b71861b 100755 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TypesSummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TypesSummary.java @@ -21,7 +21,6 @@ package org.sleuthkit.autopsy.datasourcesummary.datamodel; 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; @@ -33,9 +32,25 @@ import org.sleuthkit.datamodel.TskData; */ public class TypesSummary { - private TypesSummary() { + 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; + } + + /** * Get count of regular files (not directories) in a data source. * @@ -43,13 +58,17 @@ public class TypesSummary { * * @return The count. * + * @throws SleuthkitCaseProviderException * @throws TskCoreException * @throws SQLException - * @throws NoCurrentCaseException */ - public static Long getCountOfFiles(DataSource currentDataSource) - throws TskCoreException, SQLException, NoCurrentCaseException { - return DataSourceInfoUtilities.getCountOfRegularFiles(currentDataSource, null); + public Long getCountOfFiles(DataSource currentDataSource) + throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException { + return DataSourceInfoUtilities.getCountOfRegularFiles( + provider.get(), + currentDataSource, + null + ); } /** @@ -59,14 +78,14 @@ public class TypesSummary { * * @return The count. * + * @throws SleuthkitCaseProviderException * @throws TskCoreException * @throws SQLException - * @throws NoCurrentCaseException */ - public static Long getCountOfAllocatedFiles(DataSource currentDataSource) - throws TskCoreException, SQLException, NoCurrentCaseException { + public Long getCountOfAllocatedFiles(DataSource currentDataSource) + throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException { - return DataSourceInfoUtilities.getCountOfRegNonSlackFiles(currentDataSource, + return DataSourceInfoUtilities.getCountOfRegNonSlackFiles(provider.get(), currentDataSource, DataSourceInfoUtilities.getMetaFlagsContainsStatement(TskData.TSK_FS_META_FLAG_ENUM.ALLOC)); } @@ -77,14 +96,14 @@ public class TypesSummary { * * @return The count. * + * @throws SleuthkitCaseProviderException * @throws TskCoreException * @throws SQLException - * @throws NoCurrentCaseException */ - public static Long getCountOfUnallocatedFiles(DataSource currentDataSource) - throws NoCurrentCaseException, TskCoreException, SQLException { + public Long getCountOfUnallocatedFiles(DataSource currentDataSource) + throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException { - return DataSourceInfoUtilities.getCountOfRegNonSlackFiles(currentDataSource, + return DataSourceInfoUtilities.getCountOfRegNonSlackFiles(provider.get(), currentDataSource, DataSourceInfoUtilities.getMetaFlagsContainsStatement(TskData.TSK_FS_META_FLAG_ENUM.UNALLOC)); } @@ -95,14 +114,14 @@ public class TypesSummary { * * @return The count. * + * @throws SleuthkitCaseProviderException * @throws TskCoreException * @throws SQLException - * @throws NoCurrentCaseException */ - public static Long getCountOfDirectories(DataSource currentDataSource) - throws NoCurrentCaseException, TskCoreException, SQLException { + public Long getCountOfDirectories(DataSource currentDataSource) + throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException { - return DataSourceInfoUtilities.getCountOfTskFiles(currentDataSource, + 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()); } @@ -114,16 +133,18 @@ public class TypesSummary { * * @return The count. * + * @throws SleuthkitCaseProviderException * @throws TskCoreException * @throws SQLException - * @throws NoCurrentCaseException */ - public static Long getCountOfSlackFiles(DataSource currentDataSource) - throws NoCurrentCaseException, TskCoreException, SQLException { + public Long getCountOfSlackFiles(DataSource currentDataSource) + throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException { - return DataSourceInfoUtilities.getCountOfRegularFiles(currentDataSource, + return DataSourceInfoUtilities.getCountOfRegularFiles(provider.get(), currentDataSource, "type=" + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType()); } + + // ELTODO everything below is not in develop /** * Information concerning a particular file type category. diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummary.java index 5b51d10461..8310c1f5b0 100755 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummary.java @@ -31,13 +31,13 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.Function; +import java.util.logging.Level; import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.DataSource; @@ -144,7 +144,35 @@ public class UserActivitySummary { private static final long DOMAIN_WINDOW_DAYS = 30; private static final long DOMAIN_WINDOW_MS = DOMAIN_WINDOW_DAYS * MS_PER_DAY; - private UserActivitySummary() { + private final SleuthkitCaseProvider caseProvider; + private final TextTranslationService translationService; + private final java.util.logging.Logger logger; + + /** + * Main constructor. + */ + public UserActivitySummary() { + this(SleuthkitCaseProvider.DEFAULT, TextTranslationService.getInstance(), + org.sleuthkit.autopsy.coreutils.Logger.getLogger(UserActivitySummary.class.getName())); + } + + /** + * Main constructor with external dependencies specified. This constructor + * is designed with unit testing in mind since mocked dependencies can be + * utilized. + * + * @param provider The object providing the current SleuthkitCase. + * @param translationService The translation service. + * @param logger The logger to use. + */ + public UserActivitySummary( + SleuthkitCaseProvider provider, + TextTranslationService translationService, + java.util.logging.Logger logger) { + + this.caseProvider = provider; + this.translationService = translationService; + this.logger = logger; } /** @@ -158,6 +186,7 @@ public class UserActivitySummary { } } + // ELTODO this method is not in develop /** * Determines a short folder name if any. Otherwise, returns empty string. * @@ -199,10 +228,9 @@ public class UserActivitySummary { * * @return The list of items retrieved from the database. * - * @throws TskCoreException - * @throws NoCurrentCaseException + * @throws InterruptedException */ - public static List getRecentDomains(DataSource dataSource, int count) throws TskCoreException, NoCurrentCaseException { + public List getRecentDomains(DataSource dataSource, int count) throws TskCoreException, SleuthkitCaseProviderException { assertValidCount(count); if (dataSource == null) { @@ -240,7 +268,7 @@ public class UserActivitySummary { * @return The TopDomainsResult or null if no visits to this domain within * 30 days of mostRecentMs. */ - private static TopDomainsResult getDomainsResult(String domain, List> visits, long mostRecentMs) { + private TopDomainsResult getDomainsResult(String domain, List> visits, long mostRecentMs) { long visitCount = 0; Long thisMostRecentMs = null; BlackboardArtifact thisMostRecentArtifact = null; @@ -283,10 +311,10 @@ public class UserActivitySummary { * visited and the relevant artifact. * * @throws TskCoreException - * @throws NoCurrentCaseException + * @throws SleuthkitCaseProviderException */ - private static Pair>>> getDomainGroupsAndMostRecent(DataSource dataSource) throws TskCoreException, NoCurrentCaseException { - List artifacts = DataSourceInfoUtilities.getArtifacts(Case.getCurrentCaseThrows().getSleuthkitCase(), TYPE_WEB_HISTORY, + private Pair>>> getDomainGroupsAndMostRecent(DataSource dataSource) throws TskCoreException, SleuthkitCaseProviderException { + List artifacts = DataSourceInfoUtilities.getArtifacts(caseProvider.get(), TYPE_WEB_HISTORY, dataSource, TYPE_DATETIME_ACCESSED, DataSourceInfoUtilities.SortOrder.DESCENDING, 0); Long mostRecentMs = null; @@ -368,10 +396,11 @@ public class UserActivitySummary { * @return The list of most recent web searches where most recent search * appears first. * - * @throws NoCurrentCaseException + * @throws + * org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException * @throws TskCoreException */ - public static List getMostRecentWebSearches(DataSource dataSource, int count) throws NoCurrentCaseException, TskCoreException { + public List getMostRecentWebSearches(DataSource dataSource, int count) throws SleuthkitCaseProviderException, TskCoreException { assertValidCount(count); if (dataSource == null) { @@ -379,7 +408,7 @@ public class UserActivitySummary { } // get the artifacts - List webSearchArtifacts = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboard() + List webSearchArtifacts = caseProvider.get().getBlackboard() .getArtifacts(ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY.getTypeID(), dataSource.getId()); // group by search string (case insensitive) @@ -406,7 +435,6 @@ public class UserActivitySummary { .collect(Collectors.toList()); // get translation if possible - TextTranslationService translationService = TextTranslationService.getInstance(); if (translationService.hasProvider()) { for (TopWebSearchResult result : results) { result.setTranslatedResult(getTranslationOrNull(result.getSearchString())); @@ -423,10 +451,9 @@ public class UserActivitySummary { * @param original The original text. * * @return The translated text or null if no translation can be determined - * or exists. + * or exists. */ - private static String getTranslationOrNull(String original) { - TextTranslationService translationService = TextTranslationService.getInstance(); + private String getTranslationOrNull(String original) { if (!translationService.hasProvider() || StringUtils.isBlank(original)) { return null; } @@ -434,9 +461,8 @@ public class UserActivitySummary { String translated = null; try { translated = translationService.translate(original); - } catch (NoServiceProviderException | TranslationException ignore) { - // Original logic ignored this error and simply logged it as warning so i'm keeping the same logic - // logger.log(Level.WARNING, String.format("There was an error translating text: '%s'", original), ex); + } catch (NoServiceProviderException | TranslationException ex) { + logger.log(Level.WARNING, String.format("There was an error translating text: '%s'", original), ex); } // if there is no translation or the translation is the same as the original, return null. @@ -458,8 +484,8 @@ public class UserActivitySummary { * * @return The most recent one with a non-null date. */ - private static TopDeviceAttachedResult getMostRecentDevice(TopDeviceAttachedResult r1, TopDeviceAttachedResult r2) { - if (r2.getLastAccessed() == null) { + private TopDeviceAttachedResult getMostRecentDevice(TopDeviceAttachedResult r1, TopDeviceAttachedResult r2) { + if (r2.getLastAccessed()== null) { return r1; } @@ -480,17 +506,18 @@ public class UserActivitySummary { * @return The list of most recent devices attached where most recent device * attached appears first. * - * @throws NoCurrentCaseException + * @throws + * org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException * @throws TskCoreException */ - public static List getRecentDevices(DataSource dataSource, int count) throws NoCurrentCaseException, TskCoreException { + public List getRecentDevices(DataSource dataSource, int count) throws SleuthkitCaseProviderException, TskCoreException { assertValidCount(count); if (dataSource == null) { return Collections.emptyList(); } - Collection results = DataSourceInfoUtilities.getArtifacts(Case.getCurrentCaseThrows().getSleuthkitCase(), TYPE_DEVICE_ATTACHED, + Collection results = DataSourceInfoUtilities.getArtifacts(caseProvider.get(), TYPE_DEVICE_ATTACHED, dataSource, TYPE_DATETIME, DataSourceInfoUtilities.SortOrder.DESCENDING, 0) .stream() .map(artifact -> { @@ -565,30 +592,30 @@ public class UserActivitySummary { * sent. * * @param dataSource The data source. - * @param count The maximum number of records to be shown (must be > - * 0). + * @param count The maximum number of records to be shown (must be > 0). * * @return The list of most recent accounts used where the most recent - * account by last message sent occurs first. + * account by last message sent occurs first. * - * @throws NoCurrentCaseException + * @throws + * org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException * @throws TskCoreException */ @Messages({ "DataSourceUserActivitySummary_getRecentAccounts_emailMessage=Email Message", "DataSourceUserActivitySummary_getRecentAccounts_calllogMessage=Call Log",}) - public static List getRecentAccounts(DataSource dataSource, int count) throws NoCurrentCaseException, TskCoreException { + public List getRecentAccounts(DataSource dataSource, int count) throws SleuthkitCaseProviderException, TskCoreException { assertValidCount(count); if (dataSource == null) { return Collections.emptyList(); } - Stream messageResults = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboard().getArtifacts(ARTIFACT_TYPE.TSK_MESSAGE.getTypeID(), dataSource.getId()) + Stream messageResults = caseProvider.get().getBlackboard().getArtifacts(ARTIFACT_TYPE.TSK_MESSAGE.getTypeID(), dataSource.getId()) .stream() .map((art) -> getMessageAccountResult(art)); - Stream emailResults = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboard().getArtifacts(ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID(), dataSource.getId()) + Stream emailResults = caseProvider.get().getBlackboard().getArtifacts(ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID(), dataSource.getId()) .stream() .map((art) -> { return getAccountResult( @@ -598,7 +625,7 @@ public class UserActivitySummary { TYPE_DATETIME_SENT); }); - Stream calllogResults = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboard().getArtifacts(ARTIFACT_TYPE.TSK_CALLLOG.getTypeID(), dataSource.getId()) + Stream calllogResults = caseProvider.get().getBlackboard().getArtifacts(ARTIFACT_TYPE.TSK_CALLLOG.getTypeID(), dataSource.getId()) .stream() .map((art) -> { return getAccountResult( @@ -639,7 +666,7 @@ public class UserActivitySummary { * * @return The generated TopProgramsResult. */ - private static TopProgramsResult getTopProgramsResult(BlackboardArtifact artifact) { + private TopProgramsResult getTopProgramsResult(BlackboardArtifact artifact) { String programName = DataSourceInfoUtilities.getStringOrNull(artifact, TYPE_PROG_NAME); // ignore items with no name or a ntos boot identifier @@ -691,7 +718,7 @@ public class UserActivitySummary { * @param long2 Second possibly null long. * * @return Returns the compare value: 1,0,-1 favoring the higher non-null - * value. + * value. */ private static int nullableCompare(Long long1, Long long2) { if (long1 == null && long2 == null) { @@ -732,10 +759,10 @@ public class UserActivitySummary { * @return The sorted list and limited to the count if last run or run count * information is available on any item. * - * @throws NoCurrentCaseException + * @throws SleuthkitCaseProviderException * @throws TskCoreException */ - public static List getTopPrograms(DataSource dataSource, int count) throws NoCurrentCaseException, TskCoreException { + public List getTopPrograms(DataSource dataSource, int count) throws SleuthkitCaseProviderException, TskCoreException { assertValidCount(count); if (dataSource == null) { @@ -743,7 +770,7 @@ public class UserActivitySummary { } // Get TopProgramsResults for each TSK_PROG_RUN artifact - Collection results = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboard().getArtifacts(ARTIFACT_TYPE.TSK_PROG_RUN.getTypeID(), dataSource.getId()) + Collection results = caseProvider.get().getBlackboard().getArtifacts(ARTIFACT_TYPE.TSK_PROG_RUN.getTypeID(), dataSource.getId()) .stream() // convert to a TopProgramsResult object or null if missing critical information .map((art) -> getTopProgramsResult(art)) diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/AnalysisSummaryGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/AnalysisSummaryGetter.java index 9f2a19d72b..f4891a0b37 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/AnalysisSummaryGetter.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/AnalysisSummaryGetter.java @@ -25,9 +25,8 @@ import java.util.HashSet; import java.util.List; import java.util.Set; import org.apache.commons.lang3.tuple.Pair; -import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.datasourcesummary.datamodel.AnalysisSummary; -import org.sleuthkit.autopsy.datasourcesummary.ui.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.TskCoreException; @@ -46,10 +45,13 @@ public class AnalysisSummaryGetter implements DefaultArtifactUpdateGovernor { ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID() )); + AnalysisSummary analysisSummary; + /** * Main constructor. */ public AnalysisSummaryGetter() { + analysisSummary = new AnalysisSummary(); } @Override @@ -68,11 +70,7 @@ public class AnalysisSummaryGetter implements DefaultArtifactUpdateGovernor { * @throws TskCoreException */ public List> getHashsetCounts(DataSource dataSource) throws SleuthkitCaseProviderException, TskCoreException { - try { - return AnalysisSummary.getHashsetCounts(dataSource); - } catch (NoCurrentCaseException ex) { - throw new SleuthkitCaseProviderException("No currently open case.", ex); - } + return analysisSummary.getHashsetCounts(dataSource); } /** @@ -86,11 +84,7 @@ public class AnalysisSummaryGetter implements DefaultArtifactUpdateGovernor { * @throws TskCoreException */ public List> getKeywordCounts(DataSource dataSource) throws SleuthkitCaseProviderException, TskCoreException { - try { - return AnalysisSummary.getKeywordCounts(dataSource); - } catch (NoCurrentCaseException ex) { - throw new SleuthkitCaseProviderException("No currently open case.", ex); - } + return analysisSummary.getKeywordCounts(dataSource); } /** @@ -106,10 +100,6 @@ public class AnalysisSummaryGetter implements DefaultArtifactUpdateGovernor { * @throws TskCoreException */ public List> getInterestingItemCounts(DataSource dataSource) throws SleuthkitCaseProviderException, TskCoreException { - try { - return AnalysisSummary.getInterestingItemCounts(dataSource); - } catch (NoCurrentCaseException ex) { - throw new SleuthkitCaseProviderException("No currently open case.", ex); - } + return analysisSummary.getInterestingItemCounts(dataSource); } } diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerSummaryGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerSummaryGetter.java index 68bff3d987..4770359911 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerSummaryGetter.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerSummaryGetter.java @@ -24,9 +24,8 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Set; -import org.sleuthkit.autopsy.datasourcesummary.ui.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider; import org.sleuthkit.autopsy.datasourcesummary.datamodel.ContainerSummary; -import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.ingest.ModuleContentEvent; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; @@ -45,10 +44,13 @@ public class ContainerSummaryGetter implements DefaultArtifactUpdateGovernor { BlackboardArtifact.ARTIFACT_TYPE.TSK_DATA_SOURCE_USAGE.getTypeID() )); + private ContainerSummary containerSummary; + /** * Main constructor. */ public ContainerSummaryGetter() { + containerSummary = new ContainerSummary(); } @Override @@ -79,11 +81,7 @@ public class ContainerSummaryGetter implements DefaultArtifactUpdateGovernor { */ public Long getSizeOfUnallocatedFiles(DataSource currentDataSource) throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException { - try { - return ContainerSummary.getSizeOfUnallocatedFiles(currentDataSource); - } catch (NoCurrentCaseException ex) { - throw new SleuthkitCaseProviderException("No currently open case.", ex); - } + return containerSummary.getSizeOfUnallocatedFiles(currentDataSource); } /** @@ -101,11 +99,7 @@ public class ContainerSummaryGetter implements DefaultArtifactUpdateGovernor { */ public String getOperatingSystems(DataSource dataSource) throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException { - try { - return ContainerSummary.getOperatingSystems(dataSource); - } catch (NoCurrentCaseException ex) { - throw new SleuthkitCaseProviderException("No currently open case.", ex); - } + return containerSummary.getOperatingSystems(dataSource); } /** @@ -123,11 +117,7 @@ public class ContainerSummaryGetter implements DefaultArtifactUpdateGovernor { */ public String getDataSourceType(DataSource dataSource) throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException { - try { - return ContainerSummary.getDataSourceType(dataSource); - } catch (NoCurrentCaseException ex) { - throw new SleuthkitCaseProviderException("No currently open case.", ex); - } + return containerSummary.getDataSourceType(dataSource); } /** @@ -145,10 +135,6 @@ public class ContainerSummaryGetter implements DefaultArtifactUpdateGovernor { */ public ContainerSummary.ContainerDetails getContainerDetails(DataSource dataSource) throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException { - try { - return ContainerSummary.getContainerDetails(dataSource); - } catch (NoCurrentCaseException ex) { - throw new SleuthkitCaseProviderException("No currently open case.", ex); - } + return containerSummary.getContainerDetails(dataSource); } } diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/GeolocationSummaryGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/GeolocationSummaryGetter.java index 9a9dc7f61c..cea19db803 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/GeolocationSummaryGetter.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/GeolocationSummaryGetter.java @@ -23,7 +23,7 @@ import java.util.List; import java.util.Set; import org.sleuthkit.autopsy.datasourcesummary.datamodel.GeolocationSummary; import org.sleuthkit.autopsy.datasourcesummary.datamodel.GeolocationSummary.CityData; -import org.sleuthkit.autopsy.datasourcesummary.ui.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultArtifactUpdateGovernor; import org.sleuthkit.autopsy.geolocation.datamodel.GeoLocationDataException; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; @@ -37,10 +37,13 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; */ public class GeolocationSummaryGetter implements DefaultArtifactUpdateGovernor { + private GeolocationSummary geoSummary; + /** * Default constructor. */ public GeolocationSummaryGetter() { + geoSummary = new GeolocationSummary(); } /** @@ -71,11 +74,6 @@ public class GeolocationSummaryGetter implements DefaultArtifactUpdateGovernor { */ public CityData getCityCounts(DataSource dataSource, int daysCount, int maxCount) throws SleuthkitCaseProviderException, GeoLocationDataException, InterruptedException, IOException { - - try { - return GeolocationSummary.getCityCounts(dataSource, daysCount, maxCount); - } catch (NoCurrentCaseException ex) { - throw new SleuthkitCaseProviderException("No currently open case.", ex); - } + return geoSummary.getCityCounts(dataSource, daysCount, maxCount); } } diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/MimeTypeSummaryGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/MimeTypeSummaryGetter.java index f2a96cdd92..e4b06262ca 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/MimeTypeSummaryGetter.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/MimeTypeSummaryGetter.java @@ -26,8 +26,8 @@ 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.ui.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceInfoUtilities; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.ModuleContentEvent; @@ -44,10 +44,22 @@ public class MimeTypeSummaryGetter implements DefaultUpdateGovernor { private static final Set INGEST_JOB_EVENTS = new HashSet<>( Arrays.asList(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED)); + private final SleuthkitCaseProvider provider; + /** * Main constructor. */ public MimeTypeSummaryGetter() { + this(SleuthkitCaseProvider.DEFAULT); + } + + /** + * Main constructor. + * + * @param provider The means of obtaining a sleuthkit case. + */ + public MimeTypeSummaryGetter(SleuthkitCaseProvider provider) { + this.provider = provider; } @Override @@ -90,11 +102,7 @@ public class MimeTypeSummaryGetter implements DefaultUpdateGovernor { */ public Long getCountOfFilesForMimeTypes(DataSource currentDataSource, Set setOfMimeTypes) throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException { - try { - return DataSourceInfoUtilities.getCountOfRegNonSlackFiles(currentDataSource, "mime_type IN " + getSqlSet(setOfMimeTypes)); - } catch (NoCurrentCaseException ex) { - throw new SleuthkitCaseProviderException("No currently open case.", ex); - } + return DataSourceInfoUtilities.getCountOfRegNonSlackFiles(provider.get(), currentDataSource, "mime_type IN " + getSqlSet(setOfMimeTypes)); } /** @@ -115,13 +123,9 @@ public class MimeTypeSummaryGetter implements DefaultUpdateGovernor { */ public Long getCountOfFilesNotInMimeTypes(DataSource currentDataSource, Set setOfMimeTypes) throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException { - 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); - } + return DataSourceInfoUtilities.getCountOfRegNonSlackFiles(provider.get(), currentDataSource, + "mime_type NOT IN " + getSqlSet(setOfMimeTypes) + + " AND mime_type IS NOT NULL AND mime_type <> '' "); } /** @@ -137,11 +141,7 @@ public class MimeTypeSummaryGetter implements DefaultUpdateGovernor { */ public Long getCountOfAllRegularFiles(DataSource dataSource) throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException { - try { - return DataSourceInfoUtilities.getCountOfRegNonSlackFiles(dataSource, null); - } catch (NoCurrentCaseException ex) { - throw new SleuthkitCaseProviderException("No currently open case.", ex); - } + return DataSourceInfoUtilities.getCountOfRegNonSlackFiles(provider.get(), dataSource, null); } /** @@ -158,11 +158,7 @@ public class MimeTypeSummaryGetter implements DefaultUpdateGovernor { */ public Long getCountOfFilesWithNoMimeType(DataSource currentDataSource) throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException { - try { - return DataSourceInfoUtilities.getCountOfRegNonSlackFiles(currentDataSource, "(mime_type IS NULL OR mime_type = '') "); - } catch (NoCurrentCaseException ex) { - throw new SleuthkitCaseProviderException("No currently open case.", ex); - } + return DataSourceInfoUtilities.getCountOfRegNonSlackFiles(provider.get(), currentDataSource, "(mime_type IS NULL OR mime_type = '') "); } /** diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesSummaryGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesSummaryGetter.java index f7b76081f7..c4ed083852 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesSummaryGetter.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesSummaryGetter.java @@ -23,7 +23,8 @@ import java.util.Collections; import java.util.HashSet; import java.util.Set; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; -import org.sleuthkit.autopsy.datasourcesummary.ui.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultArtifactUpdateGovernor; import org.sleuthkit.autopsy.datasourcesummary.datamodel.PastCasesSummary; import org.sleuthkit.autopsy.datasourcesummary.datamodel.PastCasesSummary.PastCasesResult; @@ -32,8 +33,9 @@ import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.TskCoreException; /** - * Wrapper class for converting org.sleuthkit.autopsy.contentutils.PastCasesSummary - * functionality into a DefaultArtifactUpdateGovernor used by PastCases tab. + * Wrapper class for converting + * org.sleuthkit.autopsy.contentutils.PastCasesSummary functionality into a + * DefaultArtifactUpdateGovernor used by PastCases tab. */ public class PastCasesSummaryGetter implements DefaultArtifactUpdateGovernor { @@ -42,7 +44,10 @@ public class PastCasesSummaryGetter implements DefaultArtifactUpdateGovernor { ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID() )); + private PastCasesSummary pastSummary; + public PastCasesSummaryGetter() { + pastSummary = new PastCasesSummary(); } @Override @@ -67,10 +72,6 @@ public class PastCasesSummaryGetter implements DefaultArtifactUpdateGovernor { return null; } - try { - return PastCasesSummary.getPastCasesData(dataSource); - } catch (NoCurrentCaseException ex) { - throw new SleuthkitCaseProviderException("No currently open case.", ex); - } + return pastSummary.getPastCasesData(dataSource); } } diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesGetter.java index 0c6db1d7e1..02824dacb7 100755 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesGetter.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesGetter.java @@ -24,14 +24,13 @@ import java.util.HashSet; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultArtifactUpdateGovernor; import java.util.List; import java.util.Set; -import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.datasourcesummary.datamodel.RecentFilesSummary; import org.sleuthkit.autopsy.datasourcesummary.datamodel.RecentFilesSummary.RecentAttachmentDetails; import org.sleuthkit.autopsy.datasourcesummary.datamodel.RecentFilesSummary.RecentDownloadDetails; import org.sleuthkit.autopsy.datasourcesummary.datamodel.RecentFilesSummary.RecentFileDetails; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.TskCoreException; -import org.sleuthkit.autopsy.datasourcesummary.ui.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.datamodel.BlackboardArtifact; /** @@ -49,10 +48,13 @@ public class RecentFilesGetter implements DefaultArtifactUpdateGovernor { BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE.getTypeID() )); + private RecentFilesSummary recentSummary; + /** * Default constructor. */ public RecentFilesGetter() { + recentSummary = new RecentFilesSummary(); } @Override @@ -75,11 +77,7 @@ public class RecentFilesGetter implements DefaultArtifactUpdateGovernor { * @throws TskCoreException */ public List getRecentlyOpenedDocuments(DataSource dataSource, int maxCount) throws SleuthkitCaseProviderException, TskCoreException { - try { - return RecentFilesSummary.getRecentlyOpenedDocuments(dataSource, maxCount); - } catch (NoCurrentCaseException ex) { - throw new SleuthkitCaseProviderException("No currently open case.", ex); - } + return recentSummary.getRecentlyOpenedDocuments(dataSource, maxCount); } /** @@ -97,11 +95,7 @@ public class RecentFilesGetter implements DefaultArtifactUpdateGovernor { * @throws SleuthkitCaseProviderException */ public List getRecentDownloads(DataSource dataSource, int maxCount) throws TskCoreException, SleuthkitCaseProviderException { - try { - return RecentFilesSummary.getRecentDownloads(dataSource, maxCount); - } catch (NoCurrentCaseException ex) { - throw new SleuthkitCaseProviderException("No currently open case.", ex); - } + return recentSummary.getRecentDownloads(dataSource, maxCount); } /** @@ -117,10 +111,6 @@ public class RecentFilesGetter implements DefaultArtifactUpdateGovernor { * @throws TskCoreException */ public List getRecentAttachments(DataSource dataSource, int maxCount) throws SleuthkitCaseProviderException, TskCoreException { - try { - return RecentFilesSummary.getRecentAttachments(dataSource, maxCount); - } catch (NoCurrentCaseException ex) { - throw new SleuthkitCaseProviderException("No currently open case.", ex); - } + return recentSummary.getRecentAttachments(dataSource, maxCount); } } diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java index 42a7b1ba8f..eed41cda3d 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java @@ -30,8 +30,8 @@ import org.joda.time.DateTime; import org.joda.time.Interval; import org.openide.util.NbBundle.Messages; import org.openide.util.actions.CallableSystemAction; -import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineDataSourceUtils; import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary; import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary.DailyActivityAmount; import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary.TimelineSummaryData; @@ -77,6 +77,7 @@ public class TimelinePanel extends BaseDataSourceSummaryPanel { private final LoadableLabel earliestLabel = new LoadableLabel(Bundle.TimelinePanel_earliestLabel_title()); private final LoadableLabel latestLabel = new LoadableLabel(Bundle.TimelinePanel_latestLabel_title()); private final BarChartPanel last30DaysChart = new BarChartPanel(Bundle.TimlinePanel_last30DaysChart_title(), "", ""); + private final TimelineDataSourceUtils timelineUtils = TimelineDataSourceUtils.getInstance(); // all loadable components on this tab private final List> loadableComponents = Arrays.asList(earliestLabel, latestLabel, last30DaysChart); @@ -96,7 +97,7 @@ public class TimelinePanel extends BaseDataSourceSummaryPanel { public TimelinePanel(TimelineSummaryGetter timelineData) { super(timelineData); - dataFetcher = (dataSource) -> TimelineSummary.getTimelineSummaryData(dataSource, MOST_RECENT_DAYS_COUNT); + dataFetcher = (dataSource) -> timelineData.getData(dataSource, MOST_RECENT_DAYS_COUNT); // set up data acquisition methods dataFetchComponents = Arrays.asList( @@ -228,13 +229,13 @@ public class TimelinePanel extends BaseDataSourceSummaryPanel { final TimeLineController controller = TimeLineModule.getController(); if (dataSource != null) { - controller.pushFilters(TimelineSummary.getDataSourceFilterState(dataSource)); + controller.pushFilters(timelineUtils.getDataSourceFilterState(dataSource)); } if (minDate != null && maxDate != null) { timeSpan = new Interval(new DateTime(minDate), new DateTime(maxDate)); } - } catch (NoCurrentCaseException | TskCoreException ex) { + } catch (TskCoreException ex) { logger.log(Level.WARNING, "Unable to view time range in Timeline view", ex); } diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java.bak b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java.bak new file mode 100755 index 0000000000..6b1292139e --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java.bak @@ -0,0 +1,358 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2020-2021 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.datasourcesummary.ui; + +import java.awt.Color; +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.logging.Level; +import org.apache.commons.collections.CollectionUtils; +import org.joda.time.DateTime; +import org.joda.time.Interval; +import org.openide.util.NbBundle.Messages; +import org.openide.util.actions.CallableSystemAction; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary.DailyActivityAmount; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary.TimelineSummaryData; +import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartPanel; +import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartSeries; +import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartPanel.OrderedKey; +import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartSeries.BarChartItem; +import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult; +import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; +import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents; +import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetcher; +import org.sleuthkit.autopsy.datasourcesummary.uiutils.IngestRunningLabel; +import org.sleuthkit.autopsy.datasourcesummary.uiutils.LoadableComponent; +import org.sleuthkit.autopsy.datasourcesummary.uiutils.LoadableLabel; +import org.sleuthkit.autopsy.timeline.OpenTimelineAction; +import org.sleuthkit.autopsy.timeline.TimeLineController; +import org.sleuthkit.autopsy.timeline.TimeLineModule; +import org.sleuthkit.datamodel.DataSource; +import org.sleuthkit.datamodel.TskCoreException; + +/** + * A tab shown in data source summary displaying information about a data + * source's timeline events. + */ +@Messages({ + "TimelinePanel_earliestLabel_title=Earliest", + "TimelinePanel_latestLabel_title=Latest", + "TimlinePanel_last30DaysChart_title=Last 30 Days", + "TimlinePanel_last30DaysChart_fileEvts_title=File Events", + "TimlinePanel_last30DaysChart_artifactEvts_title=Result Events",}) +public class TimelinePanel extends BaseDataSourceSummaryPanel { + + private static final Logger logger = Logger.getLogger(TimelinePanel.class.getName()); + private static final long serialVersionUID = 1L; + + private static final String EARLIEST_LATEST_FORMAT_STR = "MMM d, yyyy"; + private static final DateFormat EARLIEST_LATEST_FORMAT = TimelineSummary.getUtcFormat(EARLIEST_LATEST_FORMAT_STR); + private static final DateFormat CHART_FORMAT = TimelineSummary.getUtcFormat("MMM d, yyyy"); + private static final int MOST_RECENT_DAYS_COUNT = 30; + + // components displayed in the tab + private final IngestRunningLabel ingestRunningLabel = new IngestRunningLabel(); + private final LoadableLabel earliestLabel = new LoadableLabel(Bundle.TimelinePanel_earliestLabel_title()); + private final LoadableLabel latestLabel = new LoadableLabel(Bundle.TimelinePanel_latestLabel_title()); + private final BarChartPanel last30DaysChart = new BarChartPanel(Bundle.TimlinePanel_last30DaysChart_title(), "", ""); + private final TimelineDataSourceUtils timelineUtils = TimelineDataSourceUtils.getInstance(); + + // all loadable components on this tab + private final List> loadableComponents = Arrays.asList(earliestLabel, latestLabel, last30DaysChart); + + private final DataFetcher dataFetcher; + + // actions to load data for this tab + private final List> dataFetchComponents; + + public TimelinePanel() { + this(new TimelineSummaryGetter()); + } + + /** + * Creates new form PastCasesPanel + */ + public TimelinePanel(TimelineSummaryGetter timelineData) { + super(timelineData); + + dataFetcher = (dataSource) -> timelineData.getData(dataSource, MOST_RECENT_DAYS_COUNT); + + // set up data acquisition methods + dataFetchComponents = Arrays.asList( + new DataFetchWorker.DataFetchComponents<>(dataFetcher, (result) -> handleResult(result))); + + initComponents(); + } + + private static final Color FILE_EVT_COLOR = new Color(228, 22, 28); + private static final Color ARTIFACT_EVT_COLOR = new Color(21, 227, 100); + + /** + * Converts DailyActivityAmount data retrieved from TimelineSummaryGetter + * into data to be displayed as a bar chart. + * + * @param recentDaysActivity The data retrieved from + * TimelineSummaryGetter. + * @param showIntermediateDates If true, shows all dates. If false, shows + * only first and last date. + * + * @return The data to be displayed in the BarChart. + */ + private List parseChartData(List recentDaysActivity, boolean showIntermediateDates) { + // if no data, return null indicating no result. + if (CollectionUtils.isEmpty(recentDaysActivity)) { + return null; + } + + // Create a bar chart item for each recent days activity item + List fileEvtCounts = new ArrayList<>(); + List artifactEvtCounts = new ArrayList<>(); + + for (int i = 0; i < recentDaysActivity.size(); i++) { + DailyActivityAmount curItem = recentDaysActivity.get(i); + + long fileAmt = curItem.getFileActivityCount(); + long artifactAmt = curItem.getArtifactActivityCount() * 100; + String formattedDate = (showIntermediateDates || i == 0 || i == recentDaysActivity.size() - 1) + ? TimelineSummary.formatDate(curItem.getDay(), CHART_FORMAT) : ""; + + OrderedKey thisKey = new OrderedKey(formattedDate, i); + fileEvtCounts.add(new BarChartItem(thisKey, fileAmt)); + artifactEvtCounts.add(new BarChartItem(thisKey, artifactAmt)); + } + + return Arrays.asList( + new BarChartSeries(Bundle.TimlinePanel_last30DaysChart_fileEvts_title(), FILE_EVT_COLOR, fileEvtCounts), + new BarChartSeries(Bundle.TimlinePanel_last30DaysChart_artifactEvts_title(), ARTIFACT_EVT_COLOR, artifactEvtCounts)); + } + + private final Object timelineBtnLock = new Object(); + private TimelineSummaryData curTimelineData = null; + + /** + * Handles displaying the result for each displayable item in the + * TimelinePanel by breaking the TimelineSummaryData result into its + * constituent parts and then sending each data item to the pertinent + * component. + * + * @param result The result to be displayed on this tab. + */ + private void handleResult(DataFetchResult result) { + earliestLabel.showDataFetchResult(DataFetchResult.getSubResult(result, r -> TimelineSummary.formatDate(r.getMinDate(), EARLIEST_LATEST_FORMAT))); + latestLabel.showDataFetchResult(DataFetchResult.getSubResult(result, r -> TimelineSummary.formatDate(r.getMaxDate(), EARLIEST_LATEST_FORMAT))); + last30DaysChart.showDataFetchResult(DataFetchResult.getSubResult(result, r -> parseChartData(r.getMostRecentDaysActivity(), false))); + + if (result != null + && result.getResultType() == DataFetchResult.ResultType.SUCCESS + && result.getData() != null) { + + synchronized (this.timelineBtnLock) { + this.curTimelineData = result.getData(); + this.viewInTimelineBtn.setEnabled(true); + } + } else { + synchronized (this.timelineBtnLock) { + this.viewInTimelineBtn.setEnabled(false); + } + } + } + + /** + * Action that occurs when 'View in Timeline' button is pressed. + */ + private void openFilteredChart() { + DataSource dataSource = null; + Date minDate = null; + Date maxDate = null; + + // get date from current timelineData if that data exists. + synchronized (this.timelineBtnLock) { + if (curTimelineData == null) { + return; + } + + dataSource = curTimelineData.getDataSource(); + if (CollectionUtils.isNotEmpty(curTimelineData.getMostRecentDaysActivity())) { + minDate = curTimelineData.getMostRecentDaysActivity().get(0).getDay(); + maxDate = curTimelineData.getMostRecentDaysActivity().get(curTimelineData.getMostRecentDaysActivity().size() - 1).getDay(); + // set outer bound to end of day instead of beginning + if (maxDate != null) { + maxDate = new Date(maxDate.getTime() + 1000 * 60 * 60 * 24); + } + } + } + + openFilteredChart(dataSource, minDate, maxDate); + } + + /** + * Action that occurs when 'View in Timeline' button is pressed. + * + * @param dataSource The data source to filter to. + * @param minDate The min date for the zoom of the window. + * @param maxDate The max date for the zoom of the window. + */ + private void openFilteredChart(DataSource dataSource, Date minDate, Date maxDate) { + OpenTimelineAction openTimelineAction = CallableSystemAction.get(OpenTimelineAction.class); + if (openTimelineAction == null) { + logger.log(Level.WARNING, "No OpenTimelineAction provided by CallableSystemAction; taking no redirect action."); + } + + // notify dialog (if in dialog) should close. + TimelinePanel.this.notifyParentClose(); + + Interval timeSpan = null; + + try { + final TimeLineController controller = TimeLineModule.getController(); + + if (dataSource != null) { + controller.pushFilters(TimelineSummary.getDataSourceFilterState(dataSource)); + } + + if (minDate != null && maxDate != null) { + timeSpan = new Interval(new DateTime(minDate), new DateTime(maxDate)); + } + } catch (NoCurrentCaseException | TskCoreException ex) { + logger.log(Level.WARNING, "Unable to view time range in Timeline view", ex); + } + + try { + openTimelineAction.showTimeline(timeSpan); + } catch (TskCoreException ex) { + logger.log(Level.WARNING, "An unexpected exception occurred while opening the timeline.", ex); + } + } + + @Override + protected void fetchInformation(DataSource dataSource) { + fetchInformation(dataFetchComponents, dataSource); + } + + @Override + protected void onNewDataSource(DataSource dataSource) { + onNewDataSource(dataFetchComponents, loadableComponents, dataSource); + } + + @Override + public void close() { + ingestRunningLabel.unregister(); + super.close(); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + javax.swing.JScrollPane mainScrollPane = new javax.swing.JScrollPane(); + javax.swing.JPanel mainContentPanel = new javax.swing.JPanel(); + javax.swing.JPanel ingestRunningPanel = ingestRunningLabel; + javax.swing.JLabel activityRangeLabel = new javax.swing.JLabel(); + javax.swing.Box.Filler filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 2), new java.awt.Dimension(0, 2), new java.awt.Dimension(0, 2)); + javax.swing.JPanel earliestLabelPanel = earliestLabel; + javax.swing.JPanel latestLabelPanel = latestLabel; + javax.swing.Box.Filler filler2 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 20), new java.awt.Dimension(0, 20), new java.awt.Dimension(0, 20)); + javax.swing.JPanel last30DaysPanel = last30DaysChart; + viewInTimelineBtn = new javax.swing.JButton(); + javax.swing.Box.Filler filler5 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 32767)); + + mainContentPanel.setBorder(javax.swing.BorderFactory.createEmptyBorder(10, 10, 10, 10)); + mainContentPanel.setLayout(new javax.swing.BoxLayout(mainContentPanel, javax.swing.BoxLayout.PAGE_AXIS)); + + ingestRunningPanel.setAlignmentX(0.0F); + ingestRunningPanel.setMaximumSize(new java.awt.Dimension(32767, 25)); + ingestRunningPanel.setMinimumSize(new java.awt.Dimension(10, 25)); + ingestRunningPanel.setPreferredSize(new java.awt.Dimension(10, 25)); + mainContentPanel.add(ingestRunningPanel); + + activityRangeLabel.setFont(new java.awt.Font("Segoe UI", 1, 12)); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(activityRangeLabel, org.openide.util.NbBundle.getMessage(TimelinePanel.class, "TimelinePanel.activityRangeLabel.text")); // NOI18N + mainContentPanel.add(activityRangeLabel); + activityRangeLabel.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(TimelinePanel.class, "PastCasesPanel.notableFileLabel.text")); // NOI18N + + filler1.setAlignmentX(0.0F); + mainContentPanel.add(filler1); + + earliestLabelPanel.setAlignmentX(0.0F); + earliestLabelPanel.setMaximumSize(new java.awt.Dimension(32767, 20)); + earliestLabelPanel.setMinimumSize(new java.awt.Dimension(100, 20)); + earliestLabelPanel.setPreferredSize(new java.awt.Dimension(100, 20)); + mainContentPanel.add(earliestLabelPanel); + + latestLabelPanel.setAlignmentX(0.0F); + latestLabelPanel.setMaximumSize(new java.awt.Dimension(32767, 20)); + latestLabelPanel.setMinimumSize(new java.awt.Dimension(100, 20)); + latestLabelPanel.setPreferredSize(new java.awt.Dimension(100, 20)); + mainContentPanel.add(latestLabelPanel); + + filler2.setAlignmentX(0.0F); + mainContentPanel.add(filler2); + + last30DaysPanel.setAlignmentX(0.0F); + last30DaysPanel.setMaximumSize(new java.awt.Dimension(600, 300)); + last30DaysPanel.setMinimumSize(new java.awt.Dimension(600, 300)); + last30DaysPanel.setPreferredSize(new java.awt.Dimension(600, 300)); + last30DaysPanel.setVerifyInputWhenFocusTarget(false); + mainContentPanel.add(last30DaysPanel); + + org.openide.awt.Mnemonics.setLocalizedText(viewInTimelineBtn, org.openide.util.NbBundle.getMessage(TimelinePanel.class, "TimelinePanel.viewInTimelineBtn.text")); // NOI18N + viewInTimelineBtn.setEnabled(false); + viewInTimelineBtn.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + viewInTimelineBtnActionPerformed(evt); + } + }); + mainContentPanel.add(viewInTimelineBtn); + + filler5.setAlignmentX(0.0F); + mainContentPanel.add(filler5); + + mainScrollPane.setViewportView(mainContentPanel); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(mainScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(mainScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE) + ); + }// //GEN-END:initComponents + + private void viewInTimelineBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_viewInTimelineBtnActionPerformed + openFilteredChart(); + }//GEN-LAST:event_viewInTimelineBtnActionPerformed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton viewInTimelineBtn; + // End of variables declaration//GEN-END:variables + +} diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelineSummaryGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelineSummaryGetter.java index 99bdc2737c..4ea7a51f36 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelineSummaryGetter.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelineSummaryGetter.java @@ -22,7 +22,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Set; -import org.sleuthkit.autopsy.datasourcesummary.ui.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultUpdateGovernor; import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary; import org.sleuthkit.autopsy.ingest.IngestManager; @@ -30,7 +30,6 @@ import org.sleuthkit.autopsy.ingest.ModuleContentEvent; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.TskCoreException; -import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary.TimelineSummaryData; /** @@ -41,10 +40,13 @@ public class TimelineSummaryGetter implements DefaultUpdateGovernor { private static final Set INGEST_JOB_EVENTS = new HashSet<>( Arrays.asList(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED)); + private TimelineSummary timelineSummary; + /** * Default constructor. */ public TimelineSummaryGetter() { + timelineSummary = new TimelineSummary(); } @Override @@ -70,20 +72,17 @@ public class TimelineSummaryGetter implements DefaultUpdateGovernor { /** * Retrieves timeline summary data. * - * @param dataSource The data source for which timeline data will be - * retrieved. + * @param dataSource The data source for which timeline data will be + * retrieved. * @param recentDaysNum The maximum number of most recent days' activity to - * include. + * include. + * * @return The retrieved data. + * * @throws SleuthkitCaseProviderException * @throws TskCoreException - * @throws NoCurrentCaseException */ - public TimelineSummaryData getData(DataSource dataSource, int recentDaysNum) throws SleuthkitCaseProviderException, TskCoreException, NoCurrentCaseException { - try { - return TimelineSummary.getTimelineSummaryData(dataSource, recentDaysNum); - } catch (NoCurrentCaseException ex) { - throw new SleuthkitCaseProviderException("No currently open case.", ex); - } + public TimelineSummaryData getData(DataSource dataSource, int recentDaysNum) throws SleuthkitCaseProviderException, TskCoreException { + return timelineSummary.getTimelineSummaryData(dataSource, recentDaysNum); } } diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java index ea4a85f406..45eba82918 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java @@ -31,7 +31,7 @@ import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.coreutils.FileTypeUtils.FileTypeCategory; import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceInfoUtilities; import org.sleuthkit.autopsy.datasourcesummary.datamodel.TypesSummary.FileTypeCategoryData; -import org.sleuthkit.autopsy.datasourcesummary.ui.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult.ResultType; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesSummaryGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesSummaryGetter.java index 5bc6bf92ab..3b0887c52f 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesSummaryGetter.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesSummaryGetter.java @@ -24,9 +24,9 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Set; -import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.autopsy.datasourcesummary.datamodel.TypesSummary; -import org.sleuthkit.autopsy.datasourcesummary.ui.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.ModuleContentEvent; import org.sleuthkit.datamodel.AbstractFile; @@ -34,18 +34,22 @@ import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.TskCoreException; /** - * Wrapper class for converting org.sleuthkit.autopsy.contentutils.TypesSummary functionality into a - * DefaultArtifactUpdateGovernor used by DataSourceSummaryCountsPanel. + * Wrapper class for converting org.sleuthkit.autopsy.contentutils.TypesSummary + * functionality into a DefaultArtifactUpdateGovernor used by + * DataSourceSummaryCountsPanel. */ public class TypesSummaryGetter implements DefaultUpdateGovernor { private static final Set INGEST_JOB_EVENTS = new HashSet<>( Arrays.asList(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED)); + private TypesSummary typesSummary; + /** * Main constructor. */ public TypesSummaryGetter() { + typesSummary = new TypesSummary(); } @Override @@ -81,11 +85,7 @@ public class TypesSummaryGetter implements DefaultUpdateGovernor { */ public Long getCountOfFiles(DataSource currentDataSource) throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException { - try { - return TypesSummary.getCountOfFiles(currentDataSource); - } catch (NoCurrentCaseException ex) { - throw new SleuthkitCaseProviderException("No currently open case.", ex); - } + return typesSummary.getCountOfFiles(currentDataSource); } /** @@ -101,11 +101,7 @@ public class TypesSummaryGetter implements DefaultUpdateGovernor { */ public Long getCountOfAllocatedFiles(DataSource currentDataSource) throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException { - try { - return TypesSummary.getCountOfAllocatedFiles(currentDataSource); - } catch (NoCurrentCaseException ex) { - throw new SleuthkitCaseProviderException("No currently open case.", ex); - } + return typesSummary.getCountOfAllocatedFiles(currentDataSource); } /** @@ -121,11 +117,7 @@ public class TypesSummaryGetter implements DefaultUpdateGovernor { */ public Long getCountOfUnallocatedFiles(DataSource currentDataSource) throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException { - try { - return TypesSummary.getCountOfUnallocatedFiles(currentDataSource); - } catch (NoCurrentCaseException ex) { - throw new SleuthkitCaseProviderException("No currently open case.", ex); - } + return typesSummary.getCountOfUnallocatedFiles(currentDataSource); } /** @@ -141,11 +133,7 @@ public class TypesSummaryGetter implements DefaultUpdateGovernor { */ public Long getCountOfDirectories(DataSource currentDataSource) throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException { - try { - return TypesSummary.getCountOfDirectories(currentDataSource); - } catch (NoCurrentCaseException ex) { - throw new SleuthkitCaseProviderException("No currently open case.", ex); - } + return typesSummary.getCountOfDirectories(currentDataSource); } /** @@ -161,10 +149,6 @@ public class TypesSummaryGetter implements DefaultUpdateGovernor { */ public Long getCountOfSlackFiles(DataSource currentDataSource) throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException { - try { - return TypesSummary.getCountOfSlackFiles(currentDataSource); - } catch (NoCurrentCaseException ex) { - throw new SleuthkitCaseProviderException("No currently open case.", ex); - } + return typesSummary.getCountOfSlackFiles(currentDataSource); } } diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivitySummaryGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivitySummaryGetter.java index 04da065833..ab98b0e271 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivitySummaryGetter.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivitySummaryGetter.java @@ -25,8 +25,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; -import org.sleuthkit.autopsy.datasourcesummary.ui.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary; @@ -54,7 +53,10 @@ public class UserActivitySummaryGetter implements DefaultArtifactUpdateGovernor ARTIFACT_TYPE.TSK_PROG_RUN.getTypeID() )); + private final UserActivitySummary userActivity; + public UserActivitySummaryGetter() { + userActivity = new UserActivitySummary(); } @Override @@ -90,11 +92,7 @@ public class UserActivitySummaryGetter implements DefaultArtifactUpdateGovernor return Collections.emptyList(); } - try { - return UserActivitySummary.getRecentDomains(dataSource, count); - } catch (NoCurrentCaseException ex) { - throw new SleuthkitCaseProviderException("No currently open case.", ex); - } + return userActivity.getRecentDomains(dataSource, count); } /** @@ -119,11 +117,7 @@ public class UserActivitySummaryGetter implements DefaultArtifactUpdateGovernor return Collections.emptyList(); } - try { - return UserActivitySummary.getMostRecentWebSearches(dataSource, count); - } catch (NoCurrentCaseException ex) { - throw new SleuthkitCaseProviderException("No currently open case.", ex); - } + return userActivity.getMostRecentWebSearches(dataSource, count); } /** @@ -147,11 +141,7 @@ public class UserActivitySummaryGetter implements DefaultArtifactUpdateGovernor return Collections.emptyList(); } - try { - return UserActivitySummary.getRecentDevices(dataSource, count); - } catch (NoCurrentCaseException ex) { - throw new SleuthkitCaseProviderException("No currently open case.", ex); - } + return userActivity.getRecentDevices(dataSource, count); } /** @@ -179,11 +169,7 @@ public class UserActivitySummaryGetter implements DefaultArtifactUpdateGovernor return Collections.emptyList(); } - try { - return UserActivitySummary.getRecentAccounts(dataSource, count); - } catch (NoCurrentCaseException ex) { - throw new SleuthkitCaseProviderException("No currently open case.", ex); - } + return userActivity.getRecentAccounts(dataSource, count); } /** @@ -228,10 +214,6 @@ public class UserActivitySummaryGetter implements DefaultArtifactUpdateGovernor return Collections.emptyList(); } - try { - return UserActivitySummary.getTopPrograms(dataSource, count); - } catch (NoCurrentCaseException ex) { - throw new SleuthkitCaseProviderException("No currently open case.", ex); - } + return userActivity.getTopPrograms(dataSource, count); } } diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java index f513f26b89..3d7f303ea5 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java @@ -118,7 +118,7 @@ class ExcelExportAction { // Export file and MIME type data progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_gatheringFileData()); progressPanel.setProgress(step); - List exports = ExportTypes.getExports(dataSource); + List exports = new ExportTypes().getExports(dataSource); if (exports != null) { sheetExports.addAll(exports); } @@ -126,7 +126,7 @@ class ExcelExportAction { // Export user activity progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_gatheringUserData()); progressPanel.setProgress(++step); - exports = ExportUserActivity.getExports(dataSource); + exports = new ExportUserActivity().getExports(dataSource); if (exports != null) { sheetExports.addAll(exports); } @@ -134,7 +134,7 @@ class ExcelExportAction { // Export Recent Activity data progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_gatheringRecentActivityData()); progressPanel.setProgress(++step); - exports = ExportRecentFiles.getExports(dataSource); + exports = new ExportRecentFiles().getExports(dataSource); if (exports != null) { sheetExports.addAll(exports); } @@ -142,7 +142,7 @@ class ExcelExportAction { // Export hash set hits, keyword hits, and interesting item hits progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_gatheringAnalysisData()); progressPanel.setProgress(++step); - exports = ExportAnalysisResults.getExports(dataSource); + exports = new ExportAnalysisResults().getExports(dataSource); if (exports != null) { sheetExports.addAll(exports); } @@ -150,7 +150,7 @@ class ExcelExportAction { // Export past cases data progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_gatheringPastData()); progressPanel.setProgress(++step); - exports = ExportPastCases.getExports(dataSource); + exports = new ExportPastCases().getExports(dataSource); if (exports != null) { sheetExports.addAll(exports); } @@ -158,7 +158,7 @@ class ExcelExportAction { // Export geolocation data progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_gatheringGeoData()); progressPanel.setProgress(++step); - exports = ExportGeolocation.getExports(dataSource); + exports = new ExportGeolocation().getExports(dataSource); if (exports != null) { sheetExports.addAll(exports); } @@ -166,7 +166,7 @@ class ExcelExportAction { // Export Timeline data progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_gatheringTimelineData()); progressPanel.setProgress(++step); - exports = ExportTimeline.getExports(dataSource); + exports = new ExportTimeline().getExports(dataSource); if (exports != null) { sheetExports.addAll(exports); } @@ -182,7 +182,7 @@ class ExcelExportAction { // Export Container & Image info data progressPanel.updateStatusLabel(Bundle.ExcelExportAction_exportToXLSX_gatheringContainerData()); progressPanel.setProgress(++step); - exports = ExportContainerInfo.getExports(dataSource); + exports = new ExportContainerInfo().getExports(dataSource); if (exports != null) { sheetExports.addAll(exports); } diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportAnalysisResults.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportAnalysisResults.java index 865ffddd01..8d154bd847 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportAnalysisResults.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportAnalysisResults.java @@ -56,14 +56,17 @@ class ExportAnalysisResults { ) ); - private ExportAnalysisResults() { + private final AnalysisSummary analysisSummary; + + ExportAnalysisResults() { + analysisSummary = new AnalysisSummary(); } - static List getExports(DataSource dataSource) { + List getExports(DataSource dataSource) { - DataFetcher>> hashsetsFetcher = (ds) -> AnalysisSummary.getHashsetCounts(ds); - DataFetcher>> keywordsFetcher = (ds) -> AnalysisSummary.getKeywordCounts(ds); - DataFetcher>> interestingItemsFetcher = (ds) -> AnalysisSummary.getInterestingItemCounts(ds); + DataFetcher>> hashsetsFetcher = (ds) -> analysisSummary.getHashsetCounts(ds); + DataFetcher>> keywordsFetcher = (ds) -> analysisSummary.getKeywordCounts(ds); + DataFetcher>> interestingItemsFetcher = (ds) -> analysisSummary.getInterestingItemCounts(ds); return Stream.of( getTableExport(hashsetsFetcher, DEFAULT_COLUMNS, Bundle.ExportAnalysisResults_hashsetHits_tabName(), dataSource), diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportContainerInfo.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportContainerInfo.java index 949bd853af..e6af2ce2a0 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportContainerInfo.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportContainerInfo.java @@ -39,11 +39,14 @@ import org.sleuthkit.datamodel.DataSource; * Class to export additional details associated with a specific DataSource */ class ExportContainerInfo { + + private final ContainerSummary containerSummary; /** * Creates new form ExportContainerInfo. */ - private ExportContainerInfo() { + ExportContainerInfo() { + containerSummary = new ContainerSummary(); } /** @@ -81,8 +84,8 @@ class ExportContainerInfo { "ExportContainerInfo_export_sha256=SHA256:", "ExportContainerInfo_export_unallocatedSize=Unallocated Space:", "ExportContainerInfo_export_filePaths=File Paths:",}) - static List getExports(DataSource ds) { - DataFetcher containerDataFetcher = (dataSource) -> ContainerSummary.getContainerDetails(dataSource); + List getExports(DataSource ds) { + DataFetcher containerDataFetcher = (dataSource) -> containerSummary.getContainerDetails(dataSource); ContainerDetails containerDetails = ExcelExportAction.getFetchResult(containerDataFetcher, "Container sheets", ds); if (ds == null || containerDetails == null) { return Collections.emptyList(); diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportGeolocation.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportGeolocation.java index d320311485..8cdecf8338 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportGeolocation.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportGeolocation.java @@ -46,6 +46,8 @@ import org.sleuthkit.datamodel.DataSource; "ExportGeolocation_mostCommon_tabName=Most Common Cities", "ExportGeolocation_mostRecent_tabName=Most Recent Cities",}) class ExportGeolocation { + + private final GeolocationSummary geoSummary; /** * Object encapsulating geolocation data. @@ -109,7 +111,8 @@ class ExportGeolocation { COUNT_COL ); - private ExportGeolocation() { + ExportGeolocation() { + geoSummary = new GeolocationSummary(); } /** @@ -203,9 +206,9 @@ class ExportGeolocation { } } - static List getExports(DataSource dataSource) { + List getExports(DataSource dataSource) { - DataFetcher geolocationFetcher = (ds) -> convertToViewModel(GeolocationSummary.getCityCounts(ds, DAYS_COUNT, MAX_COUNT)); + DataFetcher geolocationFetcher = (ds) -> convertToViewModel(geoSummary.getCityCounts(ds, DAYS_COUNT, MAX_COUNT)); GeolocationData model = getFetchResult(geolocationFetcher, "Geolocation sheets", dataSource); diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportPastCases.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportPastCases.java index de6f027ed0..da91b8744e 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportPastCases.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportPastCases.java @@ -39,6 +39,8 @@ import org.sleuthkit.datamodel.DataSource; "ExportPastCases_notableFileTable_tabName=Cases with Common Notable", "ExportPastCases_sameIdsTable_tabName=Past Cases with the Same Devices",}) class ExportPastCases { + + private final PastCasesSummary pastSummary; // model for column indicating the case private static final ColumnModel, DefaultCellModel> CASE_COL = new ColumnModel<>( @@ -58,11 +60,12 @@ class ExportPastCases { private static List, DefaultCellModel>> DEFAULT_TEMPLATE = Arrays.asList(CASE_COL, COUNT_COL); - private ExportPastCases() { + ExportPastCases() { + pastSummary = new PastCasesSummary(); } - static List getExports(DataSource dataSource) { - DataFetcher pastCasesFetcher = (ds) -> PastCasesSummary.getPastCasesData(ds); + List getExports(DataSource dataSource) { + DataFetcher pastCasesFetcher = (ds) -> pastSummary.getPastCasesData(ds); PastCasesResult result = getFetchResult(pastCasesFetcher, "Past cases sheets", dataSource); if (result == null) { return Collections.emptyList(); diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportRecentFiles.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportRecentFiles.java index adb6068fe5..38dbc59a78 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportRecentFiles.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportRecentFiles.java @@ -47,6 +47,8 @@ import org.sleuthkit.datamodel.DataSource; "ExportRecentFiles_col_header_sender=Sender" }) final class ExportRecentFiles { + + private final RecentFilesSummary recentSummary; private static final String DATETIME_FORMAT_STR = "yyyy/MM/dd HH:mm:ss"; private static final DateFormat DATETIME_FORMAT = new SimpleDateFormat(DATETIME_FORMAT_STR, Locale.getDefault()); @@ -86,7 +88,8 @@ final class ExportRecentFiles { return new DefaultCellModel<>(prog.getSender()); }, 150)); - private ExportRecentFiles() { + ExportRecentFiles() { + recentSummary = new RecentFilesSummary(); } /** @@ -103,11 +106,11 @@ final class ExportRecentFiles { }; } - static List getExports(DataSource dataSource) { + List getExports(DataSource dataSource) { - DataFetcher> docsFetcher = (ds) -> RecentFilesSummary.getRecentlyOpenedDocuments(ds, 10); - DataFetcher> downloadsFetcher = (ds) -> RecentFilesSummary.getRecentDownloads(ds, 10); - DataFetcher> attachmentsFetcher = (ds) -> RecentFilesSummary.getRecentAttachments(ds, 10); + DataFetcher> docsFetcher = (ds) -> recentSummary.getRecentlyOpenedDocuments(ds, 10); + DataFetcher> downloadsFetcher = (ds) -> recentSummary.getRecentDownloads(ds, 10); + DataFetcher> attachmentsFetcher = (ds) -> recentSummary.getRecentAttachments(ds, 10); return Stream.of( ExcelExportAction.getTableExport(docsFetcher, docsTemplate, Bundle.ExportRecentFiles_docsTable_tabName(), dataSource), diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTimeline.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTimeline.java index 3af85058a3..efefa6bc97 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTimeline.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTimeline.java @@ -46,6 +46,8 @@ import org.sleuthkit.datamodel.DataSource; "TimlinePanel_last30DaysChart_fileEvts_title=File Events", "TimlinePanel_last30DaysChart_artifactEvts_title=Result Events",}) class ExportTimeline { + + private final TimelineSummary timelineSummary; private static final String EARLIEST_LATEST_FORMAT_STR = "MMM d, yyyy"; private static final DateFormat EARLIEST_LATEST_FORMAT = TimelineSummary.getUtcFormat(EARLIEST_LATEST_FORMAT_STR); @@ -58,7 +60,8 @@ class ExportTimeline { /** * Creates new form PastCasesPanel */ - private ExportTimeline() { + ExportTimeline() { + timelineSummary = new TimelineSummary(); } /** @@ -118,8 +121,8 @@ class ExportTimeline { "TimelinePanel_getExports_latest=Latest:", "TimelinePanel_getExports_dateColumnHeader=Date", "TimelinePanel_getExports_chartName=Last 30 Days",}) - static List getExports(DataSource dataSource) { - DataFetcher dataFetcher = (ds) -> TimelineSummary.getTimelineSummaryData(ds, MOST_RECENT_DAYS_COUNT); + List getExports(DataSource dataSource) { + DataFetcher dataFetcher = (ds) -> timelineSummary.getTimelineSummaryData(ds, MOST_RECENT_DAYS_COUNT); TimelineSummaryData summaryData = ExcelExportAction.getFetchResult(dataFetcher, "Timeline", dataSource); if (summaryData == null) { return Collections.emptyList(); diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTypes.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTypes.java index 1523540f23..1321a4b511 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTypes.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTypes.java @@ -33,6 +33,7 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.datasourcesummary.datamodel.ContainerSummary; import org.sleuthkit.autopsy.coreutils.FileTypeUtils.FileTypeCategory; import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceInfoUtilities; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider; import org.sleuthkit.autopsy.datasourcesummary.datamodel.TypesSummary; import org.sleuthkit.autopsy.datasourcesummary.datamodel.TypesSummary.FileTypeCategoryData; import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelSpecialFormatExport.KeyValueItemExportable; @@ -99,6 +100,10 @@ class ExportTypes { return usefulContent; } } + + private final ContainerSummary containerSummary; + private final TypesSummary typesSummary; + private final SleuthkitCaseProvider provider; private static final Color IMAGES_COLOR = new Color(156, 39, 176); private static final Color VIDEOS_COLOR = Color.YELLOW; @@ -119,7 +124,10 @@ class ExportTypes { new FileTypeCategoryData(Bundle.ExportTypes_fileMimeTypesChart_unknown_title(), new HashSet<>(Arrays.asList("application/octet-stream")), UNKNOWN_COLOR) ); - private ExportTypes() { + ExportTypes() { + this.provider = SleuthkitCaseProvider.DEFAULT; + containerSummary = new ContainerSummary(); + typesSummary = new TypesSummary(); } /** @@ -160,8 +168,8 @@ class ExportTypes { * @throws TskCoreException * @throws SQLException */ - private static Long getCountOfFilesForMimeTypes(DataSource currentDataSource, Set setOfMimeTypes) throws TskCoreException, SQLException, NoCurrentCaseException { - return DataSourceInfoUtilities.getCountOfRegNonSlackFiles(currentDataSource, "mime_type IN " + getSqlSet(setOfMimeTypes)); + private Long getCountOfFilesForMimeTypes(DataSource currentDataSource, Set setOfMimeTypes) throws TskCoreException, SQLException, SleuthkitCaseProvider.SleuthkitCaseProviderException { + return DataSourceInfoUtilities.getCountOfRegNonSlackFiles(provider.get(), currentDataSource, "mime_type IN " + getSqlSet(setOfMimeTypes)); } /** @@ -176,8 +184,8 @@ class ExportTypes { * @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 = '') "); + private Long getCountOfFilesWithNoMimeType(DataSource currentDataSource) throws TskCoreException, SQLException, SleuthkitCaseProvider.SleuthkitCaseProviderException { + return DataSourceInfoUtilities.getCountOfRegNonSlackFiles(provider.get(), currentDataSource, "(mime_type IS NULL OR mime_type = '') "); } /** @@ -188,8 +196,8 @@ class ExportTypes { * * @return The pie chart items. */ - private static TypesPieChartData getMimeTypeCategoriesModel(DataSource dataSource) - throws SQLException, TskCoreException, NoCurrentCaseException { + private TypesPieChartData getMimeTypeCategoriesModel(DataSource dataSource) + throws SQLException, TskCoreException, SleuthkitCaseProvider.SleuthkitCaseProviderException { if (dataSource == null) { return null; @@ -213,7 +221,7 @@ class ExportTypes { long noMimeTypeCount = DataSourceInfoUtilities.getLongOrZero(getCountOfFilesWithNoMimeType(dataSource)); // get a count of all regular files - long allRegularFiles = DataSourceInfoUtilities.getLongOrZero(DataSourceInfoUtilities.getCountOfRegNonSlackFiles(dataSource, null)); + long allRegularFiles = DataSourceInfoUtilities.getLongOrZero(DataSourceInfoUtilities.getCountOfRegNonSlackFiles(provider.get(), dataSource, null)); // create entry for mime types in other category long otherCount = allRegularFiles - (categoryTotalCount + noMimeTypeCount); @@ -268,21 +276,21 @@ class ExportTypes { new DefaultCellModel(count, DataSourceInfoUtilities.COMMA_FORMATTER::format, DataSourceInfoUtilities.COMMA_FORMAT_STR)); } - static List getExports(DataSource dataSource) { + List getExports(DataSource dataSource) { if (dataSource == null) { return Collections.emptyList(); } - DataFetcher usageFetcher = (ds) -> ContainerSummary.getDataSourceType(ds); - DataFetcher osFetcher = (ds) -> ContainerSummary.getOperatingSystems(ds); + DataFetcher usageFetcher = (ds) -> containerSummary.getDataSourceType(ds); + DataFetcher osFetcher = (ds) -> containerSummary.getOperatingSystems(ds); DataFetcher sizeFetcher = (ds) -> ds == null ? null : ds.getSize(); DataFetcher typesFetcher = (ds) -> getMimeTypeCategoriesModel(ds); - DataFetcher allocatedFetcher = (ds) -> TypesSummary.getCountOfAllocatedFiles(ds); - DataFetcher unallocatedFetcher = (ds) -> TypesSummary.getCountOfUnallocatedFiles(ds); - DataFetcher slackFetcher = (ds) -> TypesSummary.getCountOfSlackFiles(ds); - DataFetcher directoriesFetcher = (ds) -> TypesSummary.getCountOfDirectories(ds); + DataFetcher allocatedFetcher = (ds) -> typesSummary.getCountOfAllocatedFiles(ds); + DataFetcher unallocatedFetcher = (ds) -> typesSummary.getCountOfUnallocatedFiles(ds); + DataFetcher slackFetcher = (ds) -> typesSummary.getCountOfSlackFiles(ds); + DataFetcher directoriesFetcher = (ds) -> typesSummary.getCountOfDirectories(ds); // Retrieve data to create the types pie chart TypesPieChartData typesData = ExcelExportAction.getFetchResult(typesFetcher, "Types", dataSource); diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportUserActivity.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportUserActivity.java index 6a1cb491e2..028073e53d 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportUserActivity.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportUserActivity.java @@ -67,6 +67,8 @@ import static org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.Excel "ExportUserActivity_noDataExists=No communication data exists"}) class ExportUserActivity { + private final UserActivitySummary userSummary; + private static final String DATETIME_FORMAT_STR = "yyyy/MM/dd HH:mm:ss"; private static final DateFormat DATETIME_FORMAT = new SimpleDateFormat(DATETIME_FORMAT_STR, Locale.getDefault()); private static final int TOP_PROGS_COUNT = 10; @@ -206,7 +208,8 @@ class ExportUserActivity { ) ); - private ExportUserActivity() { + ExportUserActivity() { + userSummary = new UserActivitySummary(); } private static Function> getDateFunct() { @@ -228,13 +231,13 @@ class ExportUserActivity { return UserActivitySummary.getShortFolderName(path, appName); } - static List getExports(DataSource dataSource) { + List getExports(DataSource dataSource) { - DataFetcher> topProgramsFetcher = (ds) -> UserActivitySummary.getTopPrograms(ds, TOP_PROGS_COUNT); - DataFetcher> topDomainsFetcher = (ds) -> UserActivitySummary.getRecentDomains(ds, TOP_DOMAINS_COUNT); - DataFetcher> topWebSearchesFetcher = (ds) -> UserActivitySummary.getMostRecentWebSearches(ds, TOP_SEARCHES_COUNT); - DataFetcher> topDevicesAttachedFetcher = (ds) -> UserActivitySummary.getRecentDevices(ds, TOP_DEVICES_COUNT); - DataFetcher> topAccountsFetcher = (ds) -> UserActivitySummary.getRecentAccounts(ds, TOP_ACCOUNTS_COUNT); + DataFetcher> topProgramsFetcher = (ds) -> userSummary.getTopPrograms(ds, TOP_PROGS_COUNT); + DataFetcher> topDomainsFetcher = (ds) -> userSummary.getRecentDomains(ds, TOP_DOMAINS_COUNT); + DataFetcher> topWebSearchesFetcher = (ds) -> userSummary.getMostRecentWebSearches(ds, TOP_SEARCHES_COUNT); + DataFetcher> topDevicesAttachedFetcher = (ds) -> userSummary.getRecentDevices(ds, TOP_DEVICES_COUNT); + DataFetcher> topAccountsFetcher = (ds) -> userSummary.getRecentAccounts(ds, TOP_ACCOUNTS_COUNT); return Stream.of( getTableExport(topProgramsFetcher, topProgramsTemplate, Bundle.ExportUserActivity_TopProgramsTableModel_tabName(), dataSource), diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/datasourcesummary/UserActivitySummaryTests.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/datasourcesummary/UserActivitySummaryTests.java index 73fc864c61..5cfdfca671 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/datasourcesummary/UserActivitySummaryTests.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/datasourcesummary/UserActivitySummaryTests.java @@ -25,7 +25,7 @@ import java.util.Map; import java.util.stream.Collectors; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; -import org.sleuthkit.autopsy.datasourcesummary.ui.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.autopsy.datasourcesummary.ui.UserActivitySummaryGetter; import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopDomainsResult; import org.sleuthkit.datamodel.Content; diff --git a/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesSummaryTest.java b/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesSummaryTest.java index 244a7da113..535f258ced 100644 --- a/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesSummaryTest.java +++ b/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesSummaryTest.java @@ -44,7 +44,7 @@ import static org.mockito.Mockito.when; import org.sleuthkit.autopsy.datasourcesummary.datamodel.RecentFilesSummary.RecentAttachmentDetails; import org.sleuthkit.autopsy.datasourcesummary.datamodel.RecentFilesSummary.RecentDownloadDetails; import org.sleuthkit.autopsy.datasourcesummary.datamodel.RecentFilesSummary.RecentFileDetails; -import org.sleuthkit.autopsy.datasourcesummary.ui.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.autopsy.testutils.RandomizationUtils; import org.sleuthkit.autopsy.testutils.TskMockUtils; import org.sleuthkit.datamodel.Blackboard; diff --git a/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummaryTest.java b/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummaryTest.java index 0fd7b72d9c..81983ce4d5 100644 --- a/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummaryTest.java +++ b/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummaryTest.java @@ -44,7 +44,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceSummaryMockUtils.getArtifactsTSKMock; -import org.sleuthkit.autopsy.datasourcesummary.ui.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopAccountResult; import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopDeviceAttachedResult; import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopDomainsResult; From 2b7f40a5844c622763689deab49f7e21b91aa220 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Wed, 18 Aug 2021 18:33:35 -0400 Subject: [PATCH 27/33] Restored unit tests --- .../UserActivitySummaryTests.java | 10 +- .../datamodel/RecentFilesSummaryTest.java | 35 +++--- .../datamodel/UserActivitySummaryTest.java | 113 ++++++++++-------- 3 files changed, 82 insertions(+), 76 deletions(-) diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/datasourcesummary/UserActivitySummaryTests.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/datasourcesummary/UserActivitySummaryTests.java index 5cfdfca671..14455b27c9 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/datasourcesummary/UserActivitySummaryTests.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/datasourcesummary/UserActivitySummaryTests.java @@ -26,7 +26,7 @@ import java.util.stream.Collectors; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; -import org.sleuthkit.autopsy.datasourcesummary.ui.UserActivitySummaryGetter; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary; import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopDomainsResult; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.DataSource; @@ -36,14 +36,14 @@ import org.sleuthkit.autopsy.integrationtesting.IntegrationTest; import org.sleuthkit.autopsy.integrationtesting.IntegrationTestGroup; /** - * Tests for the UserActivitySummaryGetter class. + * Tests for the UserActivitySummary class. */ @ServiceProvider(service = IntegrationTestGroup.class) public class UserActivitySummaryTests implements IntegrationTestGroup { /** - * Runs UserActivitySummaryGetter.getRecentDomains for all data sources found in - the current case. + * Runs UserActivitySummary.getRecentDomains for all data sources found in + * the current case. * * @return A map where the key is the data source name and the value are the * results of that method. @@ -52,7 +52,7 @@ public class UserActivitySummaryTests implements IntegrationTestGroup { public Map>> getRecentDomainsTest() throws NoCurrentCaseException, TskCoreException, SleuthkitCaseProviderException { - UserActivitySummaryGetter userActivitySummary = new UserActivitySummaryGetter(); + UserActivitySummary userActivitySummary = new UserActivitySummary(); Map>> toRet = new HashMap<>(); for (Content c : Case.getCurrentCaseThrows().getDataSources()) { if (c instanceof DataSource) { diff --git a/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesSummaryTest.java b/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesSummaryTest.java index 535f258ced..0acda3954a 100644 --- a/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesSummaryTest.java +++ b/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/RecentFilesSummaryTest.java @@ -18,7 +18,6 @@ */ package org.sleuthkit.autopsy.datasourcesummary.datamodel; -import org.sleuthkit.autopsy.datasourcesummary.ui.RecentFilesGetter; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; @@ -63,15 +62,15 @@ import org.sleuthkit.datamodel.TskCoreException; public class RecentFilesSummaryTest { /** - * An interface for calling methods in RecentFilesGetter in a uniform - manner. + * An interface for calling methods in RecentFilesSummary in a uniform + * manner. */ private interface RecentFilesMethod { /** - * Means of acquiring data from a method in RecentFilesGetter. + * Means of acquiring data from a method in RecentFilesSummary. * - * @param recentFilesSummary The RecentFilesGetter object. + * @param recentFilesSummary The RecentFilesSummary object. * @param dataSource The datasource. * @param count The number of items to retrieve. * @@ -80,7 +79,7 @@ public class RecentFilesSummaryTest { * @throws SleuthkitCaseProviderException * @throws TskCoreException */ - List fetch(RecentFilesGetter recentFilesSummary, DataSource dataSource, int count) + List fetch(RecentFilesSummary recentFilesSummary, DataSource dataSource, int count) throws SleuthkitCaseProviderException, TskCoreException; } @@ -106,7 +105,7 @@ public class RecentFilesSummaryTest { throws TskCoreException, SleuthkitCaseProviderException { Pair casePair = DataSourceSummaryMockUtils.getArtifactsTSKMock(null); DataSource dataSource = TskMockUtils.getDataSource(1); - RecentFilesGetter summary = new RecentFilesGetter(); + RecentFilesSummary summary = new RecentFilesSummary(() -> casePair.getLeft()); try { method.fetch(summary, dataSource, -1); @@ -147,7 +146,7 @@ public class RecentFilesSummaryTest { throws SleuthkitCaseProviderException, TskCoreException { Pair casePair = DataSourceSummaryMockUtils.getArtifactsTSKMock(null); - RecentFilesGetter summary = new RecentFilesGetter(); + RecentFilesSummary summary = new RecentFilesSummary(() -> casePair.getLeft()); List items = recentFilesMethod.fetch(summary, null, 10); Assert.assertNotNull("Expected method " + methodName + " to return an empty list.", items); @@ -185,7 +184,7 @@ public class RecentFilesSummaryTest { throws SleuthkitCaseProviderException, TskCoreException { Pair casePair = DataSourceSummaryMockUtils.getArtifactsTSKMock(Collections.emptyList()); - RecentFilesGetter summary = new RecentFilesGetter(); + RecentFilesSummary summary = new RecentFilesSummary(() -> casePair.getLeft()); DataSource dataSource = TskMockUtils.getDataSource(1); List items = recentFilesMethod.fetch(summary, dataSource, 10); Assert.assertNotNull("Expected method " + methodName + " to return an empty list.", items); @@ -279,7 +278,7 @@ public class RecentFilesSummaryTest { // run through method Pair casePair = DataSourceSummaryMockUtils.getArtifactsTSKMock(RandomizationUtils.getMixedUp(artifacts)); - RecentFilesGetter summary = new RecentFilesGetter(); + RecentFilesSummary summary = new RecentFilesSummary(() -> casePair.getLeft()); List results = summary.getRecentlyOpenedDocuments(dataSource, countRequest); // verify results @@ -303,7 +302,7 @@ public class RecentFilesSummaryTest { List artifacts = Arrays.asList(item2, item3, item1); Pair casePair = DataSourceSummaryMockUtils.getArtifactsTSKMock(RandomizationUtils.getMixedUp(artifacts)); - RecentFilesGetter summary = new RecentFilesGetter(); + RecentFilesSummary summary = new RecentFilesSummary(() -> casePair.getLeft()); List results = summary.getRecentlyOpenedDocuments(dataSource, 10); // verify results (only successItem) @@ -323,7 +322,7 @@ public class RecentFilesSummaryTest { List artifacts = Arrays.asList(nullTime, zeroTime, successItem); Pair casePair = DataSourceSummaryMockUtils.getArtifactsTSKMock(RandomizationUtils.getMixedUp(artifacts)); - RecentFilesGetter summary = new RecentFilesGetter(); + RecentFilesSummary summary = new RecentFilesSummary(() -> casePair.getLeft()); List results = summary.getRecentlyOpenedDocuments(dataSource, 10); // verify results (only successItem) @@ -374,7 +373,7 @@ public class RecentFilesSummaryTest { // call method Pair casePair = DataSourceSummaryMockUtils.getArtifactsTSKMock(RandomizationUtils.getMixedUp(artifacts)); - RecentFilesGetter summary = new RecentFilesGetter(); + RecentFilesSummary summary = new RecentFilesSummary(() -> casePair.getLeft()); List results = summary.getRecentDownloads(dataSource, countRequest); // verify results @@ -400,7 +399,7 @@ public class RecentFilesSummaryTest { List artifacts = Arrays.asList(item2, item3, item1); Pair casePair = DataSourceSummaryMockUtils.getArtifactsTSKMock(RandomizationUtils.getMixedUp(artifacts)); - RecentFilesGetter summary = new RecentFilesGetter(); + RecentFilesSummary summary = new RecentFilesSummary(() -> casePair.getLeft()); // call method List results = summary.getRecentDownloads(dataSource, 10); @@ -423,7 +422,7 @@ public class RecentFilesSummaryTest { List artifacts = Arrays.asList(nullTime, zeroTime, successItem); Pair casePair = DataSourceSummaryMockUtils.getArtifactsTSKMock(RandomizationUtils.getMixedUp(artifacts)); - RecentFilesGetter summary = new RecentFilesGetter(); + RecentFilesSummary summary = new RecentFilesSummary(() -> casePair.getLeft()); // call method List results = summary.getRecentDownloads(dataSource, 10); @@ -652,7 +651,7 @@ public class RecentFilesSummaryTest { List mixedUpItems = RandomizationUtils.getMixedUp(items); Pair casePair = getRecentAttachmentArtifactCase(mixedUpItems); - RecentFilesGetter summary = new RecentFilesGetter(); + RecentFilesSummary summary = new RecentFilesSummary(() -> casePair.getLeft()); // retrieve results List results = summary.getRecentAttachments(dataSource, countRequest); @@ -699,7 +698,7 @@ public class RecentFilesSummaryTest { noParentFile, noAssocAttr, missingAssocArt); Pair casePair = getRecentAttachmentArtifactCase(items); - RecentFilesGetter summary = new RecentFilesGetter(); + RecentFilesSummary summary = new RecentFilesSummary(() -> casePair.getLeft()); // get data List results = summary.getRecentAttachments(dataSource, 10); @@ -736,7 +735,7 @@ public class RecentFilesSummaryTest { List items = Arrays.asList(item1, item2, item3); Pair casePair = getRecentAttachmentArtifactCase(items); - RecentFilesGetter summary = new RecentFilesGetter(); + RecentFilesSummary summary = new RecentFilesSummary(() -> casePair.getLeft()); // get data List results = summary.getRecentAttachments(dataSource, 10); diff --git a/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummaryTest.java b/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummaryTest.java index 81983ce4d5..2b6a1c6600 100644 --- a/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummaryTest.java +++ b/Core/test/unit/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummaryTest.java @@ -18,7 +18,6 @@ */ package org.sleuthkit.autopsy.datasourcesummary.datamodel; -import org.sleuthkit.autopsy.datasourcesummary.ui.UserActivitySummaryGetter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -64,27 +63,27 @@ import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; /** - * Tests for UserActivitySummaryGetter. + * Tests for UserActivitySummary. */ public class UserActivitySummaryTest { /** - * Function to retrieve data from UserActivitySummaryGetter with the provided - arguments. + * Function to retrieve data from UserActivitySummary with the provided + * arguments. */ private interface DataFunction { /** - * A UserActivitySummaryGetter method encapsulated in a uniform manner. + * A UserActivitySummary method encapsulated in a uniform manner. * - * @param userActivitySummary The UserActivitySummaryGetter class to use. + * @param userActivitySummary The UserActivitySummary class to use. * @param datasource The data source. * @param count The count. * @return The list of objects to return. * @throws SleuthkitCaseProviderException * @throws TskCoreException */ - List retrieve(UserActivitySummaryGetter userActivitySummary, DataSource datasource, int count) throws + List retrieve(UserActivitySummary userActivitySummary, DataSource datasource, int count) throws SleuthkitCaseProviderException, TskCoreException; } @@ -120,21 +119,25 @@ public class UserActivitySummaryTest { } /** - * Gets a UserActivitySummaryGetter class to test. + * Gets a UserActivitySummary class to test. * * @param tskCase The SleuthkitCase. * @param hasTranslation Whether the translation service is functional. * @param translateFunction Function for translation. * - * @return The UserActivitySummaryGetter class to use for testing. + * @return The UserActivitySummary class to use for testing. * * @throws NoServiceProviderException * @throws TranslationException */ - private static UserActivitySummaryGetter getTestClass(SleuthkitCase tskCase, boolean hasTranslation, Function translateFunction) + private static UserActivitySummary getTestClass(SleuthkitCase tskCase, boolean hasTranslation, Function translateFunction) throws NoServiceProviderException, TranslationException { - return new UserActivitySummaryGetter(); + return new UserActivitySummary( + () -> tskCase, + TskMockUtils.getTextTranslationService(translateFunction, hasTranslation), + TskMockUtils.getJavaLogger("UNIT TEST LOGGER") + ); } private void testMinCount(DataFunction funct, String id) @@ -142,7 +145,7 @@ public class UserActivitySummaryTest { for (int count : new int[]{0, -1}) { Pair tskPair = getArtifactsTSKMock(null); - UserActivitySummaryGetter summary = getTestClass(tskPair.getLeft(), false, null); + UserActivitySummary summary = getTestClass(tskPair.getLeft(), false, null); try { funct.retrieve(summary, TskMockUtils.getDataSource(1), -1); @@ -180,7 +183,7 @@ public class UserActivitySummaryTest { throws TskCoreException, NoServiceProviderException, TranslationException, SleuthkitCaseProviderException { Pair tskPair = getArtifactsTSKMock(null); - UserActivitySummaryGetter summary = getTestClass(tskPair.getLeft(), false, null); + UserActivitySummary summary = getTestClass(tskPair.getLeft(), false, null); List retArr = funct.retrieve(summary, null, 10); verify(tskPair.getRight(), never() .description(String.format("Expected method %s to return empty list for null data source and not call SleuthkitCase", id))) @@ -213,7 +216,7 @@ public class UserActivitySummaryTest { long dataSourceId = 1; int count = 10; Pair tskPair = getArtifactsTSKMock(new ArrayList<>()); - UserActivitySummaryGetter summary = getTestClass(tskPair.getLeft(), false, null); + UserActivitySummary summary = getTestClass(tskPair.getLeft(), false, null); List retArr = funct.retrieve(summary, TskMockUtils.getDataSource(dataSourceId), count); Assert.assertTrue(String.format("Expected non null empty list returned from %s", id), retArr != null); @@ -287,7 +290,7 @@ public class UserActivitySummaryTest { .collect(Collectors.toList()); Pair tskPair = getArtifactsTSKMock(artifacts); - UserActivitySummaryGetter summary = getTestClass(tskPair.getLeft(), false, null); + UserActivitySummary summary = getTestClass(tskPair.getLeft(), false, null); List results = summary.getRecentDevices(ds, count); @@ -301,8 +304,8 @@ public class UserActivitySummaryTest { } /** - * Ensures that UserActivitySummaryGetter.getRecentDevices limits returned entries - to count provided. + * Ensures that UserActivitySummary.getRecentDevices limits returned entries + * to count provided. * * @throws TskCoreException * @throws NoServiceProviderException @@ -324,7 +327,7 @@ public class UserActivitySummaryTest { .collect(Collectors.toList()); Pair tskPair = getArtifactsTSKMock(returnedArtifacts); - UserActivitySummaryGetter summary = getTestClass(tskPair.getLeft(), false, null); + UserActivitySummary summary = getTestClass(tskPair.getLeft(), false, null); List results = summary.getRecentDevices(dataSource, countRequested); verifyCalled(tskPair.getRight(), ARTIFACT_TYPE.TSK_DEVICE_ATTACHED.getTypeID(), dataSourceId, @@ -345,7 +348,7 @@ public class UserActivitySummaryTest { BlackboardArtifact item3 = getRecentDeviceArtifact(1003, dataSource, "ID1", "MAKE1", "MODEL1", DAY_SECONDS + 2); Pair tskPair = getArtifactsTSKMock(Arrays.asList(item1, item2, item3)); - UserActivitySummaryGetter summary = getTestClass(tskPair.getLeft(), false, null); + UserActivitySummary summary = getTestClass(tskPair.getLeft(), false, null); List results = summary.getRecentDevices(dataSource, 10); @@ -393,7 +396,7 @@ public class UserActivitySummaryTest { List artList = Arrays.asList(art1a, art2a, art2b, art1b, art1c); Pair tskPair = getArtifactsTSKMock(artList); - UserActivitySummaryGetter summary = getTestClass(tskPair.getLeft(), false, null); + UserActivitySummary summary = getTestClass(tskPair.getLeft(), false, null); List results = summary.getMostRecentWebSearches(ds, 10); verifyCalled(tskPair.getRight(), ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY.getTypeID(), dataSourceId, "Expected getRecentDevices to call getArtifacts with correct arguments."); @@ -430,7 +433,11 @@ public class UserActivitySummaryTest { // set up a mock TextTranslationService returning a translation TextTranslationService translationService = TskMockUtils.getTextTranslationService(translator, hasProvider); - UserActivitySummaryGetter summary = new UserActivitySummaryGetter(); + UserActivitySummary summary = new UserActivitySummary( + () -> tskPair.getLeft(), + translationService, + TskMockUtils.getJavaLogger("UNIT TEST LOGGER") + ); List results = summary.getMostRecentWebSearches(ds, queries.size()); @@ -466,8 +473,8 @@ public class UserActivitySummaryTest { } /** - * Verify that UserActivitySummaryGetter.getMostRecentWebSearches handles - translation appropriately. + * Verify that UserActivitySummary.getMostRecentWebSearches handles + * translation appropriately. * * @throws SleuthkitCaseProviderException * @throws TskCoreException @@ -495,8 +502,8 @@ public class UserActivitySummaryTest { } /** - * Ensure that UserActivitySummaryGetter.getMostRecentWebSearches results limited - to count. + * Ensure that UserActivitySummary.getMostRecentWebSearches results limited + * to count. * * @throws TskCoreException * @throws NoServiceProviderException @@ -518,7 +525,7 @@ public class UserActivitySummaryTest { .collect(Collectors.toList()); Pair tskPair = getArtifactsTSKMock(returnedArtifacts); - UserActivitySummaryGetter summary = getTestClass(tskPair.getLeft(), false, null); + UserActivitySummary summary = getTestClass(tskPair.getLeft(), false, null); List results = summary.getMostRecentWebSearches(dataSource, countRequested); verifyCalled(tskPair.getRight(), ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY.getTypeID(), dataSourceId, @@ -551,8 +558,8 @@ public class UserActivitySummaryTest { private static final long DOMAIN_WINDOW_DAYS = 30; /** - * UserActivitySummaryGetter.getRecentDomains should return results within 30 days - of the most recent access. + * UserActivitySummary.getRecentDomains should return results within 30 days + * of the most recent access. * * @throws TskCoreException * @throws SleuthkitCaseProviderException @@ -582,7 +589,7 @@ public class UserActivitySummaryTest { Pair tskPair = getArtifactsTSKMock(retArr); - UserActivitySummaryGetter summary = getTestClass(tskPair.getLeft(), false, null); + UserActivitySummary summary = getTestClass(tskPair.getLeft(), false, null); List domains = summary.getRecentDomains(dataSource, 10); @@ -626,7 +633,7 @@ public class UserActivitySummaryTest { Pair tskPair = getArtifactsTSKMock(retArr); - UserActivitySummaryGetter summary = getTestClass(tskPair.getLeft(), false, null); + UserActivitySummary summary = getTestClass(tskPair.getLeft(), false, null); List domains = summary.getRecentDomains(dataSource, 10); @@ -663,7 +670,7 @@ public class UserActivitySummaryTest { List retArr = Arrays.asList(artifact1, artifact1a, artifact2, artifact2a, artifact2b); Pair tskPair = getArtifactsTSKMock(retArr); - UserActivitySummaryGetter summary = getTestClass(tskPair.getLeft(), false, null); + UserActivitySummary summary = getTestClass(tskPair.getLeft(), false, null); List domains = summary.getRecentDomains(dataSource, 10); @@ -682,8 +689,8 @@ public class UserActivitySummaryTest { } /** - * Ensure that UserActivitySummaryGetter.getRecentDomains limits to count - appropriately. + * Ensure that UserActivitySummary.getRecentDomains limits to count + * appropriately. * * @throws TskCoreException * @throws NoServiceProviderException @@ -712,7 +719,7 @@ public class UserActivitySummaryTest { .collect(Collectors.toList()); Pair tskPair = getArtifactsTSKMock(returnedArtifacts); - UserActivitySummaryGetter summary = getTestClass(tskPair.getLeft(), false, null); + UserActivitySummary summary = getTestClass(tskPair.getLeft(), false, null); List results = summary.getRecentDomains(dataSource, countRequested); verifyCalled(tskPair.getRight(), ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID(), dataSourceId, @@ -811,7 +818,7 @@ public class UserActivitySummaryTest { } /** - * Performs a test on UserActivitySummaryGetter.getRecentAccounts. + * Performs a test on UserActivitySummary.getRecentAccounts. * * @param dataSource The datasource to use as parameter. * @param count The count to use as a parameter. @@ -842,7 +849,7 @@ public class UserActivitySummaryTest { .collect(Collectors.toList()); }); - UserActivitySummaryGetter summary = getTestClass(mockCase, false, null); + UserActivitySummary summary = getTestClass(mockCase, false, null); List receivedResults = summary.getRecentAccounts(dataSource, count); @@ -873,8 +880,8 @@ public class UserActivitySummaryTest { } /** - * Verify that UserActivitySummaryGetter.getRecentAccounts attempts to find a date - but if none present, the artifact is excluded. + * Verify that UserActivitySummary.getRecentAccounts attempts to find a date + * but if none present, the artifact is excluded. * * @throws TskCoreException * @throws NoServiceProviderException @@ -943,8 +950,8 @@ public class UserActivitySummaryTest { } /** - * Verifies that UserActivitySummaryGetter.getRecentAccounts groups appropriately - by account type. + * Verifies that UserActivitySummary.getRecentAccounts groups appropriately + * by account type. * * @throws TskCoreException * @throws NoServiceProviderException @@ -979,8 +986,8 @@ public class UserActivitySummaryTest { } /** - * Verifies that UserActivitySummaryGetter.getRecentAccounts properly limits - results returned. + * Verifies that UserActivitySummary.getRecentAccounts properly limits + * results returned. * * @throws TskCoreException * @throws NoServiceProviderException @@ -1000,7 +1007,7 @@ public class UserActivitySummaryTest { .collect(Collectors.toList()); Pair tskPair = getArtifactsTSKMock(returnedArtifacts); - UserActivitySummaryGetter summary = getTestClass(tskPair.getLeft(), false, null); + UserActivitySummary summary = getTestClass(tskPair.getLeft(), false, null); List results = summary.getRecentAccounts(dataSource, countRequested); verifyCalled(tskPair.getRight(), ARTIFACT_TYPE.TSK_MESSAGE.getTypeID(), dataSource.getId(), @@ -1037,7 +1044,7 @@ public class UserActivitySummaryTest { expected.put("/Other Path/Item/Item.exe", ""); Pair tskPair = getArtifactsTSKMock(null); - UserActivitySummaryGetter summary = getTestClass(tskPair.getLeft(), false, null); + UserActivitySummary summary = getTestClass(tskPair.getLeft(), false, null); for (Entry path : expected.entrySet()) { Assert.assertTrue(path.getValue().equalsIgnoreCase(summary.getShortFolderName(path.getKey(), "Item.exe"))); @@ -1105,7 +1112,7 @@ public class UserActivitySummaryTest { successful, successful2 )); - UserActivitySummaryGetter summary = getTestClass(tskPair.getLeft(), false, null); + UserActivitySummary summary = getTestClass(tskPair.getLeft(), false, null); List results = summary.getTopPrograms(ds1, 10); Assert.assertEquals(2, results.size()); @@ -1143,7 +1150,7 @@ public class UserActivitySummaryTest { prog2, prog2a, prog2b, prog3, prog3a, prog3b )); - UserActivitySummaryGetter summary = getTestClass(tskPair.getLeft(), false, null); + UserActivitySummary summary = getTestClass(tskPair.getLeft(), false, null); List results = summary.getTopPrograms(ds1, 10); Assert.assertEquals(3, results.size()); @@ -1167,7 +1174,7 @@ public class UserActivitySummaryTest { throws TskCoreException, NoServiceProviderException, TranslationException, SleuthkitCaseProviderException { Pair tskPair = getArtifactsTSKMock(artifacts); - UserActivitySummaryGetter summary = getTestClass(tskPair.getLeft(), false, null); + UserActivitySummary summary = getTestClass(tskPair.getLeft(), false, null); List results = summary.getTopPrograms(ds1, 10); Assert.assertEquals(programNamesReturned.size(), results.size()); @@ -1177,8 +1184,8 @@ public class UserActivitySummaryTest { } /** - * Ensure that UserActivitySummaryGetter.getTopPrograms properly orders results - (first by run count, then date, then program name). + * Ensure that UserActivitySummary.getTopPrograms properly orders results + * (first by run count, then date, then program name). * * @throws TskCoreException * @throws NoServiceProviderException @@ -1207,8 +1214,8 @@ public class UserActivitySummaryTest { } /** - * Ensure that UserActivitySummaryGetter.getTopPrograms properly limits results - (if no run count and no run date, then no limit). + * Ensure that UserActivitySummary.getTopPrograms properly limits results + * (if no run count and no run date, then no limit). * * @throws TskCoreException * @throws NoServiceProviderException @@ -1232,7 +1239,7 @@ public class UserActivitySummaryTest { .collect(Collectors.toList()); Pair tskPair = getArtifactsTSKMock(returnedArtifacts); - UserActivitySummaryGetter summary = getTestClass(tskPair.getLeft(), false, null); + UserActivitySummary summary = getTestClass(tskPair.getLeft(), false, null); List results = summary.getTopPrograms(dataSource, countRequested); verifyCalled(tskPair.getRight(), ARTIFACT_TYPE.TSK_PROG_RUN.getTypeID(), dataSourceId, @@ -1246,7 +1253,7 @@ public class UserActivitySummaryTest { .collect(Collectors.toList()); Pair tskPairAlphabetical = getArtifactsTSKMock(returnedArtifactsAlphabetical); - UserActivitySummaryGetter summaryAlphabetical = getTestClass(tskPairAlphabetical.getLeft(), false, null); + UserActivitySummary summaryAlphabetical = getTestClass(tskPairAlphabetical.getLeft(), false, null); List resultsAlphabetical = summaryAlphabetical.getTopPrograms(dataSource, countRequested); verifyCalled(tskPairAlphabetical.getRight(), ARTIFACT_TYPE.TSK_PROG_RUN.getTypeID(), dataSourceId, From b469e2b5bf97309da84a8c7ac09a5d649fad46ab Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Thu, 19 Aug 2021 09:48:30 -0400 Subject: [PATCH 28/33] Resolved TODOs --- .../datamodel/ContainerSummary.java | 2 -- .../datamodel/DataSourceInfoUtilities.java | 2 -- .../datamodel/TypesSummary.java | 2 -- .../datamodel/UserActivitySummary.java | 1 - .../datasourcesummary/ui/UserActivityPanel.java | 5 +++-- .../ui/UserActivitySummaryGetter.java | 16 ---------------- .../ExportUserActivity.java | 14 +------------- 7 files changed, 4 insertions(+), 38 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummary.java index 428c92047f..4ecacdb059 100755 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummary.java @@ -212,8 +212,6 @@ public class ContainerSummary { String separator = ", "; return getConcattedStringsResult(query, valueParam, separator); } - - // ELTODO everything below is NOT in develop! /** * Data model data for data source images. diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceInfoUtilities.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceInfoUtilities.java index 7e51a53037..dfbe49c282 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceInfoUtilities.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceInfoUtilities.java @@ -433,8 +433,6 @@ public final class DataSourceInfoUtilities { Long longVal = getLongOrNull(artifact, attributeType); return (longVal == null || longVal == 0) ? null : new Date(longVal * 1000); } - - // ELTODO everything below is not in develop /** * Returns the long value or zero if longVal is null. diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TypesSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TypesSummary.java index 6c1b71861b..b13e852b95 100755 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TypesSummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TypesSummary.java @@ -143,8 +143,6 @@ public class TypesSummary { return DataSourceInfoUtilities.getCountOfRegularFiles(provider.get(), currentDataSource, "type=" + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType()); } - - // ELTODO everything below is not in develop /** * Information concerning a particular file type category. diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummary.java index 8310c1f5b0..a32867ffce 100755 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/UserActivitySummary.java @@ -186,7 +186,6 @@ public class UserActivitySummary { } } - // ELTODO this method is not in develop /** * Determines a short folder name if any. Otherwise, returns empty string. * diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivityPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivityPanel.java index 3ac26a3b1e..bb81dc9b2e 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivityPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivityPanel.java @@ -28,6 +28,7 @@ import java.util.Locale; import java.util.function.Function; import org.apache.commons.lang.StringUtils; import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary; import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.LastAccessedArtifact; import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopAccountResult; import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopDeviceAttachedResult; @@ -342,8 +343,8 @@ public class UserActivityPanel extends BaseDataSourceSummaryPanel { * * @return The underlying short folder name if one exists. */ - private String getShortFolderName(String path, String appName) { - return this.userActivityData.getShortFolderName(path, appName); + private static String getShortFolderName(String path, String appName) { + return UserActivitySummary.getShortFolderName(path, appName); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivitySummaryGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivitySummaryGetter.java index ab98b0e271..70ad958be5 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivitySummaryGetter.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivitySummaryGetter.java @@ -172,22 +172,6 @@ public class UserActivitySummaryGetter implements DefaultArtifactUpdateGovernor return userActivity.getRecentAccounts(dataSource, count); } - /** - * Determines a short folder name if any. Otherwise, returns empty string. - * - * @param strPath The string path. - * @param applicationName The application name. - * - * @return The short folder name or empty string if not found. - */ - public String getShortFolderName(String strPath, String applicationName) { - if (strPath == null) { - return ""; - } - - return UserActivitySummary.getShortFolderName(strPath, applicationName); - } - /** * Retrieves the top programs results for the given data source limited to * the count provided as a parameter. The highest run times are at the top diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportUserActivity.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportUserActivity.java index 028073e53d..7be189cc1b 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportUserActivity.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportUserActivity.java @@ -91,7 +91,7 @@ class ExportUserActivity { Bundle.ExportUserActivity_TopProgramsTableModel_folder_header(), (prog) -> { return new DefaultCellModel<>( - getShortFolderName( + UserActivitySummary.getShortFolderName( prog.getProgramPath(), prog.getProgramName())); }, @@ -219,18 +219,6 @@ class ExportUserActivity { }; } - /** - * Queries DataSourceTopProgramsSummary instance for short folder name. - * - * @param path The path for the application. - * @param appName The application name. - * - * @return The underlying short folder name if one exists. - */ - private static String getShortFolderName(String path, String appName) { - return UserActivitySummary.getShortFolderName(path, appName); - } - List getExports(DataSource dataSource) { DataFetcher> topProgramsFetcher = (ds) -> userSummary.getTopPrograms(ds, TOP_PROGS_COUNT); From 519d201ccfc1b4836474dafd1b2ed2b1843b9417 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Thu, 19 Aug 2021 13:08:26 -0400 Subject: [PATCH 29/33] Removed unused imports --- .../datamodel/DataSourceInfoUtilities.java | 2 - .../ui/TimelinePanel.java.bak | 358 ------------------ 2 files changed, 360 deletions(-) delete mode 100755 Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java.bak diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceInfoUtilities.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceInfoUtilities.java index dfbe49c282..becd78f418 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceInfoUtilities.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceInfoUtilities.java @@ -30,8 +30,6 @@ import java.util.TreeMap; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; import org.apache.commons.lang.StringUtils; -import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute.Type; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java.bak b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java.bak deleted file mode 100755 index 6b1292139e..0000000000 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java.bak +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2020-2021 Basis Technology Corp. - * Contact: carrier sleuthkit org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sleuthkit.autopsy.datasourcesummary.ui; - -import java.awt.Color; -import java.text.DateFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Date; -import java.util.List; -import java.util.logging.Level; -import org.apache.commons.collections.CollectionUtils; -import org.joda.time.DateTime; -import org.joda.time.Interval; -import org.openide.util.NbBundle.Messages; -import org.openide.util.actions.CallableSystemAction; -import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary.DailyActivityAmount; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary.TimelineSummaryData; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartPanel; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartSeries; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartPanel.OrderedKey; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartSeries.BarChartItem; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetcher; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.IngestRunningLabel; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.LoadableComponent; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.LoadableLabel; -import org.sleuthkit.autopsy.timeline.OpenTimelineAction; -import org.sleuthkit.autopsy.timeline.TimeLineController; -import org.sleuthkit.autopsy.timeline.TimeLineModule; -import org.sleuthkit.datamodel.DataSource; -import org.sleuthkit.datamodel.TskCoreException; - -/** - * A tab shown in data source summary displaying information about a data - * source's timeline events. - */ -@Messages({ - "TimelinePanel_earliestLabel_title=Earliest", - "TimelinePanel_latestLabel_title=Latest", - "TimlinePanel_last30DaysChart_title=Last 30 Days", - "TimlinePanel_last30DaysChart_fileEvts_title=File Events", - "TimlinePanel_last30DaysChart_artifactEvts_title=Result Events",}) -public class TimelinePanel extends BaseDataSourceSummaryPanel { - - private static final Logger logger = Logger.getLogger(TimelinePanel.class.getName()); - private static final long serialVersionUID = 1L; - - private static final String EARLIEST_LATEST_FORMAT_STR = "MMM d, yyyy"; - private static final DateFormat EARLIEST_LATEST_FORMAT = TimelineSummary.getUtcFormat(EARLIEST_LATEST_FORMAT_STR); - private static final DateFormat CHART_FORMAT = TimelineSummary.getUtcFormat("MMM d, yyyy"); - private static final int MOST_RECENT_DAYS_COUNT = 30; - - // components displayed in the tab - private final IngestRunningLabel ingestRunningLabel = new IngestRunningLabel(); - private final LoadableLabel earliestLabel = new LoadableLabel(Bundle.TimelinePanel_earliestLabel_title()); - private final LoadableLabel latestLabel = new LoadableLabel(Bundle.TimelinePanel_latestLabel_title()); - private final BarChartPanel last30DaysChart = new BarChartPanel(Bundle.TimlinePanel_last30DaysChart_title(), "", ""); - private final TimelineDataSourceUtils timelineUtils = TimelineDataSourceUtils.getInstance(); - - // all loadable components on this tab - private final List> loadableComponents = Arrays.asList(earliestLabel, latestLabel, last30DaysChart); - - private final DataFetcher dataFetcher; - - // actions to load data for this tab - private final List> dataFetchComponents; - - public TimelinePanel() { - this(new TimelineSummaryGetter()); - } - - /** - * Creates new form PastCasesPanel - */ - public TimelinePanel(TimelineSummaryGetter timelineData) { - super(timelineData); - - dataFetcher = (dataSource) -> timelineData.getData(dataSource, MOST_RECENT_DAYS_COUNT); - - // set up data acquisition methods - dataFetchComponents = Arrays.asList( - new DataFetchWorker.DataFetchComponents<>(dataFetcher, (result) -> handleResult(result))); - - initComponents(); - } - - private static final Color FILE_EVT_COLOR = new Color(228, 22, 28); - private static final Color ARTIFACT_EVT_COLOR = new Color(21, 227, 100); - - /** - * Converts DailyActivityAmount data retrieved from TimelineSummaryGetter - * into data to be displayed as a bar chart. - * - * @param recentDaysActivity The data retrieved from - * TimelineSummaryGetter. - * @param showIntermediateDates If true, shows all dates. If false, shows - * only first and last date. - * - * @return The data to be displayed in the BarChart. - */ - private List parseChartData(List recentDaysActivity, boolean showIntermediateDates) { - // if no data, return null indicating no result. - if (CollectionUtils.isEmpty(recentDaysActivity)) { - return null; - } - - // Create a bar chart item for each recent days activity item - List fileEvtCounts = new ArrayList<>(); - List artifactEvtCounts = new ArrayList<>(); - - for (int i = 0; i < recentDaysActivity.size(); i++) { - DailyActivityAmount curItem = recentDaysActivity.get(i); - - long fileAmt = curItem.getFileActivityCount(); - long artifactAmt = curItem.getArtifactActivityCount() * 100; - String formattedDate = (showIntermediateDates || i == 0 || i == recentDaysActivity.size() - 1) - ? TimelineSummary.formatDate(curItem.getDay(), CHART_FORMAT) : ""; - - OrderedKey thisKey = new OrderedKey(formattedDate, i); - fileEvtCounts.add(new BarChartItem(thisKey, fileAmt)); - artifactEvtCounts.add(new BarChartItem(thisKey, artifactAmt)); - } - - return Arrays.asList( - new BarChartSeries(Bundle.TimlinePanel_last30DaysChart_fileEvts_title(), FILE_EVT_COLOR, fileEvtCounts), - new BarChartSeries(Bundle.TimlinePanel_last30DaysChart_artifactEvts_title(), ARTIFACT_EVT_COLOR, artifactEvtCounts)); - } - - private final Object timelineBtnLock = new Object(); - private TimelineSummaryData curTimelineData = null; - - /** - * Handles displaying the result for each displayable item in the - * TimelinePanel by breaking the TimelineSummaryData result into its - * constituent parts and then sending each data item to the pertinent - * component. - * - * @param result The result to be displayed on this tab. - */ - private void handleResult(DataFetchResult result) { - earliestLabel.showDataFetchResult(DataFetchResult.getSubResult(result, r -> TimelineSummary.formatDate(r.getMinDate(), EARLIEST_LATEST_FORMAT))); - latestLabel.showDataFetchResult(DataFetchResult.getSubResult(result, r -> TimelineSummary.formatDate(r.getMaxDate(), EARLIEST_LATEST_FORMAT))); - last30DaysChart.showDataFetchResult(DataFetchResult.getSubResult(result, r -> parseChartData(r.getMostRecentDaysActivity(), false))); - - if (result != null - && result.getResultType() == DataFetchResult.ResultType.SUCCESS - && result.getData() != null) { - - synchronized (this.timelineBtnLock) { - this.curTimelineData = result.getData(); - this.viewInTimelineBtn.setEnabled(true); - } - } else { - synchronized (this.timelineBtnLock) { - this.viewInTimelineBtn.setEnabled(false); - } - } - } - - /** - * Action that occurs when 'View in Timeline' button is pressed. - */ - private void openFilteredChart() { - DataSource dataSource = null; - Date minDate = null; - Date maxDate = null; - - // get date from current timelineData if that data exists. - synchronized (this.timelineBtnLock) { - if (curTimelineData == null) { - return; - } - - dataSource = curTimelineData.getDataSource(); - if (CollectionUtils.isNotEmpty(curTimelineData.getMostRecentDaysActivity())) { - minDate = curTimelineData.getMostRecentDaysActivity().get(0).getDay(); - maxDate = curTimelineData.getMostRecentDaysActivity().get(curTimelineData.getMostRecentDaysActivity().size() - 1).getDay(); - // set outer bound to end of day instead of beginning - if (maxDate != null) { - maxDate = new Date(maxDate.getTime() + 1000 * 60 * 60 * 24); - } - } - } - - openFilteredChart(dataSource, minDate, maxDate); - } - - /** - * Action that occurs when 'View in Timeline' button is pressed. - * - * @param dataSource The data source to filter to. - * @param minDate The min date for the zoom of the window. - * @param maxDate The max date for the zoom of the window. - */ - private void openFilteredChart(DataSource dataSource, Date minDate, Date maxDate) { - OpenTimelineAction openTimelineAction = CallableSystemAction.get(OpenTimelineAction.class); - if (openTimelineAction == null) { - logger.log(Level.WARNING, "No OpenTimelineAction provided by CallableSystemAction; taking no redirect action."); - } - - // notify dialog (if in dialog) should close. - TimelinePanel.this.notifyParentClose(); - - Interval timeSpan = null; - - try { - final TimeLineController controller = TimeLineModule.getController(); - - if (dataSource != null) { - controller.pushFilters(TimelineSummary.getDataSourceFilterState(dataSource)); - } - - if (minDate != null && maxDate != null) { - timeSpan = new Interval(new DateTime(minDate), new DateTime(maxDate)); - } - } catch (NoCurrentCaseException | TskCoreException ex) { - logger.log(Level.WARNING, "Unable to view time range in Timeline view", ex); - } - - try { - openTimelineAction.showTimeline(timeSpan); - } catch (TskCoreException ex) { - logger.log(Level.WARNING, "An unexpected exception occurred while opening the timeline.", ex); - } - } - - @Override - protected void fetchInformation(DataSource dataSource) { - fetchInformation(dataFetchComponents, dataSource); - } - - @Override - protected void onNewDataSource(DataSource dataSource) { - onNewDataSource(dataFetchComponents, loadableComponents, dataSource); - } - - @Override - public void close() { - ingestRunningLabel.unregister(); - super.close(); - } - - /** - * This method is called from within the constructor to initialize the form. - * WARNING: Do NOT modify this code. The content of this method is always - * regenerated by the Form Editor. - */ - @SuppressWarnings("unchecked") - // //GEN-BEGIN:initComponents - private void initComponents() { - - javax.swing.JScrollPane mainScrollPane = new javax.swing.JScrollPane(); - javax.swing.JPanel mainContentPanel = new javax.swing.JPanel(); - javax.swing.JPanel ingestRunningPanel = ingestRunningLabel; - javax.swing.JLabel activityRangeLabel = new javax.swing.JLabel(); - javax.swing.Box.Filler filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 2), new java.awt.Dimension(0, 2), new java.awt.Dimension(0, 2)); - javax.swing.JPanel earliestLabelPanel = earliestLabel; - javax.swing.JPanel latestLabelPanel = latestLabel; - javax.swing.Box.Filler filler2 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 20), new java.awt.Dimension(0, 20), new java.awt.Dimension(0, 20)); - javax.swing.JPanel last30DaysPanel = last30DaysChart; - viewInTimelineBtn = new javax.swing.JButton(); - javax.swing.Box.Filler filler5 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 32767)); - - mainContentPanel.setBorder(javax.swing.BorderFactory.createEmptyBorder(10, 10, 10, 10)); - mainContentPanel.setLayout(new javax.swing.BoxLayout(mainContentPanel, javax.swing.BoxLayout.PAGE_AXIS)); - - ingestRunningPanel.setAlignmentX(0.0F); - ingestRunningPanel.setMaximumSize(new java.awt.Dimension(32767, 25)); - ingestRunningPanel.setMinimumSize(new java.awt.Dimension(10, 25)); - ingestRunningPanel.setPreferredSize(new java.awt.Dimension(10, 25)); - mainContentPanel.add(ingestRunningPanel); - - activityRangeLabel.setFont(new java.awt.Font("Segoe UI", 1, 12)); // NOI18N - org.openide.awt.Mnemonics.setLocalizedText(activityRangeLabel, org.openide.util.NbBundle.getMessage(TimelinePanel.class, "TimelinePanel.activityRangeLabel.text")); // NOI18N - mainContentPanel.add(activityRangeLabel); - activityRangeLabel.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(TimelinePanel.class, "PastCasesPanel.notableFileLabel.text")); // NOI18N - - filler1.setAlignmentX(0.0F); - mainContentPanel.add(filler1); - - earliestLabelPanel.setAlignmentX(0.0F); - earliestLabelPanel.setMaximumSize(new java.awt.Dimension(32767, 20)); - earliestLabelPanel.setMinimumSize(new java.awt.Dimension(100, 20)); - earliestLabelPanel.setPreferredSize(new java.awt.Dimension(100, 20)); - mainContentPanel.add(earliestLabelPanel); - - latestLabelPanel.setAlignmentX(0.0F); - latestLabelPanel.setMaximumSize(new java.awt.Dimension(32767, 20)); - latestLabelPanel.setMinimumSize(new java.awt.Dimension(100, 20)); - latestLabelPanel.setPreferredSize(new java.awt.Dimension(100, 20)); - mainContentPanel.add(latestLabelPanel); - - filler2.setAlignmentX(0.0F); - mainContentPanel.add(filler2); - - last30DaysPanel.setAlignmentX(0.0F); - last30DaysPanel.setMaximumSize(new java.awt.Dimension(600, 300)); - last30DaysPanel.setMinimumSize(new java.awt.Dimension(600, 300)); - last30DaysPanel.setPreferredSize(new java.awt.Dimension(600, 300)); - last30DaysPanel.setVerifyInputWhenFocusTarget(false); - mainContentPanel.add(last30DaysPanel); - - org.openide.awt.Mnemonics.setLocalizedText(viewInTimelineBtn, org.openide.util.NbBundle.getMessage(TimelinePanel.class, "TimelinePanel.viewInTimelineBtn.text")); // NOI18N - viewInTimelineBtn.setEnabled(false); - viewInTimelineBtn.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - viewInTimelineBtnActionPerformed(evt); - } - }); - mainContentPanel.add(viewInTimelineBtn); - - filler5.setAlignmentX(0.0F); - mainContentPanel.add(filler5); - - mainScrollPane.setViewportView(mainContentPanel); - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); - this.setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(mainScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(mainScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE) - ); - }// //GEN-END:initComponents - - private void viewInTimelineBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_viewInTimelineBtnActionPerformed - openFilteredChart(); - }//GEN-LAST:event_viewInTimelineBtnActionPerformed - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JButton viewInTimelineBtn; - // End of variables declaration//GEN-END:variables - -} From af68f025f09089a51e0231ed78d1ac6989d988a8 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Mon, 23 Aug 2021 12:36:43 -0400 Subject: [PATCH 30/33] Review feedback --- .../datamodel/Bundle_ja.properties | 3 + .../CaseDataSourcesSummary.java | 2 +- .../DataSourceLabeledValueCallback.java | 2 +- .../DataSourceSingleValueCallback.java | 2 +- .../datamodel/MimeTypeSummary.java | 151 ++++++++++++++++++ .../ui/AnalysisSummaryGetter.java | 2 +- .../ui/ContainerSummaryGetter.java | 2 +- .../ui/DataSourceBrowser.java | 1 + .../ui/GeolocationSummaryGetter.java | 3 +- .../ui/MimeTypeSummaryGetter.java | 47 +----- .../ui/PastCasesSummaryGetter.java | 8 +- .../ui/RecentFilesGetter.java | 2 +- .../ui/TimelineSummaryGetter.java | 2 +- .../datasourcesummary/ui/TypesPanel.java | 4 +- .../ui/TypesSummaryGetter.java | 2 +- .../ui/UserActivitySummaryGetter.java | 41 ----- .../datasourcesummaryexport/ExportTypes.java | 65 +------- 17 files changed, 179 insertions(+), 160 deletions(-) create mode 100755 Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/Bundle_ja.properties rename Core/src/org/sleuthkit/autopsy/datasourcesummary/{ui => datamodel}/CaseDataSourcesSummary.java (99%) rename Core/src/org/sleuthkit/autopsy/datasourcesummary/{ui => datamodel}/DataSourceLabeledValueCallback.java (97%) rename Core/src/org/sleuthkit/autopsy/datasourcesummary/{ui => datamodel}/DataSourceSingleValueCallback.java (97%) create mode 100755 Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/MimeTypeSummary.java diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/Bundle_ja.properties new file mode 100755 index 0000000000..a8185f73ff --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/Bundle_ja.properties @@ -0,0 +1,3 @@ +#Mon Jun 14 12:23:19 UTC 2021 +DataSourceUserActivitySummary_getRecentAccounts_calllogMessage=\u901a\u8a71\u8a18\u9332 +DataSourceUserActivitySummary_getRecentAccounts_emailMessage=\u30e1\u30fc\u30eb\u30e1\u30c3\u30bb\u30fc\u30b8 diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/CaseDataSourcesSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/CaseDataSourcesSummary.java similarity index 99% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/CaseDataSourcesSummary.java rename to Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/CaseDataSourcesSummary.java index 4181af5b8e..50e883e29a 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/CaseDataSourcesSummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/CaseDataSourcesSummary.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datasourcesummary.ui; +package org.sleuthkit.autopsy.datasourcesummary.datamodel; import java.util.Collections; import java.util.HashMap; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceLabeledValueCallback.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceLabeledValueCallback.java similarity index 97% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceLabeledValueCallback.java rename to Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceLabeledValueCallback.java index cbb4b18e86..6c9c918667 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceLabeledValueCallback.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceLabeledValueCallback.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datasourcesummary.ui; +package org.sleuthkit.autopsy.datasourcesummary.datamodel; import java.sql.ResultSet; import java.sql.SQLException; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSingleValueCallback.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceSingleValueCallback.java similarity index 97% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSingleValueCallback.java rename to Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceSingleValueCallback.java index 901c3d9416..6b1ff205fa 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSingleValueCallback.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataSourceSingleValueCallback.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datasourcesummary.ui; +package org.sleuthkit.autopsy.datasourcesummary.datamodel; import java.sql.ResultSet; import java.sql.SQLException; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/MimeTypeSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/MimeTypeSummary.java new file mode 100755 index 0000000000..ced8e85d95 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/MimeTypeSummary.java @@ -0,0 +1,151 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2020-2021 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.datasourcesummary.datamodel; + +import java.sql.SQLException; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; +import org.sleuthkit.datamodel.DataSource; +import org.sleuthkit.datamodel.TskCoreException; + +/** + * Wrapper class for converting org.sleuthkit.autopsy.contentutils.TypesSummary + * functionality into a DefaultArtifactUpdateGovernor used by TypesPanel tab. + */ +public class MimeTypeSummary { + + private final SleuthkitCaseProvider provider; + + /** + * 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; + } + + /** + * 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 SleuthkitCaseProviderException + * @throws TskCoreException + * @throws SQLException + */ + public Long getCountOfFilesForMimeTypes(DataSource currentDataSource, Set setOfMimeTypes) + throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException { + return DataSourceInfoUtilities.getCountOfRegNonSlackFiles(provider.get(), currentDataSource, "mime_type IN " + getSqlSet(setOfMimeTypes)); + } + + /** + * Get the number of files in the case database for the current data source + * which do not have the specified mimetypes. + * + * @param currentDataSource the data source which we are finding a file + * count + * + * @param setOfMimeTypes the set of mime types that should be excluded. + * + * @return a Long value which represents the number of files that do not + * have the specific mime type, but do have a mime type. + * + * @throws SleuthkitCaseProviderException + * @throws TskCoreException + * @throws SQLException + */ + public Long getCountOfFilesNotInMimeTypes(DataSource currentDataSource, Set 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 <> '' "); + } + + /** + * Get a count of all regular files in a datasource. + * + * @param dataSource The datasource. + * + * @return The count of regular files. + * + * @throws SleuthkitCaseProviderException + * @throws TskCoreException + * @throws SQLException + */ + public Long getCountOfAllRegularFiles(DataSource dataSource) + throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException { + return DataSourceInfoUtilities.getCountOfRegNonSlackFiles(provider.get(), dataSource, null); + } + + /** + * 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 SleuthkitCaseProviderException + * @throws TskCoreException + * @throws SQLException + */ + public Long getCountOfFilesWithNoMimeType(DataSource currentDataSource) + throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException { + return DataSourceInfoUtilities.getCountOfRegNonSlackFiles(provider.get(), currentDataSource, "(mime_type IS NULL OR 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 String getSqlSet(Set setValues) { + List quotedValues = setValues + .stream() + .map(str -> String.format("'%s'", str.replace("'", ""))) + .collect(Collectors.toList()); + + String commaSeparatedQuoted = String.join(", ", quotedValues); + return String.format("(%s) ", commaSeparatedQuoted); + } +} diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/AnalysisSummaryGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/AnalysisSummaryGetter.java index f4891a0b37..135a5ef757 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/AnalysisSummaryGetter.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/AnalysisSummaryGetter.java @@ -45,7 +45,7 @@ public class AnalysisSummaryGetter implements DefaultArtifactUpdateGovernor { ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID() )); - AnalysisSummary analysisSummary; + private final AnalysisSummary analysisSummary; /** * Main constructor. diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerSummaryGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerSummaryGetter.java index 4770359911..41be8c4644 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerSummaryGetter.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerSummaryGetter.java @@ -44,7 +44,7 @@ public class ContainerSummaryGetter implements DefaultArtifactUpdateGovernor { BlackboardArtifact.ARTIFACT_TYPE.TSK_DATA_SOURCE_USAGE.getTypeID() )); - private ContainerSummary containerSummary; + private final ContainerSummary containerSummary; /** * Main constructor. diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceBrowser.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceBrowser.java index 5d2694f9ff..e6942058e9 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceBrowser.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceBrowser.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.datasourcesummary.ui; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.CaseDataSourcesSummary; import java.awt.Cursor; import org.sleuthkit.autopsy.datasourcesummary.uiutils.RightAlignedTableCellRenderer; import java.awt.EventQueue; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/GeolocationSummaryGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/GeolocationSummaryGetter.java index cea19db803..2278b4ac60 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/GeolocationSummaryGetter.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/GeolocationSummaryGetter.java @@ -28,7 +28,6 @@ import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultArtifactUpdateGove import org.sleuthkit.autopsy.geolocation.datamodel.GeoLocationDataException; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import org.sleuthkit.datamodel.DataSource; -import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; /** * Wrapper class for converting @@ -37,7 +36,7 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; */ public class GeolocationSummaryGetter implements DefaultArtifactUpdateGovernor { - private GeolocationSummary geoSummary; + private final GeolocationSummary geoSummary; /** * Default constructor. diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/MimeTypeSummaryGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/MimeTypeSummaryGetter.java index e4b06262ca..5468ec668a 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/MimeTypeSummaryGetter.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/MimeTypeSummaryGetter.java @@ -23,12 +23,10 @@ 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.datasourcesummary.datamodel.SleuthkitCaseProvider; import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceInfoUtilities; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.MimeTypeSummary; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.ModuleContentEvent; import org.sleuthkit.datamodel.AbstractFile; @@ -44,22 +42,13 @@ public class MimeTypeSummaryGetter implements DefaultUpdateGovernor { private static final Set INGEST_JOB_EVENTS = new HashSet<>( Arrays.asList(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED)); - private final SleuthkitCaseProvider provider; + private final MimeTypeSummary mimeTypeSummary; /** * Main constructor. */ public MimeTypeSummaryGetter() { - this(SleuthkitCaseProvider.DEFAULT); - } - - /** - * Main constructor. - * - * @param provider The means of obtaining a sleuthkit case. - */ - public MimeTypeSummaryGetter(SleuthkitCaseProvider provider) { - this.provider = provider; + mimeTypeSummary = new MimeTypeSummary(); } @Override @@ -102,7 +91,7 @@ public class MimeTypeSummaryGetter implements DefaultUpdateGovernor { */ public Long getCountOfFilesForMimeTypes(DataSource currentDataSource, Set setOfMimeTypes) throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException { - return DataSourceInfoUtilities.getCountOfRegNonSlackFiles(provider.get(), currentDataSource, "mime_type IN " + getSqlSet(setOfMimeTypes)); + return mimeTypeSummary.getCountOfFilesForMimeTypes(currentDataSource, setOfMimeTypes); } /** @@ -123,9 +112,7 @@ public class MimeTypeSummaryGetter implements DefaultUpdateGovernor { */ public Long getCountOfFilesNotInMimeTypes(DataSource currentDataSource, Set 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 <> '' "); + return mimeTypeSummary.getCountOfFilesNotInMimeTypes(currentDataSource, setOfMimeTypes); } /** @@ -141,7 +128,7 @@ public class MimeTypeSummaryGetter implements DefaultUpdateGovernor { */ public Long getCountOfAllRegularFiles(DataSource dataSource) throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, SQLException { - return DataSourceInfoUtilities.getCountOfRegNonSlackFiles(provider.get(), dataSource, null); + return mimeTypeSummary.getCountOfAllRegularFiles(dataSource); } /** @@ -158,26 +145,6 @@ public class MimeTypeSummaryGetter 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 = '') "); - } - - /** - * 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 String getSqlSet(Set setValues) { - List quotedValues = setValues - .stream() - .map(str -> String.format("'%s'", str.replace("'", ""))) - .collect(Collectors.toList()); - - String commaSeparatedQuoted = String.join(", ", quotedValues); - return String.format("(%s) ", commaSeparatedQuoted); + return mimeTypeSummary.getCountOfFilesWithNoMimeType(currentDataSource); } } diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesSummaryGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesSummaryGetter.java index c4ed083852..2a2c0b8a55 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesSummaryGetter.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesSummaryGetter.java @@ -22,7 +22,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Set; -import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider; import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultArtifactUpdateGovernor; @@ -44,7 +43,7 @@ public class PastCasesSummaryGetter implements DefaultArtifactUpdateGovernor { ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID() )); - private PastCasesSummary pastSummary; + private final PastCasesSummary pastSummary; public PastCasesSummaryGetter() { pastSummary = new PastCasesSummary(); @@ -67,11 +66,6 @@ public class PastCasesSummaryGetter implements DefaultArtifactUpdateGovernor { */ public PastCasesResult getPastCasesData(DataSource dataSource) throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException { - - if (dataSource == null) { - return null; - } - return pastSummary.getPastCasesData(dataSource); } } diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesGetter.java index 02824dacb7..5275ec2c62 100755 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesGetter.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesGetter.java @@ -48,7 +48,7 @@ public class RecentFilesGetter implements DefaultArtifactUpdateGovernor { BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE.getTypeID() )); - private RecentFilesSummary recentSummary; + private final RecentFilesSummary recentSummary; /** * Default constructor. diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelineSummaryGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelineSummaryGetter.java index 4ea7a51f36..81be37577f 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelineSummaryGetter.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelineSummaryGetter.java @@ -40,7 +40,7 @@ public class TimelineSummaryGetter implements DefaultUpdateGovernor { private static final Set INGEST_JOB_EVENTS = new HashSet<>( Arrays.asList(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED)); - private TimelineSummary timelineSummary; + private final TimelineSummary timelineSummary; /** * Default constructor. diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java index 45eba82918..e34288449a 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java @@ -171,7 +171,7 @@ class TypesPanel extends BaseDataSourceSummaryPanel { /** * Creates a new TypesPanel. */ - public TypesPanel() { + TypesPanel() { this(new MimeTypeSummaryGetter(), new TypesSummaryGetter(), new ContainerSummaryGetter()); } @@ -188,7 +188,7 @@ class TypesPanel extends BaseDataSourceSummaryPanel { * @param typeData The service for file types data. * @param containerData The service for container information. */ - public TypesPanel( + TypesPanel( MimeTypeSummaryGetter mimeTypeData, TypesSummaryGetter typeData, ContainerSummaryGetter containerData) { diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesSummaryGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesSummaryGetter.java index 3b0887c52f..fee3f178cc 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesSummaryGetter.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesSummaryGetter.java @@ -43,7 +43,7 @@ public class TypesSummaryGetter implements DefaultUpdateGovernor { private static final Set INGEST_JOB_EVENTS = new HashSet<>( Arrays.asList(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED)); - private TypesSummary typesSummary; + private final TypesSummary typesSummary; /** * Main constructor. diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivitySummaryGetter.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivitySummaryGetter.java index 70ad958be5..e9f9dd30b0 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivitySummaryGetter.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivitySummaryGetter.java @@ -64,17 +64,6 @@ public class UserActivitySummaryGetter implements DefaultArtifactUpdateGovernor return Collections.unmodifiableSet(ARTIFACT_UPDATE_TYPE_IDS); } - /** - * Throws an IllegalArgumentException if count <= 0. - * - * @param count The count being checked. - */ - private void assertValidCount(int count) { - if (count <= 0) { - throw new IllegalArgumentException("Count must be greater than 0"); - } - } - /** * Gets a list of recent domains based on the datasource. * @@ -86,12 +75,6 @@ public class UserActivitySummaryGetter implements DefaultArtifactUpdateGovernor * @throws InterruptedException */ public List getRecentDomains(DataSource dataSource, int count) throws TskCoreException, SleuthkitCaseProviderException { - assertValidCount(count); - - if (dataSource == null) { - return Collections.emptyList(); - } - return userActivity.getRecentDomains(dataSource, count); } @@ -111,12 +94,6 @@ public class UserActivitySummaryGetter implements DefaultArtifactUpdateGovernor * @throws TskCoreException */ public List getMostRecentWebSearches(DataSource dataSource, int count) throws SleuthkitCaseProviderException, TskCoreException { - assertValidCount(count); - - if (dataSource == null) { - return Collections.emptyList(); - } - return userActivity.getMostRecentWebSearches(dataSource, count); } @@ -135,12 +112,6 @@ public class UserActivitySummaryGetter implements DefaultArtifactUpdateGovernor * @throws TskCoreException */ public List getRecentDevices(DataSource dataSource, int count) throws SleuthkitCaseProviderException, TskCoreException { - assertValidCount(count); - - if (dataSource == null) { - return Collections.emptyList(); - } - return userActivity.getRecentDevices(dataSource, count); } @@ -163,12 +134,6 @@ public class UserActivitySummaryGetter implements DefaultArtifactUpdateGovernor "DataSourceUserActivitySummary_getRecentAccounts_emailMessage=Email Message", "DataSourceUserActivitySummary_getRecentAccounts_calllogMessage=Call Log",}) public List getRecentAccounts(DataSource dataSource, int count) throws SleuthkitCaseProviderException, TskCoreException { - assertValidCount(count); - - if (dataSource == null) { - return Collections.emptyList(); - } - return userActivity.getRecentAccounts(dataSource, count); } @@ -192,12 +157,6 @@ public class UserActivitySummaryGetter implements DefaultArtifactUpdateGovernor * @throws TskCoreException */ public List getTopPrograms(DataSource dataSource, int count) throws SleuthkitCaseProviderException, TskCoreException { - assertValidCount(count); - - if (dataSource == null) { - return Collections.emptyList(); - } - return userActivity.getTopPrograms(dataSource, count); } } diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTypes.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTypes.java index 1321a4b511..3d1687eb91 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTypes.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTypes.java @@ -33,6 +33,7 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.datasourcesummary.datamodel.ContainerSummary; import org.sleuthkit.autopsy.coreutils.FileTypeUtils.FileTypeCategory; import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceInfoUtilities; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.MimeTypeSummary; import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider; import org.sleuthkit.autopsy.datasourcesummary.datamodel.TypesSummary; import org.sleuthkit.autopsy.datasourcesummary.datamodel.TypesSummary.FileTypeCategoryData; @@ -101,6 +102,7 @@ class ExportTypes { } } + private final MimeTypeSummary mimeTypeSummary; private final ContainerSummary containerSummary; private final TypesSummary typesSummary; private final SleuthkitCaseProvider provider; @@ -128,64 +130,7 @@ class ExportTypes { this.provider = SleuthkitCaseProvider.DEFAULT; containerSummary = new ContainerSummary(); typesSummary = new TypesSummary(); - } - - /** - * Derives a sql set string (i.e. "('val1', 'val2', 'val3')"). A naive - * attempt is made to sanitize the strings by removing single quotes from - * values. - * - * @param setValues The values that should be present in the set. Single - * quotes are removed. - * - * @return The sql set string. - */ - private static String getSqlSet(Set setValues) { - List quotedValues = setValues - .stream() - .map(str -> String.format("'%s'", str.replace("'", ""))) - .collect(Collectors.toList()); - - String commaSeparatedQuoted = String.join(", ", quotedValues); - return String.format("(%s) ", commaSeparatedQuoted); - } - - /** - * 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 Long getCountOfFilesForMimeTypes(DataSource currentDataSource, Set setOfMimeTypes) throws TskCoreException, SQLException, SleuthkitCaseProvider.SleuthkitCaseProviderException { - return DataSourceInfoUtilities.getCountOfRegNonSlackFiles(provider.get(), 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 Long getCountOfFilesWithNoMimeType(DataSource currentDataSource) throws TskCoreException, SQLException, SleuthkitCaseProvider.SleuthkitCaseProviderException { - return DataSourceInfoUtilities.getCountOfRegNonSlackFiles(provider.get(), currentDataSource, "(mime_type IS NULL OR mime_type = '') "); + mimeTypeSummary = new MimeTypeSummary(); } /** @@ -208,7 +153,7 @@ class ExportTypes { long categoryTotalCount = 0; for (FileTypeCategoryData cat : FILE_MIME_TYPE_CATEGORIES) { - long thisValue = DataSourceInfoUtilities.getLongOrZero(getCountOfFilesForMimeTypes(dataSource, cat.getMimeTypes())); + long thisValue = DataSourceInfoUtilities.getLongOrZero(mimeTypeSummary.getCountOfFilesForMimeTypes(dataSource, cat.getMimeTypes())); categoryTotalCount += thisValue; fileCategoryItems.add(new PieChartItem( @@ -218,7 +163,7 @@ class ExportTypes { } // get a count of all files with no mime type - long noMimeTypeCount = DataSourceInfoUtilities.getLongOrZero(getCountOfFilesWithNoMimeType(dataSource)); + long noMimeTypeCount = DataSourceInfoUtilities.getLongOrZero(mimeTypeSummary.getCountOfFilesWithNoMimeType(dataSource)); // get a count of all regular files long allRegularFiles = DataSourceInfoUtilities.getLongOrZero(DataSourceInfoUtilities.getCountOfRegNonSlackFiles(provider.get(), dataSource, null)); From b4a32c3d2eedfa4fb5fb1acfa7553eb61742c2a8 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Mon, 23 Aug 2021 14:39:07 -0400 Subject: [PATCH 31/33] Using DataFetcher from datasourcesummary package instead --- .../{uiutils => datamodel}/DataFetcher.java | 2 +- .../datasourcesummary/ui/AnalysisPanel.java | 2 +- .../ui/BaseDataSourceSummaryPanel.java | 2 +- .../datasourcesummary/ui/ContainerPanel.java | 2 +- .../ui/GeolocationPanel.java | 2 +- .../datasourcesummary/ui/PastCasesPanel.java | 2 +- .../ui/RecentFilesPanel.java | 2 +- .../datasourcesummary/ui/TimelinePanel.java | 2 +- .../datasourcesummary/ui/TypesPanel.java | 2 +- .../ui/UserActivityPanel.java | 2 +- .../uiutils/DataFetchWorker.java | 1 + .../datasourcesummaryexport/DataFetcher.java | 43 ------------------- .../ExcelExportAction.java | 1 + .../ExportAnalysisResults.java | 1 + .../ExportContainerInfo.java | 1 + .../ExportGeolocation.java | 1 + .../ExportPastCases.java | 1 + .../ExportRecentFiles.java | 1 + .../ExportTimeline.java | 1 + .../datasourcesummaryexport/ExportTypes.java | 3 +- .../ExportUserActivity.java | 1 + 21 files changed, 20 insertions(+), 55 deletions(-) rename Core/src/org/sleuthkit/autopsy/datasourcesummary/{uiutils => datamodel}/DataFetcher.java (96%) delete mode 100755 Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DataFetcher.java diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DataFetcher.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataFetcher.java similarity index 96% rename from Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DataFetcher.java rename to Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataFetcher.java index 6eabe79634..45dcae5f35 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DataFetcher.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/DataFetcher.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datasourcesummary.uiutils; +package org.sleuthkit.autopsy.datasourcesummary.datamodel; /** * A function that accepts input of type I and outputs type O. This function is diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/AnalysisPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/AnalysisPanel.java index 929f2d2364..c8b708d371 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/AnalysisPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/AnalysisPanel.java @@ -25,7 +25,7 @@ import org.apache.commons.lang3.tuple.Pair; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.datasourcesummary.uiutils.ColumnModel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetcher; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataFetcher; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultCellModel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.IngestRunningLabel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.JTablePanel; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/BaseDataSourceSummaryPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/BaseDataSourceSummaryPanel.java index 6ac490eb11..1cf103052a 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/BaseDataSourceSummaryPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/BaseDataSourceSummaryPanel.java @@ -41,7 +41,7 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetcher; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataFetcher; import org.sleuthkit.autopsy.datasourcesummary.uiutils.EventUpdateHandler; import org.sleuthkit.autopsy.datasourcesummary.uiutils.GuiCellModel.DefaultMenuItem; import org.sleuthkit.autopsy.datasourcesummary.uiutils.GuiCellModel.MenuItem; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java index fc313d1ef8..9278b3e349 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ContainerPanel.java @@ -32,7 +32,7 @@ import org.sleuthkit.autopsy.datasourcesummary.datamodel.ContainerSummary.Contai import org.sleuthkit.autopsy.datasourcesummary.datamodel.ContainerSummary.ImageDetails; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult.ResultType; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetcher; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataFetcher; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultUpdateGovernor; import org.sleuthkit.autopsy.datasourcesummary.uiutils.UpdateGovernor; import org.sleuthkit.datamodel.DataSource; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/GeolocationPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/GeolocationPanel.java index 55d37a3d2e..2551e7a3ae 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/GeolocationPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/GeolocationPanel.java @@ -42,7 +42,7 @@ import org.sleuthkit.autopsy.datasourcesummary.uiutils.ColumnModel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetcher; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataFetcher; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultCellModel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.IngestRunningLabel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.JTablePanel; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesPanel.java index f893098313..08679169d3 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/PastCasesPanel.java @@ -27,7 +27,7 @@ import org.sleuthkit.autopsy.datasourcesummary.uiutils.ColumnModel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetcher; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataFetcher; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultCellModel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.IngestRunningLabel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.JTablePanel; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesPanel.java index 1794c24aec..0bc09d59ec 100755 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/RecentFilesPanel.java @@ -34,7 +34,7 @@ import org.sleuthkit.autopsy.datasourcesummary.datamodel.RecentFilesSummary.Rece import org.sleuthkit.autopsy.datasourcesummary.uiutils.CellModelTableCellRenderer; import org.sleuthkit.autopsy.datasourcesummary.uiutils.ColumnModel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetcher; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataFetcher; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultCellModel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.GuiCellModel.MenuItem; import org.sleuthkit.autopsy.datasourcesummary.uiutils.IngestRunningLabel; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java index eed41cda3d..9eaf3bb130 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java @@ -42,7 +42,7 @@ import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartSeries.BarChartIt import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetcher; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataFetcher; import org.sleuthkit.autopsy.datasourcesummary.uiutils.IngestRunningLabel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.LoadableComponent; import org.sleuthkit.autopsy.datasourcesummary.uiutils.LoadableLabel; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java index e34288449a..f1421665c5 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TypesPanel.java @@ -36,7 +36,7 @@ import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult.ResultType; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetcher; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataFetcher; import org.sleuthkit.autopsy.datasourcesummary.uiutils.IngestRunningLabel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.LoadableComponent; import org.sleuthkit.autopsy.datasourcesummary.uiutils.LoadableLabel; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivityPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivityPanel.java index bb81dc9b2e..46f5deca36 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivityPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/UserActivityPanel.java @@ -37,7 +37,7 @@ import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.Top import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopWebSearchResult; import org.sleuthkit.autopsy.datasourcesummary.uiutils.ColumnModel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetcher; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataFetcher; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultCellModel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.GuiCellModel.MenuItem; import org.sleuthkit.autopsy.datasourcesummary.uiutils.IngestRunningLabel; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DataFetchWorker.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DataFetchWorker.java index 46e68a1f55..8d007c2a01 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DataFetchWorker.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DataFetchWorker.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.datasourcesummary.uiutils; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataFetcher; import java.util.concurrent.ExecutionException; import java.util.function.Consumer; import javax.swing.SwingWorker; diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DataFetcher.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DataFetcher.java deleted file mode 100755 index b513762280..0000000000 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/DataFetcher.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2020 Basis Technology Corp. - * Contact: carrier sleuthkit 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; - -/** - * A function that accepts input of type I and outputs type O. This function is - * meant to be utilized with DataFetchWorker and can therefore, throw an - * interrupted exception if the processing is cancelled or an Exception of on - * another type in the event that the fetching encountered an error. - */ -@FunctionalInterface -interface DataFetcher { - - /** - * A function that accepts an input argument and outputs a result. Since it - * is meant to be used with the DataFetchWorker, it may throw an interrupted - * exception if the thread has been interrupted. It throws another type of - * exception if there is an error during fetching. - * - * @param input The input argument. - * - * @return The output result. - * - * @throws Exception - */ - O runQuery(I input) throws Exception; -} diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java index 3d7f303ea5..f9b1b2b988 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExcelExportAction.java @@ -33,6 +33,7 @@ import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.coreutils.FileUtil; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataFetcher; import org.sleuthkit.autopsy.report.ReportProgressPanel; import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExport.ExcelExportException; import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExport.ExcelSheetExport; diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportAnalysisResults.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportAnalysisResults.java index 8d154bd847..57786f1f8e 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportAnalysisResults.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportAnalysisResults.java @@ -24,6 +24,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.commons.lang3.tuple.Pair; import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataFetcher; import org.sleuthkit.autopsy.datasourcesummary.datamodel.AnalysisSummary; import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExport.ExcelSheetExport; import static org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExportAction.getTableExport; diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportContainerInfo.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportContainerInfo.java index e6af2ce2a0..44ede9064c 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportContainerInfo.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportContainerInfo.java @@ -25,6 +25,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.commons.lang.StringUtils; import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataFetcher; import org.sleuthkit.autopsy.datasourcesummary.datamodel.ContainerSummary; import org.sleuthkit.autopsy.datasourcesummary.datamodel.ContainerSummary.ContainerDetails; import org.sleuthkit.autopsy.datasourcesummary.datamodel.ContainerSummary.ImageDetails; diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportGeolocation.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportGeolocation.java index 8cdecf8338..a0a6b0874c 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportGeolocation.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportGeolocation.java @@ -27,6 +27,7 @@ import java.util.stream.Stream; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataFetcher; import org.sleuthkit.autopsy.datasourcesummary.datamodel.GeolocationSummary.CityCountsList; import org.sleuthkit.autopsy.datasourcesummary.datamodel.GeolocationSummary.CityData; import org.sleuthkit.autopsy.datasourcesummary.datamodel.GeolocationSummary.CityRecordCount; diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportPastCases.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportPastCases.java index da91b8744e..be824477a1 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportPastCases.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportPastCases.java @@ -23,6 +23,7 @@ import java.util.Collections; import java.util.List; import org.apache.commons.lang3.tuple.Pair; import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataFetcher; import org.sleuthkit.autopsy.datasourcesummary.datamodel.PastCasesSummary; import org.sleuthkit.autopsy.datasourcesummary.datamodel.PastCasesSummary.PastCasesResult; import static org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExportAction.getFetchResult; diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportRecentFiles.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportRecentFiles.java index 38dbc59a78..a7d5471343 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportRecentFiles.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportRecentFiles.java @@ -28,6 +28,7 @@ import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataFetcher; import org.sleuthkit.autopsy.datasourcesummary.datamodel.RecentFilesSummary; import org.sleuthkit.autopsy.datasourcesummary.datamodel.RecentFilesSummary.RecentAttachmentDetails; import org.sleuthkit.autopsy.datasourcesummary.datamodel.RecentFilesSummary.RecentDownloadDetails; diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTimeline.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTimeline.java index efefa6bc97..8e51199678 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTimeline.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTimeline.java @@ -27,6 +27,7 @@ import java.util.Date; import java.util.List; import org.apache.commons.collections.CollectionUtils; import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataFetcher; import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary; import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary.DailyActivityAmount; import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary.TimelineSummaryData; diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTypes.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTypes.java index 3d1687eb91..c5c04acb52 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTypes.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTypes.java @@ -25,13 +25,12 @@ 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.datasourcesummary.datamodel.ContainerSummary; import org.sleuthkit.autopsy.coreutils.FileTypeUtils.FileTypeCategory; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataFetcher; import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceInfoUtilities; import org.sleuthkit.autopsy.datasourcesummary.datamodel.MimeTypeSummary; import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider; diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportUserActivity.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportUserActivity.java index 7be189cc1b..f1a4198b42 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportUserActivity.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportUserActivity.java @@ -30,6 +30,7 @@ import java.util.stream.Stream; import org.apache.commons.lang.StringUtils; import org.openide.util.NbBundle.Messages; import org.sleuthkit.datamodel.DataSource; +import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataFetcher; import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary; import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.LastAccessedArtifact; import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopAccountResult; From b056881cd9d8896028523c719c7ed82343545022 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Mon, 23 Aug 2021 14:43:58 -0400 Subject: [PATCH 32/33] Minor --- .../autopsy/datasourcesummary/datamodel/MimeTypeSummary.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/MimeTypeSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/MimeTypeSummary.java index ced8e85d95..4c5e0331eb 100755 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/MimeTypeSummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/MimeTypeSummary.java @@ -27,8 +27,8 @@ import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.TskCoreException; /** - * Wrapper class for converting org.sleuthkit.autopsy.contentutils.TypesSummary - * functionality into a DefaultArtifactUpdateGovernor used by TypesPanel tab. + * Class to export summary information used by TypesPanel tab on the known files + * present in the specified DataSource. */ public class MimeTypeSummary { From fcfb17c5251e58f0ae16dbdb1dd9deb0038d3233 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Tue, 24 Aug 2021 09:18:28 -0400 Subject: [PATCH 33/33] Reusing BarChartSeries and PieChartItem classes --- .../datasourcesummary/ui/TimelinePanel.java | 4 +- .../uiutils/BarChartPanel.java | 78 -------- .../uiutils/BarChartSeries.java | 78 ++++++++ .../BarChartExport.java | 1 + .../BarChartSeries.java | 178 ------------------ .../ExportTimeline.java | 5 +- .../datasourcesummaryexport/ExportTypes.java | 1 + .../PieChartExport.java | 1 + .../datasourcesummaryexport/PieChartItem.java | 67 ------- 9 files changed, 86 insertions(+), 327 deletions(-) delete mode 100755 Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/BarChartSeries.java delete mode 100755 Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/PieChartItem.java diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java index 9eaf3bb130..4b16aef7a3 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/TimelinePanel.java @@ -36,13 +36,13 @@ import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary; import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary.DailyActivityAmount; import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary.TimelineSummaryData; import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartPanel; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartSeries; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartPanel.OrderedKey; +import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartSeries.OrderedKey; import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartSeries.BarChartItem; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker.DataFetchComponents; import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataFetcher; +import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartSeries; import org.sleuthkit.autopsy.datasourcesummary.uiutils.IngestRunningLabel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.LoadableComponent; import org.sleuthkit.autopsy.datasourcesummary.uiutils.LoadableLabel; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/BarChartPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/BarChartPanel.java index 21f3bca572..eb363a8a47 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/BarChartPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/BarChartPanel.java @@ -39,84 +39,6 @@ import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartSeries.BarChartIt */ public class BarChartPanel extends AbstractLoadableComponent> { - /** - * JFreeChart bar charts don't preserve the order of bars provided to the - * chart, but instead uses the comparable nature to order items. This - * provides order using a provided index as well as the value for the axis. - */ - public static class OrderedKey implements Comparable { - - private final Object keyValue; - private final int keyIndex; - - /** - * Main constructor. - * - * @param keyValue The value for the key to be displayed in the domain - * axis. - * @param keyIndex The index at which it will be displayed. - */ - public OrderedKey(Object keyValue, int keyIndex) { - this.keyValue = keyValue; - this.keyIndex = keyIndex; - } - - /** - * @return The value for the key to be displayed in the domain axis. - */ - Object getKeyValue() { - return keyValue; - } - - /** - * @return The index at which it will be displayed. - */ - int getKeyIndex() { - return keyIndex; - } - - @Override - public int compareTo(OrderedKey o) { - // this will have a higher value than null. - if (o == null) { - return 1; - } - - // compare by index - return Integer.compare(this.getKeyIndex(), o.getKeyIndex()); - } - - @Override - public int hashCode() { - int hash = 3; - return hash; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final OrderedKey other = (OrderedKey) obj; - if (this.keyIndex != other.keyIndex) { - return false; - } - return true; - } - - @Override - public String toString() { - // use toString on the key. - return this.getKeyValue() == null ? null : this.getKeyValue().toString(); - } - } - private static final long serialVersionUID = 1L; private static final Font DEFAULT_FONT = new JLabel().getFont(); diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/BarChartSeries.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/BarChartSeries.java index c1626f34b2..8709fc8ae1 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/BarChartSeries.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/BarChartSeries.java @@ -98,4 +98,82 @@ public class BarChartSeries { return key; } + /** + * JFreeChart bar charts don't preserve the order of bars provided to the + * chart, but instead uses the comparable nature to order items. This + * provides order using a provided index as well as the value for the axis. + */ + public static class OrderedKey implements Comparable { + + private final Object keyValue; + private final int keyIndex; + + /** + * Main constructor. + * + * @param keyValue The value for the key to be displayed in the domain + * axis. + * @param keyIndex The index at which it will be displayed. + */ + public OrderedKey(Object keyValue, int keyIndex) { + this.keyValue = keyValue; + this.keyIndex = keyIndex; + } + + /** + * @return The value for the key to be displayed in the domain axis. + */ + Object getKeyValue() { + return keyValue; + } + + /** + * @return The index at which it will be displayed. + */ + int getKeyIndex() { + return keyIndex; + } + + @Override + public int compareTo(OrderedKey o) { + // this will have a higher value than null. + if (o == null) { + return 1; + } + + // compare by index + return Integer.compare(this.getKeyIndex(), o.getKeyIndex()); + } + + @Override + public int hashCode() { + int hash = 3; + return hash; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final OrderedKey other = (OrderedKey) obj; + if (this.keyIndex != other.keyIndex) { + return false; + } + return true; + } + + @Override + public String toString() { + // use toString on the key. + return this.getKeyValue() == null ? null : this.getKeyValue().toString(); + } + } + } diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/BarChartExport.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/BarChartExport.java index 8ff16075e3..330aac4cff 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/BarChartExport.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/BarChartExport.java @@ -49,6 +49,7 @@ import org.apache.poi.xssf.usermodel.XSSFChart; import org.apache.poi.xssf.usermodel.XSSFClientAnchor; import org.apache.poi.xssf.usermodel.XSSFDrawing; import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartSeries; import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExport.ExcelExportException; import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExport.ExcelSheetExport; import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelSpecialFormatExport.ExcelItemExportable; diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/BarChartSeries.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/BarChartSeries.java deleted file mode 100755 index 99a5d1b557..0000000000 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/BarChartSeries.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2021 Basis Technology Corp. - * Contact: carrier sleuthkit 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.util.Collections; -import java.util.List; - -/** - * Represents a series in a bar chart where all items pertain to one category. - */ -class BarChartSeries { - - /** - * An individual bar to be displayed in the bar chart. - */ - static class BarChartItem { - - private final Comparable key; - private final double value; - - /** - * Main constructor. - * - * @param key The key. - * @param value The value for this item. - */ - BarChartItem(Comparable key, double value) { - this.key = key; - this.value = value; - } - - /** - * @return The key for this item. - */ - Comparable getKey() { - return key; - } - - /** - * @return The value for this item. - */ - double getValue() { - return value; - } - } - private final Comparable key; - private final Color color; - private final List items; - - /** - * Main constructor. - * - * @param key The key. - * @param color The color for this series. - * @param items The bars to be displayed for this series. - */ - BarChartSeries(Comparable key, Color color, List items) { - this.key = key; - this.color = color; - this.items = (items == null) ? Collections.emptyList() : Collections.unmodifiableList(items); - } - - /** - * @return The color for this series. - */ - Color getColor() { - return color; - } - - /** - * @return The bars to be displayed for this series. - */ - List getItems() { - return items; - } - - /** - * @return The key for this item. - */ - Comparable getKey() { - return key; - } - - /** - * JFreeChart bar charts don't preserve the order of bars provided to the - * chart, but instead uses the comparable nature to order items. This - * provides order using a provided index as well as the value for the axis. - */ - static class OrderedKey implements Comparable { - - private final Object keyValue; - private final int keyIndex; - - /** - * Main constructor. - * - * @param keyValue The value for the key to be displayed in the domain - * axis. - * @param keyIndex The index at which it will be displayed. - */ - OrderedKey(Object keyValue, int keyIndex) { - this.keyValue = keyValue; - this.keyIndex = keyIndex; - } - - /** - * @return The value for the key to be displayed in the domain axis. - */ - Object getKeyValue() { - return keyValue; - } - - /** - * @return The index at which it will be displayed. - */ - int getKeyIndex() { - return keyIndex; - } - - @Override - public int compareTo(OrderedKey o) { - // this will have a higher value than null. - if (o == null) { - return 1; - } - - // compare by index - return Integer.compare(this.getKeyIndex(), o.getKeyIndex()); - } - - @Override - public int hashCode() { - int hash = 3; - return hash; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final OrderedKey other = (OrderedKey) obj; - if (this.keyIndex != other.keyIndex) { - return false; - } - return true; - } - - @Override - public String toString() { - // use toString on the key. - return this.getKeyValue() == null ? null : this.getKeyValue().toString(); - } - } -} diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTimeline.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTimeline.java index 8e51199678..cbb385b60a 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTimeline.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTimeline.java @@ -27,12 +27,13 @@ import java.util.Date; import java.util.List; import org.apache.commons.collections.CollectionUtils; import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartSeries; +import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartSeries.BarChartItem; +import org.sleuthkit.autopsy.datasourcesummary.uiutils.BarChartSeries.OrderedKey; import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataFetcher; import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary; import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary.DailyActivityAmount; import org.sleuthkit.autopsy.datasourcesummary.datamodel.TimelineSummary.TimelineSummaryData; -import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.BarChartSeries.BarChartItem; -import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.BarChartSeries.OrderedKey; import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelSpecialFormatExport.KeyValueItemExportable; import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelSpecialFormatExport.TitledExportable; import org.sleuthkit.datamodel.DataSource; diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTypes.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTypes.java index c5c04acb52..f3787a4a98 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTypes.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/ExportTypes.java @@ -28,6 +28,7 @@ import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.datasourcesummary.uiutils.PieChartItem; import org.sleuthkit.autopsy.datasourcesummary.datamodel.ContainerSummary; import org.sleuthkit.autopsy.coreutils.FileTypeUtils.FileTypeCategory; import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataFetcher; diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/PieChartExport.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/PieChartExport.java index 33ed70cb21..395637acb1 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/PieChartExport.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/PieChartExport.java @@ -35,6 +35,7 @@ import org.apache.poi.xssf.usermodel.XSSFClientAnchor; import org.apache.poi.xssf.usermodel.XSSFDrawing; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.openxmlformats.schemas.drawingml.x2006.chart.CTPieChart; +import org.sleuthkit.autopsy.datasourcesummary.uiutils.PieChartItem; import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExport.ExcelExportException; import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelExport.ExcelSheetExport; import org.sleuthkit.autopsy.report.modules.datasourcesummaryexport.ExcelSpecialFormatExport.ExcelItemExportable; diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/PieChartItem.java b/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/PieChartItem.java deleted file mode 100755 index 4db4f41bfe..0000000000 --- a/Core/src/org/sleuthkit/autopsy/report/modules/datasourcesummaryexport/PieChartItem.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2021 Basis Technology Corp. - * Contact: carrier sleuthkit 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; - -/** - * An individual pie chart slice in the pie chart. - */ -class PieChartItem { - - private final String label; - private final double value; - private final Color color; - - /** - * Main constructor. - * - * @param label The label for this pie slice. - * @param value The value for this item. - * @param color The color for the pie slice. Can be null for - * auto-determined. - */ - PieChartItem(String label, double value, Color color) { - this.label = label; - this.value = value; - this.color = color; - } - - /** - * @return The label for this item. - */ - String getLabel() { - return label; - } - - /** - * @return The value for this item. - */ - double getValue() { - return value; - } - - /** - * @return The color for the pie slice or null for auto-determined. - */ - Color getColor() { - return color; - } - -}