mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-12 07:56:16 +00:00
Refactored PastCasesSummary
This commit is contained in:
parent
ee2f1c39c3
commit
44ad30fd80
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2019 Basis Technology Corp.
|
||||
* Copyright 2021 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> 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<Integer> 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<Integer> 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<Pair<String, Long>> getCaseCounts(Stream<String> cases) {
|
||||
private static List<Pair<String, Long>> getCaseCounts(Stream<String> cases) {
|
||||
Collection<List<String>> 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<String> deviceArtifactCases = new ArrayList<>();
|
||||
List<String> nonDeviceArtifactCases = new ArrayList<>();
|
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2019 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datasourcesummary.datamodel;
|
||||
|
||||
import java.util.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<Integer> 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<Integer> 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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<DataSource, PastCasesResult> 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<ExcelExport.ExcelSheetExport> 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();
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2021 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.report.modules.datasourcesummaryexport;
|
||||
|
||||
import java.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<Pair<String, Long>, 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<Pair<String, Long>, 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<ColumnModel<Pair<String, Long>, DefaultCellModel<?>>> DEFAULT_TEMPLATE
|
||||
= Arrays.asList(CASE_COL, COUNT_COL);
|
||||
|
||||
private ExportPastCases() {
|
||||
}
|
||||
|
||||
static List<ExcelExport.ExcelSheetExport> getExports(DataSource dataSource) {
|
||||
DataFetcher<DataSource, PastCasesResult> 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())
|
||||
);
|
||||
}
|
||||
}
|
@ -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({
|
||||
|
Loading…
x
Reference in New Issue
Block a user